]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - common/usb_cdc.c
change product desc to 9 and add extra null byte
[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 "at91sam7s512.h"\r
37#include "config_gpio.h"\r
38\r
39\r
40#define AT91C_EP_CONTROL 0\r
41#define AT91C_EP_OUT 1\r
42#define AT91C_EP_IN 2\r
43#define AT91C_EP_NOTIFY 3\r
44#define AT91C_EP_OUT_SIZE 0x40\r
45#define AT91C_EP_IN_SIZE 0x40\r
46\r
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
52static const char devDescriptor[] = {\r
53 /* Device descriptor */\r
54 0x12, // bLength\r
55 0x01, // bDescriptorType\r
56 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)\r
57 0x02, // bDeviceClass: (Communication Device Class)\r
58 0x00, // bDeviceSubclass: (unused at this time)\r
59 0x00, // bDeviceProtocol: (unused at this time)\r
60 0x08, // bMaxPacketSize0\r
61 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)\r
62 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)\r
63 0x01,0x00, // Device release number (0001)\r
64 STR_MANUFACTURER, // iManufacturer\r
65 STR_PRODUCT, // iProduct\r
66 0x00, // iSerialNumber\r
67 0x01 // bNumConfigs\r
68};\r
69\r
70static const char cfgDescriptor[] = {\r
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
80 0x80, // CbmAttributes (Bus Powered)\r
81 0x4B, // CMaxPower (150mA max current drawn from bus)\r
82\r
83 /* Interface 0 Descriptor: Communication Class Interface */\r
84 0x09, // bLength\r
85 0x04, // bDescriptorType\r
86 0x00, // bInterfaceNumber\r
87 0x00, // bAlternateSetting\r
88 0x01, // bNumEndpoints\r
89 0x02, // bInterfaceClass: Communication Interface Class\r
90 0x02, // bInterfaceSubclass: Abstract Control Model\r
91 0x01, // bInterfaceProtocol: Common AT Commands, V.25ter\r
92 0x00, // iInterface\r
93\r
94 /* Header Functional Descriptor */\r
95 0x05, // bFunction Length\r
96 0x24, // bDescriptor type: CS_INTERFACE\r
97 0x00, // bDescriptor subtype: Header Functional Descriptor\r
98 0x10, // bcdCDC:1.1\r
99 0x01,\r
100\r
101 /* ACM Functional Descriptor */\r
102 0x04, // bFunctionLength\r
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
106\r
107 /* Union Functional Descriptor */\r
108 0x05, // bFunctionLength\r
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
113\r
114 /* Call Management Functional Descriptor */\r
115 0x05, // bFunctionLength\r
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
120\r
121 /* Endpoint 1 descriptor */\r
122 0x07, // bLength\r
123 0x05, // bDescriptorType\r
124 0x83, // bEndpointAddress: Endpoint 03 - IN\r
125 0x03, // bmAttributes: INT\r
126 0x08, // wMaxPacketSize: 8\r
127 0x00,\r
128 0xFF, // bInterval\r
129\r
130 /* Interface 1 Descriptor: Data Class Interface */\r
131 0x09, // bLength\r
132 0x04, // bDescriptorType\r
133 0x01, // bInterfaceNumber\r
134 0x00, // bAlternateSetting\r
135 0x02, // bNumEndpoints\r
136 0x0A, // bInterfaceClass: Data Interface Class\r
137 0x00, // bInterfaceSubclass: not used\r
138 0x00, // bInterfaceProtocol: No class specific protocol required)\r
139 0x00, // iInterface\r
140\r
141 /* Endpoint 1 descriptor */\r
142 0x07, // bLength\r
143 0x05, // bDescriptorType\r
144 0x01, // bEndpointAddress: Endpoint 01 - OUT\r
145 0x02, // bmAttributes: BULK\r
146 AT91C_EP_OUT_SIZE, // wMaxPacketSize\r
147 0x00,\r
148 0x00, // bInterval\r
149\r
150 /* Endpoint 2 descriptor */\r
151 0x07, // bLength\r
152 0x05, // bDescriptorType\r
153 0x82, // bEndpointAddress: Endpoint 02 - IN\r
154 0x02, // bmAttributes: BULK\r
155 AT91C_EP_IN_SIZE, // wMaxPacketSize\r
156 0x00,\r
157 0x00 // bInterval\r
158};\r
159\r
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
165\r
166// Note: ModemManager (Linux) ignores Proxmark3 devices by matching the\r
167// manufacturer string "proxmark.org". Don't change this.\r
168static const char StrDescManufacturer[] = {\r
169 26, // Length\r
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
182 'g', 0x00\r
183};\r
184\r
185static const char StrDescProduct[] = {\r
186 9, // Length\r
187 0x03, // Type is string\r
188 'P', 0x00,\r
189 'M', 0x00,\r
190 '3', 0x00,\r
191 0x00\r
192};\r
193\r
194const char* getStringDescriptor(uint8_t idx)\r
195{\r
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
205 }\r
206}\r
207\r
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
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
271\r
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
279\r
280//*----------------------------------------------------------------------------\r
281//* \fn usb_disable\r
282//* \brief This function deactivates the USB device\r
283//*----------------------------------------------------------------------------\r
284void usb_disable() {\r
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
292}\r
293\r
294\r
295//*----------------------------------------------------------------------------\r
296//* \fn usb_enable\r
297//* \brief This function Activates the USB device\r
298//*----------------------------------------------------------------------------\r
299void usb_enable() {\r
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
311 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output\r
312\r
313 // Clear for set the Pullup resistor\r
314 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;\r
315\r
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
325}\r
326\r
327\r
328//*----------------------------------------------------------------------------\r
329//* \fn usb_check\r
330//* \brief Test if the device is configured and handle enumeration\r
331//*----------------------------------------------------------------------------\r
332bool usb_check() {\r
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
343 pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);\r
344 } else if (isr & AT91C_UDP_EPINT0) {\r
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
354 if (!usb_check()) return false;\r
355 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
356}\r
357\r
358\r
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
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
374//*----------------------------------------------------------------------------\r
375//* \fn usb_read\r
376//* \brief Read available data from Endpoint OUT\r
377//*----------------------------------------------------------------------------\r
378uint32_t usb_read(byte_t* data, size_t len) {\r
379 byte_t bank = btReceiveBank;\r
380 uint32_t packetSize, nbBytesRcv = 0;\r
381 uint32_t time_out = 0;\r
382 \r
383 while (len) {\r
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
388 len -= packetSize;\r
389 while(packetSize--)\r
390 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];\r
391 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);\r
392 if (bank == AT91C_UDP_RX_DATA_BK0) {\r
393 bank = AT91C_UDP_RX_DATA_BK1;\r
394 } else {\r
395 bank = AT91C_UDP_RX_DATA_BK0;\r
396 }\r
397 }\r
398 if (time_out++ == 0x1fff) break;\r
399 }\r
400\r
401 btReceiveBank = bank;\r
402 return nbBytesRcv;\r
403}\r
404\r
405\r
406//*----------------------------------------------------------------------------\r
407//* \fn usb_write\r
408//* \brief Send through endpoint 2\r
409//*----------------------------------------------------------------------------\r
410uint32_t usb_write(const byte_t* data, const size_t len) {\r
411 size_t length = len;\r
412 uint32_t cpt = 0;\r
413\r
414 if (!length) return 0;\r
415 if (!usb_check()) return 0;\r
416\r
417 // Send the first packet\r
418 cpt = MIN(length, AT91C_EP_IN_SIZE);\r
419 length -= cpt;\r
420 while (cpt--) {\r
421 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
422 }\r
423 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);\r
424\r
425 while (length) {\r
426 // Fill the next bank\r
427 cpt = MIN(length, AT91C_EP_IN_SIZE);\r
428 length -= cpt;\r
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
433 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
434 if (!usb_check()) return length;\r
435 }\r
436 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);\r
437 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
438 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);\r
439 }\r
440\r
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
444 }\r
445\r
446 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);\r
447 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
448\r
449 return length;\r
450}\r
451\r
452\r
453//*----------------------------------------------------------------------------\r
454//* \fn AT91F_USB_SendData\r
455//* \brief Send Data through the control endpoint\r
456//*----------------------------------------------------------------------------\r
457unsigned int csrTab[100] = {0x00};\r
458unsigned char csrIdx = 0;\r
459\r
460static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {\r
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
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
474 }\r
475\r
476 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);\r
477 do {\r
478 csr = pUdp->UDP_CSR[AT91C_EP_CONTROL];\r
479\r
480 // Data IN stage has been stopped by a status OUT\r
481 if (csr & AT91C_UDP_RX_DATA_BK0) {\r
482 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);\r
483 return;\r
484 }\r
485 } while ( !(csr & AT91C_UDP_TXCOMP) );\r
486\r
487 } while (length);\r
488\r
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
492 }\r
493}\r
494\r
495\r
496//*----------------------------------------------------------------------------\r
497//* \fn AT91F_USB_SendZlp\r
498//* \brief Send zero length packet through the control endpoint\r
499//*----------------------------------------------------------------------------\r
500void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {\r
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
505}\r
506\r
507\r
508//*----------------------------------------------------------------------------\r
509//* \fn AT91F_USB_SendStall\r
510//* \brief Stall the control endpoint\r
511//*----------------------------------------------------------------------------\r
512void AT91F_USB_SendStall(AT91PS_UDP pUdp) {\r
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
517}\r
518\r
519\r
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
524void AT91F_CDC_Enumerate() {\r
525 byte_t bmRequestType, bRequest;\r
526 uint16_t wValue, wIndex, wLength, wStatus;\r
527\r
528 if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) )\r
529 return;\r
530\r
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
539\r
540 if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host\r
541 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);\r
542 while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) );\r
543 }\r
544 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);\r
545 while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) );\r
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
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
559 AT91F_USB_SendStall(pUdp);\r
560 }\r
561 }\r
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
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
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
582 wStatus = 0; // Device is Bus powered, remote wakeup disabled\r
583 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
584 break;\r
585 case STD_GET_STATUS_INTERFACE:\r
586 wStatus = 0; // reserved for future use\r
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
592 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {\r
593 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
594 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
595 }\r
596 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {\r
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
611 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {\r
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
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
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
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
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