]> git.zerfleddert.de Git - proxmark3-svn/blob - common/usb_cdc.c
change product desc to 9 and add extra null byte
[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 9, // Length
187 0x03, // Type is string
188 'P', 0x00,
189 'M', 0x00,
190 '3', 0x00,
191 0x00
192 };
193
194 const char* getStringDescriptor(uint8_t idx)
195 {
196 switch (idx) {
197 case STR_LANGUAGE_CODES:
198 return StrDescLanguageCodes;
199 case STR_MANUFACTURER:
200 return StrDescManufacturer;
201 case STR_PRODUCT:
202 return StrDescProduct;
203 default:
204 return NULL;
205 }
206 }
207
208 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect
209 #define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
210 |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
211 |AT91C_UDP_TXCOMP
212
213 // Clear flags in the UDP_CSR register
214 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
215 volatile unsigned int reg; \
216 reg = pUdp->UDP_CSR[(endpoint)]; \
217 reg |= REG_NO_EFFECT_1_ALL; \
218 reg &= ~(flags); \
219 pUdp->UDP_CSR[(endpoint)] = reg; \
220 }
221
222 // Set flags in the UDP_CSR register
223 #define UDP_SET_EP_FLAGS(endpoint, flags) { \
224 volatile unsigned int reg; \
225 reg = pUdp->UDP_CSR[(endpoint)]; \
226 reg |= REG_NO_EFFECT_1_ALL; \
227 reg |= (flags); \
228 pUdp->UDP_CSR[(endpoint)] = reg; \
229 }
230
231 /* USB standard request codes */
232 #define STD_GET_STATUS_ZERO 0x0080
233 #define STD_GET_STATUS_INTERFACE 0x0081
234 #define STD_GET_STATUS_ENDPOINT 0x0082
235
236 #define STD_CLEAR_FEATURE_ZERO 0x0100
237 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
238 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
239
240 #define STD_SET_FEATURE_ZERO 0x0300
241 #define STD_SET_FEATURE_INTERFACE 0x0301
242 #define STD_SET_FEATURE_ENDPOINT 0x0302
243
244 #define STD_SET_ADDRESS 0x0500
245 #define STD_GET_DESCRIPTOR 0x0680
246 #define STD_SET_DESCRIPTOR 0x0700
247 #define STD_GET_CONFIGURATION 0x0880
248 #define STD_SET_CONFIGURATION 0x0900
249 #define STD_GET_INTERFACE 0x0A81
250 #define STD_SET_INTERFACE 0x0B01
251 #define STD_SYNCH_FRAME 0x0C82
252
253 /* CDC Class Specific Request Code */
254 #define GET_LINE_CODING 0x21A1
255 #define SET_LINE_CODING 0x2021
256 #define SET_CONTROL_LINE_STATE 0x2221
257
258 typedef struct {
259 unsigned int dwDTERRate;
260 char bCharFormat;
261 char bParityType;
262 char bDataBits;
263 } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
264
265 AT91S_CDC_LINE_CODING line = {
266 115200, // baudrate
267 0, // 1 Stop Bit
268 0, // None Parity
269 8}; // 8 Data bits
270
271
272 void AT91F_CDC_Enumerate();
273
274 AT91PS_UDP pUdp = AT91C_BASE_UDP;
275 byte_t btConfiguration = 0;
276 byte_t btConnection = 0;
277 byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
278
279
280 //*----------------------------------------------------------------------------
281 //* \fn usb_disable
282 //* \brief This function deactivates the USB device
283 //*----------------------------------------------------------------------------
284 void usb_disable() {
285 // Disconnect the USB device
286 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
287
288 // Clear all lingering interrupts
289 if(pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {
290 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
291 }
292 }
293
294
295 //*----------------------------------------------------------------------------
296 //* \fn usb_enable
297 //* \brief This function Activates the USB device
298 //*----------------------------------------------------------------------------
299 void usb_enable() {
300 // Set the PLL USB Divider
301 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
302
303 // Specific Chip USB Initialisation
304 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
305 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
306 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
307
308 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
309 // Set in PIO mode and Configure in Output
310 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
311 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
312
313 // Clear for set the Pullup resistor
314 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
315
316 // Disconnect and reconnect USB controller for 100ms
317 usb_disable();
318
319 // Wait for a short while
320 for (volatile size_t i=0; i<0x100000; i++);
321
322 // Reconnect USB reconnect
323 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
324 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
325 }
326
327
328 //*----------------------------------------------------------------------------
329 //* \fn usb_check
330 //* \brief Test if the device is configured and handle enumeration
331 //*----------------------------------------------------------------------------
332 bool usb_check() {
333 AT91_REG isr = pUdp->UDP_ISR;
334
335 if (isr & AT91C_UDP_ENDBUSRES) {
336 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
337 // reset all endpoints
338 pUdp->UDP_RSTEP = (unsigned int)-1;
339 pUdp->UDP_RSTEP = 0;
340 // Enable the function
341 pUdp->UDP_FADDR = AT91C_UDP_FEN;
342 // Configure endpoint 0
343 pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
344 } else if (isr & AT91C_UDP_EPINT0) {
345 pUdp->UDP_ICR = AT91C_UDP_EPINT0;
346 AT91F_CDC_Enumerate();
347 }
348 return (btConfiguration) ? true : false;
349 }
350
351
352 bool usb_poll()
353 {
354 if (!usb_check()) return false;
355 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
356 }
357
358
359 /**
360 In github PR #129, some users appears to get a false positive from
361 usb_poll, which returns true, but the usb_read operation
362 still returns 0.
363 This check is basically the same as above, but also checks
364 that the length available to read is non-zero, thus hopefully fixes the
365 bug.
366 **/
367 bool usb_poll_validate_length()
368 {
369 if (!usb_check()) return false;
370 if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
371 return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
372 }
373
374 //*----------------------------------------------------------------------------
375 //* \fn usb_read
376 //* \brief Read available data from Endpoint OUT
377 //*----------------------------------------------------------------------------
378 uint32_t usb_read(byte_t* data, size_t len) {
379 byte_t bank = btReceiveBank;
380 uint32_t packetSize, nbBytesRcv = 0;
381 uint32_t time_out = 0;
382
383 while (len) {
384 if (!usb_check()) break;
385
386 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
387 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
388 len -= packetSize;
389 while(packetSize--)
390 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
391 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);
392 if (bank == AT91C_UDP_RX_DATA_BK0) {
393 bank = AT91C_UDP_RX_DATA_BK1;
394 } else {
395 bank = AT91C_UDP_RX_DATA_BK0;
396 }
397 }
398 if (time_out++ == 0x1fff) break;
399 }
400
401 btReceiveBank = bank;
402 return nbBytesRcv;
403 }
404
405
406 //*----------------------------------------------------------------------------
407 //* \fn usb_write
408 //* \brief Send through endpoint 2
409 //*----------------------------------------------------------------------------
410 uint32_t usb_write(const byte_t* data, const size_t len) {
411 size_t length = len;
412 uint32_t cpt = 0;
413
414 if (!length) return 0;
415 if (!usb_check()) return 0;
416
417 // Send the first packet
418 cpt = MIN(length, AT91C_EP_IN_SIZE);
419 length -= cpt;
420 while (cpt--) {
421 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
422 }
423 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
424
425 while (length) {
426 // Fill the next bank
427 cpt = MIN(length, AT91C_EP_IN_SIZE);
428 length -= cpt;
429 while (cpt--) {
430 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
431 }
432 // Wait for the previous bank to be sent
433 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
434 if (!usb_check()) return length;
435 }
436 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
437 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
438 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
439 }
440
441 // Wait for the end of transfer
442 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
443 if (!usb_check()) return length;
444 }
445
446 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
447 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
448
449 return length;
450 }
451
452
453 //*----------------------------------------------------------------------------
454 //* \fn AT91F_USB_SendData
455 //* \brief Send Data through the control endpoint
456 //*----------------------------------------------------------------------------
457 unsigned int csrTab[100] = {0x00};
458 unsigned char csrIdx = 0;
459
460 static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
461 uint32_t cpt = 0;
462 AT91_REG csr;
463
464 do {
465 cpt = MIN(length, 8);
466 length -= cpt;
467
468 while (cpt--)
469 pUdp->UDP_FDR[0] = *pData++;
470
471 if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
472 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
473 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
474 }
475
476 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
477 do {
478 csr = pUdp->UDP_CSR[AT91C_EP_CONTROL];
479
480 // Data IN stage has been stopped by a status OUT
481 if (csr & AT91C_UDP_RX_DATA_BK0) {
482 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
483 return;
484 }
485 } while ( !(csr & AT91C_UDP_TXCOMP) );
486
487 } while (length);
488
489 if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
490 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
491 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
492 }
493 }
494
495
496 //*----------------------------------------------------------------------------
497 //* \fn AT91F_USB_SendZlp
498 //* \brief Send zero length packet through the control endpoint
499 //*----------------------------------------------------------------------------
500 void AT91F_USB_SendZlp(AT91PS_UDP pUdp) {
501 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
502 while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) );
503 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
504 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP);
505 }
506
507
508 //*----------------------------------------------------------------------------
509 //* \fn AT91F_USB_SendStall
510 //* \brief Stall the control endpoint
511 //*----------------------------------------------------------------------------
512 void AT91F_USB_SendStall(AT91PS_UDP pUdp) {
513 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
514 while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) );
515 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
516 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
517 }
518
519
520 //*----------------------------------------------------------------------------
521 //* \fn AT91F_CDC_Enumerate
522 //* \brief This function is a callback invoked when a SETUP packet is received
523 //*----------------------------------------------------------------------------
524 void AT91F_CDC_Enumerate() {
525 byte_t bmRequestType, bRequest;
526 uint16_t wValue, wIndex, wLength, wStatus;
527
528 if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) )
529 return;
530
531 bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
532 bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
533 wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
534 wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
535 wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
536 wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
537 wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
538 wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
539
540 if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
541 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
542 while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) );
543 }
544 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
545 while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) );
546
547 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
548 switch ((bRequest << 8) | bmRequestType) {
549 case STD_GET_DESCRIPTOR:
550 if (wValue == 0x100) // Return Device Descriptor
551 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
552 else if (wValue == 0x200) // Return Configuration Descriptor
553 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
554 else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
555 const char *strDescriptor = getStringDescriptor(wValue & 0xff);
556 if (strDescriptor != NULL) {
557 AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
558 } else {
559 AT91F_USB_SendStall(pUdp);
560 }
561 }
562 else
563 AT91F_USB_SendStall(pUdp);
564 break;
565 case STD_SET_ADDRESS:
566 AT91F_USB_SendZlp(pUdp);
567 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);
568 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
569 break;
570 case STD_SET_CONFIGURATION:
571 btConfiguration = wValue;
572 AT91F_USB_SendZlp(pUdp);
573 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
574 pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
575 pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
576 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
577 break;
578 case STD_GET_CONFIGURATION:
579 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
580 break;
581 case STD_GET_STATUS_ZERO:
582 wStatus = 0; // Device is Bus powered, remote wakeup disabled
583 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
584 break;
585 case STD_GET_STATUS_INTERFACE:
586 wStatus = 0; // reserved for future use
587 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
588 break;
589 case STD_GET_STATUS_ENDPOINT:
590 wStatus = 0;
591 wIndex &= 0x0F;
592 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
593 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
594 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
595 }
596 else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
597 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
598 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
599 }
600 else
601 AT91F_USB_SendStall(pUdp);
602 break;
603 case STD_SET_FEATURE_ZERO:
604 AT91F_USB_SendStall(pUdp);
605 break;
606 case STD_SET_FEATURE_INTERFACE:
607 AT91F_USB_SendZlp(pUdp);
608 break;
609 case STD_SET_FEATURE_ENDPOINT:
610 wIndex &= 0x0F;
611 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
612 pUdp->UDP_CSR[wIndex] = 0;
613 AT91F_USB_SendZlp(pUdp);
614 }
615 else
616 AT91F_USB_SendStall(pUdp);
617 break;
618 case STD_CLEAR_FEATURE_ZERO:
619 AT91F_USB_SendStall(pUdp);
620 break;
621 case STD_CLEAR_FEATURE_INTERFACE:
622 AT91F_USB_SendZlp(pUdp);
623 break;
624 case STD_CLEAR_FEATURE_ENDPOINT:
625 wIndex &= 0x0F;
626 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
627 if (wIndex == AT91C_EP_OUT)
628 pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
629 else if (wIndex == AT91C_EP_IN)
630 pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
631 else if (wIndex == AT91C_EP_NOTIFY)
632 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
633 AT91F_USB_SendZlp(pUdp);
634 }
635 else
636 AT91F_USB_SendStall(pUdp);
637 break;
638
639 // handle CDC class requests
640 case SET_LINE_CODING:
641 while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) );
642 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
643 AT91F_USB_SendZlp(pUdp);
644 break;
645 case GET_LINE_CODING:
646 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
647 break;
648 case SET_CONTROL_LINE_STATE:
649 btConnection = wValue;
650 AT91F_USB_SendZlp(pUdp);
651 break;
652 default:
653 AT91F_USB_SendStall(pUdp);
654 break;
655 }
656 }
Impressum, Datenschutz