📄 usbspeakerlib.c
字号:
** \NOMANUAL*/LOCAL STATUS usbSpkrReadBlkLim ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ int *maxBlkLimit, /* maximum block size for device */ int *minBlkLimit /* minimum block size for device */ ) { if (maxBlkLimit != NULL) *maxBlkLimit = A_REALLY_BIG_INTEGER; if (minBlkLimit != 0) *minBlkLimit = 0; return OK; }/***************************************************************************** usbSpkrLoad - SEQ_DEV load routine** This function is not implemented** RETURNS: not implemented, always returns OK for compatibility.** ERRNO: none** \NOMANUAL*/LOCAL STATUS usbSpkrLoad ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ BOOL load /* load or unload device */ ) { return OK; }/***************************************************************************** usbSpkrSpace - SEQ_DEV space routine** This function is not implemented** RETURNS: not implemented, always returns OK for compatibility.** ERRNO: none** \NOMANUAL*/LOCAL STATUS usbSpkrSpace ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ int count, /* number of spaces */ int spaceCode /* type of space */ ) { return OK; }/***************************************************************************** usbSpkrErase - SEQ_DEV erase routine** This function is not implemented** RETURNS: not implemented, always returns OK for compatibility.** ERRNO: none** \NOMANUAL*/LOCAL STATUS usbSpkrErase ( pUSB_SPKR_SEQ_DEV pSeqDev /* pointer to device descriptor */ ) { return OK; }/***************************************************************************** destroyAttachRequest - disposes of an ATTACH_REQUEST structure** This function disposes of an ATTACH_REQUEST structure** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID destroyAttachRequest ( pATTACH_REQUEST pRequest ) { /* Unlink request */ usbListUnlink (&pRequest->reqLink); /* Dispose of structure */ OSS_FREE (pRequest); }/***************************************************************************** destroySeqDev - disposes of a USB_SPKR_SEQ_DEV structure** Unlinks the indicated USB_SPKR_SEQ_DEV structure and de-allocates* resources associated with the device.** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID destroySeqDev ( pUSB_SPKR_SEQ_DEV pSeqDev ) { /* Unlink the structure. */ usbListUnlink (&pSeqDev->devLink); /* Release audio stream-related info */ destroyAudioStream (pSeqDev, TRUE); /* Release per-channel data */ if (pSeqDev->pCaps != NULL) OSS_FREE (pSeqDev->pCaps); /* Release audio format data */ if (pSeqDev->pFmt != NULL) OSS_FREE (pSeqDev->pFmt); /* Release structure. */ OSS_FREE (pSeqDev); }/***************************************************************************** createSeqDev - creates a new USB_SPKR_SEQ_DEV structure** Creates a new USB_SPKR_SEQ_DEV structure for the indicated <nodeId>.* If successful, the new structure is linked into the devList upon * return.** <configuration> and <interface> identify the configuration/interface* that first reported itself as an audio device.** RETURNS: pointer to newly created structure, or NULL if failure** ERRNO: none** \NOMANUAL*/LOCAL pUSB_SPKR_SEQ_DEV createSeqDev ( USBD_NODE_ID nodeId, UINT16 configuration, UINT16 interface ) { pUSB_SPKR_SEQ_DEV pSeqDev; /* Try to allocate space for a new speaker struct */ if ((pSeqDev = OSS_CALLOC (sizeof (*pSeqDev))) == NULL) return NULL; pSeqDev->seqDev.sd_seqRd = usbSpkrSeqRd; pSeqDev->seqDev.sd_seqWrt = usbSpkrSeqWrt; pSeqDev->seqDev.sd_ioctl = usbSpkrIoctl; pSeqDev->seqDev.sd_seqWrtFileMarks = usbSpkrSeqWrtFileMarks; pSeqDev->seqDev.sd_rewind = usbSpkrRewind; pSeqDev->seqDev.sd_reserve = usbSpkrReserve; pSeqDev->seqDev.sd_release = usbSpkrRelease; pSeqDev->seqDev.sd_readBlkLim = usbSpkrReadBlkLim; pSeqDev->seqDev.sd_load = usbSpkrLoad; pSeqDev->seqDev.sd_space = usbSpkrSpace; pSeqDev->seqDev.sd_erase = usbSpkrErase; pSeqDev->seqDev.sd_reset = NULL; pSeqDev->seqDev.sd_statusChk = NULL; pSeqDev->seqDev.sd_blkSize = 0; pSeqDev->seqDev.sd_mode = O_WRONLY; pSeqDev->seqDev.sd_readyChanged = TRUE; pSeqDev->seqDev.sd_maxVarBlockLimit = A_REALLY_BIG_INTEGER; pSeqDev->seqDev.sd_density = 0; pSeqDev->nodeId = nodeId; pSeqDev->configuration = configuration; pSeqDev->connected = TRUE; /* Try to configure the speaker. */ if (configureSeqDev (pSeqDev) != OK) { destroySeqDev (pSeqDev); return NULL; } /* Link the newly created structure. */ usbListLink (&devList, pSeqDev, &pSeqDev->devLink, LINK_TAIL); return pSeqDev; }/***************************************************************************** findSeqDev - Searches for a USB_SPKR_SEQ_DEV for indicated node ID** This fucntion Searches for a USB_SPKR_SEQ_DEV for indicated <nodeId>* * RETURNS: pointer to matching USB_SPKR_SEQ_DEV or NULL if not found** ERRNO: none** \NOMANUAL*/LOCAL pUSB_SPKR_SEQ_DEV findSeqDev ( USBD_NODE_ID nodeId ) { pUSB_SPKR_SEQ_DEV pSeqDev = usbListFirst (&devList); while (pSeqDev != NULL) { if (pSeqDev->nodeId == nodeId) break; pSeqDev = usbListNext (&pSeqDev->devLink); } return pSeqDev; }/***************************************************************************** notifyAttach - Notifies registered callers of attachment/removal** This function notifies the registered client of the device attachment and* its removal** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID notifyAttach ( pUSB_SPKR_SEQ_DEV pSeqDev, UINT16 attachCode ) { pATTACH_REQUEST pRequest = usbListFirst (&reqList); while (pRequest != NULL) { (*pRequest->callback) (pRequest->callbackArg, (SEQ_DEV *) pSeqDev, attachCode); pRequest = usbListNext (&pRequest->reqLink); } }/***************************************************************************** usbSpeakerAttachCallback - called by USBD when speaker attached/removed** The USBD will invoke this callback when a USB audio device is attached to or* removed from the system. <nodeId> is the USBD_NODE_ID of the node being* attached or removed. <attachAction> is USBD_DYNA_ATTACH or USBD_DYNA_REMOVE.* Audio devices report their class information at the interface level, so * <configuration> and <interface> will indicate the configuratin/interface that * reports itself as an audio device. Finally, <deviceClass>, <deviceSubClass>,* and <deviceProtocol> will identify the type of audio device (eg. a speaker).** NOTE: The USBD will invoke this function once for each configuration/* interface which reports itself as an audio device. So, it is possible that* a single device insertion/removal may trigger multiple callbacks. We* ignore all callbacks except the first for a given device. We also ignore* audio devices that are not speakers (eg., we ignore microphones and other* input audio devices).** RETURNS: N/A** ERRNO: none** \NOMANUAL*/LOCAL VOID usbSpeakerAttachCallback ( USBD_NODE_ID nodeId, UINT16 attachAction, UINT16 configuration, UINT16 interface, UINT16 deviceClass, UINT16 deviceSubClass, UINT16 deviceProtocol ) { pUSB_SPKR_SEQ_DEV pSeqDev; OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); /* Depending on the attach code, add a new speaker or disabled one * that's already been created. */ switch (attachAction) { case USBD_DYNA_ATTACH: /* A new device is being attached. Check if we already * have a structure for this device. */ if (findSeqDev (nodeId) != NULL) break; /* Create a new structure to manage this device. If there's * an error, there's nothing we can do about it, so skip the * device and return immediately. */ if ((pSeqDev = createSeqDev (nodeId, configuration, interface)) == NULL) break; /* Notify registered callers that a new speaker has been * added and a new channel created. */ notifyAttach (pSeqDev, USB_SPKR_ATTACH); break; case USBD_DYNA_REMOVE: /* A device is being detached. Check if we have any * structures to manage this device. */ if ((pSeqDev = findSeqDev (nodeId)) == NULL) break; /* The device has been disconnected. */ pSeqDev->connected = FALSE; /* Notify registered callers that the speaker has been * removed and the channel disabled. * * NOTE: We temporarily increment the channel's lock count * to prevent usbSpeakerSeqDevUnlock() from destroying the * structure while we're still using it. */ pSeqDev->lockCount++; /* Release the mutex so that the application * can access the speakerLib functions on notification */ OSS_MUTEX_RELEASE (speakerMutex); notifyAttach (pSeqDev, USB_SPKR_REMOVE); /* Take the mutex again */ OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); pSeqDev->lockCount--; /* If no callers have the channel structure locked, destroy * it now. If it is locked, it will be destroyed later during * a call to usbSpeakerUnlock(). */ if (pSeqDev->lockCount == 0) destroySeqDev (pSeqDev); break; } OSS_MUTEX_RELEASE (speakerMutex); }/***************************************************************************** doShutdown - shuts down USB speaker SIO driver** <errCode> should be OK or S_usbSpeakerLib_xxxx. This value will be* passed to ossStatus() and the return value from ossStatus() is the* return value of this function.** RETURNS: OK, or ERROR per value of <errCode> passed by caller** ERRNO: appropaite error code** \NOMANUAL*/LOCAL STATUS doShutdown ( int errCode ) { pATTACH_REQUEST pRequest; pUSB_SPKR_SEQ_DEV pSeqDev; /* Dispose of any outstanding notification requests */ while ((pRequest = usbListFirst (&reqList)) != NULL) destroyAttachRequest (pRequest); /* Dispose of any open speaker connections. */ while ((pSeqDev = usbListFirst (&devList)) != NULL) destroySeqDev (pSeqDev); /* Release our connection to the USBD. The USBD automatically * releases any outstanding dynamic attach requests when a client * unregisters. */ if (usbdHandle != NULL) { usbdClientUnregister (usbdHandle); usbdHandle = NULL; } /* Release resources. */ if (speakerMutex != NULL) { OSS_MUTEX_DESTROY (speakerMutex); speakerMutex = NULL; } return ossStatus (errCode); }/***************************************************************************** usbSpeakerDevInit - initialize USB speaker SIO driver** Initializes the USB speaker SIO driver. The USB speaker SIO driver* maintains an initialization count, so calls to this function may be* nested.** RETURNS: OK, or ERROR if unable to initialize.** ERRNO:* \is* \i S_usbSpeakerLib_OUT_OF_RESOURCES* Sufficient resources not available** \i S_usbSpeakerLib_USBD_FAULT* Fault in the USBD Layer* \ie*/STATUS usbSpeakerDevInit (void) { /* If not already initialized, then initialize internal structures * and connection to USBD. */ if (initCount == 0) { /* Initialize lists, structures, resources. */ memset (&devList, 0, sizeof (devList)); memset (&reqList, 0, sizeof (reqList)); speakerMutex = NULL; usbdHandle = NULL; if (OSS_MUTEX_CREATE (&speakerMutex) != OK) return doShutdown (S_usbSpeakerLib_OUT_OF_RESOURCES); /* Establish connection to USBD */ if (usbdClientRegister (SPKR_CLIENT_NAME, &usbdHandle) != OK || usbdDynamicAttachRegister (usbdHandle, USB_CLASS_AUDIO, USBD_NOTIFY_ALL, USBD_NOTIFY_ALL, usbSpeakerAttachCallback)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -