/** Parses the given Configuration descriptor (followed by relevant * interface, endpoint and class-specific descriptors) into three arrays. * *Each array must have its size equal or greater to the number of * descriptors it stores plus one*. A null-value is inserted after the last * descriptor of each type to indicate the array end. * * Note that if the pointer to an array is null (0), nothing is stored in * it. * \param configuration Pointer to the start of the whole Configuration * descriptor. * \param interfaces Pointer to the Interface descriptor array. * \param endpoints Pointer to the Endpoint descriptor array. * \param others Pointer to the class-specific descriptor array. */ void USBConfigurationDescriptor_Parse( const USBConfigurationDescriptor *configuration, USBInterfaceDescriptor **interfaces, USBEndpointDescriptor **endpoints, USBGenericDescriptor **others) { /* Get size of configuration to parse */ int size = USBConfigurationDescriptor_GetTotalLength(configuration); size -= sizeof(USBConfigurationDescriptor); /* Start parsing descriptors */ USBGenericDescriptor *descriptor = (USBGenericDescriptor *) configuration; while (size > 0) { /* Get next descriptor */ descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor); size -= USBGenericDescriptor_GetLength(descriptor); /* Store descriptor in correponding array */ if (USBGenericDescriptor_GetType(descriptor) == USBGenericDescriptor_INTERFACE) { if (interfaces) { *interfaces = (USBInterfaceDescriptor *) descriptor; interfaces++; } } else if (USBGenericDescriptor_GetType(descriptor) == USBGenericDescriptor_ENDPOINT) { if (endpoints) { *endpoints = (USBEndpointDescriptor *) descriptor; endpoints++; } } else if (others) { *others = descriptor; others++; } } /* Null-terminate arrays */ if (interfaces) { *interfaces = 0; } if (endpoints) { *endpoints = 0; } if (others) { *others = 0; } }
//------------------------------------------------------------------------------ /// Sends the requested USB descriptor to the host if available, or STALLs the /// request. /// \param pDriver Pointer to a USBDDriver instance. /// \param type Type of the requested descriptor /// \param index Index of the requested descriptor. /// \param length Maximum number of bytes to return. //------------------------------------------------------------------------------ static void GetDescriptor( const USBDDriver *pDriver, unsigned char type, unsigned char indexRDesc, unsigned int length) { const USBDeviceDescriptor *pDevice; const USBConfigurationDescriptor *pConfiguration; const USBDeviceQualifierDescriptor *pQualifier; const USBConfigurationDescriptor *pOtherSpeed; const USBGenericDescriptor **pStrings = (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings; const USBGenericDescriptor *pString; unsigned char numStrings = pDriver->pDescriptors->numStrings; unsigned char terminateWithNull = 0; // Use different set of descriptors depending on device speed if (USBD_IsHighSpeed()) { TRACE_DEBUG("HS "); pDevice = pDriver->pDescriptors->pHsDevice; pConfiguration = pDriver->pDescriptors->pHsConfiguration; pQualifier = pDriver->pDescriptors->pHsQualifier; pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed; } else { TRACE_DEBUG("FS "); pDevice = pDriver->pDescriptors->pFsDevice; pConfiguration = pDriver->pDescriptors->pFsConfiguration; pQualifier = pDriver->pDescriptors->pFsQualifier; pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed; } // Check the descriptor type switch (type) { case USBGenericDescriptor_DEVICE: TRACE_INFO_WP("Dev "); // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice); } USBD_Write(0, pDevice, length, 0, 0); break; case USBGenericDescriptor_CONFIGURATION: TRACE_INFO_WP("Cfg "); // Adjust length and send descriptor if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) { length = USBConfigurationDescriptor_GetTotalLength(pConfiguration); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pConfiguration, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); break; case USBGenericDescriptor_DEVICEQUALIFIER: TRACE_INFO_WP("Qua "); // Check if descriptor exists if (!pQualifier) { USBD_Stall(0); } else { // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier); } USBD_Write(0, pQualifier, length, 0, 0); } break; case USBGenericDescriptor_OTHERSPEEDCONFIGURATION: TRACE_INFO_WP("OSC "); // Check if descriptor exists if (!pOtherSpeed) { USBD_Stall(0); } else { // Adjust length and send descriptor if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) { length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pOtherSpeed, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } break; case USBGenericDescriptor_STRING: TRACE_INFO_WP("Str%d ", indexRDesc); // Check if descriptor exists if (indexRDesc > numStrings) { USBD_Stall(0); } else { pString = pStrings[indexRDesc]; // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength(pString)) { length = USBGenericDescriptor_GetLength(pString); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pString, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } break; default: TRACE_WARNING( "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r", type); USBD_Stall(0); } }
/** * Sends the requested USB descriptor to the host if available, or STALLs the * request. * \param pDriver Pointer to a USBDDriver instance. * \param type Type of the requested descriptor * \param index Index of the requested descriptor. * \param length Maximum number of bytes to return. */ static void GetDescriptor( const USBDDriver *pDriver, uint8_t type, uint8_t indexRDesc, uint32_t length) { const USBDeviceDescriptor *pDevice; const USBConfigurationDescriptor *pConfiguration; const USBDeviceQualifierDescriptor *pQualifier; const USBConfigurationDescriptor *pOtherSpeed; const USBGenericDescriptor **pStrings = (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings; const USBGenericDescriptor *pString; uint8_t numStrings = pDriver->pDescriptors->numStrings; uint8_t terminateWithNull = 0; /* Use different set of descriptors depending on device speed */ if (USBD_IsHighSpeed()) { TRACE_DEBUG("HS "); pDevice = pDriver->pDescriptors->pHsDevice; pConfiguration = pDriver->pDescriptors->pHsConfiguration; pQualifier = pDriver->pDescriptors->pHsQualifier; pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed; } else { TRACE_DEBUG("FS "); pDevice = pDriver->pDescriptors->pFsDevice; pConfiguration = pDriver->pDescriptors->pFsConfiguration; pQualifier = pDriver->pDescriptors->pFsQualifier; pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed; } /* Check the descriptor type */ switch (type) { case USBGenericDescriptor_DEVICE: TRACE_INFO_WP("Dev "); /* Adjust length and send descriptor */ if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice); } USBD_Write(0, pDevice, length, 0, 0); break; case USBGenericDescriptor_CONFIGURATION: TRACE_INFO_WP("Cfg "); /* Adjust length and send descriptor */ if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) { length = USBConfigurationDescriptor_GetTotalLength(pConfiguration); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pConfiguration, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); break; case USBGenericDescriptor_DEVICEQUALIFIER: TRACE_INFO_WP("Qua "); /* Check if descriptor exists */ if (!pQualifier) { USBD_Stall(0); } else { /* Adjust length and send descriptor */ if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier); } USBD_Write(0, pQualifier, length, 0, 0); } break; case USBGenericDescriptor_OTHERSPEEDCONFIGURATION: TRACE_INFO_WP("OSC "); /* Check if descriptor exists */ if (!pOtherSpeed) { USBD_Stall(0); } else { /* Adjust length and send descriptor */ if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) { length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pOtherSpeed, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } break; case USBGenericDescriptor_STRING: TRACE_INFO_WP("Str%d ", indexRDesc); /* Check if descriptor exists */ if (indexRDesc == 0xEE) { // https://github.com/pbatard/libwdi/wiki/WCID-Devices const uint8_t osStringDescriptor[] = { 0x12, // bLength USBGenericDescriptor_STRING, // bDescriptorType 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00, 0x54, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, // qwSignature USBGenericRequest_GETMSDESCRIPTOR, // bMS_VendorCode 0x00, // bPad }; const uint8_t osStringDescriptorLength = sizeof(osStringDescriptor); /* Adjust length and send descriptor */ if (length > osStringDescriptorLength) { length = osStringDescriptorLength; terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, osStringDescriptor, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } else if (indexRDesc >= numStrings) { USBD_Stall(0); } else { pString = pStrings[indexRDesc]; /* Adjust length and send descriptor */ if (length > USBGenericDescriptor_GetLength(pString)) { length = USBGenericDescriptor_GetLength(pString); terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } USBD_Write(0, pString, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); } break; default: TRACE_WARNING( "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r", type); USBD_Stall(0); } }
//------------------------------------------------------------------------------ /// Sends the requested USB descriptor to the host if available, or STALLs the /// request. /// \param pDriver Pointer to a USBDDriver instance. /// \param type Type of the requested descriptor /// \param index Index of the requested descriptor. /// \param length Maximum number of bytes to return. //------------------------------------------------------------------------------ static void GetDescriptor( const USBDDriver *pDriver, unsigned char type, unsigned char index, unsigned int length) { const USBDeviceDescriptor *pDevice; const USBConfigurationDescriptor *pConfiguration; const USBGenericDescriptor **pStrings = (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings; unsigned char numStrings = pDriver->pDescriptors->numStrings; const USBGenericDescriptor *pString; pDevice = pDriver->pDescriptors->pFsDevice; pConfiguration = pDriver->pDescriptors->pFsConfiguration; // Check the descriptor type switch (type) { case USBGenericDescriptor_DEVICE: TRACE_INFO_WP("Dev "); // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice); } USBD_Write(0, pDevice, length, 0, 0); break; case USBGenericDescriptor_CONFIGURATION: TRACE_INFO_WP("Cfg "); // Adjust length and send descriptor if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) { length = USBConfigurationDescriptor_GetTotalLength(pConfiguration); } USBD_Write(0, pConfiguration, length, 0, 0); break; case USBGenericDescriptor_STRING: TRACE_INFO_WP("Str%d ", index); // Check if descriptor exists if (index > numStrings) { USBD_Stall(0); } else { pString = pStrings[index]; // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength(pString)) { length = USBGenericDescriptor_GetLength(pString); } USBD_Write(0, pString, length, 0, 0); } break; default: TRACE_WARNING( "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r", type); USBD_Stall(0); } }
//------------------------------------------------------------------------------ /// Sends the requested USB descriptor to the host if available, or STALLs the /// request. /// \param pDriver Pointer to a USBDDriver instance. /// \param type Type of the requested descriptor /// \param index Index of the requested descriptor. /// \param length Maximum number of bytes to return. //------------------------------------------------------------------------------ static void GetDescriptor( const USBDDriver *pDriver, unsigned char type, unsigned char index, unsigned int length) { const USBDeviceDescriptor *pDevice; const USBConfigurationDescriptor *pConfiguration; const USBDeviceQualifierDescriptor *pQualifier; const USBConfigurationDescriptor *pOtherSpeed; const USBGenericDescriptor **pStrings = (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings; unsigned char numStrings = pDriver->pDescriptors->numStrings; const USBGenericDescriptor *pString; // Use different set of descriptors depending on device speed if (USBD_IsHighSpeed()) { trace_LOG(trace_DEBUG, "HS "); pDevice = pDriver->pDescriptors->pHsDevice; pConfiguration = pDriver->pDescriptors->pHsConfiguration; pQualifier = pDriver->pDescriptors->pHsQualifier; pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed; } else { trace_LOG(trace_DEBUG, "FS "); pDevice = pDriver->pDescriptors->pFsDevice; pConfiguration = pDriver->pDescriptors->pFsConfiguration; pQualifier = pDriver->pDescriptors->pFsQualifier; pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed; } // Check the descriptor type switch (type) { case USBGenericDescriptor_DEVICE: trace_LOG(trace_INFO, "Dev "); // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice); } USBD_Write(0, pDevice, length, 0, 0); break; case USBGenericDescriptor_CONFIGURATION: trace_LOG(trace_INFO, "Cfg "); // Adjust length and send descriptor if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) { length = USBConfigurationDescriptor_GetTotalLength(pConfiguration); } USBD_Write(0, pConfiguration, length, 0, 0); break; case USBGenericDescriptor_DEVICEQUALIFIER: trace_LOG(trace_INFO, "Qua "); // Check if descriptor exists if (!pQualifier) { USBD_Stall(0); } else { // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) { length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier); } USBD_Write(0, pQualifier, length, 0, 0); } break; case USBGenericDescriptor_OTHERSPEEDCONFIGURATION: trace_LOG(trace_INFO, "OSC "); // Check if descriptor exists if (!pOtherSpeed) { USBD_Stall(0); } else { // Adjust length and send descriptor if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) { length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed); } USBD_Write(0, pOtherSpeed, length, 0, 0); } break; case USBGenericDescriptor_STRING: trace_LOG(trace_INFO, "Str%d ", index); // Check if descriptor exists if (index > numStrings) { USBD_Stall(0); } else { pString = pStrings[index]; // Adjust length and send descriptor if (length > USBGenericDescriptor_GetLength(pString)) { length = USBGenericDescriptor_GetLength(pString); } USBD_Write(0, pString, length, 0, 0); } break; default: trace_LOG(trace_WARNING, "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r", type); USBD_Stall(0); } }