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