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