//------------------------------------------------------------------------------ /// Sends the current status of the device to the host. /// \param pDriver Pointer to a USBDDriver instance. //------------------------------------------------------------------------------ static void GetDeviceStatus(const USBDDriver *pDriver) { static unsigned short data; const USBConfigurationDescriptor *pConfiguration; data = 0; // Use different configuration depending on device speed if (USBD_IsHighSpeed()) { pConfiguration = pDriver->pDescriptors->pHsConfiguration; } else { pConfiguration = pDriver->pDescriptors->pFsConfiguration; } // Check current configuration for power mode (if device is configured) if (pDriver->cfgnum != 0) { if (USBConfigurationDescriptor_IsSelfPowered(pConfiguration)) { data |= 1; } } // Check if remote wake-up is enabled if (pDriver->isRemoteWakeUpEnabled) { data |= 2; } // Send the device status USBD_Write(0, &data, 2, 0, 0); }
/** * Returns the descriptor requested by the host. * \param type Descriptor type. * \param length Maximum number of bytes to send. * \return 1 if the request has been handled by this function, otherwise 0. */ static uint8_t HIDDTransferDriver_GetDescriptor(uint8_t type, uint8_t length) { HIDDTransferDriver *pDrv = &hiddTransferDriver; HIDDFunction *pHidd = &pDrv->hidFunction; const USBConfigurationDescriptor *pConfiguration; HIDDescriptor *hidDescriptors[2]; switch (type) { case HIDGenericDescriptor_REPORT: TRACE_INFO("Report "); /* Adjust length and send report descriptor */ if (length > HIDDTransferDriver_REPORTDESCRIPTORSIZE) { length = HIDDTransferDriver_REPORTDESCRIPTORSIZE; } USBD_Write(0, &hiddTransferReportDescriptor, length, 0, 0); break; case HIDGenericDescriptor_HID: TRACE_INFO("HID "); /* Configuration descriptor is different depending on configuration */ if (USBD_IsHighSpeed()) { pConfiguration = pHidd->pUsbd->pDescriptors->pHsConfiguration; } else { pConfiguration = pHidd->pUsbd->pDescriptors->pFsConfiguration; } /* Parse the device configuration to get the HID descriptor */ USBConfigurationDescriptor_Parse(pConfiguration, 0, 0, (USBGenericDescriptor **) hidDescriptors); /* Adjust length and send HID descriptor */ if (length > sizeof(HIDDescriptor)) { length = sizeof(HIDDescriptor); } USBD_Write(0, hidDescriptors[0], length, 0, 0); break; default: return 0; } return 1; }
/** * Configures the device by setting it into the Configured state and * initializing all endpoints. * \param pDriver Pointer to a USBDDriver instance. * \param cfgnum Configuration number to set. */ static void SetConfiguration(USBDDriver *pDriver, uint8_t cfgnum) { USBEndpointDescriptor *pEndpoints[17]; const USBConfigurationDescriptor *pConfiguration; /* Use different descriptor depending on device speed */ if (USBD_IsHighSpeed()) { pConfiguration = pDriver->pDescriptors->pHsConfiguration; } else { pConfiguration = pDriver->pDescriptors->pFsConfiguration; } /* Set & save the desired configuration */ USBD_SetConfiguration(cfgnum); pDriver->cfgnum = cfgnum; pDriver->isRemoteWakeUpEnabled = ((pConfiguration->bmAttributes & 0x20) > 0); /* If the configuration is not 0, configure endpoints */ if (cfgnum != 0) { /* Parse configuration to get endpoint descriptors */ USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0); /* Configure endpoints */ int i = 0; while (pEndpoints[i] != 0) { USBD_ConfigureEndpoint(pEndpoints[i]); i++; } } /* Should be done before send the ZLP */ USBDDriverCallbacks_ConfigurationChanged(cfgnum); /* Acknowledge the request */ USBD_Write(0, /* Endpoint #0 */ 0, /* No data buffer */ 0, /* No data buffer */ (TransferCallback) 0, (void *) 0); }
//------------------------------------------------------------------------------ /// Configures the device by setting it into the Configured state and /// initializing all endpoints. /// \param pDriver Pointer to a USBDDriver instance. /// \param cfgnum Configuration number to set. //------------------------------------------------------------------------------ static void SetConfiguration(USBDDriver *pDriver, unsigned char cfgnum) { USBEndpointDescriptor *pEndpoints[CHIP_USB_NUMENDPOINTS+1]; const USBConfigurationDescriptor *pConfiguration; // Use different descriptor depending on device speed if (USBD_IsHighSpeed()) { pConfiguration = pDriver->pDescriptors->pHsConfiguration; } else { pConfiguration = pDriver->pDescriptors->pFsConfiguration; } // Set & save the desired configuration USBD_SetConfiguration(cfgnum); pDriver->cfgnum = cfgnum; // If the configuration is not 0, configure endpoints if (cfgnum != 0) { // Parse configuration to get endpoint descriptors USBConfigurationDescriptor_Parse(pConfiguration, 0, pEndpoints, 0); // Configure endpoints int i = 0; while (pEndpoints[i] != 0) { USBD_ConfigureEndpoint(pEndpoints[i]); i++; } } // Should be done before send the ZLP USBDDriverCallbacks_ConfigurationChanged(cfgnum); // Acknowledge the request USBD_Write(0, // Endpoint #0 0, // No data buffer 0, // No data buffer (TransferCallback) 0, (void *) 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); } }
// https://github.com/pbatard/libwdi/wiki/WCID-Devices static void GetMSDescriptor( const USBDDriver *pDriver, uint16_t indexRDesc, uint32_t length) { const USBDeviceDescriptor *pDevice; uint8_t terminateWithNull = 0; /* Use different set of descriptors depending on device speed */ if (USBD_IsHighSpeed()) { TRACE_DEBUG("HS "); pDevice = pDriver->pDescriptors->pHsDevice; } else { TRACE_DEBUG("FS "); pDevice = pDriver->pDescriptors->pFsDevice; } /* Check the descriptor index */ switch (indexRDesc) { // https://github.com/pbatard/libwdi/wiki/WCID-Devices case 0x0004: { // Extended Compat ID (Microsoft OS 1.0 Descriptors) const uint8_t extendedCompatID[] = { 0x28, 0x00, 0x00, 0x00, // dwLength 0x00, 0x01, // bcdVersion 0x04, 0x00, // wIndex 0x01, // bCount 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved 0x00, // bFirstInterfaceNumber 0x01, // Reserved 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // CompatibleID "WINUSB\0\0" 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // SubCompatibleID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved }; const uint8_t extendedCompatIDLength = sizeof(extendedCompatID); /* Adjust length and send descriptor */ if (length > extendedCompatIDLength) { length = extendedCompatIDLength; terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); USBD_Write(0, extendedCompatID, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); break; } case 0x0005: { // Extended Properties (Microsoft OS 1.0 Descriptors) const uint8_t extendedProperties[] = { 0x92, 0x00, 0x00, 0x00, // dwLength 0x00, 0x01, // bcdVersion 0x05, 0x00, // wIndex 0x01, 0x00, // wCount 0x88, 0x00, 0x00, 0x00, // dwSize 0x07, 0x00, 0x00, 0x00, // dwPropertyDataType 0x2a, 0x00, // wPropertyNameLength 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00, 0x47, 0x00, 0x55, 0x00, 0x49, 0x00, 0x44, 0x00, 0x73, 0x00, 0x00, 0x00, // bPropertyName "DeviceInterfaceGUIDs\0" 0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength 0x7b, 0x00, 0x38, 0x00, 0x37, 0x00, 0x30, 0x00, 0x30, 0x00, 0x31, 0x00, 0x33, 0x00, 0x44, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x46, 0x00, 0x42, 0x00, 0x31, 0x00, 0x44, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x42, 0x00, 0x44, 0x00, 0x37, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x39, 0x00, 0x36, 0x00, 0x43, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x46, 0x00, 0x30, 0x00, 0x42, 0x00, 0x37, 0x00, 0x44, 0x00, 0x33, 0x00, 0x31, 0x00, 0x41, 0x00, 0x46, 0x00, 0x34, 0x00, 0x31, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, // bPropertyData "{870013DD-FB1D-4BD7-A96C-1F0B7D31AF41}\0\0" }; const uint8_t extendedPropertiesLength = sizeof(extendedProperties); /* Adjust length and send descriptor */ if (length > extendedPropertiesLength) { length = extendedPropertiesLength; terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); } terminateWithNull = ((length % pDevice->bMaxPacketSize0) == 0); USBD_Write(0, extendedProperties, length, terminateWithNull ? TerminateCtrlInWithNull : 0, 0); break; } default: TRACE_WARNING( "USBDDriver_GetMSDescriptor: Unknown descriptor index (%d)\n\r", indexRDesc); 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); } }
//------------------------------------------------------------------------------ /// Handles the given request if it is standard, otherwise STALLs it. /// \param pDriver Pointer to a USBDDriver instance. /// \param pRequest Pointer to a USBGenericRequest instance. //------------------------------------------------------------------------------ void USBDDriver_RequestHandler( USBDDriver *pDriver, const USBGenericRequest *pRequest) { unsigned char cfgnum; unsigned char infnum; unsigned char eptnum; unsigned char setting; unsigned char type; unsigned char index; unsigned int length; unsigned int address; trace_LOG(trace_INFO, "Std "); // Check request code switch (USBGenericRequest_GetRequest(pRequest)) { case USBGenericRequest_GETDESCRIPTOR: trace_LOG(trace_INFO, "gDesc "); // Send the requested descriptor type = USBGetDescriptorRequest_GetDescriptorType(pRequest); index = USBGetDescriptorRequest_GetDescriptorIndex(pRequest); length = USBGenericRequest_GetLength(pRequest); GetDescriptor(pDriver, type, index, length); break; case USBGenericRequest_SETADDRESS: trace_LOG(trace_INFO, "sAddr "); // Sends a zero-length packet and then set the device address address = USBSetAddressRequest_GetAddress(pRequest); if( USBD_IsHighSpeed() ) { USBD_SetAddress( address ); } else { USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address); } break; case USBGenericRequest_SETCONFIGURATION: trace_LOG(trace_INFO, "sCfg "); // Set the requested configuration cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest); SetConfiguration(pDriver, cfgnum); break; case USBGenericRequest_GETCONFIGURATION: trace_LOG(trace_INFO, "gCfg "); // Send the current configuration number GetConfiguration(pDriver); break; case USBGenericRequest_GETSTATUS: trace_LOG(trace_INFO, "gSta "); // Check who is the recipient switch (USBGenericRequest_GetRecipient(pRequest)) { case USBGenericRequest_DEVICE: trace_LOG(trace_INFO, "Dev "); // Send the device status GetDeviceStatus(pDriver); break; case USBGenericRequest_ENDPOINT: trace_LOG(trace_INFO, "Ept "); // Send the endpoint status eptnum = USBGenericRequest_GetEndpointNumber(pRequest); GetEndpointStatus(eptnum); break; default: trace_LOG(trace_WARNING, "W: USBDDriver_RequestHandler: Unknown recipient (%d)\n\r", USBGenericRequest_GetRecipient(pRequest)); USBD_Stall(0); } break; case USBGenericRequest_CLEARFEATURE: trace_LOG(trace_INFO, "cFeat "); // Check which is the requested feature switch (USBFeatureRequest_GetFeatureSelector(pRequest)) { case USBFeatureRequest_ENDPOINTHALT: trace_LOG(trace_INFO, "Hlt "); // Unhalt endpoint and send a zero-length packet USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest)); USBD_Write(0, 0, 0, 0, 0); break; case USBFeatureRequest_DEVICEREMOTEWAKEUP: trace_LOG(trace_INFO, "RmWU "); // Disable remote wake-up and send a zero-length packet pDriver->isRemoteWakeUpEnabled = 0; USBD_Write(0, 0, 0, 0, 0); break; default: trace_LOG(trace_WARNING, "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r", USBFeatureRequest_GetFeatureSelector(pRequest)); USBD_Stall(0); } break; case USBGenericRequest_SETFEATURE: trace_LOG(trace_INFO, "sFeat "); // Check which is the selected feature switch (USBFeatureRequest_GetFeatureSelector(pRequest)) { case USBFeatureRequest_DEVICEREMOTEWAKEUP: trace_LOG(trace_INFO, "RmWU "); // Enable remote wake-up and send a ZLP pDriver->isRemoteWakeUpEnabled = 1; USBD_Write(0, 0, 0, 0, 0); break; case USBFeatureRequest_ENDPOINTHALT: trace_LOG(trace_INFO, "Ept "); // Halt endpoint USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest)); USBD_Write(0, 0, 0, 0, 0); break; #if defined(BOARD_USB_UDPHS) case USBFeatureRequest_TESTMODE: // 7.1.20 Test Mode Support if ((USBGenericRequest_GetType(pRequest) == USBGenericRequest_DEVICE) && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) { // Handle test request USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest)); } else { USBD_Stall(0); } break; #endif default: trace_LOG(trace_WARNING, "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r", USBFeatureRequest_GetFeatureSelector(pRequest)); USBD_Stall(0); } break; case USBGenericRequest_SETINTERFACE: trace_LOG(trace_INFO, "sInterface "); infnum = USBInterfaceRequest_GetInterface(pRequest); setting = USBInterfaceRequest_GetAlternateSetting(pRequest); SetInterface(pDriver, infnum, setting); break; case USBGenericRequest_GETINTERFACE: trace_LOG(trace_INFO, "gInterface "); infnum = USBInterfaceRequest_GetInterface(pRequest); GetInterface(pDriver, infnum); break; default: trace_LOG(trace_WARNING, "USBDDriver_RequestHandler: Unknown request code (%d)\n\r", USBGenericRequest_GetRequest(pRequest)); 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); } }