]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A5_SAMA5D3x_Xplained_IAR/AtmelFiles/usb/common/core/USBDescriptors.c
80cd4e0c0bc7313dc6d843a7c13145726efb70c1
[freertos] / FreeRTOS / Demo / CORTEX_A5_SAMA5D3x_Xplained_IAR / AtmelFiles / usb / common / core / USBDescriptors.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2010, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /** \file\r
31  *\r
32  *    Implements for USB descriptor methods described by the USB specification.\r
33  */\r
34 \r
35 /** \addtogroup usb_descriptor\r
36  *@{\r
37  */\r
38 \r
39 /*------------------------------------------------------------------------------\r
40  *         Headers\r
41  *------------------------------------------------------------------------------*/\r
42 \r
43 #include "USBDescriptors.h"\r
44 \r
45 /*------------------------------------------------------------------------------\r
46  *         Exported functions\r
47  *------------------------------------------------------------------------------*/\r
48 \r
49 /**\r
50  * Returns the length of a descriptor.\r
51  * \param descriptor Pointer to a USBGenericDescriptor instance.\r
52  * \return Length of descriptor in bytes.\r
53  */\r
54 uint32_t USBGenericDescriptor_GetLength(\r
55     const USBGenericDescriptor *descriptor)\r
56 {\r
57     return descriptor->bLength;\r
58 }\r
59 \r
60 /**\r
61  * Returns the type of a descriptor.\r
62  * \param descriptor Pointer to a USBGenericDescriptor instance.\r
63  * \return Type of descriptor.\r
64  */\r
65 uint8_t USBGenericDescriptor_GetType(\r
66     const USBGenericDescriptor *descriptor)\r
67 {\r
68     return descriptor->bDescriptorType;\r
69 }\r
70 \r
71 /**\r
72  * Returns a pointer to the descriptor right after the given one, when\r
73  * parsing a Configuration descriptor.\r
74  * \param descriptor - Pointer to a USBGenericDescriptor instance.\r
75  * \return Pointer to the next descriptor.\r
76  */\r
77 USBGenericDescriptor *USBGenericDescriptor_GetNextDescriptor(\r
78     const USBGenericDescriptor *descriptor)\r
79 {\r
80     return (USBGenericDescriptor *)\r
81         (((char *) descriptor) + USBGenericDescriptor_GetLength(descriptor));\r
82 }\r
83 \r
84 /** Parses the given descriptor list via costomized function.\r
85  *  \param descriptor    Pointer to the start of the whole descriptors list.\r
86  *  \param totalLength   Total size of descriptors in bytes.\r
87  *  \param parseFunction Function to parse each descriptor scanned.\r
88  *                       Return 0 to continue parsing.\r
89  *  \param parseArg      Argument passed to parse function.\r
90  *  \return Pointer to USBGenericDescriptor instance for next descriptor.\r
91  */\r
92 USBGenericDescriptor *USBGenericDescriptor_Parse(\r
93     const USBGenericDescriptor *descriptor,\r
94     uint32_t totalLength,\r
95     USBDescriptorParseFunction parseFunction,\r
96     void *parseArg)\r
97 {\r
98     int32_t size = totalLength;\r
99 \r
100     if (size == 0)\r
101         return 0;\r
102 \r
103     /* Start parsing descriptors */\r
104     while (1) {\r
105 \r
106         uint32_t parseRC = 0;\r
107 \r
108         /* Parse current descriptor */\r
109         if (parseFunction) {\r
110 \r
111             parseRC = parseFunction((void*)descriptor, parseArg);\r
112         }\r
113 \r
114         /* Get next descriptor */\r
115         size -= USBGenericDescriptor_GetLength(descriptor);\r
116         descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor);\r
117 \r
118         if (size) {\r
119             if (parseRC != 0) {\r
120 \r
121                 return (USBGenericDescriptor *)descriptor;\r
122             }\r
123         }\r
124         else\r
125             break;\r
126     }\r
127     /* No descriptors remaining */\r
128     return 0;\r
129 }\r
130 \r
131 \r
132 /**\r
133  *  Returns the number of an endpoint given its descriptor.\r
134  *  \param endpoint Pointer to a USBEndpointDescriptor instance.\r
135  *  \return Endpoint number.\r
136  */\r
137 uint8_t USBEndpointDescriptor_GetNumber(\r
138     const USBEndpointDescriptor *endpoint)\r
139 {\r
140     return endpoint->bEndpointAddress & 0xF;\r
141 }\r
142 \r
143 /**\r
144  *  Returns the direction of an endpoint given its descriptor.\r
145  *  \param endpoint Pointer to a USBEndpointDescriptor instance.\r
146  *  \return Endpoint direction (see \ref usb_ep_dir).\r
147  */\r
148 uint8_t USBEndpointDescriptor_GetDirection(\r
149     const USBEndpointDescriptor *endpoint)\r
150 {\r
151     if ((endpoint->bEndpointAddress & 0x80) != 0) {\r
152 \r
153         return USBEndpointDescriptor_IN;\r
154     }\r
155     else {\r
156 \r
157         return USBEndpointDescriptor_OUT;\r
158     }\r
159 }\r
160 \r
161 /**\r
162  *  Returns the type of an endpoint given its descriptor.\r
163  *  \param endpoint Pointer to a USBEndpointDescriptor instance.\r
164  *  \return Endpoint type (see \ref usb_ep_type).\r
165  */\r
166 uint8_t USBEndpointDescriptor_GetType(\r
167     const USBEndpointDescriptor *endpoint)\r
168 {\r
169     return endpoint->bmAttributes & 0x3;\r
170 }\r
171 \r
172 /**\r
173  *  Returns the maximum size of a packet (in bytes) on an endpoint given\r
174  *  its descriptor.\r
175  *  \param endpoint - Pointer to a USBEndpointDescriptor instance.\r
176  *  \return Maximum packet size of endpoint.\r
177  */\r
178 uint16_t USBEndpointDescriptor_GetMaxPacketSize(\r
179     const USBEndpointDescriptor *endpoint)\r
180 {\r
181 uint16_t usTemp;\r
182 uint8_t *pc1, *pc2;\r
183 \r
184         pc1 = ( uint8_t * ) &( endpoint->wMaxPacketSize );\r
185         pc2 = pc1 + 1;\r
186         usTemp = ( ( *pc2 ) << 8 ) | *pc1;\r
187 \r
188         return usTemp;\r
189 #warning The above code replaces the line below to ensure aborts are not received due to unaligned accesses.  Alternatively use the --no_unaligned_access compiler option.\r
190     //return endpoint->wMaxPacketSize;\r
191 }\r
192 \r
193 /**\r
194  *  Returns the polling interval on an endpoint given its descriptor.\r
195  *  \param endpoint - Pointer to a USBEndpointDescriptor instance.\r
196  *  \return Polling interval of endpoint.\r
197  */\r
198 uint8_t USBEndpointDescriptor_GetInterval(\r
199     const USBEndpointDescriptor *endpoint)\r
200 {\r
201     return endpoint->bInterval;\r
202 }\r
203 \r
204 \r
205 \r
206 /** Returns the total length of a configuration, i.e. including the\r
207  *  descriptors following it.\r
208  *  \param configuration Pointer to a USBConfigurationDescriptor instance.\r
209  *  \return Total length (in bytes) of the configuration.\r
210  */\r
211 volatile unsigned long ulCount = 0;\r
212 uint32_t USBConfigurationDescriptor_GetTotalLength(\r
213     const USBConfigurationDescriptor *configuration)\r
214 {\r
215 ulCount++;\r
216 if( ulCount == 5 )\r
217 {\r
218         __asm volatile( "NOP" );\r
219 }\r
220     return configuration->wTotalLength;\r
221 }\r
222 \r
223 /** Returns the number of interfaces in a configuration.\r
224  *  \param configuration Pointer to a USBConfigurationDescriptor instance.\r
225  *  \return Number of interfaces in configuration.\r
226  */\r
227 unsigned char USBConfigurationDescriptor_GetNumInterfaces(\r
228     const USBConfigurationDescriptor *configuration)\r
229 {\r
230     return configuration->bNumInterfaces;\r
231 }\r
232 \r
233 /** Indicates if the device is self-powered when in a given configuration.\r
234  *  \param configuration Pointer to a USBConfigurationDescriptor instance.\r
235  *  \return 1 if the device is self-powered when in the given configuration;\r
236  *          otherwise 0.\r
237  */\r
238 unsigned char USBConfigurationDescriptor_IsSelfPowered(\r
239     const USBConfigurationDescriptor *configuration)\r
240 {\r
241     if ((configuration->bmAttributes & (1 << 6)) != 0) {\r
242 \r
243         return 1;\r
244     }\r
245     else {\r
246 \r
247         return 0;\r
248     }\r
249 }\r
250 \r
251 /** Parses the given Configuration descriptor (followed by relevant\r
252  *  interface, endpoint and class-specific descriptors) into three arrays.\r
253  *  *Each array must have its size equal or greater to the number of\r
254  *  descriptors it stores plus one*. A null-value is inserted after the last\r
255  *  descriptor of each type to indicate the array end.\r
256  *\r
257  *  Note that if the pointer to an array is null (0), nothing is stored in\r
258  *  it.\r
259  *  \param configuration Pointer to the start of the whole Configuration\r
260  *                       descriptor.\r
261  *  \param interfaces    Pointer to the Interface descriptor array.\r
262  *  \param endpoints     Pointer to the Endpoint descriptor array.\r
263  *  \param others        Pointer to the class-specific descriptor array.\r
264  */\r
265 void USBConfigurationDescriptor_Parse(\r
266     const USBConfigurationDescriptor *configuration,\r
267     USBInterfaceDescriptor **interfaces,\r
268     USBEndpointDescriptor **endpoints,\r
269     USBGenericDescriptor **others)\r
270 {\r
271     /* Get size of configuration to parse */\r
272     int size = USBConfigurationDescriptor_GetTotalLength(configuration);\r
273     size -= sizeof(USBConfigurationDescriptor);\r
274 \r
275     /* Start parsing descriptors */\r
276     USBGenericDescriptor *descriptor = (USBGenericDescriptor *) configuration;\r
277     while (size > 0) {\r
278 \r
279         /* Get next descriptor */\r
280         descriptor = USBGenericDescriptor_GetNextDescriptor(descriptor);\r
281         size -= USBGenericDescriptor_GetLength(descriptor);\r
282 \r
283         /* Store descriptor in correponding array */\r
284         if (USBGenericDescriptor_GetType(descriptor)\r
285              == USBGenericDescriptor_INTERFACE) {\r
286 \r
287             if (interfaces) {\r
288 \r
289                 *interfaces = (USBInterfaceDescriptor *) descriptor;\r
290                 interfaces++;\r
291             }\r
292         }\r
293         else if (USBGenericDescriptor_GetType(descriptor)\r
294                   == USBGenericDescriptor_ENDPOINT) {\r
295 \r
296             if (endpoints) {\r
297 \r
298                 *endpoints = (USBEndpointDescriptor *) descriptor;\r
299                 endpoints++;\r
300             }\r
301         }\r
302         else if (others) {\r
303 \r
304             *others = descriptor;\r
305             others++;\r
306         }\r
307     }\r
308 \r
309     /* Null-terminate arrays */\r
310     if (interfaces) {\r
311 \r
312         *interfaces = 0;\r
313     }\r
314     if (endpoints) {\r
315 \r
316         *endpoints = 0;\r
317     }\r
318     if (others) {\r
319 \r
320         *others = 0;\r
321     }\r
322 }\r
323 \r
324 /**@}*/\r
325 \r