| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- //*****************************************************************************
- //
- // usbcdesc.c - Config descriptor parsing functions.
- //
- // Copyright (c) 2007-2010 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Texas Instruments (TI) is supplying this software for use solely and
- // exclusively on TI's microcontroller products. The software is owned by
- // TI and/or its suppliers, and is protected under applicable copyright
- // laws. You may not combine this software with "viral" open-source
- // software in order to form a larger program.
- //
- // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
- // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
- // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
- // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
- // DAMAGES, FOR ANY REASON WHATSOEVER.
- //
- // This is part of AM1808 StarterWare USB Library and reused from revision 6288
- // of the Stellaris USB Library.
- //
- //*****************************************************************************
- #include "hw_types.h"
- #include "debug.h"
- #include "usb.h"
- #include "usblib.h"
- #include "usbdevice.h"
- //*****************************************************************************
- //
- // The functions in this file mirror the descriptor parsing APIs available
- // in usblib.h but parse config descriptors defined in terms of a list of
- // sections rather than as a single block of descriptor data.
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- //! \addtogroup device_api
- //! @{
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- //! \internal
- //!
- //! Walk to the next descriptor after the supplied one within a section-based
- //! config descriptor.
- //!
- //! \param psConfig points to the header structure for the configuration
- //! descriptor which contains \e psDesc.
- //! \param pulSec points to a variable containing the section within \e
- //! psConfig which contains \e psDesc.
- //! \param psDesc points to the descriptor that we want to step past.
- //!
- //! This function walks forward one descriptor within a config descriptor. The
- //! value returned is a pointer to the header of the next descriptor after the
- //! descriptor supplied in \e psDesc. If the next descriptor is in the next
- //! section, \e *pulSec will be incremented accordlingly.
- //!
- //! \return Returns a pointer to the next descriptor in the config descrptor.
- //
- //*****************************************************************************
- static tDescriptorHeader *
- NextConfigDescGet(const tConfigHeader *psConfig, unsigned int *pulSec,
- tDescriptorHeader *psDesc)
- {
- //
- // Determine where the next descriptor after the supplied one should be
- // assuming it is within the current section.
- //
- psDesc = NEXT_USB_DESCRIPTOR(psDesc);
- //
- // Did we run off the end of the section?
- //
- if((unsigned char *)psDesc >= (psConfig->psSections[*pulSec]->pucData +
- psConfig->psSections[*pulSec]->ucSize))
- {
- //
- // Yes - move to the next section.
- //
- (*pulSec)++;
- //
- // Are we still within the config descriptor?
- //
- if(*pulSec < psConfig->ucNumSections)
- {
- //
- // Yes - the new descriptor is at the start of the new section.
- //
- psDesc =
- (tDescriptorHeader *)psConfig->psSections[*pulSec]->pucData;
- }
- else
- {
- //
- // No - we ran off the end of the descriptor so return NULL.
- //
- psDesc = (tDescriptorHeader *)0;
- }
- }
- //
- // Return the new descriptor pointer.
- //
- return(psDesc);
- }
- //*****************************************************************************
- //
- //! \internal
- //!
- //! Returns a pointer to the n-th interface descriptor in a config descriptor
- //! with the supplied interface number.
- //!
- //! \param psConfig points to the header structure for the config descriptor
- //! that is to be searched.
- //! \param ucInterfaceNumber is the interface number of the descriptor that is
- //! being queried.
- //! \param ulIndex is the zero based index of the descriptor to return.
- //! \param pulSection points to storage which will be written with the index
- //! of the section containing the returned descriptor.
- //!
- //! This function returns a pointer to the n-th interface descriptor in the
- //! supplied configuration which has the requested interface number. It may be
- //! used by a client to retrieve the descriptors for each alternate setting
- //! of a given interface within the configuration passed.
- //!
- //! \return Returns a pointer to the n-th interface descriptor with interface
- //! number as specified or NULL of this descriptor does not exist.
- //
- //*****************************************************************************
- static tInterfaceDescriptor *
- ConfigAlternateInterfaceGet(const tConfigHeader *psConfig,
- unsigned char ucInterfaceNumber,
- unsigned int ulIndex,
- unsigned int *pulSection)
- {
- tDescriptorHeader *psDescCheck;
- unsigned int ulCount;
- unsigned int ulSec;
- //
- // Set up for our descriptor counting loop.
- //
- psDescCheck = (tDescriptorHeader *)psConfig->psSections[0]->pucData;
- ulCount = 0;
- ulSec = 0;
- //
- // Keep looking through the supplied data until we reach the end.
- //
- while(psDescCheck)
- {
- //
- // Does this descriptor match the type passed (if a specific type
- // has been specified)?
- //
- if((psDescCheck->bDescriptorType == USB_DTYPE_INTERFACE) &&
- (((tInterfaceDescriptor *)psDescCheck)->bInterfaceNumber ==
- ucInterfaceNumber))
- {
- //
- // This is an interface descriptor for interface ucInterfaceNumber.
- // Determine if this is the n-th one we have found and, if so,
- // return its pointer.
- //
- if(ulCount == ulIndex)
- {
- //
- // Found it - return the pointer and section number.
- //
- *pulSection = ulSec;
- return((tInterfaceDescriptor *)psDescCheck);
- }
- //
- // Increment our count of matching descriptors found and go back
- // to look for another since we have not yet reached the n-th
- // match.
- //
- ulCount++;
- }
- //
- // Move on to the next descriptor.
- //
- psDescCheck = NextConfigDescGet(psConfig, &ulSec, psDescCheck);
- }
- //
- // If we drop out the end of the loop, we did not find the requested
- // descriptor so return NULL.
- //
- return((tInterfaceDescriptor *)0);
- }
- //*****************************************************************************
- //
- //! \internal
- //!
- //! Determines the total length of a config descriptor defined in terms of a
- //! collection of concatenated sections.
- //!
- //! \param psConfig points to the header structure for the configuration
- //! descriptor whose size is to be determined.
- //!
- //! \return Returns the number of bytes in the config descriptor will result
- //! from concatenating the required sections.
- //
- //*****************************************************************************
- unsigned int
- USBDCDConfigDescGetSize(const tConfigHeader *psConfig)
- {
- unsigned int ulLoop;
- unsigned int ulLen;
- ulLen = 0;
- //
- // Determine the size of the whole descriptor by adding the sizes of
- // each section which will be concatenated to produce it.
- //
- for(ulLoop = 0; ulLoop < psConfig->ucNumSections; ulLoop++)
- {
- ulLen += psConfig->psSections[ulLoop]->ucSize;
- }
- return(ulLen);
- }
- //*****************************************************************************
- //
- //! \internal
- //!
- //! Determines the number of individual descriptors of a particular type within
- //! a 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 counted. If
- //! the value is \b USB_DESC_ANY, the function returns the total number of
- //! descriptors regardless of type.
- //!
- //! This function can be used to count the number of descriptors of a
- //! particular type within a configuration descriptor. The caller can provide
- //! a specific type value which the function matches against the second byte
- //! of each descriptor or, alternatively, can specify \b USB_DESC_ANY to have
- //! the function count all descriptors regardless of their type.
- //!
- //! The search performed by this function traverses through the list of
- //! sections comprising the configuration descriptor. Note that the similar
- //! top-level function, USBDescGetNum(), searches through a single, contiguous
- //! block of data to perform the same enumeration.
- //!
- //! \return Returns the number of descriptors found in the supplied block of
- //! data.
- //
- //*****************************************************************************
- unsigned int
- USBDCDConfigDescGetNum(const tConfigHeader *psConfig, unsigned int ulType)
- {
- unsigned int ulSection;
- unsigned int ulNumDescs;
- //
- // Initialize our counts.
- //
- ulNumDescs = 0;
- //
- // Determine the number of descriptors of the given type in each of the
- // sections comprising the config descriptor. Note that this assumes each
- // section contains only whole descriptors!
- //
- for(ulSection = 0; ulSection < (unsigned int)psConfig->ucNumSections;
- ulSection++)
- {
- ulNumDescs += USBDescGetNum(
- (tDescriptorHeader *)psConfig->psSections[ulSection]->pucData,
- (unsigned int)psConfig->psSections[ulSection]->ucSize,
- ulType);
- }
- return(ulNumDescs);
- }
- //*****************************************************************************
- //
- //! \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 int ulType,
- unsigned int ulIndex, unsigned int *pulSection)
- {
- unsigned int ulSection;
- unsigned int ulTotalDescs;
- unsigned int 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 int)psConfig->ucNumSections;
- ulSection++)
- {
- //
- // How many descriptors of the requested type exist in this section?
- //
- ulNumDescs = USBDescGetNum(
- (tDescriptorHeader *)psConfig->psSections[ulSection]->pucData,
- (unsigned int)psConfig->psSections[ulSection]->ucSize,
- 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,
- (unsigned int)psConfig->psSections[ulSection]->ucSize,
- 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);
- }
- //*****************************************************************************
- //
- //! \internal
- //!
- //! Determines the number of different alternate configurations for a given
- //! interface within a config descriptor.
- //!
- //! \param psConfig points to the header structure for the configuration
- //! descriptor that is to be searched.
- //! \param ucInterfaceNumber is the interface number for which the number of
- //! alternate configurations is to be counted.
- //!
- //! This function can be used to count the number of alternate settings for a
- //! specific interface within a configuration.
- //!
- //! The search performed by this function traverses through the list of
- //! sections comprising the configuration descriptor. Note that the similar
- //! top-level function, USBDescGetNumAlternateInterfaces(), searches through
- //! a single, contiguous block of data to perform the same enumeration.
- //!
- //! \return Returns the number of alternate versions of the specified interface
- //! or 0 if the interface number supplied cannot be found in the config
- //! descriptor.
- //
- //*****************************************************************************
- unsigned int
- USBDCDConfigGetNumAlternateInterfaces(const tConfigHeader *psConfig,
- unsigned char ucInterfaceNumber)
- {
- tDescriptorHeader *psDescCheck;
- unsigned int ulCount;
- unsigned int ulSec;
- //
- // Set up for our descriptor counting loop.
- //
- psDescCheck = (tDescriptorHeader *)psConfig->psSections[0]->pucData;
- ulSec = 0;
- ulCount = 0;
- //
- // Keep looking through the supplied data until we reach the end.
- //
- while(psDescCheck)
- {
- //
- // Is this an interface descriptor with the required interface number?
- //
- if((psDescCheck->bDescriptorType == USB_DTYPE_INTERFACE) &&
- (((tInterfaceDescriptor *)psDescCheck)->bInterfaceNumber ==
- ucInterfaceNumber))
- {
- //
- // Yes - increment our count.
- //
- ulCount++;
- }
- //
- // Move on to the next descriptor.
- //
- psDescCheck = NextConfigDescGet(psConfig, &ulSec, psDescCheck);
- }
- //
- // Return the descriptor count to the caller.
- //
- return(ulCount);
- }
- //*****************************************************************************
- //
- //! \internal
- //!
- //! 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 header structure for the configuration
- //! descriptor that is to be searched.
- //! \param ulIndex is the zero based index of the interface that is to be
- //! found. If \e 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.
- //! \param pulSection points to storage which will receive the index of the
- //! config descriptor section which contains the requested interface
- //! descriptor.
- //!
- //! 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 \e
- //! ulAlt if \e ulIndex is set to the required interface number and \e ulAlt
- //! is set to a valid alternate setting number for that interface.
- //!
- //! The search performed by this function traverses through the list of
- //! sections comprising the configuration descriptor. Note that the similar
- //! top-level function, USBDescGetInterface(), searches through a single,
- //! contiguous block of data to perform the same enumeration.
- //!
- //! \return Returns a pointer to the required interface descriptor if
- //! found or NULL otherwise.
- //
- //*****************************************************************************
- tInterfaceDescriptor *
- USBDCDConfigGetInterface(const tConfigHeader *psConfig, unsigned int ulIndex,
- unsigned int ulAlt, unsigned int *pulSection)
- {
- //
- // 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 *)USBDCDConfigDescGet(psConfig,
- USB_DTYPE_INTERFACE,
- ulIndex,
- pulSection));
- }
- 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(ConfigAlternateInterfaceGet(psConfig, ulIndex, ulAlt,
- pulSection));
- }
- }
- //*****************************************************************************
- //
- //! \internal
- //!
- //! Return a pointer to the n-th endpoint descriptor in a particular interface
- //! within a configuration descriptor.
- //!
- //! \param psConfig points to the header structure for the configuration
- //! descriptor that is to be searched.
- //! \param ulInterfaceNumber is the interface number whose endpoint is to be
- //! found.
- //! \param ulAltCfg is the alternate setting number which is to be searched
- //! for. This must be a valid alternate setting number for the requested
- //! interface.
- //! \param ulIndex is the zero based index of the endpoint that is to be
- //! found within the appropriate alternate setting for the interface.
- //!
- //! 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.
- //!
- //! The search performed by this function traverses through the list of
- //! sections comprising the configuration descriptor. Note that the similar
- //! top-level function, USBDescGetInterfaceEndpoint(), searches through a
- //! single, contiguous block of data to perform the same enumeration.
- //!
- //! \return Returns a pointer to the requested endpoint descriptor if
- //! found or NULL otherwise.
- //
- //*****************************************************************************
- tEndpointDescriptor *
- USBDCDConfigGetInterfaceEndpoint(const tConfigHeader *psConfig,
- unsigned int ulInterfaceNumber,
- unsigned int ulAltCfg, unsigned int ulIndex)
- {
- tInterfaceDescriptor *psInterface;
- tDescriptorHeader *psEndpoint;
- unsigned int ulSection;
- unsigned int ulCount;
- //
- // Find the requested interface descriptor.
- //
- psInterface = USBDCDConfigGetInterface(psConfig, ulInterfaceNumber,
- ulAltCfg, &ulSection);
- //
- // Did we find the requested interface?
- //
- if(psInterface)
- {
- //
- // 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. We start from
- // the interface descriptor and look for following endpoint
- // descriptors.
- //
- ulCount = 0;
- psEndpoint = (tDescriptorHeader *)psInterface;
- while(psEndpoint)
- {
- if(psEndpoint->bDescriptorType == USB_DTYPE_ENDPOINT)
- {
- //
- // We found an endpoint descriptor. Have we reached the
- // one we want?
- //
- if(ulCount == ulIndex)
- {
- //
- // Yes - return the descriptor pointer to the caller.
- //
- return((tEndpointDescriptor *)psEndpoint);
- }
- //
- // Move on to look for the next endpoint.
- //
- ulCount++;
- }
- //
- // Move to the next descriptor.
- //
- psEndpoint = NextConfigDescGet(psConfig, &ulSection,
- psEndpoint);
- }
- }
- }
- //
- // We couldn't find the requested interface or we got to the end of the
- // descriptor without finding the requested endpoint.
- //
- return((tEndpointDescriptor *)0);
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|