/** \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 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 __code* usbdpGetConfigurationDesc(uint8 cfgValue, uint8 cfgIndex) { USB_CONFIGURATION_DESCRIPTOR __code *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 Internally used function that configures all endpoints for the specified interface * * The new endpoint setup overwrites the old, without any warning. Unused endpoints keep their current * setup. The user is responsible for ensuring that no endpoint buffers overwrite each other, and that * interfaces do not cause conflicts. The pUsbDblbufLutInfo table must contain an entry for each * interface descriptor to define endpoint double-buffering. * * \param[in] *pInterface * A pointer to the interface descriptor */ static void ConfigureEndpoints(USB_INTERFACE_DESCRIPTOR __xdata *pInterface) { uint8 n; uint16 maxpRegValue; uint8 csRegValue; uint8 endpoint; USB_ENDPOINT_DESCRIPTOR __xdata *pEndpoint; DBLBUF_LUT_INFO __xdata *pUsbDblbufLutInfo; // Locate the double buffer settings if (!pInterface->bNumEndpoints) { return; } pUsbDblbufLutInfo = (DBLBUF_LUT_INFO __xdata*) usbDescriptorMarker.pUsbDblbufLut; while (pUsbDblbufLutInfo->pInterface != pInterface) { pUsbDblbufLutInfo++; } // For each endpoint in this interface for (n = 0; n < pInterface->bNumEndpoints; n++) { if (pEndpoint = usbdpFindNext(DESC_TYPE_ENDPOINT, 0)) { // Get the endpoint index endpoint = pEndpoint->bEndpointAddress & 0x0F; USBFW_SELECT_ENDPOINT(endpoint); csRegValue = 0x00; maxpRegValue = (pEndpoint->wMaxPacketSize + 7) >> 3; // For IN endpoints... if (pEndpoint->bEndpointAddress & 0x80) { // Clear data toggle, and flush twice (due to double buffering) USBCSIL = USBCSIL_CLR_DATA_TOG | USBCSIL_FLUSH_PACKET; USBCSIL = USBCSIL_FLUSH_PACKET; // USBCSIH if ((pEndpoint->bmAttributes & EP_ATTR_TYPE_BM) == EP_ATTR_ISO) csRegValue |= USBCSIH_ISO; // ISO flag if (pUsbDblbufLutInfo->inMask & (1 << endpoint)) csRegValue |= USBCSIH_IN_DBL_BUF; // Double buffering USBCSIH = csRegValue; // Max transfer size USBMAXI = maxpRegValue; // Endpoint status usbfwData.pEpInStatus[endpoint - 1] = EP_IDLE; // For OUT endpoints... } else { // Clear data toggle, and flush twice (due to double buffering) USBCSOL = USBCSOL_CLR_DATA_TOG | USBCSOL_FLUSH_PACKET; USBCSOL = USBCSOL_FLUSH_PACKET; // USBCSOH if ((pEndpoint->bmAttributes & EP_ATTR_TYPE_BM) == EP_ATTR_ISO) csRegValue |= USBCSOH_ISO; // ISO flag if (pUsbDblbufLutInfo->outMask & (1 << endpoint)) csRegValue |= USBCSOH_OUT_DBL_BUF; // Double buffering USBCSOH = csRegValue; // Max transfer size USBMAXO = maxpRegValue; // Endpoint status usbfwData.pEpOutStatus[endpoint - 1] = EP_IDLE; } USBFW_SELECT_ENDPOINT(0); } }
/** \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 __code* usbdpGetDeviceDesc(void) { usbdpInit(); return usbdpFindNext(DESC_TYPE_DEVICE, 0); } // usbdpGetDeviceDesc
/** \brief Internally used function that configures all endpoints for the specified interface * * The new endpoint setup overwrites the old. Unused endpoints keep their current setup. The user is * responsible for ensuring that no endpoint buffers overwrite each other, and that interfaces do not * cause conflicts. The \ref pUsbInterfaceEpDblbufLut[] lookup table must contain an entry for each * interface descriptor to define endpoint double-buffering. * * \param[in] *pInterface * A pointer to the interface descriptor */ static void usbsrConfigureEndpoints(const USB_INTERFACE_DESCRIPTOR* pInterface) { const USB_ENDPOINT_DESCRIPTOR* pEndpoint; const USB_INTERFACE_EP_DBLBUF_LUT* pUsbInterfaceEpDblbufInfo; // // Locate the double-buffer settings // if(pInterface->bNumEndpoints) { pUsbInterfaceEpDblbufInfo = (const USB_INTERFACE_EP_DBLBUF_LUT*) pUsbInterfaceEpDblbufLut; while(pUsbInterfaceEpDblbufInfo->pInterface != pInterface) { pUsbInterfaceEpDblbufInfo++; } } // // For each endpoint in this interface // for(uint8_t n = 0; n < pInterface->bNumEndpoints; n++) { if(pEndpoint = usbdpFindNext(USB_DESC_TYPE_ENDPOINT, 0)) { // // Get the endpoint index // uint32_t endpoint = pEndpoint->bEndpointAddress & 0x0F; USBFW_SELECT_ENDPOINT(endpoint); uint32_t csRegValue = 0x00; uint32_t maxpRegValue = (pEndpoint->wMaxPacketSize + 7) >> 3; // // For IN endpoints... // if(pEndpoint->bEndpointAddress & 0x80) { // // Clear data toggle, and flush twice (due to double buffering) // HWREG(USB_CS0_CSIL) = USB_CSIL_CLRDATATOG_M | USB_CSIL_FLUSHPACKET_M; HWREG(USB_CS0_CSIL) = USB_CSIL_FLUSHPACKET_M; // // USBCSIH // if((pEndpoint->bmAttributes & USB_EP_ATTR_TYPE_BM) == USB_EP_ATTR_ISO) { // // ISO flag // csRegValue |= USB_CSIH_ISO_M; } if(pUsbInterfaceEpDblbufInfo->inMask & (1 << endpoint)) { // // Double buffering // csRegValue |= USB_CSIH_INDBLBUF_M; } HWREG(USB_CSIH) = csRegValue; // // Max transfer size // HWREG(USB_MAXI) = maxpRegValue; // // Endpoint status // usbfwData.pEpInStatus[endpoint - 1] = EP_IDLE; // // For OUT endpoints... // } else { // // Clear data toggle, and flush twice (due to double buffering) // HWREG(USB_CSOL) = USB_CSOL_CLRDATATOG_M | USB_CSOL_FLUSHPACKET_M; HWREG(USB_CSOL) = USB_CSOL_FLUSHPACKET_M; // // USBCSOH // if((pEndpoint->bmAttributes & USB_EP_ATTR_TYPE_BM) == USB_EP_ATTR_ISO) { // // ISO flag // csRegValue |= USB_CSOH_ISO_M; } if(pUsbInterfaceEpDblbufInfo->outMask & (1 << endpoint)) { // // Double buffering // csRegValue |= USB_CSOH_OUTDBLBUF_M; } HWREG(USB_CSOH) = csRegValue; // // Max transfer size // HWREG(USB_MAXO) = maxpRegValue; // // Endpoint status // usbfwData.pEpOutStatus[endpoint - 1] = EP_IDLE; } USBFW_SELECT_ENDPOINT(0); } }