]> git.zerfleddert.de Git - proxmark3-svn/blame - common/usb_cdc.c
CHG: fixed the collapsing comments when opening this file in notepad++ Need spaces...
[proxmark3-svn] / common / usb_cdc.c
CommitLineData
5bcc76c4 1/*\r
2 * at91sam7s USB CDC device implementation\r
3 *\r
4 * Copyright (c) 2012, Roel Verdult\r
5 * All rights reserved.\r
6 *\r
7 * Redistribution and use in source and binary forms, with or without\r
8 * modification, are permitted provided that the following conditions are met:\r
9 * 1. Redistributions of source code must retain the above copyright\r
10 * notice, this list of conditions and the following disclaimer.\r
11 * 2. Redistributions in binary form must reproduce the above copyright\r
12 * notice, this list of conditions and the following disclaimer in the\r
13 * documentation and/or other materials provided with the distribution.\r
14 * 3. Neither the name of the copyright holders nor the\r
15 * names of its contributors may be used to endorse or promote products\r
16 * derived from this software without specific prior written permission.\r
17 *\r
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY\r
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY\r
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
28 *\r
29 * based on the "Basic USB Example" from ATMEL (doc6123.pdf)\r
30 *\r
31 * @file usb_cdc.c\r
32 * @brief\r
33 */\r
34\r
35#include "usb_cdc.h"\r
79a73ab2 36#include "config_gpio.h"\r
5bcc76c4 37\r
38#define MIN(a, b) (((a) < (b)) ? (a) : (b))\r
39#define MAX(a, b) (((a) > (b)) ? (a) : (b))\r
40#define AT91C_EP_IN_SIZE 0x40\r
41#define AT91C_EP_OUT 1\r
42#define AT91C_EP_OUT_SIZE 0x40\r
43#define AT91C_EP_IN 2\r
44\r
45const char devDescriptor[] = {\r
46 /* Device descriptor */\r
47 0x12, // bLength\r
48 0x01, // bDescriptorType\r
0fcfad0e 49 //0x10,0x01, // Complies with USB Spec. Release (0110h = release 1.10)\r
50 0x00,0x02, // Complies with USB Spec. Release (0110h = release 2.00)\r
5bcc76c4 51 0x02, // bDeviceClass: CDC class code\r
52 0x00, // bDeviceSubclass: CDC class sub code\r
53 0x00, // bDeviceProtocol: CDC Device protocol\r
54 0x08, // bMaxPacketSize0\r
81ee3409 55 0x2d,0x2d, // Vendor ID (--)\r
56 0x4d,0x50, // Product ID (PM), transmitted in reverse\r
5bcc76c4 57 0x01,0x00, // Device release number (0001)\r
58 0x01, // iManufacturer // 0x01\r
59 0x00, // iProduct\r
60 0x00, // SerialNumber\r
61 0x01 // bNumConfigs\r
62};\r
63\r
64const char cfgDescriptor[] = {\r
65 /* ============== CONFIGURATION 1 =========== */\r
66 /* Configuration 1 descriptor */\r
67 0x09, // CbLength\r
68 0x02, // CbDescriptorType\r
69 0x43, // CwTotalLength 2 EP + Control\r
70 0x00,\r
71 0x02, // CbNumInterfaces\r
72 0x01, // CbConfigurationValue\r
73 0x00, // CiConfiguration\r
74 0xC0, // CbmAttributes 0xA0\r
75 0x00, // CMaxPower\r
76\r
77 /* Communication Class Interface Descriptor Requirement */\r
78 0x09, // bLength\r
79 0x04, // bDescriptorType\r
80 0x00, // bInterfaceNumber\r
81 0x00, // bAlternateSetting\r
82 0x01, // bNumEndpoints\r
83 0x02, // bInterfaceClass\r
84 0x02, // bInterfaceSubclass\r
cfcd8045 85 0x00, // bInterfaceProtocol\r
5bcc76c4 86 0x00, // iInterface\r
87\r
88 /* Header Functional Descriptor */\r
89 0x05, // bFunction Length\r
90 0x24, // bDescriptor type: CS_INTERFACE\r
91 0x00, // bDescriptor subtype: Header Func Desc\r
92 0x10, // bcdCDC:1.1\r
93 0x01,\r
94\r
95 /* ACM Functional Descriptor */\r
96 0x04, // bFunctionLength\r
97 0x24, // bDescriptor Type: CS_INTERFACE\r
98 0x02, // bDescriptor Subtype: ACM Func Desc\r
99 0x00, // bmCapabilities\r
100\r
101 /* Union Functional Descriptor */\r
102 0x05, // bFunctionLength\r
103 0x24, // bDescriptorType: CS_INTERFACE\r
104 0x06, // bDescriptor Subtype: Union Func Desc\r
105 0x00, // bMasterInterface: Communication Class Interface\r
106 0x01, // bSlaveInterface0: Data Class Interface\r
107\r
108 /* Call Management Functional Descriptor */\r
109 0x05, // bFunctionLength\r
110 0x24, // bDescriptor Type: CS_INTERFACE\r
111 0x01, // bDescriptor Subtype: Call Management Func Desc\r
112 0x00, // bmCapabilities: D1 + D0\r
113 0x01, // bDataInterface: Data Class Interface 1\r
114\r
115 /* Endpoint 1 descriptor */\r
116 0x07, // bLength\r
117 0x05, // bDescriptorType\r
118 0x83, // bEndpointAddress, Endpoint 03 - IN\r
119 0x03, // bmAttributes INT\r
120 0x08, // wMaxPacketSize\r
121 0x00,\r
122 0xFF, // bInterval\r
123\r
124 /* Data Class Interface Descriptor Requirement */\r
125 0x09, // bLength\r
126 0x04, // bDescriptorType\r
127 0x01, // bInterfaceNumber\r
128 0x00, // bAlternateSetting\r
129 0x02, // bNumEndpoints\r
130 0x0A, // bInterfaceClass\r
131 0x00, // bInterfaceSubclass\r
132 0x00, // bInterfaceProtocol\r
133 0x00, // iInterface\r
134\r
135 /* First alternate setting */\r
136 /* Endpoint 1 descriptor */\r
137 0x07, // bLength\r
138 0x05, // bDescriptorType\r
139 0x01, // bEndpointAddress, Endpoint 01 - OUT\r
140 0x02, // bmAttributes BULK\r
141 AT91C_EP_OUT_SIZE, // wMaxPacketSize\r
142 0x00,\r
143 0x00, // bInterval\r
144\r
145 /* Endpoint 2 descriptor */\r
146 0x07, // bLength\r
147 0x05, // bDescriptorType\r
148 0x82, // bEndpointAddress, Endpoint 02 - IN\r
149 0x02, // bmAttributes BULK\r
150 AT91C_EP_IN_SIZE, // wMaxPacketSize\r
151 0x00,\r
152 0x00 // bInterval\r
153};\r
154\r
155const char strDescriptor[] = {\r
156 26, // Length\r
157 0x03, // Type is string\r
158 'p', 0x00,\r
159 'r', 0x00,\r
160 'o', 0x00,\r
161 'x', 0x00,\r
162 'm', 0x00,\r
163 'a', 0x00,\r
164 'r', 0x00,\r
165 'k', 0x00,\r
166 '.', 0x00,\r
167 'o', 0x00,\r
168 'r', 0x00,\r
169 'g', 0x00,\r
170};\r
171\r
172\r
173/* USB standard request code */\r
174#define STD_GET_STATUS_ZERO 0x0080\r
175#define STD_GET_STATUS_INTERFACE 0x0081\r
176#define STD_GET_STATUS_ENDPOINT 0x0082\r
177\r
178#define STD_CLEAR_FEATURE_ZERO 0x0100\r
179#define STD_CLEAR_FEATURE_INTERFACE 0x0101\r
180#define STD_CLEAR_FEATURE_ENDPOINT 0x0102\r
181\r
182#define STD_SET_FEATURE_ZERO 0x0300\r
183#define STD_SET_FEATURE_INTERFACE 0x0301\r
184#define STD_SET_FEATURE_ENDPOINT 0x0302\r
185\r
186#define STD_SET_ADDRESS 0x0500\r
187#define STD_GET_DESCRIPTOR 0x0680\r
188#define STD_SET_DESCRIPTOR 0x0700\r
189#define STD_GET_CONFIGURATION 0x0880\r
190#define STD_SET_CONFIGURATION 0x0900\r
191#define STD_GET_INTERFACE 0x0A81\r
192#define STD_SET_INTERFACE 0x0B01\r
193#define STD_SYNCH_FRAME 0x0C82\r
194\r
195/* CDC Class Specific Request Code */\r
196#define GET_LINE_CODING 0x21A1\r
197#define SET_LINE_CODING 0x2021\r
198#define SET_CONTROL_LINE_STATE 0x2221\r
199\r
200typedef struct {\r
201 unsigned int dwDTERRate;\r
202 char bCharFormat;\r
203 char bParityType;\r
204 char bDataBits;\r
205} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;\r
206\r
207AT91S_CDC_LINE_CODING line = {\r
208 115200, // baudrate\r
209 0, // 1 Stop Bit\r
210 0, // None Parity\r
211 8}; // 8 Data bits\r
212\r
213void AT91F_CDC_Enumerate();\r
214\r
215AT91PS_UDP pUdp = AT91C_BASE_UDP;\r
216byte_t btConfiguration = 0;\r
217byte_t btConnection = 0;\r
218byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;\r
219\r
6e82300d 220//*----------------------------------------------------------------------------\r
79a73ab2 221//* \fn usb_disable\r
6e82300d 222//* \brief This function deactivates the USB device\r
223//*----------------------------------------------------------------------------\r
224void usb_disable() {\r
79a73ab2 225 // Disconnect the USB device\r
226 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;\r
6e82300d 227 \r
228 // Clear all lingering interrupts\r
229 if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
230 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
231 }\r
232}\r
233\r
5bcc76c4 234//*----------------------------------------------------------------------------\r
79a73ab2 235//* \fn usb_enable\r
5bcc76c4 236//* \brief This function Activates the USB device\r
237//*----------------------------------------------------------------------------\r
6e82300d 238void usb_enable() {\r
f62b5e12 239 // Set the PLL USB Divider\r
240 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;\r
241\r
242 // Specific Chip USB Initialisation\r
243 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock\r
244 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;\r
245 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);\r
246\r
247 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO\r
248 // Set in PIO mode and Configure in Output\r
249 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode\r
79a73ab2 250 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output\r
f62b5e12 251\r
252 // Clear for set the Pullup resistor\r
79a73ab2 253 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;\r
6e82300d 254\r
f62b5e12 255 // Disconnect and reconnect USB controller for 100ms\r
256 usb_disable();\r
257\r
258 // Wait for a short while\r
259 for (volatile size_t i=0; i<0x100000; i++);\r
260 //sleep(1);\r
261 \r
262 // Reconnect USB reconnect\r
263 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;\r
264 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;\r
5bcc76c4 265}\r
266\r
267//*----------------------------------------------------------------------------\r
79a73ab2 268//* \fn usb_check\r
5bcc76c4 269//* \brief Test if the device is configured and handle enumeration\r
270//*----------------------------------------------------------------------------\r
6e82300d 271bool usb_check() {\r
5bcc76c4 272 AT91_REG isr = pUdp->UDP_ISR;\r
273\r
274 if (isr & AT91C_UDP_ENDBUSRES) {\r
275 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
276 // reset all endpoints\r
277 pUdp->UDP_RSTEP = (unsigned int)-1;\r
278 pUdp->UDP_RSTEP = 0;\r
279 // Enable the function\r
280 pUdp->UDP_FADDR = AT91C_UDP_FEN;\r
281 // Configure endpoint 0\r
282 pUdp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);\r
283 }\r
284 else if (isr & AT91C_UDP_EPINT0) {\r
285 pUdp->UDP_ICR = AT91C_UDP_EPINT0;\r
286 AT91F_CDC_Enumerate();\r
287 }\r
288 return (btConfiguration) ? true : false;\r
289}\r
290\r
291\r
292bool usb_poll()\r
293{\r
294 if (!usb_check()) return false;\r
295 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
296}\r
297\r
7838f4be 298/**\r
299 In github PR #129, some users appears to get a false positive from\r
300 usb_poll, which returns true, but the usb_read operation\r
301 still returns 0.\r
302 This check is basically the same as above, but also checks\r
303 that the length available to read is non-zero, thus hopefully fixes the\r
304 bug.\r
305**/\r
306bool usb_poll_validate_length()\r
307{\r
7838f4be 308 if (!usb_check()) return false;\r
309 if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;\r
310 return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;\r
311}\r
312\r
5bcc76c4 313//*----------------------------------------------------------------------------\r
79a73ab2 314//* \fn usb_read\r
5bcc76c4 315//* \brief Read available data from Endpoint OUT\r
316//*----------------------------------------------------------------------------\r
6e82300d 317uint32_t usb_read(byte_t* data, size_t len) {\r
a82c1ac8 318 byte_t bank = btReceiveBank;\r
5bcc76c4 319 uint32_t packetSize, nbBytesRcv = 0;\r
a82c1ac8 320 uint32_t time_out = 0;\r
5bcc76c4 321 \r
23b598ee 322 while (len) {\r
5bcc76c4 323 if (!usb_check()) break;\r
324\r
325 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {\r
326 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);\r
a82c1ac8 327 len -= packetSize;\r
5bcc76c4 328 while(packetSize--)\r
329 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];\r
a82c1ac8 330 \r
5bcc76c4 331 pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);\r
a82c1ac8 332 \r
333 if (bank == AT91C_UDP_RX_DATA_BK0)\r
5bcc76c4 334 bank = AT91C_UDP_RX_DATA_BK1;\r
a82c1ac8 335 else\r
336 bank = AT91C_UDP_RX_DATA_BK0; \r
5bcc76c4 337 }\r
a82c1ac8 338 if (time_out++ == 0x1fff) break;\r
5bcc76c4 339 }\r
340\r
341 btReceiveBank = bank;\r
342 return nbBytesRcv;\r
343}\r
344\r
345//*----------------------------------------------------------------------------\r
79a73ab2 346//* \fn usb_write\r
5bcc76c4 347//* \brief Send through endpoint 2\r
348//*----------------------------------------------------------------------------\r
6e82300d 349uint32_t usb_write(const byte_t* data, const size_t len) {\r
a82c1ac8 350 size_t length = len;\r
5bcc76c4 351 uint32_t cpt = 0;\r
352\r
a82c1ac8 353 if (!length) return 0;\r
354 if (!usb_check()) return 0;\r
5bcc76c4 355 \r
356 // Send the first packet\r
357 cpt = MIN(length, AT91C_EP_IN_SIZE-1);\r
358 length -= cpt;\r
359 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
360 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
361\r
362 while (length) {\r
363 // Fill the second bank\r
364 cpt = MIN(length, AT91C_EP_IN_SIZE-1);\r
365 length -= cpt;\r
366 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
a11ca2f3 367 // Wait for the first bank to be sent\r
5bcc76c4 368 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
369 if (!usb_check()) return length;\r
a82c1ac8 370 }\r
5bcc76c4 371 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);\r
a82c1ac8 372 \r
5bcc76c4 373 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
a82c1ac8 374 \r
5bcc76c4 375 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
376 }\r
377 \r
378 // Wait for the end of transfer\r
379 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
380 if (!usb_check()) return length;\r
a82c1ac8 381 }\r
5bcc76c4 382 \r
383 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);\r
384 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
385\r
386 return length;\r
387}\r
388\r
389//*----------------------------------------------------------------------------\r
390//* \fn AT91F_USB_SendData\r
391//* \brief Send Data through the control endpoint\r
392//*----------------------------------------------------------------------------\r
5ee70129 393unsigned int csrTab[100] = {0x00};\r
5bcc76c4 394unsigned char csrIdx = 0;\r
395\r
6e82300d 396static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {\r
5bcc76c4 397 uint32_t cpt = 0;\r
398 AT91_REG csr;\r
399\r
400 do {\r
401 cpt = MIN(length, 8);\r
402 length -= cpt;\r
403\r
404 while (cpt--)\r
405 pUdp->UDP_FDR[0] = *pData++;\r
406\r
407 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
408 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
409 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
410 }\r
411\r
412 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
413 do {\r
414 csr = pUdp->UDP_CSR[0];\r
415\r
416 // Data IN stage has been stopped by a status OUT\r
417 if (csr & AT91C_UDP_RX_DATA_BK0) {\r
418 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
419 return;\r
420 }\r
421 } while ( !(csr & AT91C_UDP_TXCOMP) );\r
422\r
423 } while (length);\r
424\r
425 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
426 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
427 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
428 }\r
429}\r
430\r
431//*----------------------------------------------------------------------------\r
432//* \fn AT91F_USB_SendZlp\r
433//* \brief Send zero length packet through the control endpoint\r
434//*----------------------------------------------------------------------------\r
6e82300d 435void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {\r
5bcc76c4 436 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
437 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );\r
438 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
439 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
440}\r
441\r
442//*----------------------------------------------------------------------------\r
443//* \fn AT91F_USB_SendStall\r
444//* \brief Stall the control endpoint\r
445//*----------------------------------------------------------------------------\r
6e82300d 446void AT91F_USB_SendStall(AT91PS_UDP pUdp) {\r
5bcc76c4 447 pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;\r
448 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );\r
449 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);\r
450 while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));\r
451}\r
452\r
453//*----------------------------------------------------------------------------\r
454//* \fn AT91F_CDC_Enumerate\r
455//* \brief This function is a callback invoked when a SETUP packet is received\r
456//*----------------------------------------------------------------------------\r
6e82300d 457void AT91F_CDC_Enumerate() {\r
5bcc76c4 458 byte_t bmRequestType, bRequest;\r
459 uint16_t wValue, wIndex, wLength, wStatus;\r
460\r
461 if ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) )\r
462 return;\r
463\r
464 bmRequestType = pUdp->UDP_FDR[0];\r
465 bRequest = pUdp->UDP_FDR[0];\r
466 wValue = (pUdp->UDP_FDR[0] & 0xFF);\r
467 wValue |= (pUdp->UDP_FDR[0] << 8);\r
468 wIndex = (pUdp->UDP_FDR[0] & 0xFF);\r
469 wIndex |= (pUdp->UDP_FDR[0] << 8);\r
470 wLength = (pUdp->UDP_FDR[0] & 0xFF);\r
471 wLength |= (pUdp->UDP_FDR[0] << 8);\r
472\r
473 if (bmRequestType & 0x80) {\r
474 pUdp->UDP_CSR[0] |= AT91C_UDP_DIR;\r
475 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_DIR) );\r
476 }\r
477 pUdp->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;\r
478 while ( (pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) );\r
479\r
480 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1\r
481 switch ((bRequest << 8) | bmRequestType) {\r
482 case STD_GET_DESCRIPTOR:\r
483 if (wValue == 0x100) // Return Device Descriptor\r
484 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));\r
485 else if (wValue == 0x200) // Return Configuration Descriptor\r
486 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));\r
487 else if ((wValue & 0x300) == 0x300) // Return String Descriptor\r
488 AT91F_USB_SendData(pUdp, strDescriptor, MIN(sizeof(strDescriptor), wLength));\r
489 else\r
490 AT91F_USB_SendStall(pUdp);\r
491 break;\r
492 case STD_SET_ADDRESS:\r
493 AT91F_USB_SendZlp(pUdp);\r
494 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);\r
495 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;\r
496 break;\r
497 case STD_SET_CONFIGURATION:\r
498 btConfiguration = wValue;\r
499 AT91F_USB_SendZlp(pUdp);\r
500 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;\r
501 pUdp->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;\r
502 pUdp->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;\r
503 pUdp->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;\r
504 break;\r
505 case STD_GET_CONFIGURATION:\r
506 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));\r
507 break;\r
508 case STD_GET_STATUS_ZERO:\r
509 wStatus = 0;\r
510 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
511 break;\r
512 case STD_GET_STATUS_INTERFACE:\r
513 wStatus = 0;\r
514 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
515 break;\r
516 case STD_GET_STATUS_ENDPOINT:\r
517 wStatus = 0;\r
518 wIndex &= 0x0F;\r
519 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {\r
520 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
521 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
522 }\r
523 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) {\r
524 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
525 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
526 }\r
527 else\r
528 AT91F_USB_SendStall(pUdp);\r
529 break;\r
530 case STD_SET_FEATURE_ZERO:\r
531 AT91F_USB_SendStall(pUdp);\r
532 break;\r
533 case STD_SET_FEATURE_INTERFACE:\r
534 AT91F_USB_SendZlp(pUdp);\r
535 break;\r
536 case STD_SET_FEATURE_ENDPOINT:\r
537 wIndex &= 0x0F;\r
538 if ((wValue == 0) && wIndex && (wIndex <= 3)) {\r
539 pUdp->UDP_CSR[wIndex] = 0;\r
540 AT91F_USB_SendZlp(pUdp);\r
541 }\r
542 else\r
543 AT91F_USB_SendStall(pUdp);\r
544 break;\r
545 case STD_CLEAR_FEATURE_ZERO:\r
546 AT91F_USB_SendStall(pUdp);\r
547 break;\r
548 case STD_CLEAR_FEATURE_INTERFACE:\r
549 AT91F_USB_SendZlp(pUdp);\r
550 break;\r
551 case STD_CLEAR_FEATURE_ENDPOINT:\r
552 wIndex &= 0x0F;\r
553 if ((wValue == 0) && wIndex && (wIndex <= 3)) {\r
554 if (wIndex == 1)\r
555 pUdp->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);\r
556 else if (wIndex == 2)\r
557 pUdp->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);\r
558 else if (wIndex == 3)\r
559 pUdp->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN);\r
560 AT91F_USB_SendZlp(pUdp);\r
561 }\r
562 else\r
563 AT91F_USB_SendStall(pUdp);\r
564 break;\r
565\r
566 // handle CDC class requests\r
567 case SET_LINE_CODING:\r
568 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) );\r
569 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
570 AT91F_USB_SendZlp(pUdp);\r
571 break;\r
572 case GET_LINE_CODING:\r
573 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));\r
574 break;\r
575 case SET_CONTROL_LINE_STATE:\r
576 btConnection = wValue;\r
577 AT91F_USB_SendZlp(pUdp);\r
578 break;\r
579 default:\r
580 AT91F_USB_SendStall(pUdp);\r
581 break;\r
582 }\r
583}\r
Impressum, Datenschutz