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