]> git.zerfleddert.de Git - proxmark3-svn/blob - common/usb_cdc.c
Merge pull request #969 from pwpiwi/gcc10_fixes
[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 | AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP | AT91C_UDP_TXCOMP)
226
227
228 // Clear flags in the UDP_CSR register
229 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
230 volatile unsigned int reg; \
231 reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \
232 reg |= REG_NO_EFFECT_1_ALL; \
233 reg &= ~(flags); \
234 AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \
235 }
236
237
238 // Set flags in the UDP_CSR register
239 #define UDP_SET_EP_FLAGS(endpoint, flags) { \
240 volatile unsigned int reg; \
241 reg = AT91C_BASE_UDP->UDP_CSR[(endpoint)]; \
242 reg |= REG_NO_EFFECT_1_ALL; \
243 reg |= (flags); \
244 AT91C_BASE_UDP->UDP_CSR[(endpoint)] = reg; \
245 }
246
247
248 /* USB standard request codes */
249 #define STD_GET_STATUS_ZERO 0x0080
250 #define STD_GET_STATUS_INTERFACE 0x0081
251 #define STD_GET_STATUS_ENDPOINT 0x0082
252
253 #define STD_CLEAR_FEATURE_ZERO 0x0100
254 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
255 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
256
257 #define STD_SET_FEATURE_ZERO 0x0300
258 #define STD_SET_FEATURE_INTERFACE 0x0301
259 #define STD_SET_FEATURE_ENDPOINT 0x0302
260
261 #define STD_SET_ADDRESS 0x0500
262 #define STD_GET_DESCRIPTOR 0x0680
263 #define STD_SET_DESCRIPTOR 0x0700
264 #define STD_GET_CONFIGURATION 0x0880
265 #define STD_SET_CONFIGURATION 0x0900
266 #define STD_GET_INTERFACE 0x0A81
267 #define STD_SET_INTERFACE 0x0B01
268 #define STD_SYNCH_FRAME 0x0C82
269
270 /* CDC Class Specific Request Code */
271 #define GET_LINE_CODING 0x21A1
272 #define SET_LINE_CODING 0x2021
273 #define SET_CONTROL_LINE_STATE 0x2221
274
275
276 typedef struct {
277 unsigned int dwDTERRate;
278 char bCharFormat;
279 char bParityType;
280 char bDataBits;
281 } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
282
283
284 static AT91S_CDC_LINE_CODING line = {
285 115200, // baudrate
286 0, // 1 Stop Bit
287 0, // None Parity
288 8}; // 8 Data bits
289
290
291 static uint8_t btConfiguration = 0;
292 static uint8_t btConnection = 0;
293 static uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
294
295
296 //*----------------------------------------------------------------------------
297 //* \fn usb_disable
298 //* \brief This function deactivates the USB device
299 //*----------------------------------------------------------------------------
300 void usb_disable() {
301 // Disconnect the USB device
302 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
303
304 // Clear all lingering interrupts
305 if (AT91C_BASE_UDP->UDP_ISR & AT91C_UDP_ENDBUSRES) {
306 AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
307 }
308 }
309
310
311 //*----------------------------------------------------------------------------
312 //* \fn usb_enable
313 //* \brief This function Activates the USB device
314 //*----------------------------------------------------------------------------
315 void usb_enable() {
316 // Set the PLL USB Divider
317 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
318
319 // Specific Chip USB Initialisation
320 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
321 AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_UDP;
322 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
323
324 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
325 // Set in PIO mode and Configure in Output
326 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
327 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
328
329 // Clear for set the Pullup resistor
330 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
331
332 // Disconnect and reconnect USB controller for 100ms
333 usb_disable();
334
335 // Wait for a short while
336 for (volatile size_t i = 0; i < 0x100000; i++);
337
338 // Reconnect USB reconnect
339 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
340 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
341 }
342
343
344 //*----------------------------------------------------------------------------
345 //* \fn AT91F_USB_SendZlp
346 //* \brief Send zero length packet through an endpoint
347 //*----------------------------------------------------------------------------
348 static void AT91F_USB_SendZlp(uint8_t endpoint) {
349 UDP_SET_EP_FLAGS(endpoint, AT91C_UDP_TXPKTRDY);
350 while (!(AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP))
351 /* wait */;
352 UDP_CLEAR_EP_FLAGS(endpoint, AT91C_UDP_TXCOMP);
353 while (AT91C_BASE_UDP->UDP_CSR[endpoint] & AT91C_UDP_TXCOMP)
354 /* wait */;
355 }
356
357
358 //*----------------------------------------------------------------------------
359 //* \fn AT91F_USB_SendData
360 //* \brief Send Data through the control endpoint
361 //*----------------------------------------------------------------------------
362 static void AT91F_USB_SendData(const char *pData, uint32_t length) {
363 uint32_t cpt = 0;
364 AT91_REG csr;
365
366 do {
367 cpt = MIN(length, 8);
368 length -= cpt;
369
370 while (cpt--)
371 AT91C_BASE_UDP->UDP_FDR[0] = *pData++;
372
373 if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
374 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
375 while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
376 /* wait */;
377 }
378
379 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
380 do {
381 csr = AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL];
382
383 // Data IN stage has been stopped by a status OUT
384 if (csr & AT91C_UDP_RX_DATA_BK0) {
385 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
386 return;
387 }
388 } while (!(csr & AT91C_UDP_TXCOMP));
389
390 } while (length);
391
392 if (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
393 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
394 while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)
395 /* wait */;
396 }
397 }
398
399
400 //*----------------------------------------------------------------------------
401 //* \fn AT91F_USB_SendStall
402 //* \brief Stall the control endpoint
403 //*----------------------------------------------------------------------------
404 static void AT91F_USB_SendStall(void) {
405 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
406 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR))
407 /* wait */;
408 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
409 while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR))
410 /* wait */;
411 }
412
413
414 //*----------------------------------------------------------------------------
415 //* \fn AT91F_CDC_Enumerate
416 //* \brief This function is a callback invoked when a SETUP packet is received
417 //*----------------------------------------------------------------------------
418 static void AT91F_CDC_Enumerate() {
419 uint8_t bmRequestType, bRequest;
420 uint16_t wValue, wIndex, wLength, wStatus;
421
422 if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP))
423 return;
424
425 bmRequestType = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];
426 bRequest = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL];
427 wValue = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
428 wValue |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
429 wIndex = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
430 wIndex |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
431 wLength = (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
432 wLength |= (AT91C_BASE_UDP->UDP_FDR[AT91C_EP_CONTROL] << 8);
433
434 if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
435 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
436 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR))
437 /* wait */;
438 }
439 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
440 while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)
441 /* wait */;
442
443 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
444 switch ((bRequest << 8) | bmRequestType) {
445 case STD_GET_DESCRIPTOR:
446 if (wValue == 0x100) // Return Device Descriptor
447 AT91F_USB_SendData(devDescriptor, MIN(sizeof(devDescriptor), wLength));
448 else if (wValue == 0x200) // Return Configuration Descriptor
449 AT91F_USB_SendData(cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
450 else if ((wValue & 0xF00) == 0x300) { // Return String Descriptor
451 const char *strDescriptor = getStringDescriptor(wValue & 0xff);
452 if (strDescriptor != NULL) {
453 AT91F_USB_SendData(strDescriptor, MIN(strDescriptor[0], wLength));
454 } else {
455 AT91F_USB_SendStall();
456 }
457 }
458 else
459 AT91F_USB_SendStall();
460 break;
461 case STD_SET_ADDRESS:
462 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
463 AT91C_BASE_UDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
464 AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
465 break;
466 case STD_SET_CONFIGURATION:
467 btConfiguration = wValue;
468 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
469 AT91C_BASE_UDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
470 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
471 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
472 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
473 break;
474 case STD_GET_CONFIGURATION:
475 AT91F_USB_SendData((char *) &(btConfiguration), sizeof(btConfiguration));
476 break;
477 case STD_GET_STATUS_ZERO:
478 wStatus = 0; // Device is Bus powered, remote wakeup disabled
479 AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
480 break;
481 case STD_GET_STATUS_INTERFACE:
482 wStatus = 0; // reserved for future use
483 AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
484 break;
485 case STD_GET_STATUS_ENDPOINT:
486 wStatus = 0;
487 wIndex &= 0x0F;
488 if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
489 wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
490 AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
491 } else if ((AT91C_BASE_UDP->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
492 wStatus = (AT91C_BASE_UDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
493 AT91F_USB_SendData((char *) &wStatus, sizeof(wStatus));
494 } else
495 AT91F_USB_SendStall();
496 break;
497 case STD_SET_FEATURE_ZERO:
498 AT91F_USB_SendStall();
499 break;
500 case STD_SET_FEATURE_INTERFACE:
501 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
502 break;
503 case STD_SET_FEATURE_ENDPOINT:
504 wIndex &= 0x0F;
505 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
506 AT91C_BASE_UDP->UDP_CSR[wIndex] = 0;
507 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
508 } else
509 AT91F_USB_SendStall();
510 break;
511 case STD_CLEAR_FEATURE_ZERO:
512 AT91F_USB_SendStall();
513 break;
514 case STD_CLEAR_FEATURE_INTERFACE:
515 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
516 break;
517 case STD_CLEAR_FEATURE_ENDPOINT:
518 wIndex &= 0x0F;
519 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
520 if (wIndex == AT91C_EP_OUT)
521 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
522 else if (wIndex == AT91C_EP_IN)
523 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
524 else if (wIndex == AT91C_EP_NOTIFY)
525 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
526 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
527 }
528 else
529 AT91F_USB_SendStall();
530 break;
531
532 // handle CDC class requests
533 case SET_LINE_CODING:
534 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0))
535 /* wait */;
536 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
537 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
538 break;
539 case GET_LINE_CODING:
540 AT91F_USB_SendData((char *) &line, MIN(sizeof(line), wLength));
541 break;
542 case SET_CONTROL_LINE_STATE:
543 btConnection = wValue;
544 AT91F_USB_SendZlp(AT91C_EP_CONTROL);
545 break;
546 default:
547 AT91F_USB_SendStall();
548 break;
549 }
550 }
551
552
553 //*----------------------------------------------------------------------------
554 //* \fn usb_check
555 //* \brief Test if the device is configured and handle enumeration
556 //*----------------------------------------------------------------------------
557 static bool usb_check() {
558 AT91_REG isr = AT91C_BASE_UDP->UDP_ISR;
559
560 if (isr & AT91C_UDP_ENDBUSRES) {
561 AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
562 // reset all endpoints
563 AT91C_BASE_UDP->UDP_RSTEP = (unsigned int)-1;
564 AT91C_BASE_UDP->UDP_RSTEP = 0;
565 // Enable the function
566 AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;
567 // Configure endpoint 0
568 AT91C_BASE_UDP->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
569 } else if (isr & AT91C_UDP_EPINT0) {
570 AT91C_BASE_UDP->UDP_ICR = AT91C_UDP_EPINT0;
571 AT91F_CDC_Enumerate();
572 }
573 return (btConfiguration) ? true : false;
574 }
575
576
577 bool usb_poll() {
578 if (!usb_check()) return false;
579 return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
580 }
581
582
583 /**
584 In github PR #129, some users appears to get a false positive from
585 usb_poll, which returns true, but the usb_read operation
586 still returns 0.
587 This check is basically the same as above, but also checks
588 that the length available to read is non-zero, thus hopefully fixes the
589 bug.
590 **/
591 bool usb_poll_validate_length() {
592 if (!usb_check()) return false;
593 if (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false;
594 return (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16) > 0;
595 }
596
597
598 //*----------------------------------------------------------------------------
599 //* \fn usb_read
600 //* \brief Read available data from Endpoint OUT
601 //*----------------------------------------------------------------------------
602 static uint32_t usb_read(uint8_t* data, size_t len) {
603 uint8_t bank = btReceiveBank;
604 uint32_t packetSize, nbBytesRcv = 0;
605 uint32_t time_out = 0;
606
607 while (len) {
608 if (!usb_check()) break;
609
610 if ( AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] & bank ) {
611 packetSize = MIN(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_OUT] >> 16, len);
612 len -= packetSize;
613 while (packetSize--)
614 data[nbBytesRcv++] = AT91C_BASE_UDP->UDP_FDR[AT91C_EP_OUT];
615 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank);
616 if (bank == AT91C_UDP_RX_DATA_BK0) {
617 bank = AT91C_UDP_RX_DATA_BK1;
618 } else {
619 bank = AT91C_UDP_RX_DATA_BK0;
620 }
621 }
622 if (time_out++ == 0x1fff) break;
623 }
624
625 btReceiveBank = bank;
626 return nbBytesRcv;
627 }
628
629
630 //*----------------------------------------------------------------------------
631 //* \fn usb_write
632 //* \brief Send through endpoint 2
633 //*----------------------------------------------------------------------------
634 static uint32_t usb_write(const uint8_t* data, const size_t len) {
635 size_t length = len;
636 uint32_t cpt = 0;
637
638 if (!length) return 0;
639 if (!usb_check()) return 0;
640
641 // Send the first packet
642 cpt = MIN(length, AT91C_EP_IN_SIZE);
643 length -= cpt;
644 while (cpt--) {
645 AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;
646 }
647 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
648 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))
649 /* wait */;
650
651 while (length) {
652 // Fill the next bank
653 cpt = MIN(length, AT91C_EP_IN_SIZE);
654 length -= cpt;
655 while (cpt--) {
656 AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *data++;
657 }
658 // Wait for the previous bank to be sent
659 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
660 if (!usb_check()) return length;
661 }
662 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
663 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY))
664 /* wait */;
665 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
666 while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
667 /* wait */;
668 }
669
670 // Wait for the end of transfer
671 while (!(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
672 if (!usb_check()) return length;
673 }
674 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
675 while (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)
676 /* wait */;
677
678 if (len % AT91C_EP_IN_SIZE == 0) { // need to send a zero length packet to complete the transfer
679 AT91F_USB_SendZlp(AT91C_EP_IN);
680 }
681
682 return length;
683 }
684
685
686 //***************************************************************************
687 // Interface to the main program
688 //***************************************************************************
689
690 // The function to receive a command from the client via USB
691 bool cmd_receive(UsbCommand* cmd) {
692
693 // Check if there is a usb packet available
694 if (!usb_poll())
695 return false;
696
697 // Try to retrieve the available command frame
698 size_t rxlen = usb_read((uint8_t*)cmd, sizeof(UsbCommand));
699
700 // Check if the transfer was complete
701 if (rxlen != sizeof(UsbCommand))
702 return false;
703
704 // Received command successfully
705 return true;
706 }
707
708
709 // The function to send a response to the client via USB
710 bool cmd_send(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen) {
711
712 UsbResponse txcmd;
713
714 // Compose the outgoing response frame
715 txcmd.cmd = cmd | CMD_VARIABLE_SIZE_FLAG;
716 txcmd.arg[0] = arg0;
717 txcmd.arg[1] = arg1;
718 txcmd.arg[2] = arg2;
719
720 // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
721 if (data) {
722 datalen = MIN(datalen, USB_CMD_DATA_SIZE);
723 for (uint16_t i = 0; i < datalen; i++) {
724 txcmd.d.asBytes[i] = ((uint8_t*)data)[i];
725 }
726 txcmd.datalen = datalen;
727 } else {
728 txcmd.datalen = 0;
729 }
730
731 // Send frame and make sure all bytes are transmitted
732 size_t tx_size = offsetof(UsbResponse, d) + datalen;
733 if (usb_write((uint8_t*)&txcmd, tx_size) != 0) return false;
734
735 return true;
736 }
737
738
739 // For compatibility only: legacy function to send a response with fixed size to the client via USB
740 bool cmd_send_old(uint16_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, uint16_t datalen) {
741
742 UsbCommand txcmd;
743
744 // Compose the outgoing response frame
745 txcmd.cmd = cmd;
746 txcmd.arg[0] = arg0;
747 txcmd.arg[1] = arg1;
748 txcmd.arg[2] = arg2;
749
750 // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE
751 if (data) {
752 datalen = MIN(datalen, USB_CMD_DATA_SIZE);
753 for (uint16_t i = 0; i < datalen; i++) {
754 txcmd.d.asBytes[i] = ((uint8_t*)data)[i];
755 }
756 }
757
758 // Send frame and make sure all bytes are transmitted
759 if (usb_write((uint8_t*)&txcmd, sizeof(UsbCommand)) != 0) return false;
760
761 return true;
762 }
763
Impressum, Datenschutz