⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbspeakerlib.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    pIfDescr->interfaceSubClass == USB_SUBCLASS_AUDIO_AUDIOSTREAMING)	    {	    /* We found an AudioStreaming interface descriptor.  Now, determine 	     * how many bytes until the next interface descriptor.	This 	     * determines the range of the configuration descriptor we will 	     * examine while parsing this interface.	     */	    pTmp = pCfgBfr;	    tmpLen = cfgLen;	    if (usbDescrParseSkip (&pTmp, 				   &tmpLen, 				   USB_DESCR_INTERFACE) 				 != NULL)		rangeLen = cfgLen - tmpLen;	    else		rangeLen = cfgLen;	    parseInterface (pSeqDev, pIfDescr, pCfgBfr, rangeLen);	    }	}    return OK;    }/***************************************************************************** selectFormat - selects an audio format to match the caller's request** <pReqFmt> points to a USB_SPEAKER_AUDIO_FORMAT structure in which the* "formatTag" field has been initialized to the desired format as* USB_AUDIO_TYPEn_xxxx and "formatType" has been initialized with the * format type as USB_AUDIO_FORMAT_TYPEn.  ** Depending on the specified format, the fields "channels", "subFrameSize", * "bitRes", "sampleFrequency", "maxBitRate", and "samplesPerFrame" may also * need to be specified to qualify the format.  The other fields of the * structure *do not* need to be specified.** The field "sampleFrequency", which must be set for Type I & Type 3 formats* must be set with the desired playback frequency.  The frequency is * expressed as samples per sec.  For example, a sampleFrequency of 88,500 * is 88,500 samples per second per channel.** This function will attempt to find an audio format supported by the* speaker which is an exact match for the specified format.  If found, that* format will be selected.  If no exact match can be found, an error will be* returned.** RETURNS: OK if successful, else ERROR.*/LOCAL STATUS selectFormat    (    pUSB_SPKR_SEQ_DEV pSeqDev,    pUSB_SPKR_AUDIO_FORMAT pReqFmt    )    {    pUSB_SPKR_AUDIO_FORMAT pFmt;    UINT16 i;    /* Set the format type to "unspecified". */    pSeqDev->pSelFmt = NULL;    pSeqDev->sampleFrequency = 0;    pSeqDev->sampleSize = 0;    /* Look for an exact match for the format */    for (i = 0; i < pSeqDev->fmtCount; i++)	{	pFmt = &pSeqDev->pFmt [i];	switch (pReqFmt->formatType)	    {	    case USB_AUDIO_FORMAT_TYPE1:	    case USB_AUDIO_FORMAT_TYPE3:		if (pReqFmt->formatTag == pFmt->formatTag &&		    pReqFmt->channels == pFmt->channels &&		    pReqFmt->subFrameSize == pFmt->subFrameSize &&		    pReqFmt->bitRes == pFmt->bitRes)		    {		    pSeqDev->pSelFmt = pFmt;		    pSeqDev->sampleFrequency = pReqFmt->sampleFrequency;		    pSeqDev->sampleSize = pFmt->channels * pFmt->subFrameSize;		    pSeqDev->bytesPerSec = 		    pSeqDev->sampleFrequency * pSeqDev->sampleSize;		    return OK;		    }		break;	    case USB_AUDIO_FORMAT_TYPE2:	    if (pReqFmt->formatTag == pFmt->formatTag &&		pReqFmt->maxBitRate == pFmt->maxBitRate &&		pReqFmt->samplesPerFrame == pFmt->samplesPerFrame)		{		pSeqDev->pSelFmt = pFmt;		pSeqDev->sampleFrequency = pReqFmt->sampleFrequency;		pSeqDev->sampleSize = 1;		pSeqDev->bytesPerSec = 		pSeqDev->sampleFrequency * pSeqDev->sampleSize;		return OK;		}	    break;	    default:    /* not supported */	    return ERROR;	    }	}    /* No compatible format was found. */    return ERROR;    }/***************************************************************************** parseAudioConfig - parse configuration descriptor for audio device** Examine the configuration descriptor and build a map of the device's* capabilities.  To be used by this speaker class driver, the device must* have an "Output Terminal".  If it does, then determine which audio* formats can be passed to the device.** RETURNS: OK if successful, else ERROR*/LOCAL STATUS parseAudioConfig    (    pUSB_SPKR_SEQ_DEV pSeqDev,    pUINT8 pCfgBfr,    UINT16 cfgLen,    pUSB_CONFIG_DESCR pCfgDescr    )    {    /* Find the Audio Control descriptor and build a map of the device */    if (buildAudioMap (pSeqDev, pCfgBfr, cfgLen) != OK)	return ERROR;    if (pSeqDev->outputTerminalId == 0 || pSeqDev->inputTerminalId == 0)	return ERROR;    /* The audio device has the necessary Output Terminal.  Parse the     * configuration descriptor and make a list of the supported audio     * formats.     */    if (buildFormatList (pSeqDev, pCfgBfr, cfgLen) != OK)	return ERROR;    if (pSeqDev->fmtCount == 0)	return ERROR;    return OK;    }/***************************************************************************** configureSeqDev - configure USB speaker for operation** Examine the device's configuration & associated descriptors to determine* the audio device's capability.  If the device is an audio device capable* of output (e.g., it includes an "Output Terminal") then build a structure* to describe the device and configure it.** RETURNS: OK if successful, else ERROR if failed to configure channel*/LOCAL STATUS configureSeqDev    (    pUSB_SPKR_SEQ_DEV pSeqDev    )    {    pUSB_CONFIG_DESCR pCfgDescr;    pUINT8 pCfgBfr;    UINT16 cfgLen;    STATUS retcode;    /* Read the configuration descriptor so we can determine the device's     * capabilities.     */    if (usbConfigDescrGet (usbdHandle, 			   pSeqDev->nodeId, 			   pSeqDev->configuration, 			   &cfgLen, 			   &pCfgBfr) 			 != OK)	return ERROR;    if ((pCfgDescr = usbDescrParse (pCfgBfr, 				    cfgLen, 				    USB_DESCR_CONFIGURATION)) 				  == NULL)	{	retcode = ERROR;	}    else	{	/* Parse the configuration descriptor to see if the device has the	 * capabilities we need to use it as a speaker.	 */	retcode = parseAudioConfig (pSeqDev, pCfgBfr, cfgLen, pCfgDescr);	}    if (retcode == OK)	{	/* Select the configuration. */	if (usbdConfigurationSet (usbdHandle, 				  pSeqDev->nodeId,				  pCfgDescr->configurationValue, 				  pCfgDescr->maxPower * USB_POWER_MA_PER_UNIT) 				!= OK)	    {	    retcode = ERROR;	    }	}    /* Release the buffer allocated by usbConfigDescrGet(). */    OSS_FREE (pCfgBfr);    return retcode;    }/***************************************************************************** destroyAudioStream - releases audio stream, bandwidth, resources** Releases the resources allocated for an audio stream as long as play* has completed.  If <unconditional> is TRUE, then the stream is * destroyed whether or not play has completed. ** RETURNS: N/A*/LOCAL VOID destroyAudioStream    (    pUSB_SPKR_SEQ_DEV pSeqDev,    BOOL unconditional    )    {    /* If still playing, return. */    if (unconditional 	|| pSeqDev->streamFault 	|| (!pSeqDev->open && pSeqDev->audioBfrCount == 0))	{	/* Destroy the isoch. pipe. */	if (pSeqDev->isochPipeHandle != NULL)	    {	    usbdPipeDestroy (usbdHandle, pSeqDev->isochPipeHandle);	    pSeqDev->isochPipeHandle = NULL;	    }	/* Release buffer-not-full semaphore */	if (pSeqDev->bfrNotFullSem != NULL)	    {	    OSS_SEM_DESTROY (pSeqDev->bfrNotFullSem);	    pSeqDev->bfrNotFullSem = NULL;	    }	/* Release the audio data buffer */	if (pSeqDev->pAudioBfr != NULL)	    {	    OSS_FREE (pSeqDev->pAudioBfr);	    pSeqDev->pAudioBfr = NULL;	    }	}    }/***************************************************************************** openAudioStream - Sets up speaker to begin receiving audio data** RETURNS: OK if successful, else EIO if error.*/LOCAL STATUS openAudioStream    (    pUSB_SPKR_SEQ_DEV pSeqDev    )    {    pUSB_SPKR_AUDIO_FORMAT pFmt = pSeqDev->pSelFmt;    UINT32 halfBfrLen;    /* If the audio stream is already open or data is still in the bfr,     * return an error.     */    if (pSeqDev->open || pSeqDev->audioBfrCount > 0)	return EIO;    /* Return an error if no audio format specified. */    if (pFmt == NULL)	return EIO;    /* Select the audio interface/alt setting for the indicated format */    if (usbdInterfaceSet (usbdHandle, 			  pSeqDev->nodeId,			  pFmt->interface, 			  pFmt->altSetting)			!= OK)	return EIO;    /* Calculate the size of the data buffer for the audio stream.  We      * calculate the buffer size to ensure one second of buffering capability     * and to ensure that each half of the buffer accomodates an exactly     * multiple of the sample size.     */    halfBfrLen = pSeqDev->bytesPerSec / 2;    halfBfrLen = ((halfBfrLen + pSeqDev->sampleSize - 1) / pSeqDev->sampleSize)			* pSeqDev->sampleSize;    /* Allocate resources for the stream. */    pSeqDev->streamFault = FALSE;    if ((pSeqDev->pAudioBfr = OSS_MALLOC (halfBfrLen * 2)) == NULL)	return EIO;    pSeqDev->audioBfrLen = halfBfrLen * 2;    pSeqDev->audioBfrHalf = halfBfrLen;    pSeqDev->audioBfrCount = 0;    pSeqDev->audioBfrIn = 0;    pSeqDev->audioBfrOut = 0;    pSeqDev->audioBfrPending = 0;    pSeqDev->audioBfrTotal = 0;    pSeqDev->foregroundWaiting = FALSE;    if (OSS_SEM_CREATE (1, 0, &pSeqDev->bfrNotFullSem) != OK)	{	destroyAudioStream (pSeqDev, TRUE);	return EIO;	}    pSeqDev->nextStartFrame = 0;    pSeqDev->blocksSent = 0;    pSeqDev->nextIrp = 0;    pSeqDev->nextDoneIrp = 0;    pSeqDev->irpsInUse = 0;    /* Create the isochronous transmit pipe for the audio data. */    if (usbdPipeCreate (usbdHandle, 			pSeqDev->nodeId, 			pFmt->endpoint,			pSeqDev->configuration, 			pFmt->interface, 			USB_XFRTYPE_ISOCH,			USB_DIR_OUT, 			pFmt->maxPacketSize, 			pSeqDev->bytesPerSec, 			1, 			&pSeqDev->isochPipeHandle) 		      != OK)	{	destroyAudioStream (pSeqDev, TRUE);	return EIO;	}    pSeqDev->open = TRUE;    return OK;    }/***************************************************************************** closeAudioStream - Marks end of audio stream.** RETURNS: OK if successful, else EIO if error.*/LOCAL STATUS closeAudioStream    (    pUSB_SPKR_SEQ_DEV pSeqDev    )    {    /* If we're not playing, return an error. */    if (!pSeqDev->open)	return EIO;    /* tear down the isoch pipe, etc., if the audio transmission is      * complete...if still transmitting, the stream will be torn down     * upon completion of the data transfer.     */    pSeqDev->open = FALSE;    destroyAudioStream (pSeqDev, FALSE);    return OK;    }/***************************************************************************** updateTransmitter - starts/restarts double-buffered I/O** NOTE: Caller must ensure speakerMutex is taken before calling this* routine.** RETURNS: OK if successful, else ERROR.*/LOCAL STATUS updateTransmitter    (    pUSB_SPKR_SEQ_DEV pSeqDev    )    {    pUSB_IRP pIrp;    UINT32 currentFrame;    UINT32 extLen;    UINT32 frameCount;    STATUS status = OK;    /* If an IRP is available and there is data available but not yet     * being transmitted, then send it.     */    while (!pSeqDev->streamFault 	    && pSeqDev->irpsInUse < IRP_COUNT 	    && ((pSeqDev->audioBfrCount - pSeqDev->audioBfrPending 	         >= pSeqDev->audioBfrHalf) 	    || !pSeqDev->open))	{	/* If this is the first block of data, initialize the starting	 * frame number.	 */	if (pSeqDev->blocksSent == 0)	    {	    if (usbdCurrentFrameGet (usbdHandle, 				     pSeqDev->nodeId,				     &currentFrame, 				     &pSeqDev->frameWindow) 				   != OK)		currentFrame = 0;	    pSeqDev->nextStartFrame = (currentFrame + FRAME_SKIP) %	    pSeqDev->frameWindow;	    }	/* Use the next IRP to transmit a block of data.  Each IRP always	 * transfers half of the data buffer or the entire block of 	 * remaining data if the stream has been closed.	 */	extLen = pSeqDev->audioBfrCount - pSeqDev->audioBfrPending;	extLen = min (extLen, pSeqDev->audioBfrHalf);	if (extLen < pSeqDev->audioBfrHalf && pSeqDev->open)	    break;	frameCount = ((extLen * MSEC_PER_SEC) + pSeqDev->bytesPerSec - 1) / 	    pSeqDev->bytesPerSec;	if (frameCount == 0)	    break;	/* Initialize the IRP. */	pIrp = &pSeqDev->irp [pSeqDev->nextIrp];	pSeqDev->irpsInUse++;	if (++pSeqDev->nextIrp == IRP_COUNT)	    pSeqDev->nextIrp = 0;	memset (pIrp, 0, sizeof (*pIrp));		pIrp->userPtr = pSeqDev;	pIrp->irpLen = sizeof (*pIrp);	pIrp->userCallback = usbSpkrIrpCallback;	pIrp->timeout = USB_TIMEOUT_NONE;	pIrp->startFrame = pSeqDev->nextStartFrame;	pIrp->dataBlockSize = pSeqDev->sampleSize;	pIrp->transferLen = extLen;	pIrp->bfrCount = 1;	pIrp->bfrList [0].pid = USB_PID_OUT;	pIrp->bfrList [0].pBfr = &pSeqDev->pAudioBfr [pSeqDev->audioBfrOut];	pIrp->bfrList [0].bfrLen = extLen;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -