//***************************************************************************** // //! Returns a pointer to the n-th interface descriptor in a configuration //! descriptor that applies to the supplied alternate setting number. //! //! \param psConfig points to the first byte of a standard USB configuration //! descriptor. //! \param ulIndex is the zero based index of the interface that is to be //! found. If ulAlt is set to a value other than \b USB_DESC_ANY, this will be //! equivalent to the interface number being searched for. //! \param ulAlt is the alternate setting number which is to be //! searched for. If this value is \b USB_DESC_ANY, the alternate setting //! is ignored and all interface descriptors are considered in the search. //! //! Return a pointer to the n-th interface descriptor found in the supplied //! configuration descriptor. If \e ulAlt is not \b USB_DESC_ANY, only //! interface descriptors which are part of the supplied alternate setting are //! considered in the search otherwise all interface descriptors are //! considered. //! //! Note that, although alternate settings can be applied on an interface-by- //! interface basis, the number of interfaces offered is fixed for a given //! config descriptor. Hence, this function will correctly find the unique //! interface descriptor for that interface's alternate setting number ulAlt //! if ulIndex is set to the required interface number and ulAlt is set to a //! valid alternate setting number for that interface. //! //! \return Returns a pointer to the required interface descriptor if //! found or NULL otherwise. // //***************************************************************************** tInterfaceDescriptor * USBDescGetInterface(tConfigDescriptor *psConfig, unsigned long ulIndex, unsigned long ulAlt) { // // If we are being told to ignore the alternate configuration, this boils // down to a very simple query. // if(ulAlt == USB_DESC_ANY) { // // Return the ulIndex-th interface descriptor we find in the // configuration descriptor. // return((tInterfaceDescriptor *)USBDescGet( (tDescriptorHeader *)psConfig, (unsigned long)psConfig->wTotalLength, USB_DTYPE_INTERFACE, ulIndex)); } else { // // In this case, a specific alternate setting number is required. // Given that interface numbers are zero based indices, we can // pass the supplied ulIndex parameter directly as the interface // number to USBDescGetAlternateInterface to retrieve the requested // interface descriptor pointer. // return(USBDescGetAlternateInterface(psConfig, ulIndex, ulAlt)); } }
//***************************************************************************** // //! Return a pointer to the n-th endpoint descriptor in the supplied //! interface descriptor. //! //! \param psInterface points to the first byte of a standard USB interface //! descriptor. //! \param ulIndex is the zero based index of the endpoint that is to be //! found. //! \param ulSize contains the maximum number of bytes that the function may //! search beyond \e psInterface while looking for the requested endpoint //! descriptor. //! //! Return a pointer to the n-th endpoint descriptor found in the supplied //! interface descriptor. If the \e ulIndex parameter is invalid (greater //! than or equal to the bNumEndpoints field of the interface descriptor) or //! the endpoint cannot be found within \e ulSize bytes of the interface //! descriptor pointer, the function will return NULL. //! //! Note that, although the USB 2.0 specification states that endpoint //! descriptors must follow the interface descriptor that they relate to, it //! also states that device specific descriptors should follow any standard //! descriptor that they relate to. As a result, we cannot assume that each //! interface descriptor will be followed by nothing but an ordered list of //! its own endpoints and, hence, the function needs to be provided ulSize to //! limit the search range. //! //! \return Returns a pointer to the requested endpoint descriptor if //! found or NULL otherwise. // //***************************************************************************** tEndpointDescriptor * USBDescGetInterfaceEndpoint(tInterfaceDescriptor *psInterface, unsigned long ulIndex, unsigned long ulSize) { // // Is the index passed valid? // if(ulIndex >= psInterface->bNumEndpoints) { // // It's out of bounds so return a NULL. // return((tEndpointDescriptor *)0); } else { // // Endpoint index is valid so find the descriptor. // return((tEndpointDescriptor *)USBDescGet( (tDescriptorHeader *)psInterface, ulSize, USB_DTYPE_ENDPOINT, ulIndex)); } }
//***************************************************************************** // //! \internal //! //! Finds the n-th descriptor of a particular type within the supplied //! configuration descriptor. //! //! \param psConfig points to the header structure for the configuration //! descriptor that is to be searched. //! \param ulType identifies the type of descriptor that is to be found. If //! the value is \b USB_DESC_ANY, the function returns a pointer to the n-th //! descriptor regardless of type. //! \param ulIndex is the zero based index of the descriptor whose pointer is //! to be returned. For example, passing value 1 in \e ulIndex returns the //! second matching descriptor. //! \param pulSection points to storage which will receive the section index //! containing the requested descriptor. //! //! Return a pointer to the n-th descriptor of a particular type found in the //! configuration descriptor passed. //! //! The search performed by this function traverses through the list of //! sections comprising the configuration descriptor. Note that the similar //! top-level function, USBDescGet(), searches through a single, contiguous //! block of data to perform the same enumeration. //! //! \return Returns a pointer to the header of the required descriptor if //! found or NULL otherwise. // //***************************************************************************** tDescriptorHeader * USBDCDConfigDescGet(const tConfigHeader *psConfig, unsigned long ulType, unsigned long ulIndex, unsigned long *pulSection) { unsigned long ulSection; unsigned long ulTotalDescs; unsigned long ulNumDescs; // // Initialize our counts. // ulTotalDescs = 0; // // Determine the number of descriptors of the given type in each of the // sections comprising the config descriptor. This allows us to determine // which section contains the descriptor we are being asked for. // for(ulSection = 0; ulSection < (unsigned long)psConfig->ucNumSections; ulSection++) { // // How many descriptors of the requested type exist in this section? // ulNumDescs = USBDescGetNum( (tDescriptorHeader *)psConfig->psSections[ulSection]->pucData, psConfig->psSections[ulSection]->usSize, ulType); // // Does this section contain the descriptor whose index we are looking // for? // if((ulTotalDescs + ulNumDescs) > ulIndex) { // // We know the requested descriptor exists in the current // block so write the section number to the caller's storage. // *pulSection = ulSection; // // Now find the actual descriptor requested and return its pointer. // return(USBDescGet( (tDescriptorHeader *)psConfig->psSections[ulSection]->pucData, psConfig->psSections[ulSection]->usSize, ulType, ulIndex - ulTotalDescs)); } // // We have not found the required descriptor yet. Update our running // count of the number of type matches found so far then move on to // the next section. // ulTotalDescs += ulNumDescs; } // // If we drop out of the loop, we can't find the requested descriptor // so return NULL. // return((tDescriptorHeader *)0); }