]> git.zerfleddert.de Git - proxmark3-svn/blob - common/usb_cdc.c
usb communication (device side) refactoring
[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
37 #include <stddef.h>
38 #include <stdint.h>
39 #include <stdbool.h>
40
41 #include "common.h"
42 #include "at91sam7s512.h"
43 #include "config_gpio.h"
44
45 #define AT91C_EP_CONTROL 0
46 #define AT91C_EP_OUT 1
47 #define AT91C_EP_IN 2
48 #define AT91C_EP_NOTIFY 3
49 #define AT91C_EP_OUT_SIZE 0x40
50 #define AT91C_EP_IN_SIZE 0x40
51
52 // Language must always be 0.
53 #define STR_LANGUAGE_CODES 0x00
54 #define STR_MANUFACTURER 0x01
55 #define STR_PRODUCT 0x02
56
57
58 static const char devDescriptor[] = {
59 /* Device descriptor */
60 0x12, // bLength
61 0x01, // bDescriptorType
62 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)
63 0x02, // bDeviceClass: (Communication Device Class)
64 0x00, // bDeviceSubclass: (unused at this time)
65 0x00, // bDeviceProtocol: (unused at this time)
66 0x08, // bMaxPacketSize0
67 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)
68 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)
69 0x01,0x00, // Device release number (0001)
70 STR_MANUFACTURER, // iManufacturer
71 STR_PRODUCT, // iProduct
72 0x00, // iSerialNumber
73 0x01 // bNumConfigs
74 };
75
76
77 static const char cfgDescriptor[] = {
78 /* ============== CONFIGURATION 1 =========== */
79 /* Configuration 1 descriptor */
80 0x09, // CbLength
81 0x02, // CbDescriptorType
82 0x43, // CwTotalLength 2 EP + Control
83 0x00,
84 0x02, // CbNumInterfaces
85 0x01, // CbConfigurationValue
86 0x00, // CiConfiguration
87 0x80, // CbmAttributes (Bus Powered)
88 0x4B, // CMaxPower (150mA max current drawn from bus)
89
90 /* Interface 0 Descriptor: Communication Class Interface */
91 0x09, // bLength
92 0x04, // bDescriptorType
93 0x00, // bInterfaceNumber
94 0x00, // bAlternateSetting
95 0x01, // bNumEndpoints
96 0x02, // bInterfaceClass: Communication Interface Class
97 0x02, // bInterfaceSubclass: Abstract Control Model
98 0x01, // bInterfaceProtocol: Common AT Commands, V.25ter
99 0x00, // iInterface
100
101 /* Header Functional Descriptor */
102 0x05, // bFunction Length
103 0x24, // bDescriptor type: CS_INTERFACE
104 0x00, // bDescriptor subtype: Header Functional Descriptor
105 0x10, // bcdCDC:1.1
106 0x01,
107
108 /* ACM Functional Descriptor */
109 0x04, // bFunctionLength
110 0x24, // bDescriptor Type: CS_INTERFACE
111 0x02, // bDescriptor Subtype: Abstract Control Management Functional Descriptor
112 0x02, // bmCapabilities: D1: Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
113
114 /* Union Functional Descriptor */
115 0x05, // bFunctionLength
116 0x24, // bDescriptorType: CS_INTERFACE
117 0x06, // bDescriptor Subtype: Union Functional Descriptor
118 0x00, // bMasterInterface: Communication Class Interface
119 0x01, // bSlaveInterface0: Data Class Interface
120
121 /* Call Management Functional Descriptor */
122 0x05, // bFunctionLength
123 0x24, // bDescriptor Type: CS_INTERFACE
124 0x01, // bDescriptor Subtype: Call Management Functional Descriptor
125 0x00, // bmCapabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself
126 0x01, // bDataInterface: Data Class Interface 1
127
128 /* Endpoint 1 descriptor */
129 0x07, // bLength
130 0x05, // bDescriptorType
131 0x83, // bEndpointAddress: Endpoint 03 - IN
132 0x03, // bmAttributes: INT
133 0x08, // wMaxPacketSize: 8
134 0x00,
135 0xFF, // bInterval
136
137 /* Interface 1 Descriptor: Data Class Interface */
138 0x09, // bLength
139 0x04, // bDescriptorType
140 0x01, // bInterfaceNumber
141 0x00, // bAlternateSetting
142 0x02, // bNumEndpoints
143 0x0A, // bInterfaceClass: Data Interface Class
144 0x00, // bInterfaceSubclass: not used
145 0x00, // bInterfaceProtocol: No class specific protocol required)
146 0x00, // iInterface
147
148 /* Endpoint 1 descriptor */
149 0x07, // bLength
150 0x05, // bDescriptorType
151 0x01, // bEndpointAddress: Endpoint 01 - OUT
152 0x02, // bmAttributes: BULK
153 AT91C_EP_OUT_SIZE, // wMaxPacketSize
154 0x00,
155 0x00, // bInterval
156
157 /* Endpoint 2 descriptor */
158 0x07, // bLength
159 0x05, // bDescriptorType
160 0x82, // bEndpointAddress: Endpoint 02 - IN
161 0x02, // bmAttributes: BULK
162 AT91C_EP_IN_SIZE, // wMaxPacketSize
163 0x00,
164 0x00 // bInterval
165 };
166
167
168 static const char StrDescLanguageCodes[] = {
169 4, // Length
170 0x03, // Type is string
171 0x09, 0x04 // supported language Code 0 = 0x0409 (English)
172 };
173
174
175 // Note: ModemManager (Linux) ignores Proxmark3 devices by matching the
176 // manufacturer string "proxmark.org". Don't change this.
177 static const char StrDescManufacturer[] = {
178 26, // Length
179 0x03, // Type is string
180 'p', 0x00,
181 'r', 0x00,
182 'o', 0x00,
183 'x', 0x00,
184 'm', 0x00,
185 'a', 0x00,
186 'r', 0x00,
187 'k', 0x00,
188 '.', 0x00,
189 'o', 0x00,
190 'r', 0x00,
191 'g', 0x00
192 };
193
194
195 static const char StrDescProduct[] = {
196 20, // Length
197 0x03, // Type is string
198 'p', 0x00,
199 'r', 0x00,
200 'o', 0x00,
201 'x', 0x00,
202 'm', 0x00,
203 'a', 0x00,
204 'r', 0x00,
205 'k', 0x00,
206 '3', 0x00
207 };
208
209
210 static const char* getStringDescriptor(uint8_t idx) {
211 switch (idx) {
212 case STR_LANGUAGE_CODES:
213 return StrDescLanguageCodes;
214 case STR_MANUFACTURER:
215 return StrDescManufacturer;
216 case STR_PRODUCT:
217 return StrDescProduct;
218 default:
219 return NULL;
220 }
221 }
222
223
224 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect
225 #define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
226 |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
227 |AT91C_UDP_TXCOMP
228
229
230 // Clear flags in the UDP_CSR register
231 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
232 volatile unsigned int reg; \
233 reg = pUdp->UDP_CSR[(endpoint)]; \
234 reg |= REG_NO_EFFECT_1_ALL; \
235 reg &= ~(flags); \
236 pUdp->UDP_CSR[(endpoint)] = reg; \
237 }
238
239
240 // Set flags in the UDP_CSR register
241 #define UDP_SET_EP_FLAGS(endpoint, flags) { \
242 volatile unsigned int reg; \
243 reg = pUdp->UDP_CSR[(endpoint)]; \
244 reg |= REG_NO_EFFECT_1_ALL; \
245 reg |= (flags); \
246 pUdp->UDP_CSR[(endpoint)] = reg; \
247 }
248
249
250 /* USB standard request codes */
251 #define STD_GET_STATUS_ZERO 0x0080
252 #define STD_GET_STATUS_INTERFACE 0x0081
253 #define STD_GET_STATUS_ENDPOINT 0x0082
254
255 #define STD_CLEAR_FEATURE_ZERO 0x0100
256 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
257 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
258
259 #define STD_SET_FEATURE_ZERO 0x0300
260 #define STD_SET_FEATURE_INTERFACE 0x0301
261 #define STD_SET_FEATURE_ENDPOINT 0x0302
262
263 #define STD_SET_ADDRESS 0x0500
264 #define STD_GET_DESCRIPTOR 0x0680
265 #define STD_SET_DESCRIPTOR 0x0700
266 #define STD_GET_CONFIGURATION 0x0880
267 #define STD_SET_CONFIGURATION 0x0900
268 #define STD_GET_INTERFACE 0x0A81
269 #define STD_SET_INTERFACE 0x0B01
270 #define STD_SYNCH_FRAME 0x0C82
271
272 /* CDC Class Specific Request Code */
273 #define GET_LINE_CODING 0x21A1
274 #define SET_LINE_CODING 0x2021
275 #define SET_CONTROL_LINE_STATE 0x2221
276
277
278 typedef struct {
279 unsigned int dwDTERRate;
280 char bCharFormat;
281 char bParityType;
282 char bDataBits;
283 } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
284
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 static void AT91F_CDC_Enumerate();
294
295 AT91PS_UDP pUdp = AT91C_BASE_UDP;
296 uint8_t btConfiguration = 0;
297 uint8_t btConnection = 0;
298 uint8_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 static 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 if (!usb_check()) return false;
375 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
376 }
377
378
379 /**
380 In github PR #129, some users appears to get a false positive from
381 usb_poll, which returns true, but the usb_read operation
382 still returns 0.
383 This check is basically the same as above, but also checks
384 that the length available to read is non-zero, thus hopefully fixes the
385 bug.
386 **/
387 bool usb_poll_validate_length() {
388 if (!usb_check()) return false;
389 if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
390 return (pUdp->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
391 }
392
393
394 //*----------------------------------------------------------------------------
395 //* \fn usb_read
396 //* \brief Read available data from Endpoint OUT
397 //*----------------------------------------------------------------------------
398 static uint32_t usb_read(uint8_t* data, size_t len) {
399 uint8_t bank = btReceiveBank;
400 uint32_t packetSize, nbBytesRcv = 0;
401 uint32_t time_out = 0;
402
403 while (len) {
404 if (!usb_check()) break;
405
406 if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) {
407 packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, len);
408 len -= packetSize;
409 while (packetSize--)
410 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
411 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);
412 if (bank == AT91C_UDP_RX_DATA_BK0) {
413 bank = AT91C_UDP_RX_DATA_BK1;
414 } else {
415 bank = AT91C_UDP_RX_DATA_BK0;
416 }
417 }
418 if (time_out++ == 0x1fff) break;
419 }
420
421 btReceiveBank = bank;
422 return nbBytesRcv;
423 }
424
425
426 //*----------------------------------------------------------------------------
427 //* \fn usb_write
428 //* \brief Send through endpoint 2
429 //*----------------------------------------------------------------------------
430 static uint32_t usb_write(const uint8_t* data, const size_t len) {
431 size_t length = len;
432 uint32_t cpt = 0;
433
434 if (!length) return 0;
435 if (!usb_check()) return 0;
436
437 // Send the first packet
438 cpt = MIN(length, AT91C_EP_IN_SIZE);
439 length -= cpt;
440 while (cpt--) {
441 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
442 }
443 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
444
445 while (length) {
446 // Fill the next bank
447 cpt = MIN(length, AT91C_EP_IN_SIZE);
448 length -= cpt;
449 while (cpt--) {
450 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
451 }
452 // Wait for the previous bank to be sent
453 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
454 if (!usb_check()) return length;
455 }
456 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
457 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
458 /* wait */;
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 /* wait */;
470
471 return length;
472 }
473
474
475 //*----------------------------------------------------------------------------
476 //* \fn AT91F_USB_SendData
477 //* \brief Send Data through the control endpoint
478 //*----------------------------------------------------------------------------
479 static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) {
480 uint32_t cpt = 0;
481 AT91_REG csr;
482
483 do {
484 cpt = MIN(length, 8);
485 length -= cpt;
486
487 while (cpt--)
488 pUdp->UDP_FDR[0] = *pData++;
489
490 if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
491 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
492 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
493 /* wait */;
494 }
495
496 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
497 do {
498 csr = pUdp->UDP_CSR[AT91C_EP_CONTROL];
499
500 // Data IN stage has been stopped by a status OUT
501 if (csr & AT91C_UDP_RX_DATA_BK0) {
502 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
503 return;
504 }
505 } while (!(csr & AT91C_UDP_TXCOMP));
506
507 } while (length);
508
509 if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
510 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
511 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
512 /* wait */;
513 }
514 }
515
516
517 //*----------------------------------------------------------------------------
518 //* \fn AT91F_USB_SendZlp
519 //* \brief Send zero length packet through the control endpoint
520 //*----------------------------------------------------------------------------
521 static 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 /* wait */;
525 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
526 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
527 /* wait */;
528 }
529
530
531 //*----------------------------------------------------------------------------
532 //* \fn AT91F_USB_SendStall
533 //* \brief Stall the control endpoint
534 //*----------------------------------------------------------------------------
535 static void AT91F_USB_SendStall(AT91PS_UDP pUdp) {
536 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
537 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR))
538 /* wait */;
539 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
540 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR))
541 /* wait */;
542 }
543
544
545 //*----------------------------------------------------------------------------
546 //* \fn AT91F_CDC_Enumerate
547 //* \brief This function is a callback invoked when a SETUP packet is received
548 //*----------------------------------------------------------------------------
549 static void AT91F_CDC_Enumerate() {
550 uint8_t bmRequestType, bRequest;
551 uint16_t wValue, wIndex, wLength, wStatus;
552
553 if (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP))
554 return;
555
556 bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
557 bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
558 wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
559 wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
560 wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
561 wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
562 wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
563 wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
564
565 if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
566 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
567 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR))
568 /* wait */;
569 }
570 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
571 while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)
572 /* wait */;
573
574 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
575 switch ((bRequest << 8) | bmRequestType) {
576 case STD_GET_DESCRIPTOR:
577 if (wValue == 0x100) // Return Device Descriptor
578 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
579 else if (wValue == 0x200) // Return Configuration Descriptor
580 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
581 else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
582 const char *strDescriptor = getStringDescriptor(wValue & 0xff);
583 if (strDescriptor != NULL) {
584 AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
585 } else {
586 AT91F_USB_SendStall(pUdp);
587 }
588 }
589 else
590 AT91F_USB_SendStall(pUdp);
591 break;
592 case STD_SET_ADDRESS:
593 AT91F_USB_SendZlp(pUdp);
594 pUdp->UDP_FADDR = (AT91C_UDP_FEN | wValue);
595 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
596 break;
597 case STD_SET_CONFIGURATION:
598 btConfiguration = wValue;
599 AT91F_USB_SendZlp(pUdp);
600 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
601 pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
602 pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
603 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
604 break;
605 case STD_GET_CONFIGURATION:
606 AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration));
607 break;
608 case STD_GET_STATUS_ZERO:
609 wStatus = 0; // Device is Bus powered, remote wakeup disabled
610 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
611 break;
612 case STD_GET_STATUS_INTERFACE:
613 wStatus = 0; // reserved for future use
614 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
615 break;
616 case STD_GET_STATUS_ENDPOINT:
617 wStatus = 0;
618 wIndex &= 0x0F;
619 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
620 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
621 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
622 } else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
623 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
624 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
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 } else
640 AT91F_USB_SendStall(pUdp);
641 break;
642 case STD_CLEAR_FEATURE_ZERO:
643 AT91F_USB_SendStall(pUdp);
644 break;
645 case STD_CLEAR_FEATURE_INTERFACE:
646 AT91F_USB_SendZlp(pUdp);
647 break;
648 case STD_CLEAR_FEATURE_ENDPOINT:
649 wIndex &= 0x0F;
650 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
651 if (wIndex == AT91C_EP_OUT)
652 pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
653 else if (wIndex == AT91C_EP_IN)
654 pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
655 else if (wIndex == AT91C_EP_NOTIFY)
656 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
657 AT91F_USB_SendZlp(pUdp);
658 }
659 else
660 AT91F_USB_SendStall(pUdp);
661 break;
662
663 // handle CDC class requests
664 case SET_LINE_CODING:
665 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0))
666 /* wait */;
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 }
682
683
684 //***************************************************************************
685 // Interface to the main program
686 //***************************************************************************
687
688 // The function to receive a command from the client via USB
689 bool cmd_receive(UsbCommand* cmd) {
690
691 // Check if there is a usb packet available
692 if (!usb_poll())
693 return false;
694
695 // Try to retrieve the available command frame
696 size_t rxlen = usb_read((uint8_t*)cmd, sizeof(UsbCommand));
697
698 // Check if the transfer was complete
699 if (rxlen != sizeof(UsbCommand))
700 return false;
701
702 // Received command successfully
703 return true;
704 }
705
706
707 // The function to send a response to the client via USB
708 bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) {
709 UsbCommand txcmd;
710
711 for (size_t i = 0; i < sizeof(UsbCommand); i++) {
712 ((uint8_t*)&txcmd)[i] = 0x00;
713 }
714
715 // Compose the outgoing command frame
716 txcmd.cmd = cmd;
717 txcmd.arg[0] = arg0;
718 txcmd.arg[1] = arg1;
719 txcmd.arg[2] = arg2;
720
721 // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
722 if (data && len) {
723 len = MIN(len, USB_CMD_DATA_SIZE);
724 for (size_t i = 0; i < len; i++) {
725 txcmd.d.asBytes[i] = ((uint8_t*)data)[i];
726 }
727 }
728
729 // Send frame and make sure all bytes are transmitted
730 if (usb_write((uint8_t*)&txcmd, sizeof(UsbCommand)) != 0) return false;
731
732 return true;
733 }
Impressum, Datenschutz