usbSpeakerLib.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:67k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* usbSpeakerLib.c - USB speaker class drive with vxWorks SEQ_DEV interface */
  2. /* Copyright 2000-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01g,29oct01,wef  Remove automatic buffer creations and repalce with OSS_MALLOC.
  7. 01f,18sep01,wef  merge from wrs.tor2_0.usb1_1-f for veloce
  8. 01e,08aug01,dat  Removing warnings
  9. 01d,31jan01,wef  Fixed tab stops
  10. 01c,12apr00,wef  Fixed uninitialized variable warning: controlSelector and
  11.  settingWidth in setChannelControl()
  12. 01b,20mar00,rcb  Re-write code which de-references potentiall non-aligned word 
  13.  fields to prevent faults on certain processors (e.g., MIPS).
  14. 01a,12jan00,rcb  written.
  15. */
  16. /*
  17. DESCRIPTION
  18. This module implements the class driver for USB speaker devices.  USB speakers
  19. are a subset of the USB audio class, and this module handles only those parts
  20. of the USB audio class definition which are relevant to the operation of USB
  21. speakers.  
  22. This module presents a modified VxWorks SEQ_DEV interface to its callers.  The
  23. SEQ_DEV interface was chosen because, of the existing VxWorks driver models, it
  24. best supports the streaming data transfer model required by isochronous devices
  25. such as USB speakers.  As with other VxWorks USB class drivers, the standard
  26. driver interface has been expanded to support features unique to the USB and to
  27. speakers in general.  Functions have been added to allow callers to recognize
  28. the dynamic attachment and removal of speaker devices. IOCTL functions have 
  29. been added to retrieve and control additional settings related to speaker
  30. operation.
  31. INITIALIZATION
  32. As with standard SEQ_DEV drivers, this driver must be initialized by calling
  33. usbSpeakerDevInit().  usbSpeakerDevInit() in turn initializes its connection 
  34. to the USBD and other internal resources needed for operation. Unlike some 
  35. SEQ_DEV drivers, there are no usbSpeakerLib.c data structures which need 
  36. to be initialized prior to calling usbSpeakerDevInit().
  37. Prior to calling usbSpeakerDevInit(), the caller must ensure that the USBD
  38. has been properly initialized by calling - at a minimum - usbdInitialize().
  39. It is also the caller's responsibility to ensure that at least one USB HCD
  40. (USB Host Controller Driver) is attached to the USBD - using the USBD function
  41. usbdHcdAttach() - before speaker operation can begin.  However, it is not 
  42. necessary for usbdHcdAttach() to be alled prior to initializating usbSpeakerLib.
  43. usbSpeakerLib.c uses the USBD dynamic attach services and is capable of 
  44. recognizing USB speaker attachment and removal on the fly.  Therefore, it is 
  45. possible for USB HCDs to be attached to or detached from the USBD at run time
  46. - as may be required, for example, in systems supporting hot swapping of
  47. hardware.
  48. RECOGNIZING & HANDLING USB SPEAKERS
  49. As noted earlier, the operation of USB speakers is defined in the USB Audio Class
  50. Specification. Speakers, loosely defined, are those USB audio devices which
  51. provide an "Output Terminal".  For each USB audio device, usbSpeakerLib examines
  52. the descriptors which enumerate the "units" and "terminals" contained within the
  53. device.  These descriptors define both which kinds of units/terminals are present
  54. and how they are connected.  
  55. If an "Output Terminal" is found, usbSpeakerLib traces the device's internal
  56. connections to determine which "Input Terminal" ultiminately provides the audio
  57. stream for the "Output Terminal" and which, if any, Feature Unit is responsible
  58. for controlling audio stream attributes like volume.  Once having built such an
  59. internal "map" of the device, usbSpeakerLib configures the device and waits for
  60. a caller to provide a stream of audio data.  If no "Output Terminal" is found,
  61. usbSpeakerLib ignores the audio device.
  62. After determining that the audio device contains an Output Terminal, 
  63. usbSpeakerLib builds a list of the audio formats supported by the device. 
  64. usbSpeakerLib supports only AudioStreaming interfaces (no MidiStreaming is 
  65. supported).  
  66. For each USB speaker attached to the system and properly recognized by 
  67. usbSpeakerLib, usbSpeakerLib creates a SEQ_DEV structure to control the speaker.
  68. Each speaker is uniquely identified by the pointer to its corresponding SEQ_DEV
  69. structure.
  70. DYNAMIC ATTACHMENT & REMOVAL OF SPEAKERS
  71. As with other USB devices, USB speakers may be attached to or detached from the
  72. system dynamically.  usbSpeakerLib uses the USBD's dynamic attach services in 
  73. order to recognize these events.  Callers of usbSpeakerLib may, in turn, register
  74. with usbSpeakerLib for notification when USB speakers are attached or removed
  75. using the usbSpeakerDynamicAttachRegister() function.  When a USB speaker is
  76. attached or removed, usbSpeakerLib invokes the attach notification callbacks 
  77. for all registered callers.  The callback is passed the pointer to the affected
  78. SEQ_DEV structure and a code indicated whether the speaker is being attached or
  79. removed.
  80. usbSpeakerLib maintains a usage count for each SEQ_DEV structure.  Callers can 
  81. increment the usage count by calling usbSpeakSeqDevLock() and can decrement the 
  82. usage count by calling usbSpeakerSeqDevUnlock().  When a USB speaker is removed
  83. from the system and its usage count is 0, usbSpeakerLib automatically removes 
  84. all data structures, including the SEQ_DEV structure itself, allocated on behalf
  85. of the device. Sometimes, however, callers rely on these data structures and 
  86. must properly recognize the removal of the device before it is safe to destroy 
  87. the underlying data structures.  The lock/unlock functions provide a mechanism
  88. for callers to protect these data structures as needed.
  89. DATA FLOW
  90. Before sending audio data to a speaker device, the caller must specify the data
  91. format (e.g., PCM, MPEG) using an IOCTL (see below).  The USB speaker itself
  92. must support the indicated (or a similar) data format.
  93. USB speakers rely on an uninterrupted, time-critical stream of audio data.  The
  94. data is sent to the speaker through an isochronous pipe.  In order for the data
  95. flow to continue uninterrupted, usbSpeakerLib internally uses a double-buffering
  96. scheme.  When data is presented to usbSpeakerLib's sd_seqWrt() function by the 
  97. caller, usbSpeakerLib copies the data into an internal buffer and immediately 
  98. releases the caller's buffer.  The caller should immediately try to pass the next 
  99. buffer to usbSpeakerLib.  When usbSpeakerLib's internal buffer is filled, it will 
  100. block the caller until such time as it can accept the new data.  In this manner,
  101. the caller and usbSpeakerLib work together to ensure that an adequate supply of
  102. audio data will always be available to continue isochronous transmission 
  103. uninterrupted.
  104. Audio play begins after usbSpeakerLib has accepted half a second of audio data
  105. or when the caller closes the audio stream, whichever happens first.  The caller
  106. must use the IOCTLs to "open" and "close" each audio stream.  usbSpeakerLib
  107. relies on these IOCTLs to manage its internal buffers correctly.
  108. IOCTLs
  109. usbSpeakerLib implements a number of IOCTLs unique to the handling of audio
  110. data and devices.  usbSpeakerLib provides IOCTLs to set the following controls:
  111. mute, volume, bass, mid-range, and treble.  usbSpeakerLib also provides IOCTLs
  112. to be used by callers to interrogate a speaker's audio format capabilities or 
  113. to specify the audio format for a subsequent data stream.
  114. INCLUDE FILES:
  115. seqIo.h usbAudio.h usbSpeakerLib.h
  116. */
  117. /* includes */
  118. #include "vxWorks.h"
  119. #include "string.h"
  120. #include "ioLib.h"
  121. #include "seqIo.h"
  122. #include "errno.h"
  123. #include "usb/usbPlatform.h"
  124. #include "usb/ossLib.h"  /* operations system srvcs */
  125. #include "usb/usb.h" /* general USB definitions */
  126. #include "usb/usbListLib.h" /* linked list functions */
  127. #include "usb/usbdLib.h" /* USBD interface */
  128. #include "usb/usbLib.h"  /* USB utility functions */
  129. #include "usb/usbAudio.h" /* USB audio class definitions */
  130. #include "drv/usb/usbSpeakerLib.h"  /* our API */
  131. /* defines */
  132. #define SPKR_CLIENT_NAME "usbSpeakerLib" /* our USBD client name */
  133. #define A_REALLY_BIG_INTEGER 0x7fffffff  /* large positive integer */
  134. #define MSEC_PER_SEC 1000L /* number of msec per second */
  135. #define FRAME_SKIP 20 /* frames to skip before play */
  136. /* (makes sure h/w doesn't run 
  137.  * ahead of us) 
  138.  */
  139. #define IRP_COUNT 2 /* number of IRPs for transmit */
  140. /* typedefs */
  141. /* ATTACH_REQUEST */
  142. typedef struct attach_request
  143.     {
  144.     LINK reqLink; /* linked list of requests */
  145.     USB_SPKR_ATTACH_CALLBACK callback; /* client callback routine */
  146.     pVOID callbackArg; /* client callback argument */
  147.     } ATTACH_REQUEST, *pATTACH_REQUEST;
  148. /* USB_SPKR_SEQ_DEV is the internal data structure we use to track each USB
  149.  * speaker.
  150.  */
  151. typedef struct usb_spkr_seq_dev
  152.     {
  153.     SEQ_DEV seqDev; /* must be first field */
  154.     BOOL reserved; /* TRUE if device reserved */
  155.     LINK devLink; /* linked list of structs */
  156.     UINT16 lockCount; /* Count of times structure locked */
  157.     USBD_NODE_ID nodeId; /* speaker node Id */
  158.     UINT16 configuration; /* configuration/interface reported as */
  159.     BOOL connected; /* TRUE if speaker currently connected */
  160.     UINT8 outputTerminalId; /* ID of output terminal */
  161.     UINT8 inputTerminalId; /* ID of input terminal */
  162.     UINT8 featureUnitId; /* ID of feature unit (optional) */
  163.     UINT8 channels; /* count of channels */
  164.     UINT16 channelConfig; /* channel configuration */
  165.     UINT16 capsLen; /* size of following array */
  166.     pUSB_SPKR_CHANNEL_CAPS pCaps;   /* Indicates feature support on each
  167.      * channel...channel 0 is the "master"
  168.      * and is global to all 
  169.      */
  170.     UINT16 fmtCount; /* count of audio formats */
  171.     pUSB_SPKR_AUDIO_FORMAT pFmt;    /* indicates nature of each format */
  172.     pUSB_SPKR_AUDIO_FORMAT pSelFmt; /* pointer to selected format */
  173.     UINT32 sampleFrequency; /* playback frequency */
  174.     UINT32 sampleSize; /* data always sent in blocks which are 
  175.  * multiples of this value 
  176.  */
  177.     UINT32 bytesPerSec;  /* playback bytes per second */
  178.     BOOL open; /* TRUE when audio stream is open */
  179.     BOOL streamFault; /* TRUE if stream fault detected */
  180.     pUINT8 pAudioBfr; /* bfr for audio data */
  181.     UINT32 audioBfrLen;  /* size of audio buffer */
  182.     UINT32 audioBfrHalf; /* one half the length of the buffer */
  183.     UINT32 audioBfrCount; /* count of data available */
  184.     UINT32 audioBfrIn; /* next location to receive data */
  185.     UINT32 audioBfrOut;  /* next location to transmit */
  186.     UINT32 audioBfrPending; /* nbr of bytes being transmitted */
  187.     UINT32 audioBfrTotal; /* total data passed through bfr */
  188.     BOOL foregroundWaiting; /* TRUE if foreground waiting for bfr */
  189.     SEM_HANDLE bfrNotFullSem; /* signalled when bfr goes from 
  190.  * full->not full 
  191.  */
  192.     USBD_PIPE_HANDLE isochPipeHandle; /* USBD handle for isoch data pipe */
  193.     UINT32 frameWindow;  /* size of host controller frame ctr */
  194.     UINT32 nextStartFrame; /* next frame for isoch transfer */
  195.     UINT32 blocksSent; /* blocks sent for this stream */
  196.     USB_IRP irp [IRP_COUNT]; /* IRPs to be used for transmit */
  197.     UINT16 nextIrp; /* index of next IRP to use */
  198.     UINT16 nextDoneIrp;  /* index of next IRP to complete */
  199.     UINT16 irpsInUse; /* count of IRPs in use */
  200.     } USB_SPKR_SEQ_DEV, *pUSB_SPKR_SEQ_DEV;
  201. /* forward function declarations */
  202. LOCAL VOID usbSpkrIrpCallback 
  203.     (
  204.     pVOID p
  205.     );
  206. /* locals */
  207. LOCAL UINT16 initCount = 0; /* Count of init nesting */
  208. LOCAL MUTEX_HANDLE speakerMutex; /* mutex used to protect 
  209.  * internal structs 
  210.  */
  211. LOCAL LIST_HEAD devList; /* linked list of USB_SPKR_SEQ_DEV */
  212. LOCAL LIST_HEAD reqList; /* Attach callback request list */
  213. LOCAL USBD_CLIENT_HANDLE usbdHandle; /* our USBD client handle */
  214. /***************************************************************************
  215. *
  216. * audioIfGetRequest - executes an audio-class-specific request
  217. *
  218. * Executes a request to an AudioControl or AudioStreaming interface.
  219. * The actual length of data transferred must be equal to the <length> passed
  220. * by the caller or an ERROR is returned.
  221. *
  222. * RETURNS: OK, else ERROR if not successful
  223. */
  224. LOCAL STATUS audioIfRequest
  225.     (
  226.     pUSB_SPKR_SEQ_DEV pSeqDev,
  227.     UINT8 requestType,
  228.     UINT8 request,
  229.     UINT8 entityId,
  230.     UINT16 value,
  231.     UINT16 length,
  232.     pVOID pBfr
  233.     )
  234.     
  235.     {
  236.     UINT16 actLen;
  237.     if (usbdVendorSpecific (usbdHandle, 
  238.     pSeqDev->nodeId, 
  239.     requestType,
  240.     request, 
  241.     value, 
  242.     entityId << 8, 
  243.     length, 
  244.     (pUINT8) pBfr, 
  245.     &actLen) 
  246.   != OK 
  247. || actLen != length)
  248. {
  249. return ERROR;
  250. }
  251.     return OK;
  252.     }
  253. /***************************************************************************
  254. *
  255. * findAudioByUnit - seaches a buffer for the indicated audio descriptor
  256. *
  257. * RETURNS: ptr to a matching descriptor or NULL if not found
  258. */
  259. LOCAL pVOID findAudioDescrByUnit
  260.     (
  261.     pUINT8 pBfr,
  262.     UINT16 bfrLen,
  263.     UINT8 unitId
  264.     )
  265.     {
  266.     pUSB_AUDIO_AC_COMMON pHdr;
  267.     /* The remaining buffer length must be at least three bytes to accommodate
  268.      * the USB_AUDIO_AC_COMMON structure. 
  269.      */
  270.     while (bfrLen >= sizeof (*pHdr))
  271. {
  272. pHdr = (pUSB_AUDIO_AC_COMMON) pBfr;
  273. if (pHdr->length == 0)
  274.     return NULL; /* must be invalid */
  275. pBfr += min (pHdr->length, bfrLen);
  276. bfrLen -= min (pHdr->length, bfrLen);
  277. if (pHdr->descriptorType == USB_DESCR_AUDIO_INTERFACE &&
  278.     pHdr->unitId == unitId)
  279.     return (pVOID) pHdr;
  280. }
  281.     return NULL;
  282.     }
  283. /***************************************************************************
  284. *
  285. * findAudioDescrSkip - seaches a buffer for the indicated audio descriptor
  286. *
  287. * Upon return, <ppBfr> points to the descriptor following the last searhed
  288. * descriptor and <pBfrLen> is updated with the number of bytes remaining in 
  289. * the bfr.
  290. *
  291. * RETURNS: ptr to a matching descriptor or NULL if not found
  292. */
  293. LOCAL pVOID findAudioDescrSkip
  294.     (
  295.     pUINT8 *ppBfr,
  296.     pUINT16 pBfrLen,
  297.     UINT8 descriptorType,
  298.     UINT8 descriptorSubType
  299.     )
  300.     {
  301.     pUSB_DESCR_HDR_SUBHDR pHdr;
  302.     /* The remaining buffer length must be at least three bytes to accommodate
  303.      * the descriptor length, descriptorType, and descriptorSubType fields. 
  304.      */
  305.     while (*pBfrLen >= sizeof (*pHdr))
  306. {
  307. pHdr = (pUSB_DESCR_HDR_SUBHDR) *ppBfr;
  308. if (pHdr->length == 0)
  309.     return NULL; /* must be invalid */
  310. *ppBfr += min (pHdr->length, *pBfrLen);
  311. *pBfrLen -= min (pHdr->length, *pBfrLen);
  312. if (pHdr->descriptorType == descriptorType &&
  313.     pHdr->descriptorSubType == descriptorSubType)
  314.     return (pVOID) pHdr;
  315. }
  316.     return NULL;
  317.     }
  318. /***************************************************************************
  319. *
  320. * findAudioDescr - seaches a buffer for the indicated audio descriptor
  321. *
  322. * RETURNS: ptr to a matching descriptor or NULL if not found
  323. */
  324. LOCAL pVOID findAudioDescr
  325.     (
  326.     pUINT8 pBfr,
  327.     UINT16 bfrLen,
  328.     UINT8 descriptorType,
  329.     UINT8 descriptorSubType
  330.     )
  331.     {
  332.     return findAudioDescrSkip (&pBfr, 
  333.        &bfrLen, 
  334.        descriptorType, 
  335.        descriptorSubType);
  336.     }
  337. /***************************************************************************
  338. *
  339. * setChannelControl - Sets the specified channel control
  340. *
  341. * <funcCode> is the IOCTL code specifying the control to set.  <channel>
  342. * is the channel number (channel 0 = master channel).  <value> is the
  343. * new setting value.
  344. *
  345. * RETURNS: OK if successful, ENOSYS if not supported, else EIO if failure
  346. */
  347. LOCAL STATUS setChannelControl
  348.     (
  349.     pUSB_SPKR_SEQ_DEV pSeqDev,
  350.     int funcCode,
  351.     UINT16 channel,
  352.     UINT16 value
  353.     )
  354.     {
  355.     pUSB_SPKR_CHANNEL_CAPS pChannelCaps;
  356.     pUSB_SPKR_CTL_CAPS pCtlCaps = NULL;
  357.     UINT8 controlSelector = 0;
  358.     UINT8 settingWidth = 0;
  359.     UINT16 * pSetting;
  360.     if ((pSetting = OSS_MALLOC (sizeof (UINT16))) == NULL)
  361. return EIO;
  362.     /* validate channel number.  0 = master channel.  1..n = other channels. */
  363.     if (channel > pSeqDev->channels)
  364. return EIO;
  365.     pChannelCaps = &pSeqDev->pCaps [channel];
  366.     /* Check the capabilities of the control */
  367.     switch (funcCode)
  368. {
  369. case USB_SPKR_IOCTL_SET_MUTE:   
  370.     pCtlCaps = NULL;
  371.     controlSelector = USB_AUDIO_FCS_VOLUME;
  372.     settingWidth = USB_AUDIO_MUTE_ATTR_WIDTH;
  373.     break;
  374. case USB_SPKR_IOCTL_SET_VOLUME: 
  375.     pCtlCaps = &pChannelCaps->volume;
  376.     controlSelector = USB_AUDIO_FCS_VOLUME;
  377.     settingWidth = USB_AUDIO_VOLUME_ATTR_WIDTH;
  378.     break;
  379. case USB_SPKR_IOCTL_SET_BASS:
  380.     pCtlCaps = &pChannelCaps->bass;
  381.     controlSelector = USB_AUDIO_FCS_BASS;
  382.     settingWidth = USB_AUDIO_BASS_ATTR_WIDTH;
  383.     break;
  384. case USB_SPKR_IOCTL_SET_MID:
  385.     pCtlCaps = &pChannelCaps->mid;
  386.     controlSelector = USB_AUDIO_FCS_MID;
  387.     settingWidth = USB_AUDIO_MID_ATTR_WIDTH;
  388.     break;
  389. case USB_SPKR_IOCTL_SET_TREBLE: 
  390.     
  391.     pCtlCaps = &pChannelCaps->treble;
  392.     controlSelector = USB_AUDIO_FCS_TREBLE;
  393.     settingWidth = USB_AUDIO_TREBLE_ATTR_WIDTH;
  394.     break;
  395. }
  396.     if (pCtlCaps != NULL)
  397. {
  398. if (!pCtlCaps->supported)
  399.     return ENOSYS;
  400. if (((INT16) value) < pCtlCaps->min || ((INT16) value) > pCtlCaps->max)
  401.     return EIO;
  402. }
  403.     /* Set the control */
  404.     *pSetting = TO_LITTLEW (value);
  405.     if (audioIfRequest (pSeqDev,
  406. USB_RT_HOST_TO_DEV | USB_RT_CLASS | USB_RT_INTERFACE,
  407. USB_REQ_AUDIO_SET_CUR, 
  408. pSeqDev->featureUnitId, 
  409. controlSelector << 8 | channel, 
  410. settingWidth, 
  411. pSetting) 
  412.       != OK)
  413. {
  414. OSS_FREE (pSetting);
  415. return EIO;
  416. }
  417.     pCtlCaps->cur = value;
  418.     OSS_FREE (pSetting);
  419.     return OK;
  420.     }
  421. /***************************************************************************
  422. *
  423. * getControlSetting - read an individual setting for specified control
  424. *
  425. * <settingWidth> specifies the control value width as 1 (byte) or 2 (word).
  426. * RETURNS: OK if successfull, else ERROR
  427. */
  428. LOCAL STATUS getControlSetting
  429.     (
  430.     pUSB_SPKR_SEQ_DEV pSeqDev,
  431.     UINT8 entityId,
  432.     UINT8 channel,
  433.     UINT8 controlSelector,
  434.     UINT8 request,
  435.     pUINT16 pAttribute,
  436.     UINT16 settingWidth
  437.     )
  438.     {
  439.     UINT16 * pAttributeBuf;
  440.     if ((pAttributeBuf = OSS_CALLOC (sizeof (UINT16))) == NULL)
  441. return ERROR;
  442.     if (audioIfRequest (pSeqDev,
  443. USB_RT_DEV_TO_HOST | USB_RT_CLASS | USB_RT_INTERFACE, 
  444. request, 
  445. entityId, 
  446. controlSelector << 8 | channel, 
  447. settingWidth, 
  448. pAttributeBuf) 
  449.       != OK)
  450. {
  451. OSS_FREE (pAttributeBuf);
  452. return ERROR;
  453. }
  454.     *pAttribute = FROM_LITTLEW (*pAttributeBuf); 
  455.     
  456.     OSS_FREE (pAttributeBuf);
  457.     return OK;
  458.     }
  459. /***************************************************************************
  460. *
  461. * getControlSettings - reads settings for the specified feature unit control
  462. *
  463. * If the information can be read successfully, <pCtlCaps>->supported is set 
  464. * to TRUE.
  465. *
  466. * RETURNS: N/A
  467. */
  468. LOCAL VOID getControlSettings
  469.     (
  470.     pUSB_SPKR_SEQ_DEV pSeqDev,
  471.     UINT8 entityId,
  472.     UINT8 channel,
  473.     UINT8 controlSelector,
  474.     pUSB_SPKR_CTL_CAPS pCtlCaps,
  475.     UINT16 settingWidth
  476.     )
  477.     {
  478.     /* Get the control's resolution. */
  479.     if (getControlSetting (pSeqDev, 
  480.    entityId, 
  481.    channel, 
  482.    controlSelector,
  483.    USB_REQ_AUDIO_GET_RES, 
  484.    &pCtlCaps->res, 
  485.    settingWidth) 
  486.  != OK)
  487. return;
  488.     /* Get the control's min setting */
  489.     if (getControlSetting (pSeqDev, 
  490.    entityId, 
  491.    channel, 
  492.    controlSelector,
  493.    USB_REQ_AUDIO_GET_MIN, 
  494.    (UINT16 *)&pCtlCaps->min, 
  495.    settingWidth) 
  496.  != OK)
  497. return;
  498.     /* Get the control's max setting */
  499.     if (getControlSetting (pSeqDev, 
  500.    entityId, 
  501.    channel, 
  502.    controlSelector,
  503.    USB_REQ_AUDIO_GET_MAX, 
  504.    (UINT16 *)&pCtlCaps->max, 
  505.    settingWidth) 
  506.  != OK)
  507. return;
  508.     
  509.     /* Get the control's current setting */
  510.     if (getControlSetting (pSeqDev, 
  511.    entityId, 
  512.    channel, 
  513.    controlSelector,
  514.    USB_REQ_AUDIO_GET_CUR, 
  515.    (UINT16 *)&pCtlCaps->cur, 
  516.    settingWidth) 
  517.  != OK)
  518. return;
  519.     pCtlCaps->supported = TRUE;
  520.     }
  521. /***************************************************************************
  522. *
  523. * recordChannelsCaps - record capabilities for the specified channel
  524. *
  525. * RETURNS: N/A
  526. */
  527. LOCAL VOID recordChannelCaps
  528.     (
  529.     pUSB_SPKR_SEQ_DEV pSeqDev,
  530.     UINT8 entityId,
  531.     UINT8 channel,
  532.     pUSB_SPKR_CHANNEL_CAPS pCaps,
  533.     UINT8 controls
  534.     )
  535.     {
  536.     if ((controls & USB_AUDIO_FCM_MUTE) != 0)
  537. pCaps->mute.supported = TRUE;
  538.     if ((controls & USB_AUDIO_FCM_VOLUME) != 0)
  539. getControlSettings (pSeqDev, 
  540.     entityId, 
  541.     channel,
  542.     USB_AUDIO_FCS_VOLUME, 
  543.     &pCaps->volume, 
  544.     USB_AUDIO_VOLUME_ATTR_WIDTH);
  545.     if ((controls & USB_AUDIO_FCM_BASS) != 0)
  546. getControlSettings (pSeqDev, 
  547.     entityId, 
  548.     channel,
  549.     USB_AUDIO_FCS_BASS, 
  550.     &pCaps->bass, 
  551.     USB_AUDIO_BASS_ATTR_WIDTH);
  552.     if ((controls & USB_AUDIO_FCM_MID) != 0)
  553. getControlSettings (pSeqDev, 
  554.     entityId, 
  555.     channel,
  556.     USB_AUDIO_FCS_MID, 
  557.     &pCaps->mid, 
  558.     USB_AUDIO_MID_ATTR_WIDTH);
  559.     if ((controls & USB_AUDIO_FCM_TREBLE) != 0)
  560. getControlSettings (pSeqDev, 
  561.     entityId, 
  562.     channel,     
  563.     USB_AUDIO_FCS_TREBLE, 
  564.     &pCaps->treble, 
  565.     USB_AUDIO_TREBLE_ATTR_WIDTH);
  566.     }
  567. /***************************************************************************
  568. *
  569. * buildAudioMap - determine what capabilities the audio device has
  570. *
  571. * Search the provided <pCfgBfr> for an AudioClass (AC) descriptor and 
  572. * from that descriptor determine what capabilities the device has. 
  573. *
  574. * RETURNS: OK if successful, else ERROR.
  575. */
  576. LOCAL STATUS buildAudioMap
  577.     (
  578.     pUSB_SPKR_SEQ_DEV pSeqDev,
  579.     pUINT8 pCfgBfr,
  580.     UINT16 cfgLen
  581.     )
  582.     {
  583.     pUSB_AUDIO_AC_DESCR pAcDescr;
  584.     pUSB_AUDIO_AC_COMMON pAcCommon;
  585.     pUSB_AUDIO_OUTPUT_TERM_DESCR pOutputTerm;
  586.     pUSB_AUDIO_INPUT_TERM_DESCR pInputTerm;
  587.     pUSB_AUDIO_FEATURE_UNIT_DESCR pFeatureUnit = NULL;
  588.     pUINT8 pBfr;
  589.     UINT16 bfrLen;
  590.     UINT16 totalLength;
  591.     UINT16 remLen;
  592.     UINT8 prevId;
  593.     pUINT8 pControl;
  594.     UINT16 i;
  595.     /* Find the first AudioControl (AC) descriptor */
  596.     pBfr = pCfgBfr;
  597.     bfrLen = cfgLen;
  598.     if ((pAcDescr = findAudioDescrSkip (&pBfr, 
  599. &bfrLen, 
  600. USB_DESCR_AUDIO_INTERFACE, 
  601. USB_DESCR_AUDIO_AC_HEADER)) 
  602.       == NULL)
  603. return ERROR;
  604.     /* Find an "Output Terminal".  Then, using the terminal/unit numbers as
  605.      * links, work backwards from the output terminal to find the "Input 
  606.      * Terminal" and "Feature Unit" (if any) associated with it.
  607.      */
  608.     totalLength = pAcDescr->totalLength [0] | (pAcDescr->totalLength [1] << 8);
  609.     remLen = min (totalLength - sizeof (*pAcDescr), bfrLen);
  610.     if ((pOutputTerm = findAudioDescr (pBfr, 
  611.        remLen, 
  612.        USB_DESCR_AUDIO_INTERFACE, 
  613.        USB_DESCR_AUDIO_AC_OUTPUT_TERMINAL)) 
  614.      == NULL)
  615. return ERROR;
  616.     pSeqDev->outputTerminalId = pOutputTerm->terminalId;
  617.     prevId = pOutputTerm->sourceId;
  618.     while (prevId != 0 && pSeqDev->inputTerminalId == 0)
  619. {
  620. if ((pAcCommon = findAudioDescrByUnit (pBfr, remLen, prevId)) == NULL)
  621.     return FALSE;
  622. switch (pAcCommon->descriptorSubType)
  623.     {
  624.     case USB_DESCR_AUDIO_AC_INPUT_TERMINAL:
  625. /* Record characteristics of the input terminal */
  626. pInputTerm = (pUSB_AUDIO_INPUT_TERM_DESCR) pAcCommon;
  627. pSeqDev->inputTerminalId = pInputTerm->terminalId;
  628. pSeqDev->channels = pInputTerm->channels;
  629. pSeqDev->channelConfig = pInputTerm->channelConfig [0] 
  630. | (pInputTerm->channelConfig [1] << 8);
  631. prevId = 0;
  632. /* If there is a feature unit descriptor, record its 
  633.  * capabilities on a channel-by-channel basis. 
  634.  */
  635. if (pFeatureUnit != NULL)
  636.     {
  637.     /* Allocate space for info on a per-channel basis.
  638.      *
  639.      * NOTE: Array position 0 is for "master" (ie. 
  640.      * global) channel.
  641.      */
  642.     pSeqDev->capsLen = 
  643.     (pSeqDev->channels + 1) * sizeof (USB_SPKR_CHANNEL_CAPS);
  644.     if ((pSeqDev->pCaps = OSS_CALLOC (pSeqDev->capsLen)) 
  645.      == NULL)
  646. return ERROR;
  647.     /* Record capabilities */
  648.     for (i = 0; i <= pSeqDev->channels; i++)
  649. {
  650. pControl = &pFeatureUnit->controls[i * pFeatureUnit->controlSize];
  651. recordChannelCaps (pSeqDev, 
  652.    pFeatureUnit->unitId, 
  653.    i, 
  654.    &pSeqDev->pCaps [i], 
  655.    *pControl);
  656. }
  657.     }
  658. break;
  659.     case USB_DESCR_AUDIO_AC_MIXER_UNIT:
  660. prevId = ((pUSB_AUDIO_MIXER_UNIT_DESCR) pAcCommon)->sourceId [0];
  661. break;
  662.     case USB_DESCR_AUDIO_AC_SELECTOR_UNIT:
  663. prevId = ((pUSB_AUDIO_SELECTOR_UNIT_DESCR) pAcCommon)->sourceId [0];
  664. break;
  665.     case USB_DESCR_AUDIO_AC_FEATURE_UNIT:
  666. /* Record capabilities of the feature unit */
  667. pFeatureUnit = (pUSB_AUDIO_FEATURE_UNIT_DESCR) pAcCommon;
  668. pSeqDev->featureUnitId = pFeatureUnit->unitId;
  669. prevId = pFeatureUnit->sourceId;
  670. break;
  671.     case USB_DESCR_AUDIO_AC_PROCESSING_UNIT:
  672. prevId = ((pUSB_AUDIO_PROCESS_UNIT_DESCR) pAcCommon)->sourceId [0];
  673. break;
  674.     case USB_DESCR_AUDIO_AC_EXTENSION_UNIT:
  675. prevId = ((pUSB_AUDIO_EXT_UNIT_DESCR) pAcCommon)->sourceId [0];
  676. break;
  677.     case USB_DESCR_AUDIO_AC_UNDEFINED:
  678.     case USB_DESCR_AUDIO_AC_HEADER:
  679.     case USB_DESCR_AUDIO_AC_OUTPUT_TERMINAL:
  680.     default:
  681. /* These terminal/unit types should not be encountered at
  682.  * this point in the algorithm.
  683.  */
  684. return ERROR;
  685.     }
  686. }
  687.     return OK;
  688.     }
  689. /***************************************************************************
  690. *
  691. * reallocateFormatList - increases room for format list by one entry
  692. *
  693. * RETURNS: OK, else ERROR if out of memory
  694. */
  695. LOCAL STATUS reallocateFormatList
  696.     (
  697.     pUSB_SPKR_SEQ_DEV pSeqDev
  698.     )
  699.     {
  700.     pUSB_SPKR_AUDIO_FORMAT pNewList;
  701.     pSeqDev->fmtCount++;
  702.     if ((pNewList = OSS_CALLOC (pSeqDev->fmtCount * 
  703. sizeof (USB_SPKR_AUDIO_FORMAT))) 
  704.        == NULL)
  705. return ERROR;
  706.     if (pSeqDev->fmtCount > 1 && pSeqDev->pFmt != NULL)
  707. {
  708. memcpy (pNewList, 
  709. pSeqDev->pFmt, 
  710. (pSeqDev->fmtCount - 1) * sizeof (USB_SPKR_AUDIO_FORMAT));
  711. OSS_FREE (pSeqDev->pFmt);
  712. }
  713.     pSeqDev->pFmt = pNewList;
  714.     return OK;
  715.     }
  716. /***************************************************************************
  717. *
  718. * parseInterface - parse an interface descriptor, looking for audio formats
  719. *
  720. * NOTE: <cfgLen> should count bytes only through the end of this interface.
  721. *
  722. * RETURNS: N/A
  723. */
  724. LOCAL VOID parseInterface
  725.     (
  726.     pUSB_SPKR_SEQ_DEV pSeqDev,
  727.     pUSB_INTERFACE_DESCR pIfDescr,
  728.     pUINT8 pCfgBfr,
  729.     UINT16 cfgLen
  730.     )
  731.     {
  732.     pUSB_AUDIO_AS_DESCR pAsDescr;
  733.     pUSB_AUDIO_TYPE_DESCR pType;
  734.     pUSB_AUDIO_STD_ISOCH_EP_DESCR pStdEp;
  735.     pUSB_SPKR_AUDIO_FORMAT pFmt;
  736.     USB_SPKR_AUDIO_FORMAT fmt = {0};
  737.     /* If this interface doesn't contain a class-specific AS (AudioStreaming)
  738.      * descriptor then ignore it.  If it does, but the AudioStream doesn't
  739.      * link to the inputTerminalId, then ignore it anyway.
  740.      */
  741.     if ((pAsDescr = findAudioDescrSkip (&pCfgBfr, 
  742. &cfgLen, 
  743. USB_DESCR_AUDIO_INTERFACE, 
  744. USB_DESCR_AUDIO_AS_GENERAL)) 
  745.        == NULL)
  746. return;
  747.     if (pAsDescr->terminalLink != pSeqDev->inputTerminalId)
  748. return;
  749.     /* We must now find a format type descriptor and an endpoint descriptor. */
  750.     if ((pType = findAudioDescr (pCfgBfr, 
  751.  cfgLen,
  752.  USB_DESCR_AUDIO_INTERFACE, 
  753.  USB_DESCR_AUDIO_AS_FORMAT_TYPE)) 
  754. == NULL)
  755. return;
  756.     if ((pStdEp = usbDescrParse (pCfgBfr, cfgLen, USB_DESCR_ENDPOINT)) == NULL)
  757. return;
  758.     /* Construct a format record from the accumulated data. */
  759.     fmt.interface = pIfDescr->interfaceNumber;
  760.     fmt.altSetting = pIfDescr->alternateSetting;
  761.     fmt.delay = pAsDescr->delay;
  762.     fmt.endpoint = pStdEp->endpointAddress;
  763.     fmt.maxPacketSize = pStdEp->maxPacketSize [0] 
  764. | (pStdEp->maxPacketSize [1] << 8);
  765.     fmt.formatTag = pAsDescr->formatTag [0] | (pAsDescr->formatTag [1] << 8);
  766.     fmt.formatType = pType->formatType;
  767.     switch (pType->formatType)
  768. {
  769. case USB_AUDIO_FORMAT_TYPE1:
  770.     fmt.channels = pType->ts.type1.nbrChannels;
  771.     fmt.subFrameSize = pType->ts.type1.subFrameSize;
  772.     fmt.bitRes = pType->ts.type1.bitResolution;
  773.     break;
  774. case USB_AUDIO_FORMAT_TYPE2:
  775.     fmt.maxBitRate = pType->ts.type2.maxBitRate [0] |
  776.     (pType->ts.type2.maxBitRate [1] << 8);
  777.     fmt.samplesPerFrame = pType->ts.type2.samplesPerFrame [0] 
  778.   | (pType->ts.type2.samplesPerFrame [1] << 8);
  779.     break;
  780. case USB_AUDIO_FORMAT_TYPE3:
  781.     fmt.channels = pType->ts.type3.nbrChannels;
  782.     fmt.subFrameSize = pType->ts.type3.subFrameSize;
  783.     fmt.bitRes = pType->ts.type3.bitResolution;
  784.     break;
  785. default: /* We don't recognize this format */
  786.     return;
  787. }
  788.     /* Copy new format record to SEQ_DEV structure. */
  789.     if (reallocateFormatList (pSeqDev) != OK)
  790. return;
  791.     pFmt = &pSeqDev->pFmt [pSeqDev->fmtCount - 1];
  792.     *pFmt = fmt;
  793.     }
  794. /***************************************************************************
  795. *
  796. * buildFormatList - builds a list of formats supported by the speaker
  797. *
  798. * RETURNS: OK if successful, else ERROR.
  799. */
  800. LOCAL STATUS buildFormatList
  801.     (
  802.     pUSB_SPKR_SEQ_DEV pSeqDev,
  803.     pUINT8 pCfgBfr,
  804.     UINT16 cfgLen
  805.     )
  806.     {
  807.     pUSB_INTERFACE_DESCR pIfDescr;
  808.     pUINT8 pTmp;
  809.     UINT16 tmpLen;
  810.     UINT16 rangeLen;
  811.     /* Find each interface descriptor of type AudioStreaming.  Determine the 
  812.      * length of the descriptor, and then parse each format type supported by 
  813.      * the interface.
  814.      */
  815.     while ((pIfDescr = usbDescrParseSkip (&pCfgBfr, 
  816.   &cfgLen, 
  817.   USB_DESCR_INTERFACE)) 
  818. != NULL)
  819. {
  820. if (pIfDescr->interfaceClass == USB_CLASS_AUDIO &&
  821.     pIfDescr->interfaceSubClass == USB_SUBCLASS_AUDIO_AUDIOSTREAMING)
  822.     {
  823.     /* We found an AudioStreaming interface descriptor.  Now, determine 
  824.      * how many bytes until the next interface descriptor. This 
  825.      * determines the range of the configuration descriptor we will 
  826.      * examine while parsing this interface.
  827.      */
  828.     pTmp = pCfgBfr;
  829.     tmpLen = cfgLen;
  830.     if (usbDescrParseSkip (&pTmp, 
  831.    &tmpLen, 
  832.    USB_DESCR_INTERFACE) 
  833.  != NULL)
  834. rangeLen = cfgLen - tmpLen;
  835.     else
  836. rangeLen = cfgLen;
  837.     parseInterface (pSeqDev, pIfDescr, pCfgBfr, rangeLen);
  838.     }
  839. }
  840.     return OK;
  841.     }
  842. /***************************************************************************
  843. *
  844. * selectFormat - selects an audio format to match the caller's request
  845. *
  846. * <pReqFmt> points to a USB_SPEAKER_AUDIO_FORMAT structure in which the
  847. * "formatTag" field has been initialized to the desired format as
  848. * USB_AUDIO_TYPEn_xxxx and "formatType" has been initialized with the 
  849. * format type as USB_AUDIO_FORMAT_TYPEn.  
  850. *
  851. * Depending on the specified format, the fields "channels", "subFrameSize", 
  852. * "bitRes", "sampleFrequency", "maxBitRate", and "samplesPerFrame" may also 
  853. * need to be specified to qualify the format.  The other fields of the 
  854. * structure *do not* need to be specified.
  855. *
  856. * The field "sampleFrequency", which must be set for Type I & Type 3 formats
  857. * must be set with the desired playback frequency.  The frequency is 
  858. * expressed as samples per sec.  For example, a sampleFrequency of 88,500 
  859. * is 88,500 samples per second per channel.
  860. *
  861. * This function will attempt to find an audio format supported by the
  862. * speaker which is an exact match for the specified format.  If found, that
  863. * format will be selected.  If no exact match can be found, an error will be
  864. * returned.
  865. *
  866. * RETURNS: OK if successful, else ERROR.
  867. */
  868. LOCAL STATUS selectFormat
  869.     (
  870.     pUSB_SPKR_SEQ_DEV pSeqDev,
  871.     pUSB_SPKR_AUDIO_FORMAT pReqFmt
  872.     )
  873.     {
  874.     pUSB_SPKR_AUDIO_FORMAT pFmt;
  875.     UINT16 i;
  876.     /* Set the format type to "unspecified". */
  877.     pSeqDev->pSelFmt = NULL;
  878.     pSeqDev->sampleFrequency = 0;
  879.     pSeqDev->sampleSize = 0;
  880.     /* Look for an exact match for the format */
  881.     for (i = 0; i < pSeqDev->fmtCount; i++)
  882. {
  883. pFmt = &pSeqDev->pFmt [i];
  884. switch (pReqFmt->formatType)
  885.     {
  886.     case USB_AUDIO_FORMAT_TYPE1:
  887.     case USB_AUDIO_FORMAT_TYPE3:
  888. if (pReqFmt->formatTag == pFmt->formatTag &&
  889.     pReqFmt->channels == pFmt->channels &&
  890.     pReqFmt->subFrameSize == pFmt->subFrameSize &&
  891.     pReqFmt->bitRes == pFmt->bitRes)
  892.     {
  893.     pSeqDev->pSelFmt = pFmt;
  894.     pSeqDev->sampleFrequency = pReqFmt->sampleFrequency;
  895.     pSeqDev->sampleSize = pFmt->channels * pFmt->subFrameSize;
  896.     pSeqDev->bytesPerSec = 
  897.     pSeqDev->sampleFrequency * pSeqDev->sampleSize;
  898.     return OK;
  899.     }
  900. break;
  901.     case USB_AUDIO_FORMAT_TYPE2:
  902.     if (pReqFmt->formatTag == pFmt->formatTag &&
  903. pReqFmt->maxBitRate == pFmt->maxBitRate &&
  904. pReqFmt->samplesPerFrame == pFmt->samplesPerFrame)
  905. {
  906. pSeqDev->pSelFmt = pFmt;
  907. pSeqDev->sampleFrequency = pReqFmt->sampleFrequency;
  908. pSeqDev->sampleSize = 1;
  909. pSeqDev->bytesPerSec = 
  910. pSeqDev->sampleFrequency * pSeqDev->sampleSize;
  911. return OK;
  912. }
  913.     break;
  914.     default:    /* not supported */
  915.     return ERROR;
  916.     }
  917. }
  918.     /* No compatible format was found. */
  919.     return ERROR;
  920.     }
  921. /***************************************************************************
  922. *
  923. * parseAudioConfig - parse configuration descriptor for audio device
  924. *
  925. * Examine the configuration descriptor and build a map of the device's
  926. * capabilities.  To be used by this speaker class driver, the device must
  927. * have an "Output Terminal".  If it does, then determine which audio
  928. * formats can be passed to the device.
  929. *
  930. * RETURNS: OK if successful, else ERROR
  931. */
  932. LOCAL STATUS parseAudioConfig
  933.     (
  934.     pUSB_SPKR_SEQ_DEV pSeqDev,
  935.     pUINT8 pCfgBfr,
  936.     UINT16 cfgLen,
  937.     pUSB_CONFIG_DESCR pCfgDescr
  938.     )
  939.     {
  940.     /* Find the Audio Control descriptor and build a map of the device */
  941.     if (buildAudioMap (pSeqDev, pCfgBfr, cfgLen) != OK)
  942. return ERROR;
  943.     if (pSeqDev->outputTerminalId == 0 || pSeqDev->inputTerminalId == 0)
  944. return ERROR;
  945.     /* The audio device has the necessary Output Terminal.  Parse the
  946.      * configuration descriptor and make a list of the supported audio
  947.      * formats.
  948.      */
  949.     if (buildFormatList (pSeqDev, pCfgBfr, cfgLen) != OK)
  950. return ERROR;
  951.     if (pSeqDev->fmtCount == 0)
  952. return ERROR;
  953.     return OK;
  954.     }
  955. /***************************************************************************
  956. *
  957. * configureSeqDev - configure USB speaker for operation
  958. *
  959. * Examine the device's configuration & associated descriptors to determine
  960. * the audio device's capability.  If the device is an audio device capable
  961. * of output (e.g., it includes an "Output Terminal") then build a structure
  962. * to describe the device and configure it.
  963. *
  964. * RETURNS: OK if successful, else ERROR if failed to configure channel
  965. */
  966. LOCAL STATUS configureSeqDev
  967.     (
  968.     pUSB_SPKR_SEQ_DEV pSeqDev
  969.     )
  970.     {
  971.     pUSB_CONFIG_DESCR pCfgDescr;
  972.     pUINT8 pCfgBfr;
  973.     UINT16 cfgLen;
  974.     STATUS retcode;
  975.     /* Read the configuration descriptor so we can determine the device's
  976.      * capabilities.
  977.      */
  978.     if (usbConfigDescrGet (usbdHandle, 
  979.    pSeqDev->nodeId, 
  980.    pSeqDev->configuration, 
  981.    &cfgLen, 
  982.    &pCfgBfr) 
  983.  != OK)
  984. return ERROR;
  985.     if ((pCfgDescr = usbDescrParse (pCfgBfr, 
  986.     cfgLen, 
  987.     USB_DESCR_CONFIGURATION)) 
  988.   == NULL)
  989. {
  990. retcode = ERROR;
  991. }
  992.     else
  993. {
  994. /* Parse the configuration descriptor to see if the device has the
  995.  * capabilities we need to use it as a speaker.
  996.  */
  997. retcode = parseAudioConfig (pSeqDev, pCfgBfr, cfgLen, pCfgDescr);
  998. }
  999.     if (retcode == OK)
  1000. {
  1001. /* Select the configuration. */
  1002. if (usbdConfigurationSet (usbdHandle, 
  1003.   pSeqDev->nodeId,
  1004.   pCfgDescr->configurationValue, 
  1005.   pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) 
  1006. != OK)
  1007.     {
  1008.     retcode = ERROR;
  1009.     }
  1010. }
  1011.     /* Release the buffer allocated by usbConfigDescrGet(). */
  1012.     OSS_FREE (pCfgBfr);
  1013.     return retcode;
  1014.     }
  1015. /***************************************************************************
  1016. *
  1017. * destroyAudioStream - releases audio stream, bandwidth, resources
  1018. *
  1019. * Releases the resources allocated for an audio stream as long as play
  1020. * has completed.  If <unconditional> is TRUE, then the stream is 
  1021. * destroyed whether or not play has completed. 
  1022. *
  1023. * RETURNS: N/A
  1024. */
  1025. LOCAL VOID destroyAudioStream
  1026.     (
  1027.     pUSB_SPKR_SEQ_DEV pSeqDev,
  1028.     BOOL unconditional
  1029.     )
  1030.     {
  1031.     /* If still playing, return. */
  1032.     if (unconditional 
  1033. || pSeqDev->streamFault 
  1034. || (!pSeqDev->open && pSeqDev->audioBfrCount == 0))
  1035. {
  1036. /* Destroy the isoch. pipe. */
  1037. if (pSeqDev->isochPipeHandle != NULL)
  1038.     {
  1039.     usbdPipeDestroy (usbdHandle, pSeqDev->isochPipeHandle);
  1040.     pSeqDev->isochPipeHandle = NULL;
  1041.     }
  1042. /* Release buffer-not-full semaphore */
  1043. if (pSeqDev->bfrNotFullSem != NULL)
  1044.     {
  1045.     OSS_SEM_DESTROY (pSeqDev->bfrNotFullSem);
  1046.     pSeqDev->bfrNotFullSem = NULL;
  1047.     }
  1048. /* Release the audio data buffer */
  1049. if (pSeqDev->pAudioBfr != NULL)
  1050.     {
  1051.     OSS_FREE (pSeqDev->pAudioBfr);
  1052.     pSeqDev->pAudioBfr = NULL;
  1053.     }
  1054. }
  1055.     }
  1056. /***************************************************************************
  1057. *
  1058. * openAudioStream - Sets up speaker to begin receiving audio data
  1059. *
  1060. * RETURNS: OK if successful, else EIO if error.
  1061. */
  1062. LOCAL STATUS openAudioStream
  1063.     (
  1064.     pUSB_SPKR_SEQ_DEV pSeqDev
  1065.     )
  1066.     {
  1067.     pUSB_SPKR_AUDIO_FORMAT pFmt = pSeqDev->pSelFmt;
  1068.     UINT32 halfBfrLen;
  1069.     /* If the audio stream is already open or data is still in the bfr,
  1070.      * return an error.
  1071.      */
  1072.     if (pSeqDev->open || pSeqDev->audioBfrCount > 0)
  1073. return EIO;
  1074.     /* Return an error if no audio format specified. */
  1075.     if (pFmt == NULL)
  1076. return EIO;
  1077.     /* Select the audio interface/alt setting for the indicated format */
  1078.     if (usbdInterfaceSet (usbdHandle, 
  1079.   pSeqDev->nodeId,
  1080.   pFmt->interface, 
  1081.   pFmt->altSetting)
  1082. != OK)
  1083. return EIO;
  1084.     /* Calculate the size of the data buffer for the audio stream.  We 
  1085.      * calculate the buffer size to ensure one second of buffering capability
  1086.      * and to ensure that each half of the buffer accomodates an exactly
  1087.      * multiple of the sample size.
  1088.      */
  1089.     halfBfrLen = pSeqDev->bytesPerSec / 2;
  1090.     halfBfrLen = ((halfBfrLen + pSeqDev->sampleSize - 1) / pSeqDev->sampleSize)
  1091. * pSeqDev->sampleSize;
  1092.     /* Allocate resources for the stream. */
  1093.     pSeqDev->streamFault = FALSE;
  1094.     if ((pSeqDev->pAudioBfr = OSS_MALLOC (halfBfrLen * 2)) == NULL)
  1095. return EIO;
  1096.     pSeqDev->audioBfrLen = halfBfrLen * 2;
  1097.     pSeqDev->audioBfrHalf = halfBfrLen;
  1098.     pSeqDev->audioBfrCount = 0;
  1099.     pSeqDev->audioBfrIn = 0;
  1100.     pSeqDev->audioBfrOut = 0;
  1101.     pSeqDev->audioBfrPending = 0;
  1102.     pSeqDev->audioBfrTotal = 0;
  1103.     pSeqDev->foregroundWaiting = FALSE;
  1104.     if (OSS_SEM_CREATE (1, 0, &pSeqDev->bfrNotFullSem) != OK)
  1105. {
  1106. destroyAudioStream (pSeqDev, TRUE);
  1107. return EIO;
  1108. }
  1109.     pSeqDev->nextStartFrame = 0;
  1110.     pSeqDev->blocksSent = 0;
  1111.     pSeqDev->nextIrp = 0;
  1112.     pSeqDev->nextDoneIrp = 0;
  1113.     pSeqDev->irpsInUse = 0;
  1114.     /* Create the isochronous transmit pipe for the audio data. */
  1115.     if (usbdPipeCreate (usbdHandle, 
  1116. pSeqDev->nodeId, 
  1117. pFmt->endpoint,
  1118. pSeqDev->configuration, 
  1119. pFmt->interface, 
  1120. USB_XFRTYPE_ISOCH,
  1121. USB_DIR_OUT, 
  1122. pFmt->maxPacketSize, 
  1123. pSeqDev->bytesPerSec, 
  1124. 1, 
  1125. &pSeqDev->isochPipeHandle) 
  1126.       != OK)
  1127. {
  1128. destroyAudioStream (pSeqDev, TRUE);
  1129. return EIO;
  1130. }
  1131.     pSeqDev->open = TRUE;
  1132.     return OK;
  1133.     }
  1134. /***************************************************************************
  1135. *
  1136. * closeAudioStream - Marks end of audio stream.
  1137. *
  1138. * RETURNS: OK if successful, else EIO if error.
  1139. */
  1140. LOCAL STATUS closeAudioStream
  1141.     (
  1142.     pUSB_SPKR_SEQ_DEV pSeqDev
  1143.     )
  1144.     {
  1145.     /* If we're not playing, return an error. */
  1146.     if (!pSeqDev->open)
  1147. return EIO;
  1148.     /* tear down the isoch pipe, etc., if the audio transmission is 
  1149.      * complete...if still transmitting, the stream will be torn down
  1150.      * upon completion of the data transfer.
  1151.      */
  1152.     pSeqDev->open = FALSE;
  1153.     destroyAudioStream (pSeqDev, FALSE);
  1154.     return OK;
  1155.     }
  1156. /***************************************************************************
  1157. *
  1158. * updateTransmitter - starts/restarts double-buffered I/O
  1159. *
  1160. * NOTE: Caller must ensure speakerMutex is taken before calling this
  1161. * routine.
  1162. *
  1163. * RETURNS: OK if successful, else ERROR.
  1164. */
  1165. LOCAL STATUS updateTransmitter
  1166.     (
  1167.     pUSB_SPKR_SEQ_DEV pSeqDev
  1168.     )
  1169.     {
  1170.     pUSB_IRP pIrp;
  1171.     UINT32 currentFrame;
  1172.     UINT32 extLen;
  1173.     UINT32 frameCount;
  1174.     STATUS status = OK;
  1175.     /* If an IRP is available and there is data available but not yet
  1176.      * being transmitted, then send it.
  1177.      */
  1178.     while (!pSeqDev->streamFault 
  1179.     && pSeqDev->irpsInUse < IRP_COUNT 
  1180.     && ((pSeqDev->audioBfrCount - pSeqDev->audioBfrPending 
  1181.          >= pSeqDev->audioBfrHalf) 
  1182.     || !pSeqDev->open))
  1183. {
  1184. /* If this is the first block of data, initialize the starting
  1185.  * frame number.
  1186.  */
  1187. if (pSeqDev->blocksSent == 0)
  1188.     {
  1189.     if (usbdCurrentFrameGet (usbdHandle, 
  1190.      pSeqDev->nodeId,
  1191.      &currentFrame, 
  1192.      &pSeqDev->frameWindow) 
  1193.    != OK)
  1194. currentFrame = 0;
  1195.     pSeqDev->nextStartFrame = (currentFrame + FRAME_SKIP) %
  1196.     pSeqDev->frameWindow;
  1197.     }
  1198. /* Use the next IRP to transmit a block of data.  Each IRP always
  1199.  * transfers half of the data buffer or the entire block of 
  1200.  * remaining data if the stream has been closed.
  1201.  */
  1202. extLen = pSeqDev->audioBfrCount - pSeqDev->audioBfrPending;
  1203. extLen = min (extLen, pSeqDev->audioBfrHalf);
  1204. if (extLen < pSeqDev->audioBfrHalf && pSeqDev->open)
  1205.     break;
  1206. frameCount = ((extLen * MSEC_PER_SEC) + pSeqDev->bytesPerSec - 1) / 
  1207.     pSeqDev->bytesPerSec;
  1208. if (frameCount == 0)
  1209.     break;
  1210. /* Initialize the IRP. */
  1211. pIrp = &pSeqDev->irp [pSeqDev->nextIrp];
  1212. pSeqDev->irpsInUse++;
  1213. if (++pSeqDev->nextIrp == IRP_COUNT)
  1214.     pSeqDev->nextIrp = 0;
  1215. memset (pIrp, 0, sizeof (*pIrp));
  1216. pIrp->userPtr = pSeqDev;
  1217. pIrp->irpLen = sizeof (*pIrp);
  1218. pIrp->userCallback = usbSpkrIrpCallback;
  1219. pIrp->timeout = USB_TIMEOUT_NONE;
  1220. pIrp->startFrame = pSeqDev->nextStartFrame;
  1221. pIrp->dataBlockSize = pSeqDev->sampleSize;
  1222. pIrp->transferLen = extLen;
  1223. pIrp->bfrCount = 1;
  1224. pIrp->bfrList [0].pid = USB_PID_OUT;
  1225. pIrp->bfrList [0].pBfr = &pSeqDev->pAudioBfr [pSeqDev->audioBfrOut];
  1226. pIrp->bfrList [0].bfrLen = extLen;
  1227. pSeqDev->audioBfrPending += extLen;
  1228. if ((pSeqDev->audioBfrOut += extLen) == pSeqDev->audioBfrLen)
  1229.     pSeqDev->audioBfrOut = 0;
  1230. pSeqDev->nextStartFrame = 
  1231.     (pSeqDev->nextStartFrame + frameCount) % pSeqDev->frameWindow;
  1232. pSeqDev->blocksSent++;
  1233. /* Send the data */
  1234. if (usbdTransfer (usbdHandle, pSeqDev->isochPipeHandle, pIrp) != OK)
  1235.     {
  1236.     pSeqDev->streamFault = TRUE;
  1237.     status = ERROR;
  1238.     }
  1239. }
  1240.     return status;
  1241.     }
  1242. /***************************************************************************
  1243. *
  1244. * usbSpkrIrpCallback - invoked when IRPs complete
  1245. *
  1246. * Examines the result of each IRP.  Attempts to initiate new transmission.
  1247. *
  1248. * NOTE: By convention, the userPtr field in each IRP is a pointer to the
  1249. * corresponding USB_SPKR_SEQ_DEV structure.
  1250. *
  1251. * RETURNS: N/A
  1252. */
  1253. LOCAL VOID usbSpkrIrpCallback 
  1254.     (
  1255.     pVOID p
  1256.     )
  1257.     {
  1258.     pUSB_IRP pIrp = (pUSB_IRP) p;
  1259.     pUSB_SPKR_SEQ_DEV pSeqDev = (pUSB_SPKR_SEQ_DEV) pIrp->userPtr;
  1260.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1261.     /* Look for out-of-order IRP completion */
  1262.     if (pIrp != &pSeqDev->irp [pSeqDev->nextDoneIrp])
  1263. {
  1264. pSeqDev->streamFault = TRUE;
  1265. }
  1266.     else
  1267. {
  1268. /* Indicate an IRP has completed and update buffer pointers */
  1269. pSeqDev->irpsInUse--;
  1270. if (++pSeqDev->nextDoneIrp == IRP_COUNT)
  1271.     pSeqDev->nextDoneIrp = 0;
  1272. pSeqDev->audioBfrPending -= pIrp->transferLen;
  1273. pSeqDev->audioBfrCount -= pIrp->transferLen;
  1274. /* Examine the IRP result */
  1275. if (pIrp->result != S_usbHcdLib_IRP_CANCELED)
  1276.     updateTransmitter (pSeqDev);
  1277. else
  1278.     pSeqDev->streamFault = TRUE;
  1279. }
  1280.     /* The completion of any IRP, successfully or otherwise, unblocks 
  1281.      * the foreground thread. 
  1282.      */
  1283.     if (pSeqDev->foregroundWaiting)
  1284. {
  1285. pSeqDev->foregroundWaiting = FALSE;
  1286. OSS_SEM_GIVE (pSeqDev->bfrNotFullSem);
  1287. }
  1288.     /* The following call to destroyAudioStream() doesn't do anything
  1289.      * unless the audio play is complete or there has been an error.
  1290.      */
  1291.     destroyAudioStream (pSeqDev, FALSE);
  1292.     OSS_MUTEX_RELEASE (speakerMutex);
  1293.     }
  1294. /***************************************************************************
  1295. *
  1296. * usbSpkrSeqRd - SEQ_DEV sequential read routine
  1297. * RETURNS: not supported, always returns ERROR.
  1298. */
  1299. LOCAL STATUS usbSpkrSeqRd
  1300.     (
  1301.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1302.     int numBytes,     /* number of bytes to read */
  1303.     char *buffer,     /* pointer to buffer to receive data */
  1304.     BOOL fixed     /* TRUE => fixed block size */
  1305.     )
  1306.     {
  1307.     return ERROR;
  1308.     }
  1309. /***************************************************************************
  1310. *
  1311. * usbSpkrSeqWt - SEQ_DEV sequential write routine
  1312. *
  1313. * RETURNS: OK if transfer successful, else ERROR.
  1314. */
  1315. LOCAL STATUS usbSpkrSeqWrt
  1316.     (
  1317.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1318.     int numBytes,     /* number of bytes or blocks to be written */
  1319.     char *buffer,     /* ptr to input data buffer */
  1320.     BOOL fixed     /* TRUE => fixed block size */
  1321.     )
  1322.     {
  1323.     UINT32 extLen;
  1324.     /* If the audio stream isn't open, we don't accept input */
  1325.     if (!pSeqDev->open)
  1326.     return EIO;
  1327.     /* Copy audio data to our internal buffer. */
  1328.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1329.     while (numBytes > 0 && !pSeqDev->streamFault)
  1330. {
  1331. /* If our internal buffer is full, wait for space to become avail. */
  1332. if (pSeqDev->audioBfrCount == pSeqDev->audioBfrLen)
  1333.     {
  1334.     pSeqDev->foregroundWaiting = TRUE;
  1335.     OSS_MUTEX_RELEASE (speakerMutex);
  1336.     OSS_SEM_TAKE (pSeqDev->bfrNotFullSem, OSS_BLOCK);
  1337.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1338.     if (pSeqDev->streamFault)
  1339.     break;
  1340.     }
  1341. /* Calculate length of next contiguous extent in buffer */
  1342. if (pSeqDev->audioBfrIn < pSeqDev->audioBfrOut)
  1343.     extLen = pSeqDev->audioBfrOut - pSeqDev->audioBfrIn;
  1344. else
  1345.     extLen = pSeqDev->audioBfrLen - pSeqDev->audioBfrIn;
  1346. extLen = min (extLen, pSeqDev->audioBfrLen - pSeqDev->audioBfrCount);
  1347. /* Copy data to buffer */
  1348. extLen = min (extLen, (unsigned)numBytes);
  1349. memcpy (&pSeqDev->pAudioBfr [pSeqDev->audioBfrIn], buffer, extLen);
  1350. buffer += extLen;
  1351. numBytes -= extLen;
  1352. pSeqDev->audioBfrCount += extLen;
  1353. pSeqDev->audioBfrTotal += extLen;
  1354. if ((pSeqDev->audioBfrIn += extLen) == pSeqDev->audioBfrLen)
  1355.     pSeqDev->audioBfrIn = 0;
  1356. /* Update transmitter. */
  1357. if (updateTransmitter (pSeqDev) != OK)
  1358.     return EIO;
  1359. }
  1360.     OSS_MUTEX_RELEASE (speakerMutex);
  1361.     if (numBytes == 0)
  1362. return OK;
  1363.     else
  1364. return EIO;
  1365.     }
  1366. /***************************************************************************
  1367. *
  1368. * usbSpkrIoctl - SEQ_DEV IOCTL routine
  1369. *
  1370. * RETURNS: OK if IOCTL handled successfully, ENOSYS if unsupported
  1371. *      request, or EIO for other errors.
  1372. */
  1373. LOCAL STATUS usbSpkrIoctl
  1374.     (
  1375.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1376.     int funcCode,     /* ioctl() function code */
  1377.     int arg /* function-specific argument */
  1378.     )
  1379.     {
  1380.     STATUS status = OK;
  1381.     /* Handle IOCTL */
  1382.     switch (funcCode)
  1383.     {
  1384.     case USB_SPKR_IOCTL_GET_FORMAT_COUNT:
  1385. /* Return could of supported audio formats */
  1386. *((pUINT16) arg) = pSeqDev->fmtCount;
  1387. break;
  1388.     case USB_SPKR_IOCTL_GET_FORMAT_LIST:
  1389. /* Return pointer to array of audio formats */
  1390. *((pUSB_SPKR_AUDIO_FORMAT *) arg) = pSeqDev->pFmt;
  1391. break;
  1392.     case USB_SPKR_IOCTL_GET_CHANNEL_COUNT:
  1393. /* Return count of audio channels + 1 for master channel */
  1394. *((pUINT16) arg) = pSeqDev->channels;
  1395. break;
  1396.     case USB_SPKR_IOCTL_GET_CHANNEL_CONFIG:
  1397. /* Return configuration of channels */
  1398. *((pUINT16) arg) = pSeqDev->channelConfig;
  1399. break;
  1400.     case USB_SPKR_IOCTL_GET_CHANNEL_CAPS:
  1401. /* Return pointer to capabilities array for all channels */
  1402. *((pUSB_SPKR_CHANNEL_CAPS *) arg) = pSeqDev->pCaps;
  1403. break;
  1404.     case USB_SPKR_IOCTL_SET_AUDIO_FORMAT:
  1405. /* Find a format matching the one indicated by the caller */
  1406. if (selectFormat (pSeqDev, (pUSB_SPKR_AUDIO_FORMAT) arg) != OK)
  1407.     status = ENOSYS;
  1408. break;
  1409.     case USB_SPKR_IOCTL_OPEN_AUDIO_STREAM:
  1410. /* Begin an audio stream. */
  1411. status = openAudioStream (pSeqDev);
  1412. break;
  1413.     case USB_SPKR_IOCTL_CLOSE_AUDIO_STREAM:
  1414. /* mark the end of an audio stream */
  1415. status = closeAudioStream (pSeqDev);
  1416. break;
  1417.     case USB_SPKR_IOCTL_AUDIO_STREAM_STATUS:
  1418. /* report whether the audio device is still busy. */
  1419. *((pUINT16) arg) = 0;
  1420. if (pSeqDev->open)
  1421.     *((pUINT16) arg) |= USB_SPKR_STATUS_OPEN;
  1422. if (pSeqDev->audioBfrCount)
  1423.     *((pUINT16) arg) |= USB_SPKR_STATUS_DATA_IN_BFR;
  1424. break;
  1425.     case USB_SPKR_IOCTL_SET_MUTE:
  1426.     case USB_SPKR_IOCTL_SET_VOLUME:
  1427.     case USB_SPKR_IOCTL_SET_BASS:
  1428.     case USB_SPKR_IOCTL_SET_MID:
  1429.     case USB_SPKR_IOCTL_SET_TREBLE:
  1430. /* Set indicated channel control.  MSW(arg) = channel,
  1431.  * LSW(arg) = value.
  1432.  */
  1433. status = setChannelControl (pSeqDev, 
  1434.     funcCode, 
  1435.     MSW (arg), 
  1436.     LSW (arg));
  1437. break;
  1438.     default:
  1439. status = ENOSYS;
  1440. break;
  1441.     }
  1442.     return status;
  1443.     }
  1444. /***************************************************************************
  1445. *
  1446. * usbSpkrSeqWrtFileMarks - SEQ_DEV sequential write file marks routine
  1447. *
  1448. * RETURNS: not implemented.  Always returns OK for compatibility.
  1449. */
  1450. LOCAL STATUS usbSpkrSeqWrtFileMarks
  1451.     (
  1452.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1453.     int numMarks,     /* number of file marks to write */
  1454.     BOOL shortMark     /* short or long file marks */
  1455.     )
  1456.     {
  1457.     return OK;
  1458.     }
  1459. /***************************************************************************
  1460. *
  1461. * usbSpkrRewind - SEQ_DEV rewind routine
  1462. *
  1463. * RETURNS: not implemented.  Always returns OK for compatibility.
  1464. */
  1465. LOCAL STATUS usbSpkrRewind
  1466.     (
  1467.     pUSB_SPKR_SEQ_DEV pSeqDev     /* pointer to device descriptor */
  1468.     )
  1469.     {
  1470.     return OK;
  1471.     }
  1472. /***************************************************************************
  1473. *
  1474. * usbSpkrReserve - SEQ_DEV reserve routine
  1475. *
  1476. * RETURNS: OK if device can be reserved, else ERROR.
  1477. */
  1478. LOCAL STATUS usbSpkrReserve
  1479.     (
  1480.     pUSB_SPKR_SEQ_DEV pSeqDev     /* pointer to device descriptor */
  1481.     )
  1482.     {
  1483.     STATUS status;
  1484.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1485.     if (!pSeqDev->reserved)
  1486. {
  1487. pSeqDev->reserved = TRUE;
  1488. status = OK;
  1489. }
  1490.     else
  1491. {
  1492. status = ERROR;
  1493. }
  1494.     OSS_MUTEX_RELEASE (speakerMutex);
  1495.     return status;
  1496.     }
  1497. /***************************************************************************
  1498. *
  1499. * usbSpkrRelease - SEQ_DEV release routine
  1500. *
  1501. * RETURNS: OK if device can be released, else ERROR.
  1502. */
  1503. LOCAL STATUS usbSpkrRelease
  1504.     (
  1505.     pUSB_SPKR_SEQ_DEV pSeqDev     /* pointer to device descriptor */
  1506.     )
  1507.     {
  1508.     STATUS status;
  1509.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1510.     if (pSeqDev->reserved)
  1511. {
  1512. pSeqDev->reserved = FALSE;
  1513. status = OK;
  1514. }
  1515.     else
  1516. {
  1517. status = ERROR;
  1518. }
  1519.     OSS_MUTEX_RELEASE (speakerMutex);
  1520.     return status;
  1521.     }
  1522. /***************************************************************************
  1523. *
  1524. * usbSpkrReadBlkLim - SEQ_DEV read block limit routine
  1525. *
  1526. * RETURNS: always returns OK.
  1527. */
  1528. LOCAL STATUS usbSpkrReadBlkLim
  1529.     (
  1530.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1531.     int *maxBlkLimit, /* maximum block size for device */
  1532.     int *minBlkLimit /* minimum block size for device */
  1533.     )
  1534.     {
  1535.     if (maxBlkLimit != NULL)
  1536. *maxBlkLimit = A_REALLY_BIG_INTEGER;
  1537.     if (minBlkLimit != 0)
  1538. *minBlkLimit = 0;
  1539.     return OK;
  1540.     }
  1541. /***************************************************************************
  1542. *
  1543. * usbSpkrLoad - SEQ_DEV load routine
  1544. *
  1545. * RETURNS: not implemented, always returns OK for compatibility.
  1546. */
  1547. LOCAL STATUS usbSpkrLoad
  1548.     (
  1549.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1550.     BOOL load     /* load or unload device */
  1551.     )
  1552.     {
  1553.     return OK;
  1554.     }
  1555. /***************************************************************************
  1556. *
  1557. * usbSpkrSpace - SEQ_DEV space routine
  1558. *
  1559. * RETURNS: not implemented, always returns OK for compatibility.
  1560. */
  1561. LOCAL STATUS usbSpkrSpace
  1562.     (
  1563.     pUSB_SPKR_SEQ_DEV pSeqDev,     /* pointer to device descriptor */
  1564.     int count,     /* number of spaces */
  1565.     int spaceCode     /* type of space */
  1566.     )
  1567.     {
  1568.     return OK;
  1569.     }
  1570. /***************************************************************************
  1571. *
  1572. * usbSpkrErase - SEQ_DEV erase routine
  1573. *
  1574. * RETURNS: not implemented, always returns OK for compatibility.
  1575. */
  1576. LOCAL STATUS usbSpkrErase
  1577.     (
  1578.     pUSB_SPKR_SEQ_DEV pSeqDev     /* pointer to device descriptor */
  1579.     )
  1580.     {
  1581.     return OK;
  1582.     }
  1583. /***************************************************************************
  1584. *
  1585. * destroyAttachRequest - disposes of an ATTACH_REQUEST structure
  1586. *
  1587. * RETURNS: N/A
  1588. */
  1589. LOCAL VOID destroyAttachRequest
  1590.     (
  1591.     pATTACH_REQUEST pRequest
  1592.     )
  1593.     {
  1594.     /* Unlink request */
  1595.     usbListUnlink (&pRequest->reqLink);
  1596.     /* Dispose of structure */
  1597.     OSS_FREE (pRequest);
  1598.     }
  1599. /***************************************************************************
  1600. *
  1601. * destroySeqDev - disposes of a USB_SPKR_SEQ_DEV structure
  1602. *
  1603. * Unlinks the indicated USB_SPKR_SEQ_DEV structure and de-allocates
  1604. * resources associated with the device.
  1605. *
  1606. * RETURNS: N/A
  1607. */
  1608. LOCAL VOID destroySeqDev
  1609.     (
  1610.     pUSB_SPKR_SEQ_DEV pSeqDev
  1611.     )
  1612.     {
  1613.     /* Unlink the structure. */
  1614.     usbListUnlink (&pSeqDev->devLink);
  1615.     /* Release audio stream-related info */
  1616.     destroyAudioStream (pSeqDev, TRUE);
  1617.     /* Release per-channel data */
  1618.     if (pSeqDev->pCaps != NULL)
  1619. OSS_FREE (pSeqDev->pCaps);
  1620.     /* Release audio format data */
  1621.     if (pSeqDev->pFmt != NULL)
  1622. OSS_FREE (pSeqDev->pFmt);
  1623.     /* Release structure. */
  1624.     OSS_FREE (pSeqDev);
  1625.     }
  1626. /***************************************************************************
  1627. *
  1628. * createSeqDev - creates a new USB_SPKR_SEQ_DEV structure
  1629. *
  1630. * Creates a new USB_SPKR_SEQ_DEV structure for the indicated <nodeId>.
  1631. * If successful, the new structure is linked into the devList upon 
  1632. * return.
  1633. *
  1634. * <configuration> and <interface> identify the configuration/interface
  1635. * that first reported itself as an audio device.
  1636. *
  1637. * RETURNS: pointer to newly created structure, or NULL if failure
  1638. */
  1639. LOCAL pUSB_SPKR_SEQ_DEV createSeqDev
  1640.     (
  1641.     USBD_NODE_ID nodeId,
  1642.     UINT16 configuration,
  1643.     UINT16 interface
  1644.     )
  1645.     {
  1646.     pUSB_SPKR_SEQ_DEV pSeqDev;
  1647.     /* Try to allocate space for a new speaker struct */
  1648.     if ((pSeqDev = OSS_CALLOC (sizeof (*pSeqDev))) == NULL)
  1649. return NULL;
  1650.     pSeqDev->seqDev.sd_seqRd = usbSpkrSeqRd;
  1651.     pSeqDev->seqDev.sd_seqWrt = usbSpkrSeqWrt;
  1652.     pSeqDev->seqDev.sd_ioctl = usbSpkrIoctl;
  1653.     pSeqDev->seqDev.sd_seqWrtFileMarks = usbSpkrSeqWrtFileMarks;
  1654.     pSeqDev->seqDev.sd_rewind = usbSpkrRewind;
  1655.     pSeqDev->seqDev.sd_reserve = usbSpkrReserve;
  1656.     pSeqDev->seqDev.sd_release = usbSpkrRelease;
  1657.     pSeqDev->seqDev.sd_readBlkLim = usbSpkrReadBlkLim;
  1658.     pSeqDev->seqDev.sd_load = usbSpkrLoad;
  1659.     pSeqDev->seqDev.sd_space = usbSpkrSpace;
  1660.     pSeqDev->seqDev.sd_erase = usbSpkrErase;
  1661.     pSeqDev->seqDev.sd_reset = NULL;
  1662.     pSeqDev->seqDev.sd_statusChk = NULL;
  1663.     pSeqDev->seqDev.sd_blkSize     = 0;
  1664.     pSeqDev->seqDev.sd_mode = O_WRONLY;
  1665.     pSeqDev->seqDev.sd_readyChanged = TRUE;
  1666.     pSeqDev->seqDev.sd_maxVarBlockLimit = A_REALLY_BIG_INTEGER;
  1667.     pSeqDev->seqDev.sd_density     = 0;
  1668.     pSeqDev->nodeId = nodeId;
  1669.     pSeqDev->configuration = configuration;
  1670.     pSeqDev->connected = TRUE;
  1671.     /* Try to configure the speaker. */
  1672.     if (configureSeqDev (pSeqDev) != OK)
  1673. {
  1674. destroySeqDev (pSeqDev);
  1675. return NULL;
  1676. }
  1677.     /* Link the newly created structure. */
  1678.     usbListLink (&devList, pSeqDev, &pSeqDev->devLink, LINK_TAIL);
  1679.     return pSeqDev;
  1680.     }
  1681. /***************************************************************************
  1682. *
  1683. * findSeqDev - Searches for a USB_SPKR_SEQ_DEV for indicated node ID
  1684. *
  1685. * RETURNS: pointer to matching USB_SPKR_SEQ_DEV or NULL if not found
  1686. */
  1687. LOCAL pUSB_SPKR_SEQ_DEV findSeqDev
  1688.     (
  1689.     USBD_NODE_ID nodeId
  1690.     )
  1691.     {
  1692.     pUSB_SPKR_SEQ_DEV pSeqDev = usbListFirst (&devList);
  1693.     while (pSeqDev != NULL)
  1694. {
  1695. if (pSeqDev->nodeId == nodeId)
  1696.     break;
  1697. pSeqDev = usbListNext (&pSeqDev->devLink);
  1698. }
  1699.     return pSeqDev;
  1700.     }
  1701. /***************************************************************************
  1702. *
  1703. * notifyAttach - Notifies registered callers of attachment/removal
  1704. *
  1705. * RETURNS: N/A
  1706. */
  1707. LOCAL VOID notifyAttach
  1708.     (
  1709.     pUSB_SPKR_SEQ_DEV pSeqDev,
  1710.     UINT16 attachCode
  1711.     )
  1712.     {
  1713.     pATTACH_REQUEST pRequest = usbListFirst (&reqList);
  1714.     while (pRequest != NULL)
  1715. {
  1716. (*pRequest->callback) (pRequest->callbackArg, 
  1717.        (SEQ_DEV *) pSeqDev, 
  1718.        attachCode);
  1719. pRequest = usbListNext (&pRequest->reqLink);
  1720. }
  1721.     }
  1722. /***************************************************************************
  1723. *
  1724. * usbSpeakerAttachCallback - called by USBD when speaker attached/removed
  1725. *
  1726. * The USBD will invoke this callback when a USB audio device is attached to or
  1727. * removed from the system.  <nodeId> is the USBD_NODE_ID of the node being
  1728. * attached or removed. <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.
  1729. * Audio devices report their class information at the interface level, so 
  1730. * <configuration> and <interface> will indicate the configuratin/interface that 
  1731. * reports itself as an audio device.  Finally, <deviceClass>, <deviceSubClass>,
  1732. * and <deviceProtocol> will identify the type of audio device (eg. a speaker).
  1733. *
  1734. * NOTE: The USBD will invoke this function once for each configuration/
  1735. * interface which reports itself as an audio device.  So, it is possible that
  1736. * a single device insertion/removal may trigger multiple callbacks.  We
  1737. * ignore all callbacks except the first for a given device.  We also ignore
  1738. * audio devices that are not speakers (eg., we ignore microphones and other
  1739. * input audio devices).
  1740. *
  1741. * RETURNS: N/A
  1742. */
  1743. LOCAL VOID usbSpeakerAttachCallback
  1744.     (
  1745.     USBD_NODE_ID nodeId, 
  1746.     UINT16 attachAction, 
  1747.     UINT16 configuration,
  1748.     UINT16 interface,
  1749.     UINT16 deviceClass, 
  1750.     UINT16 deviceSubClass, 
  1751.     UINT16 deviceProtocol
  1752.     )
  1753.     {
  1754.     pUSB_SPKR_SEQ_DEV pSeqDev;
  1755.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1756.     /* Depending on the attach code, add a new speaker or disabled one
  1757.      * that's already been created.
  1758.      */
  1759.     switch (attachAction)
  1760. {
  1761. case USBD_DYNA_ATTACH:
  1762.     /* A new device is being attached.  Check if we already 
  1763.      * have a structure for this device.
  1764.      */
  1765.     if (findSeqDev (nodeId) != NULL)
  1766. break;
  1767.     /* Create a new structure to manage this device.  If there's
  1768.      * an error, there's nothing we can do about it, so skip the
  1769.      * device and return immediately. 
  1770.      */
  1771.     if ((pSeqDev = createSeqDev (nodeId, 
  1772.  configuration, 
  1773.  interface)) 
  1774. == NULL)
  1775. break;
  1776.     /* Notify registered callers that a new speaker has been
  1777.      * added and a new channel created.
  1778.      */
  1779.     notifyAttach (pSeqDev, USB_SPKR_ATTACH);
  1780.     break;
  1781. case USBD_DYNA_REMOVE:
  1782.     /* A device is being detached. Check if we have any
  1783.      * structures to manage this device.
  1784.      */
  1785.     if ((pSeqDev = findSeqDev (nodeId)) == NULL)
  1786. break;
  1787.     /* The device has been disconnected. */
  1788.     pSeqDev->connected = FALSE;
  1789.     /* Notify registered callers that the speaker has been
  1790.      * removed and the channel disabled. 
  1791.      *
  1792.      * NOTE: We temporarily increment the channel's lock count
  1793.      * to prevent usbSpeakerSeqDevUnlock() from destroying the
  1794.      * structure while we're still using it.
  1795.      */
  1796.     pSeqDev->lockCount++;
  1797.     notifyAttach (pSeqDev, USB_SPKR_REMOVE);
  1798.     pSeqDev->lockCount--;
  1799.     /* If no callers have the channel structure locked, destroy
  1800.      * it now.  If it is locked, it will be destroyed later during
  1801.      * a call to usbSpeakerUnlock().
  1802.      */
  1803.     if (pSeqDev->lockCount == 0)
  1804. destroySeqDev (pSeqDev);
  1805.     break;
  1806. }
  1807.     OSS_MUTEX_RELEASE (speakerMutex);
  1808.     }
  1809. /***************************************************************************
  1810. *
  1811. * doShutdown - shuts down USB speaker SIO driver
  1812. *
  1813. * <errCode> should be OK or S_usbSpeakerLib_xxxx.  This value will be
  1814. * passed to ossStatus() and the return value from ossStatus() is the
  1815. * return value of this function.
  1816. *
  1817. * RETURNS: OK, or ERROR per value of <errCode> passed by caller
  1818. */
  1819. LOCAL STATUS doShutdown
  1820.     (
  1821.     int errCode
  1822.     )
  1823.     {
  1824.     pATTACH_REQUEST pRequest;
  1825.     pUSB_SPKR_SEQ_DEV pSeqDev;
  1826.     /* Dispose of any outstanding notification requests */
  1827.     while ((pRequest = usbListFirst (&reqList)) != NULL)
  1828. destroyAttachRequest (pRequest);
  1829.     /* Dispose of any open speaker connections. */
  1830.     while ((pSeqDev = usbListFirst (&devList)) != NULL)
  1831. destroySeqDev (pSeqDev);
  1832.     
  1833.     /* Release our connection to the USBD.  The USBD automatically 
  1834.      * releases any outstanding dynamic attach requests when a client
  1835.      * unregisters.
  1836.      */
  1837.     if (usbdHandle != NULL)
  1838. {
  1839. usbdClientUnregister (usbdHandle);
  1840. usbdHandle = NULL;
  1841. }
  1842.     /* Release resources. */
  1843.     if (speakerMutex != NULL)
  1844. {
  1845. OSS_MUTEX_DESTROY (speakerMutex);
  1846. speakerMutex = NULL;
  1847. }
  1848.     return ossStatus (errCode);
  1849.     }
  1850. /***************************************************************************
  1851. *
  1852. * usbSpeakerDevInit - initialize USB speaker SIO driver
  1853. *
  1854. * Initializes the USB speaker SIO driver.  The USB speaker SIO driver
  1855. * maintains an initialization count, so calls to this function may be
  1856. * nested.
  1857. *
  1858. * RETURNS: OK, or ERROR if unable to initialize.
  1859. *
  1860. * ERRNO:
  1861. *
  1862. *   S_usbSpeakerLib_OUT_OF_RESOURCES
  1863. *   S_usbSpeakerLib_USBD_FAULT
  1864. */
  1865. STATUS usbSpeakerDevInit (void)
  1866.     {
  1867.     /* If not already initialized, then initialize internal structures
  1868.      * and connection to USBD.
  1869.      */
  1870.     if (initCount == 0)
  1871.     {
  1872.     /* Initialize lists, structures, resources. */
  1873.     memset (&devList, 0, sizeof (devList));
  1874.     memset (&reqList, 0, sizeof (reqList));
  1875.     speakerMutex = NULL;
  1876.     usbdHandle = NULL;
  1877.     if (OSS_MUTEX_CREATE (&speakerMutex) != OK)
  1878. return doShutdown (S_usbSpeakerLib_OUT_OF_RESOURCES);
  1879.     /* Establish connection to USBD */
  1880.     if (usbdClientRegister (SPKR_CLIENT_NAME, &usbdHandle) != OK ||
  1881. usbdDynamicAttachRegister (usbdHandle, 
  1882.    USB_CLASS_AUDIO,
  1883.    USBD_NOTIFY_ALL, 
  1884.    USBD_NOTIFY_ALL,
  1885.    usbSpeakerAttachCallback) 
  1886.    != OK)
  1887. {
  1888. return doShutdown (S_usbSpeakerLib_USBD_FAULT);
  1889. }
  1890.     }
  1891.     initCount++;
  1892.     return OK;
  1893.     }
  1894. /***************************************************************************
  1895. *
  1896. * usbSpeakerDevShutdown - shuts down speaker SIO driver
  1897. *
  1898. * RETURNS: OK, or ERROR if unable to shutdown.
  1899. *
  1900. * ERRNO:
  1901. *   S_usbSpeakerLib_NOT_INITIALIZED
  1902. */
  1903. STATUS usbSpeakerDevShutdown (void)
  1904.     {
  1905.     /* Shut down the USB speaker SIO driver if the initCount goes to 0. */
  1906.     if (initCount == 0)
  1907. return ossStatus (S_usbSpeakerLib_NOT_INITIALIZED);
  1908.     if (--initCount == 0)
  1909. return doShutdown (OK);
  1910.     return OK;
  1911.     }
  1912. /***************************************************************************
  1913. *
  1914. * usbSpeakerDynamicAttachRegister - Register speaker attach callback
  1915. *
  1916. * <callback> is a caller-supplied function of the form:
  1917. *
  1918. * .CS
  1919. * typedef (*USB_SPKR_ATTACH_CALLBACK) 
  1920. *     (
  1921. *     pVOID arg,
  1922. *     SEQ_DEV *pSeqDev,
  1923. *     UINT16 attachCode
  1924. *     );
  1925. * .CE
  1926. *
  1927. * usbSpeakerLib will invoke <callback> each time a USB speaker
  1928. * is attached to or removed from the system.  <arg> is a caller-defined
  1929. * parameter which will be passed to the <callback> each time it is
  1930. * invoked.  The <callback> will also be passed a pointer to the 
  1931. * SEQ_DEV structure for the channel being created/destroyed and
  1932. * an attach code of USB_SPKR_ATTACH or USB_SPKR_REMOVE.
  1933. *
  1934. * RETURNS: OK, or ERROR if unable to register callback
  1935. *
  1936. * ERRNO:
  1937. *   S_usbSpeakerLib_BAD_PARAM
  1938. *   S_usbSpeakerLib_OUT_OF_MEMORY
  1939. */
  1940. STATUS usbSpeakerDynamicAttachRegister
  1941.     (
  1942.     USB_SPKR_ATTACH_CALLBACK callback, /* new callback to be registered */
  1943.     pVOID arg     /* user-defined arg to callback */
  1944.     )
  1945.     {
  1946.     pATTACH_REQUEST pRequest;
  1947.     pUSB_SPKR_SEQ_DEV pSeqDev;
  1948.     int status = OK;
  1949.     /* Validate parameters */
  1950.     if (callback == NULL)
  1951. return ossStatus (S_usbSpeakerLib_BAD_PARAM);
  1952.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1953.     /* Create a new request structure to track this callback request. */
  1954.     if ((pRequest = OSS_CALLOC (sizeof (*pRequest))) == NULL)
  1955. status = S_usbSpeakerLib_OUT_OF_MEMORY;
  1956.     else
  1957. {
  1958. pRequest->callback = callback;
  1959. pRequest->callbackArg = arg;
  1960. usbListLink (&reqList, pRequest, &pRequest->reqLink, LINK_TAIL);
  1961. /* Perform an initial notification of all currrently attached
  1962.  * speaker devices.
  1963.  */
  1964. pSeqDev = usbListFirst (&devList);
  1965. while (pSeqDev != NULL)
  1966.     {
  1967.     if (pSeqDev->connected)
  1968. (*callback) (arg, (SEQ_DEV *) pSeqDev, USB_SPKR_ATTACH);
  1969.     pSeqDev = usbListNext (&pSeqDev->devLink);
  1970.     }
  1971. }
  1972.     OSS_MUTEX_RELEASE (speakerMutex);
  1973.     return ossStatus (status);
  1974.     }
  1975. /***************************************************************************
  1976. *
  1977. * usbSpeakerDynamicAttachUnregister - Unregisters speaker attach callback
  1978. *
  1979. * This function cancels a previous request to be dynamically notified for
  1980. * speaker attachment and removal.  The <callback> and <arg> paramters must
  1981. * exactly match those passed in a previous call to 
  1982. * usbSpeakerDynamicAttachRegister().
  1983. *
  1984. * RETURNS: OK, or ERROR if unable to unregister callback
  1985. *
  1986. * ERRNO:
  1987. *   S_usbSpeakerLib_NOT_REGISTERED
  1988. */
  1989. STATUS usbSpeakerDynamicAttachUnRegister
  1990.     (
  1991.     USB_SPKR_ATTACH_CALLBACK callback, /* callback to be unregistered */
  1992.     pVOID arg     /* user-defined arg to callback */
  1993.     )
  1994.     {
  1995.     pATTACH_REQUEST pRequest;
  1996.     int status = S_usbSpeakerLib_NOT_REGISTERED;
  1997.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  1998.     pRequest = usbListFirst (&reqList);
  1999.     while (pRequest != NULL)
  2000. {
  2001. if (callback == pRequest->callback && arg == pRequest->callbackArg)
  2002.     {
  2003.     /* We found a matching notification request. */
  2004.     destroyAttachRequest (pRequest);
  2005.     status = OK;
  2006.     break;
  2007.     }
  2008. pRequest = usbListNext (&pRequest->reqLink);
  2009. }
  2010.     OSS_MUTEX_RELEASE (speakerMutex);
  2011.     return ossStatus (status);
  2012.     }
  2013. /***************************************************************************
  2014. *
  2015. * usbSpeakerSeqDevLock - Marks SEQ_DEV structure as in use
  2016. *
  2017. * A caller uses usbSpeakerSeqDevLock() to notify usbSpeakerLib that
  2018. * it is using the indicated SEQ_DEV structure. usbSpeakerLib maintains
  2019. * a count of callers using a particular SEQ_DEV structure so that it 
  2020. * knows when it is safe to dispose of a structure when the underlying
  2021. * USB speaker is removed from the system.  So long as the "lock count"
  2022. * is greater than zero, usbSpeakerLib will not dispose of an SEQ_DEV
  2023. * structure.
  2024. *
  2025. * RETURNS: OK, or ERROR if unable to mark SEQ_DEV structure in use.
  2026. */
  2027. STATUS usbSpeakerSeqDevLock
  2028.     (
  2029.     SEQ_DEV *pChan /* SEQ_DEV to be marked as in use */
  2030.     )
  2031.     {
  2032.     pUSB_SPKR_SEQ_DEV pSeqDev = (pUSB_SPKR_SEQ_DEV) pChan;
  2033.     pSeqDev->lockCount++;
  2034.     return OK;
  2035.     }
  2036. /***************************************************************************
  2037. *
  2038. * usbSpeakerSeqDevUnlock - Marks SEQ_DEV structure as unused
  2039. *
  2040. * This function releases a lock placed on an SEQ_DEV structure.  When a
  2041. * caller no longer needs an SEQ_DEV structure for which it has previously
  2042. * called usbSpeakerSeqDevLock(), then it should call this function to
  2043. * release the lock.
  2044. *
  2045. * NOTE: If the underlying USB speaker device has already been removed
  2046. * from the system, then this function will automatically dispose of the
  2047. * SEQ_DEV structure if this call removes the last lock on the structure.
  2048. * Therefore, a caller must not reference the SEQ_DEV again structure after
  2049. * making this call.
  2050. *
  2051. * RETURNS: OK, or ERROR if unable to mark SEQ_DEV structure unused
  2052. *
  2053. * ERRNO:
  2054. *   S_usbSpeakerLib_NOT_LOCKED
  2055. */
  2056. STATUS usbSpeakerSeqDevUnlock
  2057.     (
  2058.     SEQ_DEV *pChan /* SEQ_DEV to be marked as unused */
  2059.     )
  2060.     {
  2061.     pUSB_SPKR_SEQ_DEV pSeqDev = (pUSB_SPKR_SEQ_DEV) pChan;
  2062.     int status = OK;
  2063.     OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK);
  2064.     if (pSeqDev->lockCount == 0)
  2065. status = S_usbSpeakerLib_NOT_LOCKED;
  2066.     else
  2067. {
  2068. /* If this is the last lock and the underlying USB speaker is
  2069.  * no longer connected, then dispose of the speaker.
  2070.  */
  2071. if (--pSeqDev->lockCount == 0 && !pSeqDev->connected)
  2072.     destroySeqDev (pSeqDev);
  2073. }
  2074.     OSS_MUTEX_RELEASE (speakerMutex);
  2075.     return ossStatus (status);
  2076.     }
  2077. /* end of file */