/* ---------------------------------------------------------------------------- | |
* ATMEL Microcontroller Software Support | |
* ---------------------------------------------------------------------------- | |
* Copyright (c) 2010, Atmel Corporation | |
* | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* - Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the disclaimer below. | |
* | |
* Atmel's name may not be used to endorse or promote products derived from | |
* this software without specific prior written permission. | |
* | |
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR | |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, | |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* ---------------------------------------------------------------------------- | |
*/ | |
/** \file | |
* | |
* Implements for USB descriptor methods described by the USB specification. | |
*/ | |
/** \addtogroup usb_descriptor | |
*@{ | |
*/ | |
/*------------------------------------------------------------------------------ | |
* Headers | |
*------------------------------------------------------------------------------*/ | |
#include "USBDescriptors.h" | |
/*------------------------------------------------------------------------------ | |
* Exported functions | |
*------------------------------------------------------------------------------*/ | |
/** | |
* Returns the length of a descriptor. | |
* \param descriptor Pointer to a USBGenericDescriptor instance. | |
* \return Length of descriptor in bytes. | |
*/ | |
uint32_t USBGenericDescriptor_GetLength( | |
const USBGenericDescriptor *descriptor) | |
{ | |
return descriptor->bLength; | |
} | |
/** | |
* Returns the type of a descriptor. | |
* \param descriptor Pointer to a USBGenericDescriptor instance. | |
* \return Type of descriptor. | |
*/ | |
uint8_t USBGenericDescriptor_GetType( | |
const USBGenericDescriptor *descriptor) | |
{ | |
return descriptor->bDescriptorType; | |
} | |
/** | |
* Returns a pointer to the descriptor right after the given one, when | |
* parsing a Configuration descriptor. | |
* \param descriptor - Pointer to a USBGenericDescriptor instance. | |
* \return Pointer to the next descriptor. | |
*/ | |
USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor( | |
const USBGenericDescriptor *descriptor) | |
{ | |
return (USBGenericDescriptor *) | |
(((char *) descriptor) + USBGenericDescriptor_GetLength(descriptor)); | |
} | |
/** Parses the given descriptor list via costomized function. | |
* \param descriptor Pointer to the start of the whole descriptors list. | |
* \param totalLength Total size of descriptors in bytes. | |
* \param parseFunction Function to parse each descriptor scanned. | |
* Return 0 to continue parsing. | |
* \param parseArg Argument passed to parse function. | |
* \return Pointer to USBGenericDescriptor instance for next descriptor. | |
*/ | |
USBGenericDescriptor *USBGenericDescriptor_Parse( | |
const USBGenericDescriptor *descriptor, | |
uint32_t totalLength, | |
USBDescriptorParseFunction parseFunction, | |
void *parseArg) | |
{ | |
int32_t size = totalLength; | |
if (size == 0) | |
return 0; | |
/* Start parsing descriptors */ | |
while (1) { | |
uint32_t parseRC = 0; | |
/* Parse current descriptor */ | |
if (parseFunction) { | |
parseRC = parseFunction((void*)descriptor, parseArg); | |
} | |
/* Get next descriptor */ | |
size -= USBGenericDescriptor_GetLength(descriptor); | |
descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor); | |
if (size) { | |
if (parseRC != 0) { | |
return (USBGenericDescriptor *)descriptor; | |
} | |
} | |
else | |
break; | |
} | |
/* No descriptors remaining */ | |
return 0; | |
} | |
/** | |
* Returns the number of an endpoint given its descriptor. | |
* \param endpoint Pointer to a USBEndpointDescriptor instance. | |
* \return Endpoint number. | |
*/ | |
uint8_t USBEndpointDescriptor_GetNumber( | |
const USBEndpointDescriptor *endpoint) | |
{ | |
return endpoint->bEndpointAddress & 0xF; | |
} | |
/** | |
* Returns the direction of an endpoint given its descriptor. | |
* \param endpoint Pointer to a USBEndpointDescriptor instance. | |
* \return Endpoint direction (see \ref usb_ep_dir). | |
*/ | |
uint8_t USBEndpointDescriptor_GetDirection( | |
const USBEndpointDescriptor *endpoint) | |
{ | |
if ((endpoint->bEndpointAddress & 0x80) != 0) { | |
return USBEndpointDescriptor_IN; | |
} | |
else { | |
return USBEndpointDescriptor_OUT; | |
} | |
} | |
/** | |
* Returns the type of an endpoint given its descriptor. | |
* \param endpoint Pointer to a USBEndpointDescriptor instance. | |
* \return Endpoint type (see \ref usb_ep_type). | |
*/ | |
uint8_t USBEndpointDescriptor_GetType( | |
const USBEndpointDescriptor *endpoint) | |
{ | |
return endpoint->bmAttributes & 0x3; | |
} | |
/** | |
* Returns the maximum size of a packet (in bytes) on an endpoint given | |
* its descriptor. | |
* \param endpoint - Pointer to a USBEndpointDescriptor instance. | |
* \return Maximum packet size of endpoint. | |
*/ | |
uint16_t USBEndpointDescriptor_GetMaxPacketSize( | |
const USBEndpointDescriptor *endpoint) | |
{ | |
uint16_t usTemp; | |
uint8_t *pc1, *pc2; | |
/* Note this is an unaligned access hence it is performed as two byte | |
accesses. */ | |
pc1 = ( uint8_t * ) &( endpoint->wMaxPacketSize ); | |
pc2 = pc1 + 1; | |
usTemp = ( ( *pc2 ) << 8 ) | *pc1; | |
return usTemp; | |
} | |
/** | |
* Returns the polling interval on an endpoint given its descriptor. | |
* \param endpoint - Pointer to a USBEndpointDescriptor instance. | |
* \return Polling interval of endpoint. | |
*/ | |
uint8_t USBEndpointDescriptor_GetInterval( | |
const USBEndpointDescriptor *endpoint) | |
{ | |
return endpoint->bInterval; | |
} | |
/** Returns the total length of a configuration, i.e. including the | |
* descriptors following it. | |
* \param configuration Pointer to a USBConfigurationDescriptor instance. | |
* \return Total length (in bytes) of the configuration. | |
*/ | |
uint32_t USBConfigurationDescriptor_GetTotalLength( | |
const USBConfigurationDescriptor *configuration) | |
{ | |
return configuration->wTotalLength; | |
} | |
/** Returns the number of interfaces in a configuration. | |
* \param configuration Pointer to a USBConfigurationDescriptor instance. | |
* \return Number of interfaces in configuration. | |
*/ | |
unsigned char USBConfigurationDescriptor_GetNumInterfaces( | |
const USBConfigurationDescriptor *configuration) | |
{ | |
return configuration->bNumInterfaces; | |
} | |
/** Indicates if the device is self-powered when in a given configuration. | |
* \param configuration Pointer to a USBConfigurationDescriptor instance. | |
* \return 1 if the device is self-powered when in the given configuration; | |
* otherwise 0. | |
*/ | |
unsigned char USBConfigurationDescriptor_IsSelfPowered( | |
const USBConfigurationDescriptor *configuration) | |
{ | |
if ((configuration->bmAttributes & (1 << 6)) != 0) { | |
return 1; | |
} | |
else { | |
return 0; | |
} | |
} | |
/** Parses the given Configuration descriptor (followed by relevant | |
* interface, endpoint and class-specific descriptors) into three arrays. | |
* *Each array must have its size equal or greater to the number of | |
* descriptors it stores plus one*. A null-value is inserted after the last | |
* descriptor of each type to indicate the array end. | |
* | |
* Note that if the pointer to an array is null (0), nothing is stored in | |
* it. | |
* \param configuration Pointer to the start of the whole Configuration | |
* descriptor. | |
* \param interfaces Pointer to the Interface descriptor array. | |
* \param endpoints Pointer to the Endpoint descriptor array. | |
* \param others Pointer to the class-specific descriptor array. | |
*/ | |
void USBConfigurationDescriptor_Parse( | |
const USBConfigurationDescriptor *configuration, | |
USBInterfaceDescriptor **interfaces, | |
USBEndpointDescriptor **endpoints, | |
USBGenericDescriptor **others) | |
{ | |
/* Get size of configuration to parse */ | |
int size = USBConfigurationDescriptor_GetTotalLength(configuration); | |
size -= sizeof(USBConfigurationDescriptor); | |
/* Start parsing descriptors */ | |
USBGenericDescriptor *descriptor = (USBGenericDescriptor *) configuration; | |
while (size > 0) { | |
/* Get next descriptor */ | |
descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor); | |
size -= USBGenericDescriptor_GetLength(descriptor); | |
/* Store descriptor in correponding array */ | |
if (USBGenericDescriptor_GetType(descriptor) | |
== USBGenericDescriptor_INTERFACE) { | |
if (interfaces) { | |
*interfaces = (USBInterfaceDescriptor *) descriptor; | |
interfaces++; | |
} | |
} | |
else if (USBGenericDescriptor_GetType(descriptor) | |
== USBGenericDescriptor_ENDPOINT) { | |
if (endpoints) { | |
*endpoints = (USBEndpointDescriptor *) descriptor; | |
endpoints++; | |
} | |
} | |
else if (others) { | |
*others = descriptor; | |
others++; | |
} | |
} | |
/* Null-terminate arrays */ | |
if (interfaces) { | |
*interfaces = 0; | |
} | |
if (endpoints) { | |
*endpoints = 0; | |
} | |
if (others) { | |
*others = 0; | |
} | |
} | |
/**@}*/ | |