recover_pk.py: replace secp192r1 by prime192v1
[RRG-proxmark3.git] / common_arm / usb_cdc.c
blobce7bda32501f7df753a5638eb8eda7c3ba88b14d
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // at91sam7s USB CDC device implementation
17 // based on the "Basic USB Example" from ATMEL (doc6123.pdf)
18 //-----------------------------------------------------------------------------
20 #include "usb_cdc.h"
21 #include "proxmark3_arm.h"
22 #include "usart_defs.h"
25 AT91SAM7S256 USB Device Port
26 • Embedded 328-byte dual-port RAM for endpoints
27 • Four endpoints
28 – Endpoint 0: 8 bytes
29 – Endpoint 1 and 2: 64 bytes ping-pong
30 – Endpoint 3: 64 bytes
31 – Ping-pong Mode (two memory banks) for bulk endpoints
35 #define AT91C_EP_CONTROL 0
36 #define AT91C_EP_OUT 1 // cfg bulk out
37 #define AT91C_EP_IN 2 // cfg bulk in
38 #define AT91C_EP_NOTIFY 3 // cfg cdc notification interrup
40 // The endpoint size is defined in usb_cdc.h
42 // Section: USB Descriptors
43 #define USB_DESCRIPTOR_DEVICE 0x01 // DescriptorType for a Device Descriptor.
44 #define USB_DESCRIPTOR_CONFIGURATION 0x02 // DescriptorType for a Configuration Descriptor.
45 #define USB_DESCRIPTOR_STRING 0x03 // DescriptorType for a String Descriptor.
46 #define USB_DESCRIPTOR_INTERFACE 0x04 // DescriptorType for an Interface Descriptor.
47 #define USB_DESCRIPTOR_ENDPOINT 0x05 // DescriptorType for an Endpoint Descriptor.
48 #define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // DescriptorType for a Device Qualifier.
49 #define USB_DESCRIPTOR_OTHER_SPEED 0x07 // DescriptorType for a Other Speed Configuration.
50 #define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // DescriptorType for Interface Power.
51 #define USB_DESCRIPTOR_OTG 0x09 // DescriptorType for an OTG Descriptor.
52 #define USB_DESCRIPTOR_IAD 0x0B // DescriptorType for a Interface Association Descriptor
53 #define USB_DESCRIPTOR_TYPE_BO 0x0F // DescriptorType for a BOS Descriptor.
55 /* Configuration Attributes */
56 #define _DEFAULT (0x01<<7) //Default Value (Bit 7 is set)
57 #define _SELF (0x01<<6) //Self-powered (Supports if set)
58 #define _RWU (0x01<<5) //Remote Wakeup (Supports if set)
59 #define _HNP (0x01 << 1) //HNP (Supports if set)
60 #define _SRP (0x01) //SRP (Supports if set)
62 /* Endpoint Transfer Type */
63 #define _CTRL 0x00 //Control Transfer
64 #define _ISO 0x01 //Isochronous Transfer
65 #define _BULK 0x02 //Bulk Transfer
66 #define _INTERRUPT 0x03 //Interrupt Transfer
68 // (bit7 | 0 = OUT, 1 = IN)
69 #define _EP_IN 0x80
70 #define _EP_OUT 0x00
71 #define _EP01_OUT 0x01
72 #define _EP01_IN 0x81
73 #define _EP02_OUT 0x02
74 #define _EP02_IN 0x82
75 #define _EP03_OUT 0x03
76 #define _EP03_IN 0x83
79 /* WCID specific Request Code */
80 #define MS_OS_DESCRIPTOR_INDEX 0xEE
81 #define MS_VENDOR_CODE 0x1C
82 #define MS_EXTENDED_COMPAT_ID 0x04
83 #define MS_EXTENDED_PROPERTIES 0x05
84 #define MS_WCID_GET_DESCRIPTOR 0xC0
85 #define MS_WCID_GET_FEATURE_DESCRIPTOR 0xC1
87 /* USB standard request code */
88 #define STD_GET_STATUS_ZERO 0x0080
89 #define STD_GET_STATUS_INTERFACE 0x0081
90 #define STD_GET_STATUS_ENDPOINT 0x0082
92 #define STD_CLEAR_FEATURE_ZERO 0x0100
93 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
94 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
96 #define STD_SET_FEATURE_ZERO 0x0300
97 #define STD_SET_FEATURE_INTERFACE 0x0301
98 #define STD_SET_FEATURE_ENDPOINT 0x0302
100 #define STD_SET_ADDRESS 0x0500
101 #define STD_GET_DESCRIPTOR 0x0680
102 #define STD_SET_DESCRIPTOR 0x0700
103 #define STD_GET_CONFIGURATION 0x0880
104 #define STD_SET_CONFIGURATION 0x0900
105 #define STD_GET_INTERFACE 0x0A81
106 #define STD_SET_INTERFACE 0x0B01
107 #define STD_SYNCH_FRAME 0x0C82
109 /* CDC Class Specific Request Code */
110 #define GET_LINE_CODING 0x21A1
111 #define SET_LINE_CODING 0x2021
112 #define SET_CONTROL_LINE_STATE 0x2221
114 static bool isAsyncRequestFinished = false;
115 static AT91PS_UDP pUdp = AT91C_BASE_UDP;
116 static uint8_t btConfiguration = 0;
117 static uint8_t btConnection = 0;
118 static uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0;
120 static const char devDescriptor[] = {
121 /* Device descriptor */
122 0x12, // Length
123 USB_DESCRIPTOR_DEVICE, // Descriptor Type (DEVICE)
124 0x00, 0x02, // Complies with USB Spec. Release (0200h = release 2.00) 0210 == release 2.10
125 2, // Device Class: Communication Device Class
126 0, // Device Subclass: CDC class sub code ACM [ice 0x02 = win10 virtual comport ]
127 0, // Device Protocol: CDC Device protocol (unused)
128 AT91C_USB_EP_CONTROL_SIZE, // MaxPacketSize0
129 0xc4, 0x9a, // Vendor ID [0x9ac4 = J. Westhues]
130 0x8f, 0x4b, // Product ID [0x4b8f = Proxmark-3 RFID Instrument]
131 0x00, 0x01, // BCD Device release number (1.00)
132 1, // index Manufacturer
133 2, // index Product
134 3, // index SerialNumber
135 1 // Number of Configs
138 static const char cfgDescriptor[] = {
140 /* Configuration 1 descriptor */
141 // -----------------------------
142 9, // Length
143 USB_DESCRIPTOR_CONFIGURATION, // Descriptor Type
144 (9 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7), 0, // Total Length 2 EP + Control
145 2, // Number of Interfaces
146 1, // Index value of this Configuration (used in SetConfiguration from Host)
147 0, // Configuration string index
148 _DEFAULT, // Attributes 0xA0
149 0xFA, // Max Power consumption
151 // IAD to associate the one CDC interface
152 // --------------------------------------
154 8, // Length
155 USB_DESCRIPTOR_IAD, // IAD_DESCRIPTOR (0x0B)
156 0, // CDC_INT_INTERFACE NUMBER (
157 2, // IAD INTERFACE COUNT (two interfaces)
158 2, // Function Class: CDC_CLASS
159 2, // Function SubClass: ACM
160 1, // Function Protocol: v.25term
161 0, // iInterface
164 /* Interface 0 Descriptor */
165 /* CDC Communication Class Interface Descriptor Requirement for Notification*/
166 // -----------------------------------------------------------
167 9, // Length
168 USB_DESCRIPTOR_INTERFACE, // Descriptor Type
169 0, // Interface Number
170 0, // Alternate Setting
171 1, // Number of Endpoints in this interface
172 2, // Interface Class code (Communication Interface Class)
173 2, // Interface Subclass code (Abstract Control Model)
174 1, // InterfaceProtocol (Common AT Commands, V.25term)
175 0, // iInterface
177 /* Header Functional Descriptor */
178 5, // Function Length
179 0x24, // Descriptor type: CS_INTERFACE
180 0, // Descriptor subtype: Header Functional Descriptor
181 0x10, 0x01, // bcd CDC:1.1
183 /* ACM Functional Descriptor */
184 4, // Function Length
185 0x24, // Descriptor Type: CS_INTERFACE
186 2, // Descriptor Subtype: Abstract Control Management Functional Descriptor
187 2, // Capabilities D1, Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
189 /* Union Functional Descriptor */
190 5, // Function Length
191 0x24, // Descriptor Type: CS_INTERFACE
192 6, // Descriptor Subtype: Union Functional Descriptor
193 0, // MasterInterface: Communication Class Interface
194 1, // SlaveInterface0: Data Class Interface
196 /* Call Management Functional Descriptor */
197 5, // Function Length
198 0x24, // Descriptor Type: CS_INTERFACE
199 1, // Descriptor Subtype: Call Management Functional Descriptor
200 0, // Capabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself
201 1, // Data Interface: Data Class Interface
203 /* Protocol Functional Descriptor */
206 0x24, // Descriptor Type: CS_INTERFACE
207 0x0B, // Descriptor Subtype: Protocol Unit functional Descriptor
208 0xDD, // constant uniq ID of unit
209 0xFE, // protocol
212 /* CDC Notification Endpoint descriptor */
213 // ---------------------------------------
214 7, // Length
215 USB_DESCRIPTOR_ENDPOINT, // Descriptor Type
216 _EP03_IN, // EndpointAddress: Endpoint 03 - IN
217 _INTERRUPT, // Attributes
218 AT91C_USB_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8
219 0xFF, // Interval polling
222 /* Interface 1 Descriptor */
223 /* CDC Data Class Interface 1 Descriptor Requirement */
224 9, // Length
225 USB_DESCRIPTOR_INTERFACE, // Descriptor Type
226 1, // Interface Number
227 0, // Alternate Setting
228 2, // Number of Endpoints
229 0x0A, // Interface Class: CDC Data interface class
230 0, // Interface Subclass: not used
231 0, // Interface Protocol: No class specific protocol required (usb spec)
232 0, // Interface
234 /* Endpoint descriptor */
235 7, // Length
236 USB_DESCRIPTOR_ENDPOINT, // Descriptor Type
237 _EP01_OUT, // Endpoint Address: Endpoint 01 - OUT
238 _BULK, // Attributes: BULK
239 AT91C_USB_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes
240 0, // Interval: ignored for bulk
242 /* Endpoint descriptor */
243 7, // Length
244 USB_DESCRIPTOR_ENDPOINT, // Descriptor Type
245 _EP02_IN, // Endpoint Address: Endpoint 02 - IN
246 _BULK, // Attribute: BULK
247 AT91C_USB_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes
248 0 // Interval: ignored for bulk
251 // BOS descriptor
252 static const char bosDescriptor[] = {
253 0x5,
254 USB_DESCRIPTOR_TYPE_BO,
255 0xC,
256 0x0,
257 0x1, // 1 device capability
258 0x7,
259 0x10, // USB_DEVICE_CAPABITY_TYPE,
260 0x2,
261 0x2, // LPM capability bit set
262 0x0,
263 0x0,
267 // Microsoft OS Extended Configuration Compatible ID Descriptor
269 static const char CompatIDFeatureDescriptor[] = {
270 0x28, 0x00, 0x00, 0x00, // Descriptor Length 40bytes (0x28)
271 0x00, 0x01, // Version ('1.0')
272 MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004
273 0x01, // Number of sections. 0x1
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved (7bytes)
275 // -----function section 1------
276 0x00, // Interface Number #0
277 0x01, // reserved (0x1)
278 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // Compatible ID ('WINUSB\0\0') (8bytes)
279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-Compatible ID (8byte)
280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved (6bytes)
284 // Microsoft Extended Properties Feature Descriptor
286 static const char OSprop[] = {
287 // u32 Descriptor Length (10+132+64+102 == 308
288 0x34, 0x01, 0, 0,
289 // u16 Version ('1.0')
290 0, 1,
291 // u16 wIndex
292 MS_EXTENDED_PROPERTIES, 0,
293 // u16 wCount -- three section
294 3, 0,
296 // -----property section 1------
297 // u32 size ( 14+40+78 == 132)
298 132, 0, 0, 0,
299 // u32 type
300 1, 0, 0, 0, // unicode string
301 // u16 namelen (20*2 = 40)
302 40, 0,
303 // name DeviceInterfaceGUID
304 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,0,0,
305 // u32 datalen (39*2 = 78)
306 78, 0, 0, 0,
307 // data {4D36E978-E325-11CE-BFC1-08002BE10318}
308 '{',0,'4',0,'d',0,'3',0,'6',0,'e',0,'9',0,'7',0,'8',0,'-',0,'e',0,'3',0,'2',0,'5',0,
309 '-',0,'1',0,'1',0,'c',0,'e',0,'-',0,'b',0,'f',0,'c',0,'1',0,'-',0,'0',0,'8',0,'0',0,
310 '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0,
312 // -----property section 2------
313 // u32 size ( 14+12+38 == 64)
314 64, 0, 0, 0,
315 // u32 type
316 1, 0, 0, 0, // unicode string
317 // u16 namelen (12)
318 12, 0,
319 // name Label
320 'L',0,'a',0,'b',0,'e',0,'l',0,0,0,
321 // u32 datalen ( 19*2 = 38 )
322 38, 0, 0, 0,
323 // data 'Awesome PM3 Device'
324 'A',0,'w',0,'e',0,'s',0,'o',0,'m',0,'e',0,' ',0,'P',0,'M',0,'3',0,' ',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,0,0,
326 // -----property section 3------
327 // u32 size ( 14+12+76 == 102)
328 102, 0, 0, 0,
329 // u32 type
330 2, 0, 0, 0, //Unicode string with environment variables
331 // u16 namelen (12)
332 12, 0,
333 // name Icons
334 'I',0,'c',0,'o',0,'n',0,'s',0,0,0,
335 // u32 datalen ( 38*2 == 76)
336 76, 0, 0, 0,
337 // data '%SystemRoot%\\system32\\Shell32.dll,-13'
338 '%',0,'S',0,'y',0,'s',0,'t',0,'e',0,'m',0,'R',0,'o',0,'o',0,'t',0,'%',0,
339 '\\',0,'s',0,'y',0,'s',0,'t',0,'e',0,'m',0,'3',0,'2',0,'\\',0,
340 'S',0,'h',0,'e',0,'l',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,',',0,
341 '-',0,'1',0,'3',0,0,0
346 static const char StrLanguageCodes[] = {
347 4, // Length
348 0x03, // Type is string
349 0x09, 0x04 // supported language Code 0 = 0x0409 (English)
352 // Note: ModemManager (Linux) ignores Proxmark3 devices by matching the
353 // manufacturer string "proxmark.org". Don't change this.
354 // or use the blacklisting file.
355 static const char StrManufacturer[] = {
356 26, // Length
357 0x03, // Type is string
358 'p', 0, 'r', 0, 'o', 0, 'x', 0, 'm', 0, 'a', 0, 'r', 0, 'k', 0, '.', 0, 'o', 0, 'r', 0, 'g', 0,
361 static const char StrProduct[] = {
362 20, // Length
363 0x03, // Type is string
364 'p', 0, 'r', 0, 'o', 0, 'x', 0, 'm', 0, 'a', 0, 'r', 0, 'k', 0, '3', 0
367 #ifndef WITH_FLASH
368 static const char StrSerialNumber[] = {
369 14, // Length
370 0x03, // Type is string
371 'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0
373 #else // WITH_FLASH is defined
375 // Manually calculated size of descriptor with unique ID:
376 // offset 0, lengt h 1: total length field
377 // offset 1, length 1: descriptor type field
378 // offset 2, length 12: 6x unicode chars (original string)
379 // offset 14, length 4: 2x unicode chars (underscores) [[ to avoid descriptor being (size % 8) == 0, OS bug workaround ]]
380 // offset 18, length 32: 16x unicode chars (8-byte serial as hex characters)
381 // ============================
382 // total: 50 bytes
383 #define USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH 50
384 char StrSerialNumber[] = {
385 14, // Length is initially identical to non-unique version ... The length updated at boot, if unique serial is available
386 0x03, // Type is string
387 'i', 0, 'c', 0, 'e', 0, 'm', 0, 'a', 0, 'n', 0,
388 '_', 0, '_', 0,
389 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
390 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0, 'x', 0,
392 void usb_update_serial(uint64_t newSerialNumber) {
393 static bool configured = false; // TODO: enable by setting to false here...
394 if (configured) {
395 return;
397 // run this only once per boot... even if it fails to find serial number
398 configured = true;
399 // reject serial number if all-zero or all-ones
400 if ((newSerialNumber == 0x0000000000000000) || (newSerialNumber == 0xFFFFFFFFFFFFFFFF)) {
401 return;
403 // Descriptor is, effectively, initially identical to non-unique serial
404 // number because it reports the shorter length in the first byte.
405 // Convert uniqueID's eight bytes to 16 unicode characters in the
406 // descriptor and, finally, update the descriptor's length, which
407 // causes the serial number to become visible.
408 for (uint8_t i = 0; i < 8; i++) {
409 // order of nibbles chosen to match display order from `hw status`
410 uint8_t nibble1 = (newSerialNumber >> ((8 * i) + 4)) & 0xFu; // bitmasks [0xF0, 0xF000, 0xF00000, ... 0xF000000000000000]
411 uint8_t nibble2 = (newSerialNumber >> ((8 * i) + 0)) & 0xFu; // bitmasks [0x0F, 0x0F00, 0x0F0000, ... 0x0F00000000000000]
412 char c1 = nibble1 < 10 ? '0' + nibble1 : 'A' + (nibble1 - 10);
413 char c2 = nibble2 < 10 ? '0' + nibble2 : 'A' + (nibble2 - 10);
414 StrSerialNumber[18 + (4 * i) + 0] = c1; // [ 18, 22, .., 42, 46 ]
415 StrSerialNumber[18 + (4 * i) + 2] = c2; // [ 20, 24, .., 44, 48 ]
417 StrSerialNumber[0] = USB_STRING_DESCRIPTOR_SERIAL_NUMBER_LENGTH;
419 #endif
422 // size includes their own field.
423 static const char StrMS_OSDescriptor[] = {
424 18, // length 0x12
425 0x03, // Type is string
426 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, MS_VENDOR_CODE, 0
429 static const char *getStringDescriptor(uint8_t idx) {
430 switch (idx) {
431 case 0:
432 return StrLanguageCodes;
433 case 1:
434 return StrManufacturer;
435 case 2:
436 return StrProduct;
437 case 3:
438 return StrSerialNumber;
439 case MS_OS_DESCRIPTOR_INDEX:
440 return StrMS_OSDescriptor;
441 default:
442 return (NULL);
446 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect
447 #define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
448 |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
449 |AT91C_UDP_TXCOMP
451 // Clear flags in the UDP_CSR register and waits for synchronization
452 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
453 volatile unsigned int reg; \
454 reg = pUdp->UDP_CSR[(endpoint)]; \
455 reg |= REG_NO_EFFECT_1_ALL; \
456 reg &= ~(flags); \
457 pUdp->UDP_CSR[(endpoint)] = reg; \
460 // reset flags in the UDP_CSR register and waits for synchronization
461 #define UDP_SET_EP_FLAGS(endpoint, flags) { \
462 volatile unsigned int reg; \
463 reg = pUdp->UDP_CSR[(endpoint)]; \
464 reg |= REG_NO_EFFECT_1_ALL; \
465 reg |= (flags); \
466 pUdp->UDP_CSR[(endpoint)] = reg; \
470 typedef struct {
471 uint32_t BitRate;
472 uint8_t Format;
473 uint8_t ParityType;
474 uint8_t DataBits;
475 } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING;
477 static AT91S_CDC_LINE_CODING line = { // purely informative, actual values don't matter
478 USART_BAUD_RATE, // baudrate
479 0, // 1 Stop Bit
480 0, // None Parity
481 8 // 8 Data bits
484 // timer counts in 21.3us increments (1024/48MHz), rounding applies
485 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
486 static void SpinDelayUs(int us) {
487 int ticks = ((MCK / 1000000) * us + 512) >> 10;
489 // Borrow a PWM unit for my real-time clock
490 AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
492 // 48 MHz / 1024 gives 46.875 kHz
493 AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register
494 AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
495 AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register
497 uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
499 for (;;) {
500 uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
501 if (now == (uint16_t)(start + ticks))
502 return;
504 WDT_HIT();
509 *----------------------------------------------------------------------------
510 * \fn usb_disable
511 * \brief This function deactivates the USB device
512 *----------------------------------------------------------------------------
514 void usb_disable(void) {
515 // Disconnect the USB device
516 AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU;
518 // Clear all lingering interrupts
519 if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) {
520 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
525 *----------------------------------------------------------------------------
526 * \fn usb_enable
527 * \brief This function Activates the USB device
528 *----------------------------------------------------------------------------
530 void usb_enable(void) {
531 // Set the PLL USB Divider
532 AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
534 // Specific Chip USB Initialisation
535 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
536 AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP;
537 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP);
539 AT91C_BASE_UDP->UDP_FADDR = 0;
540 AT91C_BASE_UDP->UDP_GLBSTATE = 0;
542 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
543 // Set in PIO mode and Configure in Output
544 AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode
545 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output
547 // Clear for set the Pullup resistor
548 AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU;
550 // Disconnect and reconnect USB controller for 100ms
551 usb_disable();
553 SpinDelayUs(100 * 1000);
554 // Wait for a short while
555 //for (volatile size_t i=0; i<0x100000; i++) {};
557 // Reconnect USB reconnect
558 AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU;
559 AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU;
563 *----------------------------------------------------------------------------
564 * \fn usb_check
565 * \brief Test if the device is configured and handle enumeration
566 *----------------------------------------------------------------------------
568 static int usb_reconnect = 0;
569 static int usb_configured = 0;
570 void SetUSBreconnect(int value) {
571 usb_reconnect = value;
573 int GetUSBreconnect(void) {
574 return usb_reconnect;
576 void SetUSBconfigured(int value) {
577 usb_configured = value;
579 int GetUSBconfigured(void) {
580 return usb_configured;
583 bool usb_check(void) {
586 // reconnected ONCE and
587 if ( !USB_ATTACHED() ){
588 usb_reconnect = 1;
589 return false;
592 // only one time after USB been disengaged and re-engaged
593 if ( USB_ATTACHED() && usb_reconnect == 1 ) {
595 if ( usb_configured == 0) {
596 usb_disable();
597 usb_enable();
599 AT91F_CDC_Enumerate();
601 usb_configured = 1;
602 return false;
607 // interrupt status register
608 AT91_REG isr = pUdp->UDP_ISR;
610 // end of bus reset
611 if (isr & AT91C_UDP_ENDBUSRES) {
612 pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES;
613 // reset all endpoints
614 pUdp->UDP_RSTEP = (unsigned int) - 1;
615 pUdp->UDP_RSTEP = 0;
616 // Enable the function
617 pUdp->UDP_FADDR = AT91C_UDP_FEN;
618 // Configure endpoint 0 (enable control endpoint)
619 pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL);
620 } else if (isr & AT91C_UDP_EPINT0) {
621 pUdp->UDP_ICR = AT91C_UDP_EPINT0;
622 AT91F_CDC_Enumerate();
625 else if (isr & AT91C_UDP_EPINT3 ) {
626 pUdp->UDP_ICR = AT91C_UDP_EPINT3;
627 AT91F_CDC_Enumerate();
628 //pUdp->UDP_ICR |= AT91C_UDP_EPINT3;
631 return (btConfiguration) ? true : false;
634 bool usb_poll(void) {
635 if (usb_check() == false) {
636 return false;
639 return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank);
642 inline uint16_t usb_available_length(void) {
643 return (((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) & 0x7FF);
647 In github PR #129, some users appears to get a false positive from
648 usb_poll, which returns true, but the usb_read operation
649 still returns 0.
650 This check is basically the same as above, but also checks
651 that the length available to read is non-zero, thus hopefully fixes the
652 bug.
654 bool usb_poll_validate_length(void) {
656 if (usb_check() == false) {
657 return false;
660 if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) {
661 return false;
664 return (((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0);
668 *----------------------------------------------------------------------------
669 * \fn usb_read
670 * \brief Read available data from Endpoint 1 OUT (host to device)
671 *----------------------------------------------------------------------------
673 uint32_t usb_read(uint8_t *data, size_t len) {
675 if (len == 0) {
676 return 0;
679 uint8_t bank = btReceiveBank;
680 uint16_t packetSize, nbBytesRcv = 0;
681 uint16_t time_out = 0;
683 while (len) {
684 if (usb_check() == false) {
685 break;
688 if (pUdp->UDP_CSR[AT91C_EP_OUT] & bank) {
690 packetSize = (((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) & 0x7FF);
691 packetSize = MIN(packetSize, len);
692 len -= packetSize;
694 while (packetSize--) {
695 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
698 // flip bank
699 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank)
701 if (bank == AT91C_UDP_RX_DATA_BK0) {
702 bank = AT91C_UDP_RX_DATA_BK1;
703 } else {
704 bank = AT91C_UDP_RX_DATA_BK0;
708 if (time_out++ == 0x1FFF) {
709 break;
713 btReceiveBank = bank;
714 return nbBytesRcv;
717 static uint8_t usb_read_ng_buffer[64] = {0};
718 static uint8_t usb_read_ng_bufoffset = 0;
719 static size_t usb_read_ng_buflen = 0;
721 bool usb_read_ng_has_buffered_data(void) {
722 return usb_read_ng_buflen > 0;
725 uint32_t usb_read_ng(uint8_t *data, size_t len) {
727 if (len == 0) {
728 return 0;
731 uint8_t bank = btReceiveBank;
732 uint16_t packetSize, nbBytesRcv = 0;
733 uint16_t time_out = 0;
735 // take first from local buffer
736 if (len <= usb_read_ng_buflen) {
738 // if local buffer has all data
740 for (size_t i = 0; i < len; i++) {
741 data[nbBytesRcv++] = usb_read_ng_buffer[usb_read_ng_bufoffset + i];
744 usb_read_ng_buflen -= len;
746 if (usb_read_ng_buflen == 0) {
747 usb_read_ng_bufoffset = 0;
748 } else {
749 usb_read_ng_bufoffset += len;
752 return nbBytesRcv;
754 } else {
756 // take all data from local buffer, then read from usb
758 for (size_t i = 0; i < usb_read_ng_buflen; i++) {
759 data[nbBytesRcv++] = usb_read_ng_buffer[usb_read_ng_bufoffset + i];
762 len -= usb_read_ng_buflen;
763 usb_read_ng_buflen = 0;
764 usb_read_ng_bufoffset = 0;
768 while (len) {
770 if (usb_check() == false) {
771 break;
774 if ((pUdp->UDP_CSR[AT91C_EP_OUT] & bank)) {
776 uint16_t available = (((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) & 0x7FF);
778 packetSize = MIN(available, len);
779 available -= packetSize;
780 len -= packetSize;
782 while (packetSize--) {
783 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
786 // fill the local buffer with the remaining bytes
787 for (uint16_t i = 0; i < available; i++) {
788 usb_read_ng_buffer[i] = pUdp->UDP_FDR[AT91C_EP_OUT];
791 // update number of available bytes in local bytes
792 usb_read_ng_buflen = available;
794 // flip bank
795 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank)
797 if (bank == AT91C_UDP_RX_DATA_BK0) {
798 bank = AT91C_UDP_RX_DATA_BK1;
799 } else {
800 bank = AT91C_UDP_RX_DATA_BK0;
804 if (time_out++ == 0x1FFF) {
805 break;
809 btReceiveBank = bank;
810 return nbBytesRcv;
814 *----------------------------------------------------------------------------
815 * \fn usb_write
816 * \brief Send through endpoint 2 (device to host)
817 *----------------------------------------------------------------------------
819 int usb_write(const uint8_t *data, const size_t len) {
821 if (len == 0) {
822 return PM3_EINVARG;
825 if (usb_check() == false) {
826 return PM3_EIO;
829 // can we write?
830 if ((pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0) {
831 return PM3_EIO;
834 size_t length = len;
835 uint32_t cpt = 0;
837 // send first chunk
838 cpt = MIN(length, AT91C_USB_EP_IN_SIZE);
839 length -= cpt;
840 while (cpt--) {
841 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
844 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
845 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
847 while (length) {
848 // Send next chunk
849 cpt = MIN(length, AT91C_USB_EP_IN_SIZE);
850 length -= cpt;
851 while (cpt--) {
852 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
855 // Wait for previous chunk to be sent
856 // (iceman) when is the bankswapping done?
857 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
858 if (usb_check() == false) {
859 return PM3_EIO;
863 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
864 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
866 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
867 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
870 // Wait for the end of transfer
871 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
872 if (usb_check() == false) {
873 return PM3_EIO;
877 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
878 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
881 if (len % AT91C_USB_EP_IN_SIZE == 0) {
882 // like AT91F_USB_SendZlp(), in non ping-pong mode
883 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
884 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {};
886 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
887 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
890 return PM3_SUCCESS;
894 *----------------------------------------------------------------------------
895 * \fn async_usb_write_start
896 * \brief Start async write process
897 * \return PM3_EIO if USB is invalid, PM3_SUCCESS if it is ready for write
899 * This function checks if the USB is connected, and wait until the FIFO
900 * is ready to be filled.
902 * Warning: usb_write() should not be called between
903 * async_usb_write_start() and async_usb_write_stop().
904 *----------------------------------------------------------------------------
906 int async_usb_write_start(void) {
908 if (usb_check() == false) {
909 return PM3_EIO;
912 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
913 if (usb_check() == false) {
914 return PM3_EIO;
918 isAsyncRequestFinished = false;
919 return PM3_SUCCESS;
923 *----------------------------------------------------------------------------
924 * \fn async_usb_write_pushByte
925 * \brief Push one byte to the FIFO of IN endpoint (time-critical)
927 * This function simply push a byte to the FIFO of IN endpoint.
928 * The FIFO size is AT91C_USB_EP_IN_SIZE. Make sure this function is not called
929 * over AT91C_USB_EP_IN_SIZE times between each async_usb_write_requestWrite().
930 *----------------------------------------------------------------------------
932 inline void async_usb_write_pushByte(uint8_t data) {
933 pUdp->UDP_FDR[AT91C_EP_IN] = data;
934 isAsyncRequestFinished = false;
938 *----------------------------------------------------------------------------
939 * \fn async_usb_write_requestWrite
940 * \brief Request a write operation (time-critical)
941 * \return false if the last write request is not finished, true if success
943 * This function requests a write operation from FIFO to the USB bus,
944 * and switch the internal banks of FIFO. It doesn't wait for the end of
945 * transmission from FIFO to the USB bus.
947 * Note: This function doesn't check if the usb is valid, as it is
948 * time-critical.
949 *----------------------------------------------------------------------------
951 inline bool async_usb_write_requestWrite(void) {
953 // check if last request is finished
954 if (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
955 return false;
958 // clear transmission completed flag
959 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
960 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
962 // start of transmission
963 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
965 // hack: no need to wait if UDP_CSR and UDP_FDR are not used immediately.
966 // while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
967 isAsyncRequestFinished = true;
968 return true;
972 *----------------------------------------------------------------------------
973 * \fn async_usb_write_stop
974 * \brief Stop async write process
975 * \return PM3_EIO if USB is invalid, PM3_SUCCESS if data is written
977 * This function makes sure the data left in the FIFO is written to the
978 * USB bus.
980 * Warning: usb_write() should not be called between
981 * async_usb_write_start() and async_usb_write_stop().
982 *----------------------------------------------------------------------------
984 int async_usb_write_stop(void) {
985 // Wait for the end of transfer
986 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
987 if (usb_check() == false) {
988 return PM3_EIO;
992 // clear transmission completed flag
993 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
994 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
996 // FIFO is not empty, request a write in non-ping-pong mode
997 if (isAsyncRequestFinished == false) {
998 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
1000 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
1001 if (usb_check() == false) {
1002 return PM3_EIO;
1006 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
1007 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
1009 return PM3_SUCCESS;
1013 *----------------------------------------------------------------------------
1014 * \fn AT91F_USB_SendData
1015 * \brief Send Data through the control endpoint
1016 *----------------------------------------------------------------------------
1018 void AT91F_USB_SendData(AT91PS_UDP pudp, const char *pData, uint32_t length) {
1019 AT91_REG csr;
1021 do {
1022 uint32_t cpt = MIN(length, AT91C_USB_EP_CONTROL_SIZE);
1023 length -= cpt;
1025 while (cpt--) {
1026 pudp->UDP_FDR[AT91C_EP_CONTROL] = *pData++;
1029 if (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
1030 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
1031 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {};
1034 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
1036 do {
1037 csr = pudp->UDP_CSR[AT91C_EP_CONTROL];
1038 // Data IN stage has been stopped by a status OUT
1039 if (csr & AT91C_UDP_RX_DATA_BK0) {
1041 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0)
1042 return;
1044 } while (!(csr & AT91C_UDP_TXCOMP));
1046 } while (length);
1048 if (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
1049 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
1050 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {};
1055 //*----------------------------------------------------------------------------
1056 //* \fn AT91F_USB_SendZlp
1057 //* \brief Send zero length packet through the control endpoint
1058 //*----------------------------------------------------------------------------
1059 void AT91F_USB_SendZlp(AT91PS_UDP pudp) {
1060 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
1061 // for non ping-pong operation, wait until the FIFO is released
1062 // the flag for FIFO released is AT91C_UDP_TXCOMP rather than AT91C_UDP_TXPKTRDY
1063 while (!(pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)) {};
1064 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
1065 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {};
1068 //*----------------------------------------------------------------------------
1069 //* \fn AT91F_USB_SendStall
1070 //* \brief Stall the control endpoint
1071 //*----------------------------------------------------------------------------
1072 void AT91F_USB_SendStall(AT91PS_UDP pudp) {
1073 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
1074 while (!(pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR)) {};
1075 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
1076 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)) {};
1079 //*----------------------------------------------------------------------------
1080 //* \fn AT91F_CDC_Enumerate
1081 //* \brief This function is a callback invoked when a SETUP packet is received
1082 //* problem:
1083 //* 1. this is for USB endpoint0. the control endpoint.
1084 //* 2. mixed with CDC ACM endpoint3 , interrupt, control endpoint
1085 //*----------------------------------------------------------------------------
1086 void AT91F_CDC_Enumerate(void) {
1087 uint8_t bmRequestType, bRequest;
1088 uint16_t wValue, wIndex, wLength, wStatus;
1090 if (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)) {
1091 return;
1094 bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
1095 bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
1096 wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
1097 wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
1098 wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
1099 wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
1100 wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
1101 wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
1103 if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
1104 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
1105 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR)) {};
1107 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
1108 while ((pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)) {};
1111 if ( bRequest == MS_VENDOR_CODE) {
1112 if ( bmRequestType == MS_WCID_GET_DESCRIPTOR ) { // C0
1113 if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4
1114 //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength));
1115 //return;
1119 if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1
1120 // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always)
1121 //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength));
1122 //return;
1123 // }
1128 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
1129 switch ((bRequest << 8) | bmRequestType) {
1130 case STD_GET_DESCRIPTOR: {
1132 if (wValue == 0x100) { // Return Device Descriptor
1133 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
1134 } else if (wValue == 0x200) { // Return Configuration Descriptor
1135 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
1136 } else if ((wValue & 0xF00) == 0xF00) { // Return BOS Descriptor
1137 AT91F_USB_SendData(pUdp, bosDescriptor, MIN(sizeof(bosDescriptor), wLength));
1138 } else if ((wValue & 0x300) == 0x300) { // Return String Descriptor
1140 const char *strDescriptor = getStringDescriptor(wValue & 0xff);
1141 if (strDescriptor != NULL) {
1142 AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
1143 } else {
1144 AT91F_USB_SendStall(pUdp);
1146 } else {
1147 AT91F_USB_SendStall(pUdp);
1150 break;
1151 case STD_SET_ADDRESS:
1152 AT91F_USB_SendZlp(pUdp);
1153 pUdp->UDP_FADDR = (AT91C_UDP_FEN | (wValue & 0x7F));
1154 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
1155 break;
1156 case STD_SET_CONFIGURATION:
1159 * Set or clear the device "configured" state.
1160 * The LSB of wValue is the "Configuration Number". If this value is non-zero,
1161 * it should be the same number as defined in the Configuration Descriptor;
1162 * otherwise an error must have occurred.
1163 * This device has only one configuration and its Config Number is CONF_NB (= 1).
1165 AT91F_USB_SendZlp(pUdp);
1166 btConfiguration = wValue;
1167 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
1169 // make sure we are not stalled
1171 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL);
1172 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL);
1173 UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL);
1176 // enable endpoints
1177 pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
1178 pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
1179 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
1180 break;
1181 case STD_GET_CONFIGURATION:
1182 AT91F_USB_SendData(pUdp, (char *) & (btConfiguration), sizeof(btConfiguration));
1183 break;
1184 case STD_GET_STATUS_ZERO:
1185 wStatus = 0; // Device is Bus powered, remote wakeup disabled
1186 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1187 break;
1188 case STD_GET_STATUS_INTERFACE:
1189 wStatus = 0; // reserved for future use
1190 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1191 break;
1192 case STD_GET_STATUS_ENDPOINT:
1193 wStatus = 0;
1194 wIndex &= 0x0F;
1195 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
1196 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
1197 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1198 } else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
1199 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
1200 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1201 } else {
1202 AT91F_USB_SendStall(pUdp);
1204 break;
1205 case STD_SET_FEATURE_ZERO:
1206 AT91F_USB_SendStall(pUdp);
1207 break;
1208 case STD_SET_FEATURE_INTERFACE:
1209 AT91F_USB_SendZlp(pUdp);
1210 break;
1211 case STD_SET_FEATURE_ENDPOINT:
1212 wIndex &= 0x0F;
1213 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
1214 pUdp->UDP_CSR[wIndex] = 0;
1215 AT91F_USB_SendZlp(pUdp);
1216 } else {
1217 AT91F_USB_SendStall(pUdp);
1219 break;
1220 case STD_CLEAR_FEATURE_ZERO:
1221 AT91F_USB_SendStall(pUdp);
1222 break;
1223 case STD_CLEAR_FEATURE_INTERFACE:
1224 AT91F_USB_SendZlp(pUdp);
1225 break;
1226 case STD_CLEAR_FEATURE_ENDPOINT:
1227 wIndex &= 0x0F;
1228 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
1230 if (wIndex == AT91C_EP_OUT) {
1231 pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
1232 } else if (wIndex == AT91C_EP_IN) {
1233 pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
1234 } else if (wIndex == AT91C_EP_NOTIFY) {
1235 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
1238 AT91F_USB_SendZlp(pUdp);
1239 } else {
1240 AT91F_USB_SendStall(pUdp);
1242 break;
1244 // handle CDC class requests
1245 case SET_LINE_CODING: {
1247 uint8_t i;
1248 for ( i = 0 ; i < 7 ; i++ ) {
1249 ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL];
1250 } */
1251 // ignore SET_LINE_CODING...
1252 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0)) {};
1253 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
1254 AT91F_USB_SendZlp(pUdp);
1255 break;
1257 case GET_LINE_CODING:
1258 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
1259 break;
1260 case SET_CONTROL_LINE_STATE:
1261 btConnection = wValue;
1262 AT91F_USB_SendZlp(pUdp);
1263 break;
1264 default:
1265 AT91F_USB_SendStall(pUdp);
1266 break;