/** \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 Initializes the USB framework * * This function should be called when the microcontroller is ready to accept USB traffic. It enables the * USB peripheral unit and enables the pull-up resistor on the D+ line. Endpoint status, current * configuration value, etc. are initialized and evenetually re-initialized in the * \ref usbfwResetHandler() function. */ void usbfwInit(void) { // Set default values usbfwData.selfPowered = (usbdpGetConfigurationDesc(1, 0)->bmAttributes & 0x40) ? TRUE : FALSE; usbfwData.remoteWakeup = FALSE; HAL_USB_ENABLE(); // Enable Resume Interrupt HAL_USB_RESUME_INT_ENABLE(); } // usbfwInit
/** \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 __code* usbdpGetInterfaceDesc(uint8 cfgValue, uint8 intNumber, uint8 altSetting) { USB_INTERFACE_DESCRIPTOR __code *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 Initializes the USB framework * * This function should be called when the microcontroller is ready to accept USB traffic. It enables the * USB peripheral unit and enables the pull-up resistor on the D+ line. */ void usbfwInit(void) { // // Set default values // usbfwData.selfPowered = (usbdpGetConfigurationDesc(1, 0)->bmAttributes & 0x40) ? true : false; usbfwData.remoteWakeup = false; usbfwResetHandler(); // // Enable the USB peripheral unit // UsbEnable(); // // Allow the USB pad IP to to enter standby // HWREG(CCTEST_USBCTRL) = CCTEST_USBCTRL_USB_STB_M; }
/** \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; } }