📄 usbspeakerlib.c
字号:
settingWidth, &setting) != OK) { return EIO; } pCtlCaps->cur = value; return OK; }/***************************************************************************** getControlSetting - read an individual setting for specified control** <settingWidth> specifies the control value width as 1 (byte) or 2 (word).* * RETURNS: OK if successfull, else ERROR*/LOCAL STATUS getControlSetting ( pUSB_SPKR_SEQ_DEV pSeqDev, UINT8 entityId, UINT8 channel, UINT8 controlSelector, UINT8 request, pUINT16 pAttribute, UINT16 settingWidth ) { UINT16 attribute = 0; if (audioIfRequest (pSeqDev, USB_RT_DEV_TO_HOST | USB_RT_CLASS | USB_RT_INTERFACE, request, entityId, controlSelector << 8 | channel, settingWidth, &attribute) != OK) { return ERROR; } *pAttribute = FROM_LITTLEW (attribute); return OK; }/***************************************************************************** getControlSettings - reads settings for the specified feature unit control** If the information can be read successfully, <pCtlCaps>->supported is set * to TRUE.** RETURNS: N/A*/LOCAL VOID getControlSettings ( pUSB_SPKR_SEQ_DEV pSeqDev, UINT8 entityId, UINT8 channel, UINT8 controlSelector, pUSB_SPKR_CTL_CAPS pCtlCaps, UINT16 settingWidth ) { /* Get the control's resolution. */ if (getControlSetting (pSeqDev, entityId, channel, controlSelector, USB_REQ_AUDIO_GET_RES, &pCtlCaps->res, settingWidth) != OK) return; /* Get the control's min setting */ if (getControlSetting (pSeqDev, entityId, channel, controlSelector, USB_REQ_AUDIO_GET_MIN, (UINT16 *)&pCtlCaps->min, settingWidth) != OK) return; /* Get the control's max setting */ if (getControlSetting (pSeqDev, entityId, channel, controlSelector, USB_REQ_AUDIO_GET_MAX, (UINT16 *)&pCtlCaps->max, settingWidth) != OK) return; /* Get the control's current setting */ if (getControlSetting (pSeqDev, entityId, channel, controlSelector, USB_REQ_AUDIO_GET_CUR, (UINT16 *)&pCtlCaps->cur, settingWidth) != OK) return; pCtlCaps->supported = TRUE; }/***************************************************************************** recordChannelsCaps - record capabilities for the specified channel** RETURNS: N/A*/LOCAL VOID recordChannelCaps ( pUSB_SPKR_SEQ_DEV pSeqDev, UINT8 entityId, UINT8 channel, pUSB_SPKR_CHANNEL_CAPS pCaps, UINT8 controls ) { if ((controls & USB_AUDIO_FCM_MUTE) != 0) pCaps->mute.supported = TRUE; if ((controls & USB_AUDIO_FCM_VOLUME) != 0) getControlSettings (pSeqDev, entityId, channel, USB_AUDIO_FCS_VOLUME, &pCaps->volume, USB_AUDIO_VOLUME_ATTR_WIDTH); if ((controls & USB_AUDIO_FCM_BASS) != 0) getControlSettings (pSeqDev, entityId, channel, USB_AUDIO_FCS_BASS, &pCaps->bass, USB_AUDIO_BASS_ATTR_WIDTH); if ((controls & USB_AUDIO_FCM_MID) != 0) getControlSettings (pSeqDev, entityId, channel, USB_AUDIO_FCS_MID, &pCaps->mid, USB_AUDIO_MID_ATTR_WIDTH); if ((controls & USB_AUDIO_FCM_TREBLE) != 0) getControlSettings (pSeqDev, entityId, channel, USB_AUDIO_FCS_TREBLE, &pCaps->treble, USB_AUDIO_TREBLE_ATTR_WIDTH); }/***************************************************************************** buildAudioMap - determine what capabilities the audio device has** Search the provided <pCfgBfr> for an AudioClass (AC) descriptor and * from that descriptor determine what capabilities the device has. ** RETURNS: OK if successful, else ERROR.*/LOCAL STATUS buildAudioMap ( pUSB_SPKR_SEQ_DEV pSeqDev, pUINT8 pCfgBfr, UINT16 cfgLen ) { pUSB_AUDIO_AC_DESCR pAcDescr; pUSB_AUDIO_AC_COMMON pAcCommon; pUSB_AUDIO_OUTPUT_TERM_DESCR pOutputTerm; pUSB_AUDIO_INPUT_TERM_DESCR pInputTerm; pUSB_AUDIO_FEATURE_UNIT_DESCR pFeatureUnit = NULL; pUINT8 pBfr; UINT16 bfrLen; UINT16 totalLength; UINT16 remLen; UINT8 prevId; pUINT8 pControl; UINT16 i; /* Find the first AudioControl (AC) descriptor */ pBfr = pCfgBfr; bfrLen = cfgLen; if ((pAcDescr = findAudioDescrSkip (&pBfr, &bfrLen, USB_DESCR_AUDIO_INTERFACE, USB_DESCR_AUDIO_AC_HEADER)) == NULL) return ERROR; /* Find an "Output Terminal". Then, using the terminal/unit numbers as * links, work backwards from the output terminal to find the "Input * Terminal" and "Feature Unit" (if any) associated with it. */ totalLength = pAcDescr->totalLength [0] | (pAcDescr->totalLength [1] << 8); remLen = min (totalLength - sizeof (*pAcDescr), bfrLen); if ((pOutputTerm = findAudioDescr (pBfr, remLen, USB_DESCR_AUDIO_INTERFACE, USB_DESCR_AUDIO_AC_OUTPUT_TERMINAL)) == NULL) return ERROR; pSeqDev->outputTerminalId = pOutputTerm->terminalId; prevId = pOutputTerm->sourceId; while (prevId != 0 && pSeqDev->inputTerminalId == 0) { if ((pAcCommon = findAudioDescrByUnit (pBfr, remLen, prevId)) == NULL) return FALSE; switch (pAcCommon->descriptorSubType) { case USB_DESCR_AUDIO_AC_INPUT_TERMINAL: /* Record characteristics of the input terminal */ pInputTerm = (pUSB_AUDIO_INPUT_TERM_DESCR) pAcCommon; pSeqDev->inputTerminalId = pInputTerm->terminalId; pSeqDev->channels = pInputTerm->channels; pSeqDev->channelConfig = pInputTerm->channelConfig [0] | (pInputTerm->channelConfig [1] << 8); prevId = 0; /* If there is a feature unit descriptor, record its * capabilities on a channel-by-channel basis. */ if (pFeatureUnit != NULL) { /* Allocate space for info on a per-channel basis. * * NOTE: Array position 0 is for "master" (ie. * global) channel. */ pSeqDev->capsLen = (pSeqDev->channels + 1) * sizeof (USB_SPKR_CHANNEL_CAPS); if ((pSeqDev->pCaps = OSS_CALLOC (pSeqDev->capsLen)) == NULL) return ERROR; /* Record capabilities */ for (i = 0; i <= pSeqDev->channels; i++) { pControl = &pFeatureUnit->controls[i * pFeatureUnit->controlSize]; recordChannelCaps (pSeqDev, pFeatureUnit->unitId, i, &pSeqDev->pCaps [i], *pControl); } } break; case USB_DESCR_AUDIO_AC_MIXER_UNIT: prevId = ((pUSB_AUDIO_MIXER_UNIT_DESCR) pAcCommon)->sourceId [0]; break; case USB_DESCR_AUDIO_AC_SELECTOR_UNIT: prevId = ((pUSB_AUDIO_SELECTOR_UNIT_DESCR) pAcCommon)->sourceId [0]; break; case USB_DESCR_AUDIO_AC_FEATURE_UNIT: /* Record capabilities of the feature unit */ pFeatureUnit = (pUSB_AUDIO_FEATURE_UNIT_DESCR) pAcCommon; pSeqDev->featureUnitId = pFeatureUnit->unitId; prevId = pFeatureUnit->sourceId; break; case USB_DESCR_AUDIO_AC_PROCESSING_UNIT: prevId = ((pUSB_AUDIO_PROCESS_UNIT_DESCR) pAcCommon)->sourceId [0]; break; case USB_DESCR_AUDIO_AC_EXTENSION_UNIT: prevId = ((pUSB_AUDIO_EXT_UNIT_DESCR) pAcCommon)->sourceId [0]; break; case USB_DESCR_AUDIO_AC_UNDEFINED: case USB_DESCR_AUDIO_AC_HEADER: case USB_DESCR_AUDIO_AC_OUTPUT_TERMINAL: default: /* These terminal/unit types should not be encountered at * this point in the algorithm. */ return ERROR; } } return OK; }/***************************************************************************** reallocateFormatList - increases room for format list by one entry** RETURNS: OK, else ERROR if out of memory*/LOCAL STATUS reallocateFormatList ( pUSB_SPKR_SEQ_DEV pSeqDev ) { pUSB_SPKR_AUDIO_FORMAT pNewList; pSeqDev->fmtCount++; if ((pNewList = OSS_CALLOC (pSeqDev->fmtCount * sizeof (USB_SPKR_AUDIO_FORMAT))) == NULL) return ERROR; if (pSeqDev->fmtCount > 1 && pSeqDev->pFmt != NULL) { memcpy (pNewList, pSeqDev->pFmt, (pSeqDev->fmtCount - 1) * sizeof (USB_SPKR_AUDIO_FORMAT)); OSS_FREE (pSeqDev->pFmt); } pSeqDev->pFmt = pNewList; return OK; }/***************************************************************************** parseInterface - parse an interface descriptor, looking for audio formats** NOTE: <cfgLen> should count bytes only through the end of this interface.** RETURNS: N/A*/LOCAL VOID parseInterface ( pUSB_SPKR_SEQ_DEV pSeqDev, pUSB_INTERFACE_DESCR pIfDescr, pUINT8 pCfgBfr, UINT16 cfgLen ) { pUSB_AUDIO_AS_DESCR pAsDescr; pUSB_AUDIO_TYPE_DESCR pType; pUSB_AUDIO_STD_ISOCH_EP_DESCR pStdEp; pUSB_SPKR_AUDIO_FORMAT pFmt; USB_SPKR_AUDIO_FORMAT fmt = {0}; /* If this interface doesn't contain a class-specific AS (AudioStreaming) * descriptor then ignore it. If it does, but the AudioStream doesn't * link to the inputTerminalId, then ignore it anyway. */ if ((pAsDescr = findAudioDescrSkip (&pCfgBfr, &cfgLen, USB_DESCR_AUDIO_INTERFACE, USB_DESCR_AUDIO_AS_GENERAL)) == NULL) return; if (pAsDescr->terminalLink != pSeqDev->inputTerminalId) return; /* We must now find a format type descriptor and an endpoint descriptor. */ if ((pType = findAudioDescr (pCfgBfr, cfgLen, USB_DESCR_AUDIO_INTERFACE, USB_DESCR_AUDIO_AS_FORMAT_TYPE)) == NULL) return; if ((pStdEp = usbDescrParse (pCfgBfr, cfgLen, USB_DESCR_ENDPOINT)) == NULL) return; /* Construct a format record from the accumulated data. */ fmt.interface = pIfDescr->interfaceNumber; fmt.altSetting = pIfDescr->alternateSetting; fmt.delay = pAsDescr->delay; fmt.endpoint = pStdEp->endpointAddress; fmt.maxPacketSize = pStdEp->maxPacketSize [0] | (pStdEp->maxPacketSize [1] << 8); fmt.formatTag = pAsDescr->formatTag [0] | (pAsDescr->formatTag [1] << 8); fmt.formatType = pType->formatType; switch (pType->formatType) { case USB_AUDIO_FORMAT_TYPE1: fmt.channels = pType->ts.type1.nbrChannels; fmt.subFrameSize = pType->ts.type1.subFrameSize; fmt.bitRes = pType->ts.type1.bitResolution; break; case USB_AUDIO_FORMAT_TYPE2: fmt.maxBitRate = pType->ts.type2.maxBitRate [0] | (pType->ts.type2.maxBitRate [1] << 8); fmt.samplesPerFrame = pType->ts.type2.samplesPerFrame [0] | (pType->ts.type2.samplesPerFrame [1] << 8); break; case USB_AUDIO_FORMAT_TYPE3: fmt.channels = pType->ts.type3.nbrChannels; fmt.subFrameSize = pType->ts.type3.subFrameSize; fmt.bitRes = pType->ts.type3.bitResolution; break; default: /* We don't recognize this format */ return; } /* Copy new format record to SEQ_DEV structure. */ if (reallocateFormatList (pSeqDev) != OK) return; pFmt = &pSeqDev->pFmt [pSeqDev->fmtCount - 1]; *pFmt = fmt; }/***************************************************************************** buildFormatList - builds a list of formats supported by the speaker** RETURNS: OK if successful, else ERROR.*/LOCAL STATUS buildFormatList ( pUSB_SPKR_SEQ_DEV pSeqDev, pUINT8 pCfgBfr, UINT16 cfgLen ) { pUSB_INTERFACE_DESCR pIfDescr; pUINT8 pTmp; UINT16 tmpLen; UINT16 rangeLen; /* Find each interface descriptor of type AudioStreaming. Determine the * length of the descriptor, and then parse each format type supported by * the interface. */ while ((pIfDescr = usbDescrParseSkip (&pCfgBfr, &cfgLen, USB_DESCR_INTERFACE)) != NULL) { if (pIfDescr->interfaceClass == USB_CLASS_AUDIO && 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -