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