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