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