]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - common/usb_cdc.c
CHG: forgot some changes to previous commit.
[proxmark3-svn] / common / usb_cdc.c
... / ...
CommitLineData
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
36#include "config_gpio.h"\r
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 0x00,0x02, // Complies with USB Spec. Release (0110h = release 2.00)\r
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
55 0x2d,0x2d, // Vendor ID (--)\r
56 0x4d,0x50, // Product ID (PM), transmitted in reverse\r
57 0x01,0x00, // Device release number (0001)\r
58 0x01, // iManufacturer // 0x01\r
59 0x00, // iProduct\r
60 0xFD, // 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 0xFA, // 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
85 0x01, // bInterfaceProtocol\r
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 0x02, // 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// Bitmap for all status bits in CSR.\r
173#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \\r
174 |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \\r
175 |AT91C_UDP_TXCOMP\r
176\r
177// Clear flags in the UDP_CSR register and waits for synchronization\r
178#define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \\r
179 volatile unsigned int reg; \\r
180 reg = pUdp->UDP_CSR[(endpoint)]; \\r
181 reg |= REG_NO_EFFECT_1_ALL; \\r
182 reg &= ~(flags); \\r
183 pUdp->UDP_CSR[(endpoint)] = reg; \\r
184 while ( (pUdp->UDP_CSR[(endpoint)] & (flags)) == (flags)); \\r
185} \\r
186\r
187// reset flags in the UDP_CSR register and waits for synchronization\r
188#define UDP_SET_EP_FLAGS(endpoint, flags) { \\r
189 volatile unsigned int reg; \\r
190 reg = pUdp->UDP_CSR[(endpoint)]; \\r
191 reg |= REG_NO_EFFECT_1_ALL; \\r
192 reg |= (flags); \\r
193 pUdp->UDP_CSR[(endpoint)] = reg; \\r
194 while ( ( pUdp->UDP_CSR[(endpoint)] & (flags)) != (flags)); \\r
195} \\r
196\r
197 \r
198/* USB standard request code */\r
199#define STD_GET_STATUS_ZERO 0x0080\r
200#define STD_GET_STATUS_INTERFACE 0x0081\r
201#define STD_GET_STATUS_ENDPOINT 0x0082\r
202\r
203#define STD_CLEAR_FEATURE_ZERO 0x0100\r
204#define STD_CLEAR_FEATURE_INTERFACE 0x0101\r
205#define STD_CLEAR_FEATURE_ENDPOINT 0x0102\r
206\r
207#define STD_SET_FEATURE_ZERO 0x0300\r
208#define STD_SET_FEATURE_INTERFACE 0x0301\r
209#define STD_SET_FEATURE_ENDPOINT 0x0302\r
210\r
211#define STD_SET_ADDRESS 0x0500\r
212#define STD_GET_DESCRIPTOR 0x0680\r
213#define STD_SET_DESCRIPTOR 0x0700\r
214#define STD_GET_CONFIGURATION 0x0880\r
215#define STD_SET_CONFIGURATION 0x0900\r
216#define STD_GET_INTERFACE 0x0A81\r
217#define STD_SET_INTERFACE 0x0B01\r
218#define STD_SYNCH_FRAME 0x0C82\r
219\r
220/* CDC Class Specific Request Code */\r
221#define GET_LINE_CODING 0x21A1\r
222#define SET_LINE_CODING 0x2021\r
223#define SET_CONTROL_LINE_STATE 0x2221\r
224\r
225typedef struct {\r
226 unsigned int dwDTERRate;\r
227 char bCharFormat;\r
228 char bParityType;\r
229 char bDataBits;\r
230} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;\r
231\r
232AT91S_CDC_LINE_CODING line = {\r
233 115200, // baudrate\r
234 0, // 1 Stop Bit\r
235 0, // None Parity\r
236 8}; // 8 Data bits\r
237\r
238void AT91F_CDC_Enumerate();\r
239\r
240AT91PS_UDP pUdp = AT91C_BASE_UDP;\r
241byte_t btConfiguration = 0;\r
242byte_t btConnection = 0;\r
243byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;\r
244\r
245//*----------------------------------------------------------------------------\r
246//* \fn usb_disable\r
247//* \brief This function deactivates the USB device\r
248//*----------------------------------------------------------------------------\r
249void usb_disable() {\r
250 // Disconnect the USB device\r
251 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;\r
252\r
253 // Clear all lingering interrupts\r
254 if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
255 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
256 }\r
257}\r
258\r
259//*----------------------------------------------------------------------------\r
260//* \fn usb_enable\r
261//* \brief This function Activates the USB device\r
262//*----------------------------------------------------------------------------\r
263void usb_enable() {\r
264 // Set the PLL USB Divider\r
265 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;\r
266\r
267 // Specific Chip USB Initialisation\r
268 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock\r
269 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;\r
270 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);\r
271\r
272 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO\r
273 // Set in PIO mode and Configure in Output\r
274 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode\r
275 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output\r
276\r
277 // Clear for set the Pullup resistor\r
278 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;\r
279\r
280 // Disconnect and reconnect USB controller for 100ms\r
281 usb_disable();\r
282\r
283 // Wait for a short while\r
284 for (volatile size_t i=0; i<0x100000; i++);\r
285 //sleep(1);\r
286 \r
287 // Reconnect USB reconnect\r
288 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;\r
289 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;\r
290}\r
291\r
292//*----------------------------------------------------------------------------\r
293//* \fn usb_check\r
294//* \brief Test if the device is configured and handle enumeration\r
295//*----------------------------------------------------------------------------\r
296bool usb_check() {\r
297 AT91_REG isr = pUdp->UDP_ISR;\r
298\r
299 if (isr & AT91C_UDP_ENDBUSRES) {\r
300 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
301 // reset all endpoints\r
302 pUdp->UDP_RSTEP = (unsigned int)-1;\r
303 pUdp->UDP_RSTEP = 0;\r
304 // Enable the function\r
305 pUdp->UDP_FADDR = AT91C_UDP_FEN;\r
306 // Configure endpoint 0\r
307 pUdp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);\r
308 }\r
309 else if (isr & AT91C_UDP_EPINT0) {\r
310 pUdp->UDP_ICR = AT91C_UDP_EPINT0;\r
311 AT91F_CDC_Enumerate();\r
312 }\r
313 return (btConfiguration) ? true : false;\r
314}\r
315\r
316\r
317bool usb_poll()\r
318{\r
319 if (!usb_check()) return false;\r
320 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
321}\r
322\r
323/**\r
324 In github PR #129, some users appears to get a false positive from\r
325 usb_poll, which returns true, but the usb_read operation\r
326 still returns 0.\r
327 This check is basically the same as above, but also checks\r
328 that the length available to read is non-zero, thus hopefully fixes the\r
329 bug.\r
330**/\r
331bool usb_poll_validate_length()\r
332{\r
333 if (!usb_check()) return false;\r
334 if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;\r
335 return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;\r
336}\r
337\r
338//*----------------------------------------------------------------------------\r
339//* \fn usb_read\r
340//* \brief Read available data from Endpoint OUT\r
341//*----------------------------------------------------------------------------\r
342uint32_t usb_read(byte_t* data, size_t len) {\r
343 byte_t bank = btReceiveBank;\r
344 uint32_t packetSize, nbBytesRcv = 0;\r
345 uint32_t time_out = 0;\r
346 \r
347 while (len) {\r
348 if (!usb_check()) break;\r
349\r
350 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {\r
351 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);\r
352 len -= packetSize;\r
353 while(packetSize--)\r
354 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];\r
355\r
356 \r
357 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) \r
358 //pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);\r
359\r
360 if (bank == AT91C_UDP_RX_DATA_BK0)\r
361 bank = AT91C_UDP_RX_DATA_BK1;\r
362 else\r
363 bank = AT91C_UDP_RX_DATA_BK0; \r
364 }\r
365 if (time_out++ == 0x1fff) break;\r
366 }\r
367\r
368 btReceiveBank = bank;\r
369 return nbBytesRcv;\r
370}\r
371\r
372//*----------------------------------------------------------------------------\r
373//* \fn usb_write\r
374//* \brief Send through endpoint 2\r
375//*----------------------------------------------------------------------------\r
376uint32_t usb_write(const byte_t* data, const size_t len) {\r
377 size_t length = len;\r
378 uint32_t cpt = 0;\r
379\r
380 if (!length) return 0;\r
381 if (!usb_check()) return 0;\r
382 \r
383 // Send the first packet\r
384 cpt = MIN(length, AT91C_EP_IN_SIZE-1);\r
385 length -= cpt;\r
386 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
387\r
388 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY)\r
389 //pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
390\r
391 while (length) {\r
392 // Fill the second bank\r
393 cpt = MIN(length, AT91C_EP_IN_SIZE-1);\r
394 length -= cpt;\r
395 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
396 // Wait for the first bank to be sent\r
397 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
398 if (!usb_check()) return length;\r
399 }\r
400 \r
401 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP)\r
402 //pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); \r
403 //while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
404 \r
405 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY)\r
406 //pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
407 }\r
408 \r
409 // Wait for the end of transfer\r
410 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
411 if (!usb_check()) return length;\r
412 }\r
413\r
414 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP)\r
415 //pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);\r
416 //while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
417\r
418 return length;\r
419}\r
420\r
421//*----------------------------------------------------------------------------\r
422//* \fn AT91F_USB_SendData\r
423//* \brief Send Data through the control endpoint\r
424//*----------------------------------------------------------------------------\r
425unsigned int csrTab[100] = {0x00};\r
426unsigned char csrIdx = 0;\r
427\r
428static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {\r
429 uint32_t cpt = 0;\r
430 AT91_REG csr;\r
431\r
432 do {\r
433 cpt = MIN(length, 8);\r
434 length -= cpt;\r
435\r
436 while (cpt--)\r
437 pUdp->UDP_FDR[0] = *pData++;\r
438\r
439 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
440 \r
441 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_TXCOMP)\r
442 //pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
443 //while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
444 }\r
445\r
446 UDP_SET_EP_FLAGS(0, AT91C_UDP_TXPKTRDY)\r
447 // pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
448 do {\r
449 csr = pUdp->UDP_CSR[0];\r
450\r
451 // Data IN stage has been stopped by a status OUT\r
452 if (csr & AT91C_UDP_RX_DATA_BK0) {\r
453 \r
454 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_RX_DATA_BK0)\r
455 //pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
456 return;\r
457 }\r
458 } while ( !(csr & AT91C_UDP_TXCOMP) );\r
459\r
460 } while (length);\r
461\r
462 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
463 \r
464 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_TXCOMP)\r
465 //pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
466 //while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
467 }\r
468}\r
469\r
470//*----------------------------------------------------------------------------\r
471//* \fn AT91F_USB_SendZlp\r
472//* \brief Send zero length packet through the control endpoint\r
473//*----------------------------------------------------------------------------\r
474void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {\r
475\r
476 UDP_SET_EP_FLAGS(0, AT91C_UDP_TXPKTRDY)\r
477 //pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
478 \r
479 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );\r
480 \r
481 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_TXCOMP)\r
482 //pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
483 //while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
484}\r
485\r
486//*----------------------------------------------------------------------------\r
487//* \fn AT91F_USB_SendStall\r
488//* \brief Stall the control endpoint\r
489//*----------------------------------------------------------------------------\r
490void AT91F_USB_SendStall(AT91PS_UDP pUdp) {\r
491 pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;\r
492 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );\r
493 \r
494 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);\r
495 while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));\r
496}\r
497\r
498//*----------------------------------------------------------------------------\r
499//* \fn AT91F_CDC_Enumerate\r
500//* \brief This function is a callback invoked when a SETUP packet is received\r
501//*----------------------------------------------------------------------------\r
502void AT91F_CDC_Enumerate() {\r
503 byte_t bmRequestType, bRequest;\r
504 uint16_t wValue, wIndex, wLength, wStatus;\r
505\r
506 if ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) )\r
507 return;\r
508\r
509 bmRequestType = pUdp->UDP_FDR[0];\r
510 bRequest = pUdp->UDP_FDR[0];\r
511 wValue = (pUdp->UDP_FDR[0] & 0xFF);\r
512 wValue |= (pUdp->UDP_FDR[0] << 8);\r
513 wIndex = (pUdp->UDP_FDR[0] & 0xFF);\r
514 wIndex |= (pUdp->UDP_FDR[0] << 8);\r
515 wLength = (pUdp->UDP_FDR[0] & 0xFF);\r
516 wLength |= (pUdp->UDP_FDR[0] << 8);\r
517\r
518 if (bmRequestType & 0x80) {\r
519\r
520 UDP_SET_EP_FLAGS(0, AT91C_UDP_DIR)\r
521 //pUdp->UDP_CSR[0] |= AT91C_UDP_DIR;\r
522 //while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_DIR) );\r
523 }\r
524 \r
525 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_RXSETUP)\r
526 //pUdp->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;\r
527 //while ( (pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) );\r
528\r
529 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1\r
530 switch ((bRequest << 8) | bmRequestType) {\r
531 case STD_GET_DESCRIPTOR:\r
532 if (wValue == 0x100) // Return Device Descriptor\r
533 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));\r
534 else if (wValue == 0x200) // Return Configuration Descriptor\r
535 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));\r
536 else if ((wValue & 0x300) == 0x300) // Return String Descriptor\r
537 AT91F_USB_SendData(pUdp, strDescriptor, MIN(sizeof(strDescriptor), wLength));\r
538 else\r
539 AT91F_USB_SendStall(pUdp);\r
540 break;\r
541 case STD_SET_ADDRESS:\r
542 AT91F_USB_SendZlp(pUdp);\r
543 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);\r
544 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;\r
545 break;\r
546 case STD_SET_CONFIGURATION:\r
547 btConfiguration = wValue;\r
548 AT91F_USB_SendZlp(pUdp);\r
549 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;\r
550 pUdp->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;\r
551 pUdp->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;\r
552 pUdp->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;\r
553 break;\r
554 case STD_GET_CONFIGURATION:\r
555 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));\r
556 break;\r
557 case STD_GET_STATUS_ZERO:\r
558 wStatus = 0;\r
559 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
560 break;\r
561 case STD_GET_STATUS_INTERFACE:\r
562 wStatus = 0;\r
563 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
564 break;\r
565 case STD_GET_STATUS_ENDPOINT:\r
566 wStatus = 0;\r
567 wIndex &= 0x0F;\r
568 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {\r
569 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
570 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
571 }\r
572 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) {\r
573 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
574 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
575 }\r
576 else\r
577 AT91F_USB_SendStall(pUdp);\r
578 break;\r
579 case STD_SET_FEATURE_ZERO:\r
580 AT91F_USB_SendStall(pUdp);\r
581 break;\r
582 case STD_SET_FEATURE_INTERFACE:\r
583 AT91F_USB_SendZlp(pUdp);\r
584 break;\r
585 case STD_SET_FEATURE_ENDPOINT:\r
586 wIndex &= 0x0F;\r
587 if ((wValue == 0) && wIndex && (wIndex <= 3)) {\r
588 pUdp->UDP_CSR[wIndex] = 0;\r
589 AT91F_USB_SendZlp(pUdp);\r
590 }\r
591 else\r
592 AT91F_USB_SendStall(pUdp);\r
593 break;\r
594 case STD_CLEAR_FEATURE_ZERO:\r
595 AT91F_USB_SendStall(pUdp);\r
596 break;\r
597 case STD_CLEAR_FEATURE_INTERFACE:\r
598 AT91F_USB_SendZlp(pUdp);\r
599 break;\r
600 case STD_CLEAR_FEATURE_ENDPOINT:\r
601 wIndex &= 0x0F;\r
602 if ((wValue == 0) && wIndex && (wIndex <= 3)) {\r
603 if (wIndex == 1)\r
604 pUdp->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);\r
605 else if (wIndex == 2)\r
606 pUdp->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);\r
607 else if (wIndex == 3)\r
608 pUdp->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN);\r
609 AT91F_USB_SendZlp(pUdp);\r
610 }\r
611 else\r
612 AT91F_USB_SendStall(pUdp);\r
613 break;\r
614\r
615 // handle CDC class requests\r
616 case SET_LINE_CODING:\r
617 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) );\r
618 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_RX_DATA_BK0)\r
619 //pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
620 AT91F_USB_SendZlp(pUdp);\r
621 break;\r
622 case GET_LINE_CODING:\r
623 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));\r
624 break;\r
625 case SET_CONTROL_LINE_STATE:\r
626 btConnection = wValue;\r
627 AT91F_USB_SendZlp(pUdp);\r
628 break;\r
629 default:\r
630 AT91F_USB_SendStall(pUdp);\r
631 break;\r
632 }\r
633}\r
Impressum, Datenschutz