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