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