/** \brief Processes the \ref GET_DESCRIPTOR request (returns the specified USB descriptor) * * The \ref module_usb_descriptor_parser module is used to locate device, configuration and string * descriptors. Note that configuration descriptors also include interface, endpoint and other * "similar" descriptor types (e.g. HID descriptor), with the total descriptor length specified by * the \ref USB_CONFIGURATION_DESCRIPTOR.wTotalLength field. * * Other descriptor types that are not returned with the configuration descriptor, must be defined in * the usbDescriptorMarker.pUsbDescLut lookup-table. This table specifies the values of the VALUE and INDEX fields, and * gives a pointer to the descriptor along with it's length. * * <b>Parameters</b>: * - VALUE.MSB: Descriptor type * - VALUE.LSB: Descriptor index * - INDEX: 0, or language ID for string descriptors (currently not supported) * - LENGTH: Descriptor length (either the requested number of bytes, or the length of the descriptor, * whichever is the smallest) * * <b>Data (IN)</b>: * The descriptor(s) */ void usbsrGetDescriptor(void) { uint8 n; // Which descriptor? switch (HI_UINT16(usbSetupHeader.value)) { // Device descriptor case DESC_TYPE_DEVICE: usbSetupData.pBuffer = (uint8 __code*) usbdpGetDeviceDesc(); usbSetupData.bytesLeft = usbSetupData.pBuffer[DESC_LENGTH_IDX]; break; // Configuration descriptor case DESC_TYPE_CONFIG: usbSetupData.pBuffer = (uint8 __code*) usbdpGetConfigurationDesc(0, LO_UINT16(usbSetupHeader.value)); usbSetupData.bytesLeft = usbSetupData.pBuffer[DESC_CONFIG_LENGTH_LSB_IDX] + usbSetupData.pBuffer[DESC_CONFIG_LENGTH_MSB_IDX] * 256; break; // String descriptor case DESC_TYPE_STRING: // OPT: Implement language ID usbSetupData.pBuffer = (uint8 __code*) usbdpGetStringDesc(LO_UINT16(usbSetupHeader.value)); usbSetupData.bytesLeft = usbSetupData.pBuffer[DESC_LENGTH_IDX]; break; // Other descriptor type default: // Perform a table search (on index and value) usbSetupData.pBuffer = NULL; for (n = 0; n < ((uint16)usbDescriptorMarker.pUsbDescLutEnd - (uint16)usbDescriptorMarker.pUsbDescLut) / sizeof(DESC_LUT_INFO); n++) { if ((usbDescriptorMarker.pUsbDescLut[n].valueMsb == HI_UINT16(usbSetupHeader.value)) && (usbDescriptorMarker.pUsbDescLut[n].valueLsb == LO_UINT16(usbSetupHeader.value)) && (usbDescriptorMarker.pUsbDescLut[n].indexMsb == HI_UINT16(usbSetupHeader.index)) && (usbDescriptorMarker.pUsbDescLut[n].indexLsb == LO_UINT16(usbSetupHeader.index)) ) { usbSetupData.pBuffer = usbDescriptorMarker.pUsbDescLut[n].pDescStart; usbSetupData.bytesLeft = usbDescriptorMarker.pUsbDescLut[n].length; } } } // Stall EP0 if no descriptor was found if (usbSetupData.pBuffer == NULL) usbfwData.ep0Status = EP_STALL; if (usbfwData.ep0Status != EP_STALL) { // Limit the returned descriptor size (the PC wants to know about sizes before // polling the complete descriptors) if (usbSetupData.bytesLeft > usbSetupHeader.length) { usbSetupData.bytesLeft = usbSetupHeader.length; } usbfwData.ep0Status = EP_TX; } } // usbsrGetDescriptor
/** \brief Processes the \c GET_DESCRIPTOR request (returns the specified USB descriptor) * * The descriptors are retrieved using either the \ref module_usb_descriptor_parser module's automatic * parsing functions (for device and configuration descriptors), or the manually generated * \ref pUsbDescriptorLut[] lookup table (for string and non-standard formatted descriptors). When the * USB host requests the configuration descriptor, this includes also the interface descriptors and their * sub-descriptors, with a total length specified by \ref USB_CONFIGURATION_DESCRIPTOR.wTotalLength. * * The \ref pUsbDescriptorLut[] lookup table takes the expected VALUE and INDEX fields for each * descriptor, and returns pointer and length. * * <b>Parameters</b>: * - VALUE.MSB: Descriptor type * - VALUE.LSB: Descriptor index * - INDEX: 0, or language ID for string descriptors (currently not supported) * - LENGTH: Descriptor length (either the requested number of bytes, or the length of the descriptor, * whichever is the smallest) * * <b>Data (IN)</b>: * The descriptor(s) */ void usbsrGetDescriptor(void) { const USB_DESCRIPTOR_LUT* pUsbDescriptorLutEntry; // // Which descriptor? // switch(usbSetupHeader.valueMsb) { case USB_DESC_TYPE_DEVICE: // // Device descriptor // usbSetupData.pBuffer = (void*) usbdpGetDeviceDesc(); usbSetupData.bytesLeft = ((USB_DEVICE_DESCRIPTOR*) usbSetupData.pBuffer)->bLength; break; case USB_DESC_TYPE_CONFIG: // // Configuration descriptor // usbSetupData.pBuffer = (void*) usbdpGetConfigurationDesc(0, usbSetupHeader.valueLsb); usbSetupData.bytesLeft = ((USB_CONFIGURATION_DESCRIPTOR*) usbSetupData.pBuffer)->wTotalLength; break; default: // // String or other type descriptor // pUsbDescriptorLutEntry = usbdpGetDescByLut(usbSetupHeader.value, usbSetupHeader.index); if(pUsbDescriptorLutEntry) { usbSetupData.pBuffer = (void*) pUsbDescriptorLutEntry->pDesc; usbSetupData.bytesLeft = pUsbDescriptorLutEntry->length; } else { // // Not found, so stall below // usbSetupData.pBuffer = NULL; } } // // Stall EP0 if no descriptor was found // if(!usbSetupData.pBuffer) { usbfwData.ep0Status = EP_STALL; } if(usbfwData.ep0Status != EP_STALL) { // // Limit the returned descriptor size (the PC wants to know about sizes before // polling the complete descriptors) // if(usbSetupData.bytesLeft > usbSetupHeader.length) { usbSetupData.bytesLeft = usbSetupHeader.length; } usbfwData.ep0Status = EP_TX; } }