]> git.zerfleddert.de Git - proxmark3-svn/blame - common/usb_cdc.c
FIX: lf hitag : Mea culpa, simulation should not have reader_field on. thanks to...
[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
44d9c722 60 0xFD, // SerialNumber\r
5bcc76c4 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
44d9c722 75 0xFA, // CMaxPower\r
5bcc76c4 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
44d9c722 85 0x01, // 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
44d9c722 99 0x02, // bmCapabilities\r
5bcc76c4 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
a2101157 156 26, // Length\r
5bcc76c4 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
a2101157 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
06c185d0 180 reg = pUdp->UDP_CSR[(endpoint)]; \\r
a2101157 181 reg |= REG_NO_EFFECT_1_ALL; \\r
182 reg &= ~(flags); \\r
06c185d0 183 pUdp->UDP_CSR[(endpoint)] = reg; \\r
184 while ( (pUdp->UDP_CSR[(endpoint)] & (flags)) == (flags)); \\r
185} \\r
a2101157 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
06c185d0 190 reg = pUdp->UDP_CSR[(endpoint)]; \\r
a2101157 191 reg |= REG_NO_EFFECT_1_ALL; \\r
192 reg |= (flags); \\r
06c185d0 193 pUdp->UDP_CSR[(endpoint)] = reg; \\r
194 while ( ( pUdp->UDP_CSR[(endpoint)] & (flags)) != (flags)); \\r
195} \\r
5bcc76c4 196\r
a2101157 197 \r
5bcc76c4 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
6e82300d 245//*----------------------------------------------------------------------------\r
79a73ab2 246//* \fn usb_disable\r
6e82300d 247//* \brief This function deactivates the USB device\r
248//*----------------------------------------------------------------------------\r
249void usb_disable() {\r
a2101157 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
6e82300d 257}\r
258\r
5bcc76c4 259//*----------------------------------------------------------------------------\r
79a73ab2 260//* \fn usb_enable\r
5bcc76c4 261//* \brief This function Activates the USB device\r
262//*----------------------------------------------------------------------------\r
6e82300d 263void usb_enable() {\r
f62b5e12 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
79a73ab2 275 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output\r
f62b5e12 276\r
277 // Clear for set the Pullup resistor\r
79a73ab2 278 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;\r
6e82300d 279\r
f62b5e12 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
5bcc76c4 290}\r
291\r
292//*----------------------------------------------------------------------------\r
79a73ab2 293//* \fn usb_check\r
5bcc76c4 294//* \brief Test if the device is configured and handle enumeration\r
295//*----------------------------------------------------------------------------\r
6e82300d 296bool usb_check() {\r
5bcc76c4 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
a1ab594e 319 if (!usb_check()) return false;\r
320 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
5bcc76c4 321}\r
322\r
7838f4be 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
7838f4be 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
5bcc76c4 338//*----------------------------------------------------------------------------\r
79a73ab2 339//* \fn usb_read\r
5bcc76c4 340//* \brief Read available data from Endpoint OUT\r
341//*----------------------------------------------------------------------------\r
6e82300d 342uint32_t usb_read(byte_t* data, size_t len) {\r
a82c1ac8 343 byte_t bank = btReceiveBank;\r
5bcc76c4 344 uint32_t packetSize, nbBytesRcv = 0;\r
a82c1ac8 345 uint32_t time_out = 0;\r
5bcc76c4 346 \r
23b598ee 347 while (len) {\r
5bcc76c4 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
a82c1ac8 352 len -= packetSize;\r
5bcc76c4 353 while(packetSize--)\r
354 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];\r
a2101157 355\r
a82c1ac8 356 \r
a2101157 357 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) \r
358 //pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);\r
359\r
a82c1ac8 360 if (bank == AT91C_UDP_RX_DATA_BK0)\r
5bcc76c4 361 bank = AT91C_UDP_RX_DATA_BK1;\r
a82c1ac8 362 else\r
363 bank = AT91C_UDP_RX_DATA_BK0; \r
5bcc76c4 364 }\r
a82c1ac8 365 if (time_out++ == 0x1fff) break;\r
5bcc76c4 366 }\r
367\r
368 btReceiveBank = bank;\r
369 return nbBytesRcv;\r
370}\r
371\r
372//*----------------------------------------------------------------------------\r
79a73ab2 373//* \fn usb_write\r
5bcc76c4 374//* \brief Send through endpoint 2\r
375//*----------------------------------------------------------------------------\r
6e82300d 376uint32_t usb_write(const byte_t* data, const size_t len) {\r
a82c1ac8 377 size_t length = len;\r
5bcc76c4 378 uint32_t cpt = 0;\r
379\r
a82c1ac8 380 if (!length) return 0;\r
381 if (!usb_check()) return 0;\r
5bcc76c4 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
a2101157 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
5bcc76c4 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
a11ca2f3 396 // Wait for the first bank to be sent\r
5bcc76c4 397 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
398 if (!usb_check()) return length;\r
a82c1ac8 399 }\r
a82c1ac8 400 \r
a2101157 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
a82c1ac8 404 \r
a2101157 405 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY)\r
406 //pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
5bcc76c4 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
a82c1ac8 412 }\r
a2101157 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
5bcc76c4 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
5ee70129 425unsigned int csrTab[100] = {0x00};\r
5bcc76c4 426unsigned char csrIdx = 0;\r
427\r
6e82300d 428static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {\r
5bcc76c4 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
a2101157 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
5bcc76c4 444 }\r
445\r
a2101157 446 UDP_SET_EP_FLAGS(0, AT91C_UDP_TXPKTRDY)\r
447 // pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
5bcc76c4 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
a2101157 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
5bcc76c4 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
a2101157 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
5bcc76c4 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
6e82300d 474void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {\r
a2101157 475\r
476 UDP_SET_EP_FLAGS(0, AT91C_UDP_TXPKTRDY)\r
477 //pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
478 \r
5bcc76c4 479 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );\r
a2101157 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
5bcc76c4 484}\r
485\r
486//*----------------------------------------------------------------------------\r
487//* \fn AT91F_USB_SendStall\r
488//* \brief Stall the control endpoint\r
489//*----------------------------------------------------------------------------\r
6e82300d 490void AT91F_USB_SendStall(AT91PS_UDP pUdp) {\r
5bcc76c4 491 pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;\r
492 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );\r
a2101157 493 \r
5bcc76c4 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
6e82300d 502void AT91F_CDC_Enumerate() {\r
5bcc76c4 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
a2101157 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
5bcc76c4 523 }\r
a2101157 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
5bcc76c4 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
a2101157 618 UDP_CLEAR_EP_FLAGS(0, AT91C_UDP_RX_DATA_BK0)\r
619 //pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
5bcc76c4 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