📄 usb_descriptor_parser.c
字号:
/// \addtogroup module_usb_descriptor_parser
/// @{
#define USBDESCRIPTORPARSER_C
#include "cc2511_usb_library_headers.h"
/** \brief Initializes a search
*
* This function must be called before each new search to reset \ref USBDP_DATA.pDesc.
*/
void usbdpInit(void) {
usbdpData.pDesc = (const BYTE __xdata *) pUsbDescStart;
} // usbdpInit
/** \brief Locates the descriptor of the wanted type
*
* This function parses through the USB descriptors until:
* \li It hits one with <tt>bDescriptorType = wantedType</tt>, in which case it returns a pointer to
* that descriptor, and exits. \ref USBDP_DATA.pDesc will then point to the next descriptor.
* \li It hits one with <tt>bDescriptorType = haltAtType</tt>, in which case it returns a NULL-pointer,
* and exits. \ref USBDP_DATA.pDesc will then point to that descriptor.
* \li \ref USBDP_DATA.pDesc = \ref pUsbDescEnd, in which case it returns a NULL-pointer, and exits.
* \ref USBDP_DATA.pDesc will continue to point to \ref pUsbDescEnd.
*
* \note To begin a search with this function, \ref usbdpInit should be called first. It should not be
* called when continuing a search - for instance after a call to \ref usbdpGetConfigurationDesc().
*
* \param[in] wantedType
* The wanted descriptor type (e.g. \ref DESC_TYPE_CONFIG)
* \param[in] haltAtType
* The parser halts when it reaches this descriptor type, unless \c haltAtType is \c 0 (which in any
* case is an invalid \c bDescriptorType value).
*
* \return
* A pointer to the wanted descriptor type, or \c NULL if it was not found.
*/
void __xdata* usbdpFindNext(BYTE wantedType, BYTE haltAtType) {
void __xdata *pResult;
pResult = NULL;
// As long as we haven't reached the end...
while (usbdpData.pDesc != pUsbDescEnd) {
// If we have a match on wantedType...
if (usbdpData.pDesc[DESC_TYPE_IDX] == wantedType) {
pResult = (void __xdata*) usbdpData.pDesc;
usbdpData.pDesc += usbdpData.pDesc[DESC_LENGTH_IDX];
break;
// If we have a match on haltAtType...
} else if (usbdpData.pDesc[DESC_TYPE_IDX] == haltAtType) {
if (haltAtType) break;
}
// Move on to the next descriptor
usbdpData.pDesc += usbdpData.pDesc[DESC_LENGTH_IDX];
}
return pResult;
} // usbdpFindNext
/** \brief Locates the (one and only) device descriptor
*
* \note It is not necessary to call \ref usbdpInit() before this function.
*
* \return
* A pointer to the \ref USB_DEVICE_DESCRIPTOR, or \c NULL if it was not found.
*/
USB_DEVICE_DESCRIPTOR __xdata* usbdpGetDeviceDesc(void) {
usbdpInit();
return usbdpFindNext(DESC_TYPE_DEVICE, 0);
} // usbdpGetDeviceDesc
/** \brief Locates a configuration descriptor
*
* The search will either look for a descriptor with a specific
* \ref USB_CONFIGURATION_DESCRIPTOR.bConfigurationValue, or simply take the n'th descriptor (by "index")
*
* \note It is not necessary to call \ref usbdpInit() before this function.
*
* \param[in] cfgValue
* The configuration value to search for (\ref USB_CONFIGURATION_DESCRIPTOR.bConfigurationValue), or
* 0 to find descriptor by index
* \param[in] cfgIndex
* A zero-based index for the configuration descriptor to find.
* This value is ignored unless \c cfgValue is 0.
*
* \return
* A pointer to the \ref USB_DEVICE_DESCRIPTOR, or \c NULL if it was not found.
*/
USB_CONFIGURATION_DESCRIPTOR __xdata* usbdpGetConfigurationDesc(UINT8 cfgValue, UINT8 cfgIndex) {
USB_CONFIGURATION_DESCRIPTOR __xdata *pConfigurationDesc;
usbdpInit();
// As long as there are more configuration descriptors...
while (pConfigurationDesc = usbdpFindNext(DESC_TYPE_CONFIG, 0)) {
// Search by value?
if (cfgValue) {
if (cfgValue == pConfigurationDesc->bConfigurationValue) break;
// Search by index? (search cfgIndex+1 times)
} else if (!cfgIndex--) {
break;
}
}
return pConfigurationDesc;
} // usbdpGetConfigurationDesc
/** \brief Locates an interface descriptor
*
* The function will first go to the configuration descriptor that matches the supplied configuration
* value, and then locate the interface descriptor that matches the given interface number and alternate
* setting.
*
* \note It is not necessary to call \ref usbdpInit() before this function.
*
* \param[in] cfgValue
* The configuration value (\ref USB_CONFIGURATION_DESCRIPTOR.bConfigurationValue)
* \param[in] intNumber
* The interface number (\ref USB_INTERFACE_DESCRIPTOR.bInterfaceNumber)
* \param[in] altSetting
* The alternate setting (\ref USB_INTERFACE_DESCRIPTOR.bAlternateSetting)
*
* \return
* A pointer to the \ref USB_INTERFACE_DESCRIPTOR, or \c NULL if it was not found.
*/
USB_INTERFACE_DESCRIPTOR __xdata* usbdpGetInterfaceDesc(UINT8 cfgValue, UINT8 intNumber, UINT8 altSetting) {
USB_INTERFACE_DESCRIPTOR __xdata *pInterfaceDesc;
// First get to the correct configuration
usbdpGetConfigurationDesc(cfgValue, 0);
// Then find a match on the interface
while (pInterfaceDesc = usbdpFindNext(DESC_TYPE_INTERFACE, DESC_TYPE_CONFIG)) {
if ((pInterfaceDesc->bInterfaceNumber == intNumber) && (pInterfaceDesc->bAlternateSetting == altSetting)) {
break;
}
}
return pInterfaceDesc;
} // usbdpGetInterfaceDesc
/** \brief Locates a string descriptor
*
* \note It is not necessary to call \ref usbdpInit() before this function.
*
* \param[in] strIndex
* A zero-based index that matches the "iXxxxxxxxxx" string indexes in the other descriptors
*
* \return
* A pointer to the \ref USB_INTERFACE_DESCRIPTOR, or \c NULL if it was not found.
*/
USB_STRING_DESCRIPTOR __xdata* usbdpGetStringDesc(UINT8 strIndex) {
USB_STRING_DESCRIPTOR __xdata *pStringDesc;
usbdpInit();
// Search strIndex+1 times
do {
pStringDesc = usbdpFindNext(DESC_TYPE_STRING, 0);
} while (strIndex--);
return pStringDesc;
} // usbdpGetStringDesc
/// @}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -