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