]> git.zerfleddert.de Git - proxmark3-svn/blob - common/usb_cdc.c
fix USB descriptors
[proxmark3-svn] / common / usb_cdc.c
1 /*
2 * at91sam7s USB CDC device implementation
3 *
4 * Copyright (c) 2012, Roel Verdult
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * based on the "Basic USB Example" from ATMEL (doc6123.pdf)
30 *
31 * @file usb_cdc.c
32 * @brief
33 */
34
35 #include "usb_cdc.h"
36 #include "at91sam7s512.h"
37 #include "config_gpio.h"
38
39 #define AT91C_EP_IN_SIZE 0x40
40 #define AT91C_EP_OUT 1
41 #define AT91C_EP_OUT_SIZE 0x40
42 #define AT91C_EP_IN 2
43
44 static const char devDescriptor[] = {
45 /* Device descriptor */
46 0x12, // bLength
47 0x01, // bDescriptorType
48 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)
49 0x02, // bDeviceClass: CDC class code
50 0x00, // bDeviceSubclass: CDC class sub code
51 0x00, // bDeviceProtocol: CDC Device protocol
52 0x08, // bMaxPacketSize0
53 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)
54 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)
55 0x01,0x00, // Device release number (0001)
56 0x01, // iManufacturer
57 0x02, // iProduct
58 0x00, // iSerialNumber
59 0x01 // bNumConfigs
60 };
61
62 static const char cfgDescriptor[] = {
63 /* ============== CONFIGURATION 1 =========== */
64 /* Configuration 1 descriptor */
65 0x09, // CbLength
66 0x02, // CbDescriptorType
67 0x43, // CwTotalLength 2 EP + Control
68 0x00,
69 0x02, // CbNumInterfaces
70 0x01, // CbConfigurationValue
71 0x00, // CiConfiguration
72 0xC0, // CbmAttributes 0xA0
73 0xFA, // CMaxPower
74
75 /* Communication Class Interface Descriptor Requirement */
76 0x09, // bLength
77 0x04, // bDescriptorType
78 0x00, // bInterfaceNumber
79 0x00, // bAlternateSetting
80 0x01, // bNumEndpoints
81 0x02, // bInterfaceClass
82 0x02, // bInterfaceSubclass
83 0x01, // bInterfaceProtocol
84 0x00, // iInterface
85
86 /* Header Functional Descriptor */
87 0x05, // bFunction Length
88 0x24, // bDescriptor type: CS_INTERFACE
89 0x00, // bDescriptor subtype: Header Func Desc
90 0x10, // bcdCDC:1.1
91 0x01,
92
93 /* ACM Functional Descriptor */
94 0x04, // bFunctionLength
95 0x24, // bDescriptor Type: CS_INTERFACE
96 0x02, // bDescriptor Subtype: ACM Func Desc
97 0x02, // bmCapabilities
98
99 /* Union Functional Descriptor */
100 0x05, // bFunctionLength
101 0x24, // bDescriptorType: CS_INTERFACE
102 0x06, // bDescriptor Subtype: Union Func Desc
103 0x00, // bMasterInterface: Communication Class Interface
104 0x01, // bSlaveInterface0: Data Class Interface
105
106 /* Call Management Functional Descriptor */
107 0x05, // bFunctionLength
108 0x24, // bDescriptor Type: CS_INTERFACE
109 0x01, // bDescriptor Subtype: Call Management Func Desc
110 0x00, // bmCapabilities: D1 + D0
111 0x01, // bDataInterface: Data Class Interface 1
112
113 /* Endpoint 1 descriptor */
114 0x07, // bLength
115 0x05, // bDescriptorType
116 0x83, // bEndpointAddress, Endpoint 03 - IN
117 0x03, // bmAttributes INT
118 0x08, // wMaxPacketSize
119 0x00,
120 0xFF, // bInterval
121
122 /* Data Class Interface Descriptor Requirement */
123 0x09, // bLength
124 0x04, // bDescriptorType
125 0x01, // bInterfaceNumber
126 0x00, // bAlternateSetting
127 0x02, // bNumEndpoints
128 0x0A, // bInterfaceClass
129 0x00, // bInterfaceSubclass
130 0x00, // bInterfaceProtocol
131 0x00, // iInterface
132
133 /* First alternate setting */
134 /* Endpoint 1 descriptor */
135 0x07, // bLength
136 0x05, // bDescriptorType
137 0x01, // bEndpointAddress, Endpoint 01 - OUT
138 0x02, // bmAttributes BULK
139 AT91C_EP_OUT_SIZE, // wMaxPacketSize
140 0x00,
141 0x00, // bInterval
142
143 /* Endpoint 2 descriptor */
144 0x07, // bLength
145 0x05, // bDescriptorType
146 0x82, // bEndpointAddress, Endpoint 02 - IN
147 0x02, // bmAttributes BULK
148 AT91C_EP_IN_SIZE, // wMaxPacketSize
149 0x00,
150 0x00 // bInterval
151 };
152
153 static const char StrDescLanguageCodes[] = {
154 4, // Length
155 0x03, // Type is string
156 0x09, 0x04 // supported language Code 0 = 0x0409 (English)
157 };
158
159 static const char StrDescManufacturer[] = {
160 26, // Length
161 0x03, // Type is string
162 'p', 0x00,
163 'r', 0x00,
164 'o', 0x00,
165 'x', 0x00,
166 'm', 0x00,
167 'a', 0x00,
168 'r', 0x00,
169 'k', 0x00,
170 '.', 0x00,
171 'o', 0x00,
172 'r', 0x00,
173 'g', 0x00
174 };
175
176 static const char StrDescProduct[] = {
177 8, // Length
178 0x03, // Type is string
179 'P', 0x00,
180 'M', 0x00,
181 '3', 0x00
182 };
183
184 static const char* const pStrings[] =
185 {
186 StrDescLanguageCodes,
187 StrDescManufacturer,
188 StrDescProduct
189 };
190
191 const char* getStringDescriptor(uint8_t idx)
192 {
193 if(idx >= (sizeof(pStrings) / sizeof(pStrings[0]))) {
194 return(NULL);
195 } else {
196 return(pStrings[idx]);
197 }
198 }
199
200 /* USB standard request code */
201 #define STD_GET_STATUS_ZERO 0x0080
202 #define STD_GET_STATUS_INTERFACE 0x0081
203 #define STD_GET_STATUS_ENDPOINT 0x0082
204
205 #define STD_CLEAR_FEATURE_ZERO 0x0100
206 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
207 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
208
209 #define STD_SET_FEATURE_ZERO 0x0300
210 #define STD_SET_FEATURE_INTERFACE 0x0301
211 #define STD_SET_FEATURE_ENDPOINT 0x0302
212
213 #define STD_SET_ADDRESS 0x0500
214 #define STD_GET_DESCRIPTOR 0x0680
215 #define STD_SET_DESCRIPTOR 0x0700
216 #define STD_GET_CONFIGURATION 0x0880
217 #define STD_SET_CONFIGURATION 0x0900
218 #define STD_GET_INTERFACE 0x0A81
219 #define STD_SET_INTERFACE 0x0B01
220 #define STD_SYNCH_FRAME 0x0C82
221
222 /* CDC Class Specific Request Code */
223 #define GET_LINE_CODING 0x21A1
224 #define SET_LINE_CODING 0x2021
225 #define SET_CONTROL_LINE_STATE 0x2221
226
227 typedef struct {
228 unsigned int dwDTERRate;
229 char bCharFormat;
230 char bParityType;
231 char bDataBits;
232 } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
233
234 AT91S_CDC_LINE_CODING line = {
235 115200, // baudrate
236 0, // 1 Stop Bit
237 0, // None Parity
238 8}; // 8 Data bits
239
240 void AT91F_CDC_Enumerate();
241
242 AT91PS_UDP pUdp = AT91C_BASE_UDP;
243 byte_t btConfiguration = 0;
244 byte_t btConnection = 0;
245 byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
246
247 //*----------------------------------------------------------------------------
248 //* \fn usb_disable
249 //* \brief This function deactivates the USB device
250 //*----------------------------------------------------------------------------
251 void usb_disable() {
252 // Disconnect the USB device
253 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
254
255 // Clear all lingering interrupts
256 if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {
257 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
258 }
259 }
260
261 //*----------------------------------------------------------------------------
262 //* \fn usb_enable
263 //* \brief This function Activates the USB device
264 //*----------------------------------------------------------------------------
265 void usb_enable() {
266 // Set the PLL USB Divider
267 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
268
269 // Specific Chip USB Initialisation
270 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
271 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
272 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
273
274 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
275 // Set in PIO mode and Configure in Output
276 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
277 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
278
279 // Clear for set the Pullup resistor
280 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
281
282 // Disconnect and reconnect USB controller for 100ms
283 usb_disable();
284
285 // Wait for a short while
286 for (volatile size_t i=0; i<0x100000; i++);
287
288 // Reconnect USB reconnect
289 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
290 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
291 }
292
293 //*----------------------------------------------------------------------------
294 //* \fn usb_check
295 //* \brief Test if the device is configured and handle enumeration
296 //*----------------------------------------------------------------------------
297 bool usb_check() {
298 AT91_REG isr = pUdp->UDP_ISR;
299
300 if (isr & AT91C_UDP_ENDBUSRES) {
301 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
302 // reset all endpoints
303 pUdp->UDP_RSTEP = (unsigned int)-1;
304 pUdp->UDP_RSTEP = 0;
305 // Enable the function
306 pUdp->UDP_FADDR = AT91C_UDP_FEN;
307 // Configure endpoint 0
308 pUdp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
309 }
310 else if (isr & AT91C_UDP_EPINT0) {
311 pUdp->UDP_ICR = AT91C_UDP_EPINT0;
312 AT91F_CDC_Enumerate();
313 }
314 return (btConfiguration) ? true : false;
315 }
316
317
318 bool usb_poll()
319 {
320 if (!usb_check()) return false;
321 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
322 }
323
324 /**
325 In github PR #129, some users appears to get a false positive from
326 usb_poll, which returns true, but the usb_read operation
327 still returns 0.
328 This check is basically the same as above, but also checks
329 that the length available to read is non-zero, thus hopefully fixes the
330 bug.
331 **/
332 bool usb_poll_validate_length()
333 {
334
335 if (!usb_check()) return false;
336 if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
337 return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
338 }
339
340 //*----------------------------------------------------------------------------
341 //* \fn usb_read
342 //* \brief Read available data from Endpoint OUT
343 //*----------------------------------------------------------------------------
344 uint32_t usb_read(byte_t* data, size_t len) {
345 byte_t bank = btReceiveBank;
346 uint32_t packetSize, nbBytesRcv = 0;
347 uint32_t time_out = 0;
348
349 while (len) {
350 if (!usb_check()) break;
351
352 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
353 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
354 len -= packetSize;
355 while(packetSize--)
356 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
357 pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(bank);
358 if (bank == AT91C_UDP_RX_DATA_BK0) {
359 bank = AT91C_UDP_RX_DATA_BK1;
360 } else {
361 bank = AT91C_UDP_RX_DATA_BK0;
362 }
363 }
364 if (time_out++ == 0x1fff) break;
365 }
366
367 btReceiveBank = bank;
368 return nbBytesRcv;
369 }
370
371 //*----------------------------------------------------------------------------
372 //* \fn usb_write
373 //* \brief Send through endpoint 2
374 //*----------------------------------------------------------------------------
375 uint32_t usb_write(const byte_t* data, const size_t len) {
376 size_t length = len;
377 uint32_t cpt = 0;
378
379 if (!length) return 0;
380 if (!usb_check()) return 0;
381
382 // Send the first packet
383 cpt = MIN(length, AT91C_EP_IN_SIZE-1);
384 length -= cpt;
385 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
386 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
387
388 while (length) {
389 // Fill the second bank
390 cpt = MIN(length, AT91C_EP_IN_SIZE-1);
391 length -= cpt;
392 while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
393 // Wait for the first bank to be sent
394 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
395 if (!usb_check()) return length;
396 }
397 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
398 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
399 pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
400 }
401
402 // Wait for the end of transfer
403 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
404 if (!usb_check()) return length;
405 }
406
407 pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
408 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
409
410 return length;
411 }
412
413 //*----------------------------------------------------------------------------
414 //* \fn AT91F_USB_SendData
415 //* \brief Send Data through the control endpoint
416 //*----------------------------------------------------------------------------
417 unsigned int csrTab[100] = {0x00};
418 unsigned char csrIdx = 0;
419
420 static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
421 uint32_t cpt = 0;
422 AT91_REG csr;
423
424 do {
425 cpt = MIN(length, 8);
426 length -= cpt;
427
428 while (cpt--)
429 pUdp->UDP_FDR[0] = *pData++;
430
431 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
432 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
433 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
434 }
435
436 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
437 do {
438 csr = pUdp->UDP_CSR[0];
439
440 // Data IN stage has been stopped by a status OUT
441 if (csr & AT91C_UDP_RX_DATA_BK0) {
442 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
443 return;
444 }
445 } while ( !(csr & AT91C_UDP_TXCOMP) );
446
447 } while (length);
448
449 if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
450 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
451 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
452 }
453 }
454
455 //*----------------------------------------------------------------------------
456 //* \fn AT91F_USB_SendZlp
457 //* \brief Send zero length packet through the control endpoint
458 //*----------------------------------------------------------------------------
459 void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {
460 pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
461 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );
462 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
463 while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
464 }
465
466 //*----------------------------------------------------------------------------
467 //* \fn AT91F_USB_SendStall
468 //* \brief Stall the control endpoint
469 //*----------------------------------------------------------------------------
470 void AT91F_USB_SendStall(AT91PS_UDP pUdp) {
471 pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;
472 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );
473 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
474 while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
475 }
476
477 //*----------------------------------------------------------------------------
478 //* \fn AT91F_CDC_Enumerate
479 //* \brief This function is a callback invoked when a SETUP packet is received
480 //*----------------------------------------------------------------------------
481 void AT91F_CDC_Enumerate() {
482 byte_t bmRequestType, bRequest;
483 uint16_t wValue, wIndex, wLength, wStatus;
484
485 if ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) )
486 return;
487
488 bmRequestType = pUdp->UDP_FDR[0];
489 bRequest = pUdp->UDP_FDR[0];
490 wValue = (pUdp->UDP_FDR[0] & 0xFF);
491 wValue |= (pUdp->UDP_FDR[0] << 8);
492 wIndex = (pUdp->UDP_FDR[0] & 0xFF);
493 wIndex |= (pUdp->UDP_FDR[0] << 8);
494 wLength = (pUdp->UDP_FDR[0] & 0xFF);
495 wLength |= (pUdp->UDP_FDR[0] << 8);
496
497 if (bmRequestType & 0x80) {
498 pUdp->UDP_CSR[0] |= AT91C_UDP_DIR;
499 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_DIR) );
500 }
501 pUdp->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
502 while ( (pUdp->UDP_CSR[0] & AT91C_UDP_RXSETUP) );
503
504 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
505 switch ((bRequest << 8) | bmRequestType) {
506 case STD_GET_DESCRIPTOR:
507 if (wValue == 0x100) // Return Device Descriptor
508 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
509 else if (wValue == 0x200) // Return Configuration Descriptor
510 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
511 else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
512 const char *strDescriptor = getStringDescriptor(wValue & 0xff);
513 if (strDescriptor != NULL) {
514 AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
515 } else {
516 AT91F_USB_SendStall(pUdp);
517 }
518 }
519 else
520 AT91F_USB_SendStall(pUdp);
521 break;
522 case STD_SET_ADDRESS:
523 AT91F_USB_SendZlp(pUdp);
524 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);
525 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
526 break;
527 case STD_SET_CONFIGURATION:
528 btConfiguration = wValue;
529 AT91F_USB_SendZlp(pUdp);
530 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
531 pUdp->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
532 pUdp->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
533 pUdp->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
534 break;
535 case STD_GET_CONFIGURATION:
536 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
537 break;
538 case STD_GET_STATUS_ZERO:
539 wStatus = 0;
540 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
541 break;
542 case STD_GET_STATUS_INTERFACE:
543 wStatus = 0;
544 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
545 break;
546 case STD_GET_STATUS_ENDPOINT:
547 wStatus = 0;
548 wIndex &= 0x0F;
549 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {
550 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
551 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
552 }
553 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) {
554 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
555 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
556 }
557 else
558 AT91F_USB_SendStall(pUdp);
559 break;
560 case STD_SET_FEATURE_ZERO:
561 AT91F_USB_SendStall(pUdp);
562 break;
563 case STD_SET_FEATURE_INTERFACE:
564 AT91F_USB_SendZlp(pUdp);
565 break;
566 case STD_SET_FEATURE_ENDPOINT:
567 wIndex &= 0x0F;
568 if ((wValue == 0) && wIndex && (wIndex <= 3)) {
569 pUdp->UDP_CSR[wIndex] = 0;
570 AT91F_USB_SendZlp(pUdp);
571 }
572 else
573 AT91F_USB_SendStall(pUdp);
574 break;
575 case STD_CLEAR_FEATURE_ZERO:
576 AT91F_USB_SendStall(pUdp);
577 break;
578 case STD_CLEAR_FEATURE_INTERFACE:
579 AT91F_USB_SendZlp(pUdp);
580 break;
581 case STD_CLEAR_FEATURE_ENDPOINT:
582 wIndex &= 0x0F;
583 if ((wValue == 0) && wIndex && (wIndex <= 3)) {
584 if (wIndex == 1)
585 pUdp->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
586 else if (wIndex == 2)
587 pUdp->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
588 else if (wIndex == 3)
589 pUdp->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN);
590 AT91F_USB_SendZlp(pUdp);
591 }
592 else
593 AT91F_USB_SendStall(pUdp);
594 break;
595
596 // handle CDC class requests
597 case SET_LINE_CODING:
598 while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) );
599 pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
600 AT91F_USB_SendZlp(pUdp);
601 break;
602 case GET_LINE_CODING:
603 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
604 break;
605 case SET_CONTROL_LINE_STATE:
606 btConnection = wValue;
607 AT91F_USB_SendZlp(pUdp);
608 break;
609 default:
610 AT91F_USB_SendStall(pUdp);
611 break;
612 }
613 }
Impressum, Datenschutz