Merge pull request #2604 from stuiterveer/envelope
[RRG-proxmark3.git] / common_arm / usb_cdc.c
blob2447330c813d47bf070ec0c41532e407380b0b9e
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 uint8_t usb_read_ng_buflen = 0;
721 uint32_t usb_read_ng(uint8_t *data, size_t len) {
723 if (len == 0) {
724 return 0;
727 uint8_t bank = btReceiveBank;
728 uint16_t packetSize, nbBytesRcv = 0;
729 uint16_t time_out = 0;
731 // take first from local buffer
732 if (len <= usb_read_ng_buflen) {
734 // if local buffer has all data
736 for (uint8_t i = 0; i < len; i++) {
737 data[nbBytesRcv++] = usb_read_ng_buffer[usb_read_ng_bufoffset + i];
740 usb_read_ng_buflen -= len;
742 if (usb_read_ng_buflen == 0) {
743 usb_read_ng_bufoffset = 0;
744 } else {
745 usb_read_ng_bufoffset += len;
748 return nbBytesRcv;
750 } else {
752 // take all data from local buffer, then read from usb
754 for (uint8_t i = 0; i < usb_read_ng_buflen; i++) {
755 data[nbBytesRcv++] = usb_read_ng_buffer[usb_read_ng_bufoffset + i];
758 len -= usb_read_ng_buflen;
759 usb_read_ng_buflen = 0;
760 usb_read_ng_bufoffset = 0;
764 while (len) {
766 if (usb_check() == false) {
767 break;
770 if ((pUdp->UDP_CSR[AT91C_EP_OUT] & bank)) {
772 uint16_t available = (((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) & 0x7FF);
774 packetSize = MIN(available, len);
775 available -= packetSize;
776 len -= packetSize;
778 while (packetSize--) {
779 data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
782 // fill the local buffer with the remaining bytes
783 for (uint16_t i = 0; i < available; i++) {
784 usb_read_ng_buffer[i] = pUdp->UDP_FDR[AT91C_EP_OUT];
787 // update number of available bytes in local bytes
788 usb_read_ng_buflen = available;
790 // flip bank
791 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank)
793 if (bank == AT91C_UDP_RX_DATA_BK0) {
794 bank = AT91C_UDP_RX_DATA_BK1;
795 } else {
796 bank = AT91C_UDP_RX_DATA_BK0;
800 if (time_out++ == 0x1FFF) {
801 break;
805 btReceiveBank = bank;
806 return nbBytesRcv;
810 *----------------------------------------------------------------------------
811 * \fn usb_write
812 * \brief Send through endpoint 2 (device to host)
813 *----------------------------------------------------------------------------
815 int usb_write(const uint8_t *data, const size_t len) {
817 if (len == 0) {
818 return PM3_EINVARG;
821 if (usb_check() == false) {
822 return PM3_EIO;
825 // can we write?
826 if ((pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0) {
827 return PM3_EIO;
830 size_t length = len;
831 uint32_t cpt = 0;
833 // send first chunk
834 cpt = MIN(length, AT91C_USB_EP_IN_SIZE);
835 length -= cpt;
836 while (cpt--) {
837 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
840 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
841 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
843 while (length) {
844 // Send next chunk
845 cpt = MIN(length, AT91C_USB_EP_IN_SIZE);
846 length -= cpt;
847 while (cpt--) {
848 pUdp->UDP_FDR[AT91C_EP_IN] = *data++;
851 // Wait for previous chunk to be sent
852 // (iceman) when is the bankswapping done?
853 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
854 if (usb_check() == false) {
855 return PM3_EIO;
859 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
860 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
862 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
863 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
866 // Wait for the end of transfer
867 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
868 if (usb_check() == false) {
869 return PM3_EIO;
873 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
874 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
877 if (len % AT91C_USB_EP_IN_SIZE == 0) {
878 // like AT91F_USB_SendZlp(), in non ping-pong mode
879 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
880 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {};
882 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
883 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
886 return PM3_SUCCESS;
890 *----------------------------------------------------------------------------
891 * \fn async_usb_write_start
892 * \brief Start async write process
893 * \return PM3_EIO if USB is invalid, PM3_SUCCESS if it is ready for write
895 * This function checks if the USB is connected, and wait until the FIFO
896 * is ready to be filled.
898 * Warning: usb_write() should not be called between
899 * async_usb_write_start() and async_usb_write_stop().
900 *----------------------------------------------------------------------------
902 int async_usb_write_start(void) {
904 if (usb_check() == false) {
905 return PM3_EIO;
908 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
909 if (usb_check() == false) {
910 return PM3_EIO;
914 isAsyncRequestFinished = false;
915 return PM3_SUCCESS;
919 *----------------------------------------------------------------------------
920 * \fn async_usb_write_pushByte
921 * \brief Push one byte to the FIFO of IN endpoint (time-critical)
923 * This function simply push a byte to the FIFO of IN endpoint.
924 * The FIFO size is AT91C_USB_EP_IN_SIZE. Make sure this function is not called
925 * over AT91C_USB_EP_IN_SIZE times between each async_usb_write_requestWrite().
926 *----------------------------------------------------------------------------
928 inline void async_usb_write_pushByte(uint8_t data) {
929 pUdp->UDP_FDR[AT91C_EP_IN] = data;
930 isAsyncRequestFinished = false;
934 *----------------------------------------------------------------------------
935 * \fn async_usb_write_requestWrite
936 * \brief Request a write operation (time-critical)
937 * \return false if the last write request is not finished, true if success
939 * This function requests a write operation from FIFO to the USB bus,
940 * and switch the internal banks of FIFO. It doesn't wait for the end of
941 * transmission from FIFO to the USB bus.
943 * Note: This function doesn't check if the usb is valid, as it is
944 * time-critical.
945 *----------------------------------------------------------------------------
947 inline bool async_usb_write_requestWrite(void) {
949 // check if last request is finished
950 if (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
951 return false;
954 // clear transmission completed flag
955 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
956 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
958 // start of transmission
959 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
961 // hack: no need to wait if UDP_CSR and UDP_FDR are not used immediately.
962 // while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {};
963 isAsyncRequestFinished = true;
964 return true;
968 *----------------------------------------------------------------------------
969 * \fn async_usb_write_stop
970 * \brief Stop async write process
971 * \return PM3_EIO if USB is invalid, PM3_SUCCESS if data is written
973 * This function makes sure the data left in the FIFO is written to the
974 * USB bus.
976 * Warning: usb_write() should not be called between
977 * async_usb_write_start() and async_usb_write_stop().
978 *----------------------------------------------------------------------------
980 int async_usb_write_stop(void) {
981 // Wait for the end of transfer
982 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) {
983 if (usb_check() == false) {
984 return PM3_EIO;
988 // clear transmission completed flag
989 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
990 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
992 // FIFO is not empty, request a write in non-ping-pong mode
993 if (isAsyncRequestFinished == false) {
994 UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
996 while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {
997 if (usb_check() == false) {
998 return PM3_EIO;
1002 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP);
1003 while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {};
1005 return PM3_SUCCESS;
1009 *----------------------------------------------------------------------------
1010 * \fn AT91F_USB_SendData
1011 * \brief Send Data through the control endpoint
1012 *----------------------------------------------------------------------------
1014 void AT91F_USB_SendData(AT91PS_UDP pudp, const char *pData, uint32_t length) {
1015 AT91_REG csr;
1017 do {
1018 uint32_t cpt = MIN(length, AT91C_USB_EP_CONTROL_SIZE);
1019 length -= cpt;
1021 while (cpt--) {
1022 pudp->UDP_FDR[AT91C_EP_CONTROL] = *pData++;
1025 if (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
1026 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
1027 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {};
1030 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
1032 do {
1033 csr = pudp->UDP_CSR[AT91C_EP_CONTROL];
1034 // Data IN stage has been stopped by a status OUT
1035 if (csr & AT91C_UDP_RX_DATA_BK0) {
1037 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0)
1038 return;
1040 } while (!(csr & AT91C_UDP_TXCOMP));
1042 } while (length);
1044 if (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {
1045 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
1046 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {};
1051 //*----------------------------------------------------------------------------
1052 //* \fn AT91F_USB_SendZlp
1053 //* \brief Send zero length packet through the control endpoint
1054 //*----------------------------------------------------------------------------
1055 void AT91F_USB_SendZlp(AT91PS_UDP pudp) {
1056 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY);
1057 // for non ping-pong operation, wait until the FIFO is released
1058 // the flag for FIFO released is AT91C_UDP_TXCOMP rather than AT91C_UDP_TXPKTRDY
1059 while (!(pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP)) {};
1060 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP);
1061 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) {};
1064 //*----------------------------------------------------------------------------
1065 //* \fn AT91F_USB_SendStall
1066 //* \brief Stall the control endpoint
1067 //*----------------------------------------------------------------------------
1068 void AT91F_USB_SendStall(AT91PS_UDP pudp) {
1069 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL);
1070 while (!(pudp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR)) {};
1071 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
1072 while (pudp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)) {};
1075 //*----------------------------------------------------------------------------
1076 //* \fn AT91F_CDC_Enumerate
1077 //* \brief This function is a callback invoked when a SETUP packet is received
1078 //* problem:
1079 //* 1. this is for USB endpoint0. the control endpoint.
1080 //* 2. mixed with CDC ACM endpoint3 , interrupt, control endpoint
1081 //*----------------------------------------------------------------------------
1082 void AT91F_CDC_Enumerate(void) {
1083 uint8_t bmRequestType, bRequest;
1084 uint16_t wValue, wIndex, wLength, wStatus;
1086 if (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)) {
1087 return;
1090 bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL];
1091 bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL];
1092 wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
1093 wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
1094 wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
1095 wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
1096 wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF);
1097 wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8);
1099 if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host
1100 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR);
1101 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR)) {};
1103 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP);
1104 while ((pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP)) {};
1107 if ( bRequest == MS_VENDOR_CODE) {
1108 if ( bmRequestType == MS_WCID_GET_DESCRIPTOR ) { // C0
1109 if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4
1110 //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength));
1111 //return;
1115 if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1
1116 // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always)
1117 //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength));
1118 //return;
1119 // }
1124 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
1125 switch ((bRequest << 8) | bmRequestType) {
1126 case STD_GET_DESCRIPTOR: {
1128 if (wValue == 0x100) { // Return Device Descriptor
1129 AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength));
1130 } else if (wValue == 0x200) { // Return Configuration Descriptor
1131 AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
1132 } else if ((wValue & 0xF00) == 0xF00) { // Return BOS Descriptor
1133 AT91F_USB_SendData(pUdp, bosDescriptor, MIN(sizeof(bosDescriptor), wLength));
1134 } else if ((wValue & 0x300) == 0x300) { // Return String Descriptor
1136 const char *strDescriptor = getStringDescriptor(wValue & 0xff);
1137 if (strDescriptor != NULL) {
1138 AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength));
1139 } else {
1140 AT91F_USB_SendStall(pUdp);
1142 } else {
1143 AT91F_USB_SendStall(pUdp);
1146 break;
1147 case STD_SET_ADDRESS:
1148 AT91F_USB_SendZlp(pUdp);
1149 pUdp->UDP_FADDR = (AT91C_UDP_FEN | (wValue & 0x7F));
1150 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
1151 break;
1152 case STD_SET_CONFIGURATION:
1155 * Set or clear the device "configured" state.
1156 * The LSB of wValue is the "Configuration Number". If this value is non-zero,
1157 * it should be the same number as defined in the Configuration Descriptor;
1158 * otherwise an error must have occurred.
1159 * This device has only one configuration and its Config Number is CONF_NB (= 1).
1161 AT91F_USB_SendZlp(pUdp);
1162 btConfiguration = wValue;
1163 pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
1165 // make sure we are not stalled
1167 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL);
1168 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL);
1169 UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL);
1172 // enable endpoints
1173 pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
1174 pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
1175 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
1176 break;
1177 case STD_GET_CONFIGURATION:
1178 AT91F_USB_SendData(pUdp, (char *) & (btConfiguration), sizeof(btConfiguration));
1179 break;
1180 case STD_GET_STATUS_ZERO:
1181 wStatus = 0; // Device is Bus powered, remote wakeup disabled
1182 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1183 break;
1184 case STD_GET_STATUS_INTERFACE:
1185 wStatus = 0; // reserved for future use
1186 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1187 break;
1188 case STD_GET_STATUS_ENDPOINT:
1189 wStatus = 0;
1190 wIndex &= 0x0F;
1191 if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) {
1192 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
1193 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1194 } else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) {
1195 wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
1196 AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus));
1197 } else {
1198 AT91F_USB_SendStall(pUdp);
1200 break;
1201 case STD_SET_FEATURE_ZERO:
1202 AT91F_USB_SendStall(pUdp);
1203 break;
1204 case STD_SET_FEATURE_INTERFACE:
1205 AT91F_USB_SendZlp(pUdp);
1206 break;
1207 case STD_SET_FEATURE_ENDPOINT:
1208 wIndex &= 0x0F;
1209 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
1210 pUdp->UDP_CSR[wIndex] = 0;
1211 AT91F_USB_SendZlp(pUdp);
1212 } else {
1213 AT91F_USB_SendStall(pUdp);
1215 break;
1216 case STD_CLEAR_FEATURE_ZERO:
1217 AT91F_USB_SendStall(pUdp);
1218 break;
1219 case STD_CLEAR_FEATURE_INTERFACE:
1220 AT91F_USB_SendZlp(pUdp);
1221 break;
1222 case STD_CLEAR_FEATURE_ENDPOINT:
1223 wIndex &= 0x0F;
1224 if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) {
1226 if (wIndex == AT91C_EP_OUT) {
1227 pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
1228 } else if (wIndex == AT91C_EP_IN) {
1229 pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
1230 } else if (wIndex == AT91C_EP_NOTIFY) {
1231 pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN);
1234 AT91F_USB_SendZlp(pUdp);
1235 } else {
1236 AT91F_USB_SendStall(pUdp);
1238 break;
1240 // handle CDC class requests
1241 case SET_LINE_CODING: {
1243 uint8_t i;
1244 for ( i = 0 ; i < 7 ; i++ ) {
1245 ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL];
1246 } */
1247 // ignore SET_LINE_CODING...
1248 while (!(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0)) {};
1249 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0);
1250 AT91F_USB_SendZlp(pUdp);
1251 break;
1253 case GET_LINE_CODING:
1254 AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength));
1255 break;
1256 case SET_CONTROL_LINE_STATE:
1257 btConnection = wValue;
1258 AT91F_USB_SendZlp(pUdp);
1259 break;
1260 default:
1261 AT91F_USB_SendStall(pUdp);
1262 break;