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