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