]> git.zerfleddert.de Git - proxmark3-svn/blame - common/usb_cdc.c
(implementing suggestion #94)
[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
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
81ee3409 54 0x2d,0x2d, // Vendor ID (--)\r
55 0x4d,0x50, // Product ID (PM), transmitted in reverse\r
5bcc76c4 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
cfcd8045 84 0x00, // bInterfaceProtocol\r
5bcc76c4 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
6e82300d 219//*----------------------------------------------------------------------------\r
79a73ab2 220//* \fn usb_disable\r
6e82300d 221//* \brief This function deactivates the USB device\r
222//*----------------------------------------------------------------------------\r
223void usb_disable() {\r
79a73ab2 224 // Disconnect the USB device\r
225 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;\r
6e82300d 226 \r
227 // Clear all lingering interrupts\r
228 if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {\r
229 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
230 }\r
231}\r
232\r
5bcc76c4 233//*----------------------------------------------------------------------------\r
79a73ab2 234//* \fn usb_enable\r
5bcc76c4 235//* \brief This function Activates the USB device\r
236//*----------------------------------------------------------------------------\r
6e82300d 237void usb_enable() {\r
5bcc76c4 238 // Set the PLL USB Divider\r
239 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;\r
240 \r
241 // Specific Chip USB Initialisation\r
242 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock\r
243 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;\r
244 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);\r
245 \r
246 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO\r
247 // Set in PIO mode and Configure in Output\r
79a73ab2 248 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode\r
249 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output\r
5bcc76c4 250 \r
79a73ab2 251 // Clear for set the Pullup resistor\r
252 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;\r
6e82300d 253 \r
79a73ab2 254 // Disconnect and reconnect USB controller for 100ms\r
6e82300d 255 usb_disable();\r
256 \r
257 // Wait for a short while\r
28fdb04f 258 for (volatile size_t i=0; i<0x100000; i++);\r
6e82300d 259\r
260 // Reconnect USB reconnect\r
79a73ab2 261 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;\r
262 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;\r
5bcc76c4 263}\r
264\r
265//*----------------------------------------------------------------------------\r
79a73ab2 266//* \fn usb_check\r
5bcc76c4 267//* \brief Test if the device is configured and handle enumeration\r
268//*----------------------------------------------------------------------------\r
6e82300d 269bool usb_check() {\r
5bcc76c4 270 AT91_REG isr = pUdp->UDP_ISR;\r
271\r
272 if (isr & AT91C_UDP_ENDBUSRES) {\r
273 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;\r
274 // reset all endpoints\r
275 pUdp->UDP_RSTEP = (unsigned int)-1;\r
276 pUdp->UDP_RSTEP = 0;\r
277 // Enable the function\r
278 pUdp->UDP_FADDR = AT91C_UDP_FEN;\r
279 // Configure endpoint 0\r
280 pUdp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);\r
281 }\r
282 else if (isr & AT91C_UDP_EPINT0) {\r
283 pUdp->UDP_ICR = AT91C_UDP_EPINT0;\r
284 AT91F_CDC_Enumerate();\r
285 }\r
286 return (btConfiguration) ? true : false;\r
287}\r
288\r
289\r
290bool usb_poll()\r
291{\r
292 if (!usb_check()) return false;\r
293 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);\r
294}\r
295\r
296//*----------------------------------------------------------------------------\r
79a73ab2 297//* \fn usb_read\r
5bcc76c4 298//* \brief Read available data from Endpoint OUT\r
299//*----------------------------------------------------------------------------\r
6e82300d 300uint32_t usb_read(byte_t* data, size_t len) {\r
5bcc76c4 301 byte_t bank = btReceiveBank;\r
302 uint32_t packetSize, nbBytesRcv = 0;\r
303 uint32_t time_out = 0;\r
304 \r
23b598ee 305 while (len) {\r
5bcc76c4 306 if (!usb_check()) break;\r
307\r
308 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {\r
309 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);\r
310 len -= packetSize;\r
311 while(packetSize--)\r
312 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];\r
313 pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);\r
23b598ee 314 if (bank == AT91C_UDP_RX_DATA_BK0) {\r
5bcc76c4 315 bank = AT91C_UDP_RX_DATA_BK1;\r
316 } else {\r
317 bank = AT91C_UDP_RX_DATA_BK0;\r
318 }\r
319 }\r
320 if (time_out++ == 0x1fff) break;\r
321 }\r
322\r
323 btReceiveBank = bank;\r
324 return nbBytesRcv;\r
325}\r
326\r
327//*----------------------------------------------------------------------------\r
79a73ab2 328//* \fn usb_write\r
5bcc76c4 329//* \brief Send through endpoint 2\r
330//*----------------------------------------------------------------------------\r
6e82300d 331uint32_t usb_write(const byte_t* data, const size_t len) {\r
5bcc76c4 332 size_t length = len;\r
333 uint32_t cpt = 0;\r
334\r
335 if (!length) return 0;\r
336 if (!usb_check()) return 0;\r
337 \r
338 // Send the first packet\r
339 cpt = MIN(length, AT91C_EP_IN_SIZE-1);\r
340 length -= cpt;\r
341 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
342 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
343\r
344 while (length) {\r
345 // Fill the second bank\r
346 cpt = MIN(length, AT91C_EP_IN_SIZE-1);\r
347 length -= cpt;\r
348 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;\r
349 // Wait for the the first bank to be sent\r
350 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
351 if (!usb_check()) return length;\r
352 }\r
353 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);\r
354 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
355 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;\r
356 }\r
357 \r
358 // Wait for the end of transfer\r
359 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {\r
360 if (!usb_check()) return length;\r
361 }\r
362 \r
363 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);\r
364 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);\r
365\r
366 return length;\r
367}\r
368\r
369//*----------------------------------------------------------------------------\r
370//* \fn AT91F_USB_SendData\r
371//* \brief Send Data through the control endpoint\r
372//*----------------------------------------------------------------------------\r
5ee70129 373unsigned int csrTab[100] = {0x00};\r
5bcc76c4 374unsigned char csrIdx = 0;\r
375\r
6e82300d 376static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {\r
5bcc76c4 377 uint32_t cpt = 0;\r
378 AT91_REG csr;\r
379\r
380 do {\r
381 cpt = MIN(length, 8);\r
382 length -= cpt;\r
383\r
384 while (cpt--)\r
385 pUdp->UDP_FDR[0] = *pData++;\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 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
393 do {\r
394 csr = pUdp->UDP_CSR[0];\r
395\r
396 // Data IN stage has been stopped by a status OUT\r
397 if (csr & AT91C_UDP_RX_DATA_BK0) {\r
398 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
399 return;\r
400 }\r
401 } while ( !(csr & AT91C_UDP_TXCOMP) );\r
402\r
403 } while (length);\r
404\r
405 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {\r
406 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
407 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
408 }\r
409}\r
410\r
411//*----------------------------------------------------------------------------\r
412//* \fn AT91F_USB_SendZlp\r
413//* \brief Send zero length packet through the control endpoint\r
414//*----------------------------------------------------------------------------\r
6e82300d 415void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {\r
5bcc76c4 416 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;\r
417 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );\r
418 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);\r
419 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);\r
420}\r
421\r
422//*----------------------------------------------------------------------------\r
423//* \fn AT91F_USB_SendStall\r
424//* \brief Stall the control endpoint\r
425//*----------------------------------------------------------------------------\r
6e82300d 426void AT91F_USB_SendStall(AT91PS_UDP pUdp) {\r
5bcc76c4 427 pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;\r
428 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );\r
429 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);\r
430 while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));\r
431}\r
432\r
433//*----------------------------------------------------------------------------\r
434//* \fn AT91F_CDC_Enumerate\r
435//* \brief This function is a callback invoked when a SETUP packet is received\r
436//*----------------------------------------------------------------------------\r
6e82300d 437void AT91F_CDC_Enumerate() {\r
5bcc76c4 438 byte_t bmRequestType, bRequest;\r
439 uint16_t wValue, wIndex, wLength, wStatus;\r
440\r
441 if ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) )\r
442 return;\r
443\r
444 bmRequestType = pUdp->UDP_FDR[0];\r
445 bRequest = pUdp->UDP_FDR[0];\r
446 wValue = (pUdp->UDP_FDR[0] & 0xFF);\r
447 wValue |= (pUdp->UDP_FDR[0] << 8);\r
448 wIndex = (pUdp->UDP_FDR[0] & 0xFF);\r
449 wIndex |= (pUdp->UDP_FDR[0] << 8);\r
450 wLength = (pUdp->UDP_FDR[0] & 0xFF);\r
451 wLength |= (pUdp->UDP_FDR[0] << 8);\r
452\r
453 if (bmRequestType & 0x80) {\r
454 pUdp->UDP_CSR[0] |= AT91C_UDP_DIR;\r
455 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_DIR) );\r
456 }\r
457 pUdp->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;\r
458 while ( (pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) );\r
459\r
460 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1\r
461 switch ((bRequest << 8) | bmRequestType) {\r
462 case STD_GET_DESCRIPTOR:\r
463 if (wValue == 0x100) // Return Device Descriptor\r
464 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));\r
465 else if (wValue == 0x200) // Return Configuration Descriptor\r
466 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));\r
467 else if ((wValue & 0x300) == 0x300) // Return String Descriptor\r
468 AT91F_USB_SendData(pUdp, strDescriptor, MIN(sizeof(strDescriptor), wLength));\r
469 else\r
470 AT91F_USB_SendStall(pUdp);\r
471 break;\r
472 case STD_SET_ADDRESS:\r
473 AT91F_USB_SendZlp(pUdp);\r
474 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);\r
475 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;\r
476 break;\r
477 case STD_SET_CONFIGURATION:\r
478 btConfiguration = wValue;\r
479 AT91F_USB_SendZlp(pUdp);\r
480 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;\r
481 pUdp->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;\r
482 pUdp->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;\r
483 pUdp->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;\r
484 break;\r
485 case STD_GET_CONFIGURATION:\r
486 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));\r
487 break;\r
488 case STD_GET_STATUS_ZERO:\r
489 wStatus = 0;\r
490 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
491 break;\r
492 case STD_GET_STATUS_INTERFACE:\r
493 wStatus = 0;\r
494 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
495 break;\r
496 case STD_GET_STATUS_ENDPOINT:\r
497 wStatus = 0;\r
498 wIndex &= 0x0F;\r
499 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {\r
500 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;\r
501 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));\r
502 }\r
503 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) {\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\r
508 AT91F_USB_SendStall(pUdp);\r
509 break;\r
510 case STD_SET_FEATURE_ZERO:\r
511 AT91F_USB_SendStall(pUdp);\r
512 break;\r
513 case STD_SET_FEATURE_INTERFACE:\r
514 AT91F_USB_SendZlp(pUdp);\r
515 break;\r
516 case STD_SET_FEATURE_ENDPOINT:\r
517 wIndex &= 0x0F;\r
518 if ((wValue == 0) && wIndex && (wIndex <= 3)) {\r
519 pUdp->UDP_CSR[wIndex] = 0;\r
520 AT91F_USB_SendZlp(pUdp);\r
521 }\r
522 else\r
523 AT91F_USB_SendStall(pUdp);\r
524 break;\r
525 case STD_CLEAR_FEATURE_ZERO:\r
526 AT91F_USB_SendStall(pUdp);\r
527 break;\r
528 case STD_CLEAR_FEATURE_INTERFACE:\r
529 AT91F_USB_SendZlp(pUdp);\r
530 break;\r
531 case STD_CLEAR_FEATURE_ENDPOINT:\r
532 wIndex &= 0x0F;\r
533 if ((wValue == 0) && wIndex && (wIndex <= 3)) {\r
534 if (wIndex == 1)\r
535 pUdp->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);\r
536 else if (wIndex == 2)\r
537 pUdp->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);\r
538 else if (wIndex == 3)\r
539 pUdp->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN);\r
540 AT91F_USB_SendZlp(pUdp);\r
541 }\r
542 else\r
543 AT91F_USB_SendStall(pUdp);\r
544 break;\r
545\r
546 // handle CDC class requests\r
547 case SET_LINE_CODING:\r
548 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) );\r
549 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);\r
550 AT91F_USB_SendZlp(pUdp);\r
551 break;\r
552 case GET_LINE_CODING:\r
553 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));\r
554 break;\r
555 case SET_CONTROL_LINE_STATE:\r
556 btConnection = wValue;\r
557 AT91F_USB_SendZlp(pUdp);\r
558 break;\r
559 default:\r
560 AT91F_USB_SendStall(pUdp);\r
561 break;\r
562 }\r
563}\r
Impressum, Datenschutz