📄 usbspeakerlib.c
字号:
if (usbdTransfer (usbdHandle, pSeqDev->isochPipeHandle, pIrp) != OK) { pSeqDev->streamFault = TRUE; status = ERROR; } } return status; }/***************************************************************************** usbSpkrIrpCallback - invoked when IRPs complete** Examines the result of each IRP. Attempts to initiate new transmission.** NOTE: By convention, the userPtr field in each IRP is a pointer to the* corresponding USB_SPKR_SEQ_DEV structure.** RETURNS: N/A*/LOCAL VOID usbSpkrIrpCallback ( pVOID p ) { pUSB_IRP pIrp = (pUSB_IRP) p; pUSB_SPKR_SEQ_DEV pSeqDev = (pUSB_SPKR_SEQ_DEV) pIrp->userPtr; OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); /* Look for out-of-order IRP completion */ if (pIrp != &pSeqDev->irp [pSeqDev->nextDoneIrp]) { pSeqDev->streamFault = TRUE; } else { /* Indicate an IRP has completed and update buffer pointers */ pSeqDev->irpsInUse--; if (++pSeqDev->nextDoneIrp == IRP_COUNT) pSeqDev->nextDoneIrp = 0; pSeqDev->audioBfrPending -= pIrp->transferLen; pSeqDev->audioBfrCount -= pIrp->transferLen; /* Examine the IRP result */ if (pIrp->result != S_usbHcdLib_IRP_CANCELED) updateTransmitter (pSeqDev); else pSeqDev->streamFault = TRUE; } /* The completion of any IRP, successfully or otherwise, unblocks * the foreground thread. */ if (pSeqDev->foregroundWaiting) { pSeqDev->foregroundWaiting = FALSE; OSS_SEM_GIVE (pSeqDev->bfrNotFullSem); } /* The following call to destroyAudioStream() doesn't do anything * unless the audio play is complete or there has been an error. */ destroyAudioStream (pSeqDev, FALSE); OSS_MUTEX_RELEASE (speakerMutex); }/***************************************************************************** usbSpkrSeqRd - SEQ_DEV sequential read routine* * RETURNS: not supported, always returns ERROR.*/LOCAL STATUS usbSpkrSeqRd ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ int numBytes, /* number of bytes to read */ char *buffer, /* pointer to buffer to receive data */ BOOL fixed /* TRUE => fixed block size */ ) { return ERROR; }/***************************************************************************** usbSpkrSeqWt - SEQ_DEV sequential write routine** RETURNS: OK if transfer successful, else ERROR.*/LOCAL STATUS usbSpkrSeqWrt ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ int numBytes, /* number of bytes or blocks to be written */ char *buffer, /* ptr to input data buffer */ BOOL fixed /* TRUE => fixed block size */ ) { UINT32 extLen; /* If the audio stream isn't open, we don't accept input */ if (!pSeqDev->open) return EIO; /* Copy audio data to our internal buffer. */ OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); while (numBytes > 0 && !pSeqDev->streamFault) { /* If our internal buffer is full, wait for space to become avail. */ if (pSeqDev->audioBfrCount == pSeqDev->audioBfrLen) { pSeqDev->foregroundWaiting = TRUE; OSS_MUTEX_RELEASE (speakerMutex); OSS_SEM_TAKE (pSeqDev->bfrNotFullSem, OSS_BLOCK); OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); if (pSeqDev->streamFault) break; } /* Calculate length of next contiguous extent in buffer */ if (pSeqDev->audioBfrIn < pSeqDev->audioBfrOut) extLen = pSeqDev->audioBfrOut - pSeqDev->audioBfrIn; else extLen = pSeqDev->audioBfrLen - pSeqDev->audioBfrIn; extLen = min (extLen, pSeqDev->audioBfrLen - pSeqDev->audioBfrCount); /* Copy data to buffer */ extLen = min (extLen, (unsigned)numBytes); memcpy (&pSeqDev->pAudioBfr [pSeqDev->audioBfrIn], buffer, extLen); buffer += extLen; numBytes -= extLen; pSeqDev->audioBfrCount += extLen; pSeqDev->audioBfrTotal += extLen; if ((pSeqDev->audioBfrIn += extLen) == pSeqDev->audioBfrLen) pSeqDev->audioBfrIn = 0; /* Update transmitter. */ if (updateTransmitter (pSeqDev) != OK) return EIO; } OSS_MUTEX_RELEASE (speakerMutex); if (numBytes == 0) return OK; else return EIO; }/***************************************************************************** usbSpkrIoctl - SEQ_DEV IOCTL routine** RETURNS: OK if IOCTL handled successfully, ENOSYS if unsupported* request, or EIO for other errors.*/LOCAL STATUS usbSpkrIoctl ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ int funcCode, /* ioctl() function code */ int arg /* function-specific argument */ ) { STATUS status = OK; /* Handle IOCTL */ switch (funcCode) { case USB_SPKR_IOCTL_GET_FORMAT_COUNT: /* Return could of supported audio formats */ *((pUINT16) arg) = pSeqDev->fmtCount; break; case USB_SPKR_IOCTL_GET_FORMAT_LIST: /* Return pointer to array of audio formats */ *((pUSB_SPKR_AUDIO_FORMAT *) arg) = pSeqDev->pFmt; break; case USB_SPKR_IOCTL_GET_CHANNEL_COUNT: /* Return count of audio channels + 1 for master channel */ *((pUINT16) arg) = pSeqDev->channels; break; case USB_SPKR_IOCTL_GET_CHANNEL_CONFIG: /* Return configuration of channels */ *((pUINT16) arg) = pSeqDev->channelConfig; break; case USB_SPKR_IOCTL_GET_CHANNEL_CAPS: /* Return pointer to capabilities array for all channels */ *((pUSB_SPKR_CHANNEL_CAPS *) arg) = pSeqDev->pCaps; break; case USB_SPKR_IOCTL_SET_AUDIO_FORMAT: /* Find a format matching the one indicated by the caller */ if (selectFormat (pSeqDev, (pUSB_SPKR_AUDIO_FORMAT) arg) != OK) status = ENOSYS; break; case USB_SPKR_IOCTL_OPEN_AUDIO_STREAM: /* Begin an audio stream. */ status = openAudioStream (pSeqDev); break; case USB_SPKR_IOCTL_CLOSE_AUDIO_STREAM: /* mark the end of an audio stream */ status = closeAudioStream (pSeqDev); break; case USB_SPKR_IOCTL_AUDIO_STREAM_STATUS: /* report whether the audio device is still busy. */ *((pUINT16) arg) = 0; if (pSeqDev->open) *((pUINT16) arg) |= USB_SPKR_STATUS_OPEN; if (pSeqDev->audioBfrCount) *((pUINT16) arg) |= USB_SPKR_STATUS_DATA_IN_BFR; break; case USB_SPKR_IOCTL_SET_MUTE: case USB_SPKR_IOCTL_SET_VOLUME: case USB_SPKR_IOCTL_SET_BASS: case USB_SPKR_IOCTL_SET_MID: case USB_SPKR_IOCTL_SET_TREBLE: /* Set indicated channel control. MSW(arg) = channel, * LSW(arg) = value. */ status = setChannelControl (pSeqDev, funcCode, MSW (arg), LSW (arg)); break; default: status = ENOSYS; break; } return status; } /***************************************************************************** usbSpkrSeqWrtFileMarks - SEQ_DEV sequential write file marks routine** RETURNS: not implemented. Always returns OK for compatibility.*/LOCAL STATUS usbSpkrSeqWrtFileMarks ( pUSB_SPKR_SEQ_DEV pSeqDev, /* pointer to device descriptor */ int numMarks, /* number of file marks to write */ BOOL shortMark /* short or long file marks */ ) { return OK; }/***************************************************************************** usbSpkrRewind - SEQ_DEV rewind routine** RETURNS: not implemented. Always returns OK for compatibility.*/LOCAL STATUS usbSpkrRewind ( pUSB_SPKR_SEQ_DEV pSeqDev /* pointer to device descriptor */ ) { return OK; }/***************************************************************************** usbSpkrReserve - SEQ_DEV reserve routine** RETURNS: OK if device can be reserved, else ERROR.*/LOCAL STATUS usbSpkrReserve ( pUSB_SPKR_SEQ_DEV pSeqDev /* pointer to device descriptor */ ) { STATUS status; OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); if (!pSeqDev->reserved) { pSeqDev->reserved = TRUE; status = OK; } else { status = ERROR; } OSS_MUTEX_RELEASE (speakerMutex); return status; }/***************************************************************************** usbSpkrRelease - SEQ_DEV release routine** RETURNS: OK if device can be released, else ERROR.*/LOCAL STATUS usbSpkrRelease ( pUSB_SPKR_SEQ_DEV pSeqDev /* pointer to device descriptor */ ) { STATUS status; OSS_MUTEX_TAKE (speakerMutex, OSS_BLOCK); if (pSeqDev->reserved) { pSeqDev->reserved = FALSE; status = OK; } else { status = ERROR; } OSS_MUTEX_RELEASE (speakerMutex); return status; }/***************************************************************************** usbSpkrReadBlkLim - SEQ_DEV read block limit routine** RETURNS: always returns OK.*/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** RETURNS: not implemented, always returns OK for compatibility.*/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** RETURNS: not implemented, always returns OK for compatibility.*/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** RETURNS: not implemented, always returns OK for compatibility.*/LOCAL STATUS usbSpkrErase ( pUSB_SPKR_SEQ_DEV pSeqDev /* pointer to device descriptor */ ) { return OK; }/***************************************************************************** destroyAttachRequest - disposes of an ATTACH_REQUEST structure** RETURNS: N/A*/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*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -