2 * at91sam7s USB CDC device implementation
4 * Copyright (c) 2012, Roel Verdult
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.
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.
29 * based on the "Basic USB Example" from ATMEL (doc6123.pdf)
36 #include "at91sam7s512.h"
37 #include "config_gpio.h"
40 #define AT91C_EP_CONTROL 0
41 #define AT91C_EP_OUT 1
43 #define AT91C_EP_NOTIFY 3
44 #define AT91C_EP_OUT_SIZE 0x40
45 #define AT91C_EP_IN_SIZE 0x40
47 // Language must always be 0.
48 #define STR_LANGUAGE_CODES 0x00
49 #define STR_MANUFACTURER 0x01
50 #define STR_PRODUCT 0x02
52 static const char devDescriptor
[] = {
53 /* Device descriptor */
55 0x01, // bDescriptorType
56 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)
57 0x02, // bDeviceClass: (Communication Device Class)
58 0x00, // bDeviceSubclass: (unused at this time)
59 0x00, // bDeviceProtocol: (unused at this time)
60 0x08, // bMaxPacketSize0
61 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)
62 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)
63 0x01,0x00, // Device release number (0001)
64 STR_MANUFACTURER
, // iManufacturer
65 STR_PRODUCT
, // iProduct
66 0x00, // iSerialNumber
70 static const char cfgDescriptor
[] = {
71 /* ============== CONFIGURATION 1 =========== */
72 /* Configuration 1 descriptor */
74 0x02, // CbDescriptorType
75 0x43, // CwTotalLength 2 EP + Control
77 0x02, // CbNumInterfaces
78 0x01, // CbConfigurationValue
79 0x00, // CiConfiguration
80 0x80, // CbmAttributes (Bus Powered)
81 0x4B, // CMaxPower (150mA max current drawn from bus)
83 /* Interface 0 Descriptor: Communication Class Interface */
85 0x04, // bDescriptorType
86 0x00, // bInterfaceNumber
87 0x00, // bAlternateSetting
88 0x01, // bNumEndpoints
89 0x02, // bInterfaceClass: Communication Interface Class
90 0x02, // bInterfaceSubclass: Abstract Control Model
91 0x01, // bInterfaceProtocol: Common AT Commands, V.25ter
94 /* Header Functional Descriptor */
95 0x05, // bFunction Length
96 0x24, // bDescriptor type: CS_INTERFACE
97 0x00, // bDescriptor subtype: Header Functional Descriptor
101 /* ACM Functional Descriptor */
102 0x04, // bFunctionLength
103 0x24, // bDescriptor Type: CS_INTERFACE
104 0x02, // bDescriptor Subtype: Abstract Control Management Functional Descriptor
105 0x02, // bmCapabilities: D1: Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
107 /* Union Functional Descriptor */
108 0x05, // bFunctionLength
109 0x24, // bDescriptorType: CS_INTERFACE
110 0x06, // bDescriptor Subtype: Union Functional Descriptor
111 0x00, // bMasterInterface: Communication Class Interface
112 0x01, // bSlaveInterface0: Data Class Interface
114 /* Call Management Functional Descriptor */
115 0x05, // bFunctionLength
116 0x24, // bDescriptor Type: CS_INTERFACE
117 0x01, // bDescriptor Subtype: Call Management Functional Descriptor
118 0x00, // bmCapabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself
119 0x01, // bDataInterface: Data Class Interface 1
121 /* Endpoint 1 descriptor */
123 0x05, // bDescriptorType
124 0x83, // bEndpointAddress: Endpoint 03 - IN
125 0x03, // bmAttributes: INT
126 0x08, // wMaxPacketSize: 8
130 /* Interface 1 Descriptor: Data Class Interface */
132 0x04, // bDescriptorType
133 0x01, // bInterfaceNumber
134 0x00, // bAlternateSetting
135 0x02, // bNumEndpoints
136 0x0A, // bInterfaceClass: Data Interface Class
137 0x00, // bInterfaceSubclass: not used
138 0x00, // bInterfaceProtocol: No class specific protocol required)
141 /* Endpoint 1 descriptor */
143 0x05, // bDescriptorType
144 0x01, // bEndpointAddress: Endpoint 01 - OUT
145 0x02, // bmAttributes: BULK
146 AT91C_EP_OUT_SIZE
, // wMaxPacketSize
150 /* Endpoint 2 descriptor */
152 0x05, // bDescriptorType
153 0x82, // bEndpointAddress: Endpoint 02 - IN
154 0x02, // bmAttributes: BULK
155 AT91C_EP_IN_SIZE
, // wMaxPacketSize
159 const char BOSDescriptor
[] = {
160 // BOS descriptor header
161 0x05, 0x0F, 0x39, 0x00, 0x02,
163 // Microsoft OS 2.0 Platform Capability Descriptor
164 0x1C, // Descriptor size (28 bytes)
165 0x10, // Descriptor type (Device Capability)
166 0x05, // Capability type (Platform)
169 // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F)
170 0xDF, 0x60, 0xDD, 0xD8,
174 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F,
176 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
178 252, // Vendor-assigned bMS_VendorCode
179 0x00 // Doesn’t support alternate enumeration
182 static const char StrDescLanguageCodes
[] = {
184 0x03, // Type is string
185 0x09, 0x04 // supported language Code 0 = 0x0409 (English)
188 // Note: ModemManager (Linux) ignores Proxmark3 devices by matching the
189 // manufacturer string "proxmark.org". Don't change this.
190 static const char StrDescManufacturer
[] = {
192 0x03, // Type is string
207 static const char StrDescProduct
[] = {
209 0x03, // Type is string
215 const char* getStringDescriptor(uint8_t idx
)
218 case STR_LANGUAGE_CODES
:
219 return StrDescLanguageCodes
;
220 case STR_MANUFACTURER
:
221 return StrDescManufacturer
;
223 return StrDescProduct
;
229 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect
230 #define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
231 |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
234 // Clear flags in the UDP_CSR register
235 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
236 volatile unsigned int reg; \
237 reg = pUdp->UDP_CSR[(endpoint)]; \
238 reg |= REG_NO_EFFECT_1_ALL; \
240 pUdp->UDP_CSR[(endpoint)] = reg; \
243 // Set flags in the UDP_CSR register
244 #define UDP_SET_EP_FLAGS(endpoint, flags) { \
245 volatile unsigned int reg; \
246 reg = pUdp->UDP_CSR[(endpoint)]; \
247 reg |= REG_NO_EFFECT_1_ALL; \
249 pUdp->UDP_CSR[(endpoint)] = reg; \
252 /* USB standard request codes */
253 #define STD_GET_STATUS_ZERO 0x0080
254 #define STD_GET_STATUS_INTERFACE 0x0081
255 #define STD_GET_STATUS_ENDPOINT 0x0082
257 #define STD_CLEAR_FEATURE_ZERO 0x0100
258 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
259 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
261 #define STD_SET_FEATURE_ZERO 0x0300
262 #define STD_SET_FEATURE_INTERFACE 0x0301
263 #define STD_SET_FEATURE_ENDPOINT 0x0302
265 #define STD_SET_ADDRESS 0x0500
266 #define STD_GET_DESCRIPTOR 0x0680
267 #define STD_SET_DESCRIPTOR 0x0700
268 #define STD_GET_CONFIGURATION 0x0880
269 #define STD_SET_CONFIGURATION 0x0900
270 #define STD_GET_INTERFACE 0x0A81
271 #define STD_SET_INTERFACE 0x0B01
272 #define STD_SYNCH_FRAME 0x0C82
274 /* CDC Class Specific Request Code */
275 #define GET_LINE_CODING 0x21A1
276 #define SET_LINE_CODING 0x2021
277 #define SET_CONTROL_LINE_STATE 0x2221
280 unsigned int dwDTERRate
;
284 } AT91S_CDC_LINE_CODING
, *AT91PS_CDC_LINE_CODING
;
286 AT91S_CDC_LINE_CODING line
= {
293 void AT91F_CDC_Enumerate();
295 AT91PS_UDP pUdp
= AT91C_BASE_UDP
;
296 byte_t btConfiguration
= 0;
297 byte_t btConnection
= 0;
298 byte_t btReceiveBank
= AT91C_UDP_RX_DATA_BK0
;
301 //*----------------------------------------------------------------------------
303 //* \brief This function deactivates the USB device
304 //*----------------------------------------------------------------------------
306 // Disconnect the USB device
307 AT91C_BASE_PIOA
->PIO_ODR
= GPIO_USB_PU
;
309 // Clear all lingering interrupts
310 if(pUdp
->UDP_ISR
& AT91C_UDP_ENDBUSRES
) {
311 pUdp
->UDP_ICR
= AT91C_UDP_ENDBUSRES
;
316 //*----------------------------------------------------------------------------
318 //* \brief This function Activates the USB device
319 //*----------------------------------------------------------------------------
321 // Set the PLL USB Divider
322 AT91C_BASE_CKGR
->CKGR_PLLR
|= AT91C_CKGR_USBDIV_1
;
324 // Specific Chip USB Initialisation
325 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
326 AT91C_BASE_PMC
->PMC_SCER
= AT91C_PMC_UDP
;
327 AT91C_BASE_PMC
->PMC_PCER
= (1 << AT91C_ID_UDP
);
329 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
330 // Set in PIO mode and Configure in Output
331 AT91C_BASE_PIOA
->PIO_PER
= GPIO_USB_PU
; // Set in PIO mode
332 AT91C_BASE_PIOA
->PIO_OER
= GPIO_USB_PU
; // Configure as Output
334 // Clear for set the Pullup resistor
335 AT91C_BASE_PIOA
->PIO_CODR
= GPIO_USB_PU
;
337 // Disconnect and reconnect USB controller for 100ms
340 // Wait for a short while
341 for (volatile size_t i
=0; i
<0x100000; i
++);
343 // Reconnect USB reconnect
344 AT91C_BASE_PIOA
->PIO_SODR
= GPIO_USB_PU
;
345 AT91C_BASE_PIOA
->PIO_OER
= GPIO_USB_PU
;
349 //*----------------------------------------------------------------------------
351 //* \brief Test if the device is configured and handle enumeration
352 //*----------------------------------------------------------------------------
354 AT91_REG isr
= pUdp
->UDP_ISR
;
356 if (isr
& AT91C_UDP_ENDBUSRES
) {
357 pUdp
->UDP_ICR
= AT91C_UDP_ENDBUSRES
;
358 // reset all endpoints
359 pUdp
->UDP_RSTEP
= (unsigned int)-1;
361 // Enable the function
362 pUdp
->UDP_FADDR
= AT91C_UDP_FEN
;
363 // Configure endpoint 0
364 pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_CTRL
);
365 } else if (isr
& AT91C_UDP_EPINT0
) {
366 pUdp
->UDP_ICR
= AT91C_UDP_EPINT0
;
367 AT91F_CDC_Enumerate();
369 return (btConfiguration
) ? true : false;
375 if (!usb_check()) return false;
376 return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
);
381 In github PR #129, some users appears to get a false positive from
382 usb_poll, which returns true, but the usb_read operation
384 This check is basically the same as above, but also checks
385 that the length available to read is non-zero, thus hopefully fixes the
388 bool usb_poll_validate_length()
390 if (!usb_check()) return false;
391 if (!(pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
)) return false;
392 return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16) > 0;
395 //*----------------------------------------------------------------------------
397 //* \brief Read available data from Endpoint OUT
398 //*----------------------------------------------------------------------------
399 uint32_t usb_read(byte_t
* data
, size_t len
) {
400 byte_t bank
= btReceiveBank
;
401 uint32_t packetSize
, nbBytesRcv
= 0;
402 uint32_t time_out
= 0;
405 if (!usb_check()) break;
407 if ( pUdp
->UDP_CSR
[AT91C_EP_OUT
] & bank
) {
408 packetSize
= MIN(pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16, len
);
411 data
[nbBytesRcv
++] = pUdp
->UDP_FDR
[AT91C_EP_OUT
];
412 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT
, bank
);
413 if (bank
== AT91C_UDP_RX_DATA_BK0
) {
414 bank
= AT91C_UDP_RX_DATA_BK1
;
416 bank
= AT91C_UDP_RX_DATA_BK0
;
419 if (time_out
++ == 0x1fff) break;
422 btReceiveBank
= bank
;
427 //*----------------------------------------------------------------------------
429 //* \brief Send through endpoint 2
430 //*----------------------------------------------------------------------------
431 uint32_t usb_write(const byte_t
* data
, const size_t len
) {
435 if (!length
) return 0;
436 if (!usb_check()) return 0;
438 // Send the first packet
439 cpt
= MIN(length
, AT91C_EP_IN_SIZE
);
442 pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++;
444 UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
);
447 // Fill the next bank
448 cpt
= MIN(length
, AT91C_EP_IN_SIZE
);
451 pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++;
453 // Wait for the previous bank to be sent
454 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) {
455 if (!usb_check()) return length
;
457 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
);
458 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
);
459 UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
);
462 // Wait for the end of transfer
463 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) {
464 if (!usb_check()) return length
;
467 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
);
468 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
);
474 //*----------------------------------------------------------------------------
475 //* \fn AT91F_USB_SendData
476 //* \brief Send Data through the control endpoint
477 //*----------------------------------------------------------------------------
478 unsigned int csrTab
[100] = {0x00};
479 unsigned char csrIdx
= 0;
481 static void AT91F_USB_SendData(AT91PS_UDP pUdp
, const char *pData
, uint32_t length
) {
486 cpt
= MIN(length
, 8);
490 pUdp
->UDP_FDR
[0] = *pData
++;
492 if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) {
493 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
);
494 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
);
497 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
);
499 csr
= pUdp
->UDP_CSR
[AT91C_EP_CONTROL
];
501 // Data IN stage has been stopped by a status OUT
502 if (csr
& AT91C_UDP_RX_DATA_BK0
) {
503 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
);
506 } while ( !(csr
& AT91C_UDP_TXCOMP
) );
510 if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) {
511 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
);
512 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
);
517 //*----------------------------------------------------------------------------
518 //* \fn AT91F_USB_SendZlp
519 //* \brief Send zero length packet through the control endpoint
520 //*----------------------------------------------------------------------------
521 void AT91F_USB_SendZlp(AT91PS_UDP pUdp
) {
522 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
);
523 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) );
524 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
);
525 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
);
529 //*----------------------------------------------------------------------------
530 //* \fn AT91F_USB_SendStall
531 //* \brief Stall the control endpoint
532 //*----------------------------------------------------------------------------
533 void AT91F_USB_SendStall(AT91PS_UDP pUdp
) {
534 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL
);
535 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_ISOERROR
) );
536 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL
| AT91C_UDP_ISOERROR
);
537 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & (AT91C_UDP_FORCESTALL
| AT91C_UDP_ISOERROR
));
541 //*----------------------------------------------------------------------------
542 //* \fn AT91F_CDC_Enumerate
543 //* \brief This function is a callback invoked when a SETUP packet is received
544 //*----------------------------------------------------------------------------
545 void AT91F_CDC_Enumerate() {
546 byte_t bmRequestType
, bRequest
;
547 uint16_t wValue
, wIndex
, wLength
, wStatus
;
549 if ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
) )
552 bmRequestType
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
];
553 bRequest
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
];
554 wValue
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF);
555 wValue
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8);
556 wIndex
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF);
557 wIndex
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8);
558 wLength
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF);
559 wLength
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8);
561 if (bmRequestType
& 0x80) { // Data Phase Transfer Direction Device to Host
562 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_DIR
);
563 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_DIR
) );
565 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RXSETUP
);
566 while ( (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
) );
568 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
569 switch ((bRequest
<< 8) | bmRequestType
) {
570 case STD_GET_DESCRIPTOR
:
571 if (wValue
== 0x100) // Return Device Descriptor
572 AT91F_USB_SendData(pUdp
, devDescriptor
, MIN(sizeof(devDescriptor
), wLength
));
573 else if (wValue
== 0x200) // Return Configuration Descriptor
574 AT91F_USB_SendData(pUdp
, cfgDescriptor
, MIN(sizeof(cfgDescriptor
), wLength
));
575 else if ((wValue
& 0xF00) == 0xF00) // Return BOS Descriptor
576 AT91F_USB_SendData(pUdp
, BOSDescriptor
, MIN(sizeof(BOSDescriptor
), wLength
));
577 else if ((wValue
& 0x300) == 0x300) // Return Manufacturer Descriptor - this is needed by Android
578 AT91F_USB_SendData(pUdp
, StrDescManufacturer
, MIN(sizeof(StrDescManufacturer
), wLength
));
579 else if ((wValue
& 0xF00) == 0x300) { // Return String Descriptor
580 const char *strDescriptor
= getStringDescriptor(wValue
& 0xff);
581 if (strDescriptor
!= NULL
) {
582 AT91F_USB_SendData(pUdp
, strDescriptor
, MIN(strDescriptor
[0], wLength
));
584 AT91F_USB_SendStall(pUdp
);
588 AT91F_USB_SendStall(pUdp
);
590 case STD_SET_ADDRESS
:
591 AT91F_USB_SendZlp(pUdp
);
592 pUdp
->UDP_FADDR
= (AT91C_UDP_FEN
| wValue
);
593 pUdp
->UDP_GLBSTATE
= (wValue
) ? AT91C_UDP_FADDEN
: 0;
595 case STD_SET_CONFIGURATION
:
596 btConfiguration
= wValue
;
597 AT91F_USB_SendZlp(pUdp
);
598 pUdp
->UDP_GLBSTATE
= (wValue
) ? AT91C_UDP_CONFG
: AT91C_UDP_FADDEN
;
599 pUdp
->UDP_CSR
[AT91C_EP_OUT
] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_OUT
) : 0;
600 pUdp
->UDP_CSR
[AT91C_EP_IN
] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_IN
) : 0;
601 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_INT_IN
) : 0;
603 case STD_GET_CONFIGURATION
:
604 AT91F_USB_SendData(pUdp
, (char *) &(btConfiguration
), sizeof(btConfiguration
));
606 case STD_GET_STATUS_ZERO
:
607 wStatus
= 0; // Device is Bus powered, remote wakeup disabled
608 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
610 case STD_GET_STATUS_INTERFACE
:
611 wStatus
= 0; // reserved for future use
612 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
614 case STD_GET_STATUS_ENDPOINT
:
617 if ((pUdp
->UDP_GLBSTATE
& AT91C_UDP_CONFG
) && (wIndex
<= AT91C_EP_NOTIFY
)) {
618 wStatus
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1;
619 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
621 else if ((pUdp
->UDP_GLBSTATE
& AT91C_UDP_FADDEN
) && (wIndex
== AT91C_EP_CONTROL
)) {
622 wStatus
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1;
623 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
626 AT91F_USB_SendStall(pUdp
);
628 case STD_SET_FEATURE_ZERO
:
629 AT91F_USB_SendStall(pUdp
);
631 case STD_SET_FEATURE_INTERFACE
:
632 AT91F_USB_SendZlp(pUdp
);
634 case STD_SET_FEATURE_ENDPOINT
:
636 if ((wValue
== 0) && (wIndex
>= AT91C_EP_OUT
) && (wIndex
<= AT91C_EP_NOTIFY
)) {
637 pUdp
->UDP_CSR
[wIndex
] = 0;
638 AT91F_USB_SendZlp(pUdp
);
641 AT91F_USB_SendStall(pUdp
);
643 case STD_CLEAR_FEATURE_ZERO
:
644 AT91F_USB_SendStall(pUdp
);
646 case STD_CLEAR_FEATURE_INTERFACE
:
647 AT91F_USB_SendZlp(pUdp
);
649 case STD_CLEAR_FEATURE_ENDPOINT
:
651 if ((wValue
== 0) && (wIndex
>= AT91C_EP_OUT
) && (wIndex
<= AT91C_EP_NOTIFY
)) {
652 if (wIndex
== AT91C_EP_OUT
)
653 pUdp
->UDP_CSR
[AT91C_EP_OUT
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_OUT
);
654 else if (wIndex
== AT91C_EP_IN
)
655 pUdp
->UDP_CSR
[AT91C_EP_IN
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_IN
);
656 else if (wIndex
== AT91C_EP_NOTIFY
)
657 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_INT_IN
);
658 AT91F_USB_SendZlp(pUdp
);
661 AT91F_USB_SendStall(pUdp
);
664 // handle CDC class requests
665 case SET_LINE_CODING
:
666 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RX_DATA_BK0
) );
667 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
);
668 AT91F_USB_SendZlp(pUdp
);
670 case GET_LINE_CODING
:
671 AT91F_USB_SendData(pUdp
, (char *) &line
, MIN(sizeof(line
), wLength
));
673 case SET_CONTROL_LINE_STATE
:
674 btConnection
= wValue
;
675 AT91F_USB_SendZlp(pUdp
);
678 AT91F_USB_SendStall(pUdp
);