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 static const char devDescriptor
[] = {
48 /* Device descriptor */
50 0x01, // bDescriptorType
51 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)
52 0x02, // bDeviceClass: (Communication Device Class)
53 0x00, // bDeviceSubclass: (unused at this time)
54 0x00, // bDeviceProtocol: (unused at this time)
55 0x08, // bMaxPacketSize0
56 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)
57 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)
58 0x01,0x00, // Device release number (0001)
59 0x01, // iManufacturer
61 0x00, // iSerialNumber
65 static const char cfgDescriptor
[] = {
66 /* ============== CONFIGURATION 1 =========== */
67 /* Configuration 1 descriptor */
69 0x02, // CbDescriptorType
70 0x43, // CwTotalLength 2 EP + Control
72 0x02, // CbNumInterfaces
73 0x01, // CbConfigurationValue
74 0x00, // CiConfiguration
75 0xC0, // CbmAttributes 0xA0
78 /* Interface 0 Descriptor: Communication Class Interface */
80 0x04, // bDescriptorType
81 0x00, // bInterfaceNumber
82 0x00, // bAlternateSetting
83 0x01, // bNumEndpoints
84 0x02, // bInterfaceClass: Communication Interface Class
85 0x02, // bInterfaceSubclass: Abstract Control Model
86 0x01, // bInterfaceProtocol: Common AT Commands, V.25ter
89 /* Header Functional Descriptor */
90 0x05, // bFunction Length
91 0x24, // bDescriptor type: CS_INTERFACE
92 0x00, // bDescriptor subtype: Header Functional Descriptor
96 /* ACM Functional Descriptor */
97 0x04, // bFunctionLength
98 0x24, // bDescriptor Type: CS_INTERFACE
99 0x02, // bDescriptor Subtype: Abstract Control Management Functional Descriptor
100 0x02, // bmCapabilities: D1: Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
102 /* Union Functional Descriptor */
103 0x05, // bFunctionLength
104 0x24, // bDescriptorType: CS_INTERFACE
105 0x06, // bDescriptor Subtype: Union Functional Descriptor
106 0x00, // bMasterInterface: Communication Class Interface
107 0x01, // bSlaveInterface0: Data Class Interface
109 /* Call Management Functional Descriptor */
110 0x05, // bFunctionLength
111 0x24, // bDescriptor Type: CS_INTERFACE
112 0x01, // bDescriptor Subtype: Call Management Functional Descriptor
113 0x00, // bmCapabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself
114 0x01, // bDataInterface: Data Class Interface 1
116 /* Endpoint 1 descriptor */
118 0x05, // bDescriptorType
119 0x83, // bEndpointAddress: Endpoint 03 - IN
120 0x03, // bmAttributes: INT
121 0x08, // wMaxPacketSize: 8
125 /* Interface 1 Descriptor: Data Class Interface */
127 0x04, // bDescriptorType
128 0x01, // bInterfaceNumber
129 0x00, // bAlternateSetting
130 0x02, // bNumEndpoints
131 0x0A, // bInterfaceClass: Data Interface Class
132 0x00, // bInterfaceSubclass: not used
133 0x00, // bInterfaceProtocol: No class specific protocol required)
136 /* Endpoint 1 descriptor */
138 0x05, // bDescriptorType
139 0x01, // bEndpointAddress: Endpoint 01 - OUT
140 0x02, // bmAttributes: BULK
141 AT91C_EP_OUT_SIZE
, // wMaxPacketSize
145 /* Endpoint 2 descriptor */
147 0x05, // bDescriptorType
148 0x82, // bEndpointAddress: Endpoint 02 - IN
149 0x02, // bmAttributes: BULK
150 AT91C_EP_IN_SIZE
, // wMaxPacketSize
155 static const char StrDescLanguageCodes
[] = {
157 0x03, // Type is string
158 0x09, 0x04 // supported language Code 0 = 0x0409 (English)
161 static const char StrDescManufacturer
[] = {
163 0x03, // Type is string
178 static const char StrDescProduct
[] = {
180 0x03, // Type is string
186 static const char* const pStrings
[] =
188 StrDescLanguageCodes
,
193 const char* getStringDescriptor(uint8_t idx
)
195 if(idx
>= (sizeof(pStrings
) / sizeof(pStrings
[0]))) {
198 return(pStrings
[idx
]);
202 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect
203 #define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
204 |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
207 // Clear flags in the UDP_CSR register
208 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \
209 volatile unsigned int reg; \
210 reg = pUdp->UDP_CSR[(endpoint)]; \
211 reg |= REG_NO_EFFECT_1_ALL; \
213 pUdp->UDP_CSR[(endpoint)] = reg; \
216 // Set flags in the UDP_CSR register
217 #define UDP_SET_EP_FLAGS(endpoint, flags) { \
218 volatile unsigned int reg; \
219 reg = pUdp->UDP_CSR[(endpoint)]; \
220 reg |= REG_NO_EFFECT_1_ALL; \
222 pUdp->UDP_CSR[(endpoint)] = reg; \
225 /* USB standard request codes */
226 #define STD_GET_STATUS_ZERO 0x0080
227 #define STD_GET_STATUS_INTERFACE 0x0081
228 #define STD_GET_STATUS_ENDPOINT 0x0082
230 #define STD_CLEAR_FEATURE_ZERO 0x0100
231 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
232 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
234 #define STD_SET_FEATURE_ZERO 0x0300
235 #define STD_SET_FEATURE_INTERFACE 0x0301
236 #define STD_SET_FEATURE_ENDPOINT 0x0302
238 #define STD_SET_ADDRESS 0x0500
239 #define STD_GET_DESCRIPTOR 0x0680
240 #define STD_SET_DESCRIPTOR 0x0700
241 #define STD_GET_CONFIGURATION 0x0880
242 #define STD_SET_CONFIGURATION 0x0900
243 #define STD_GET_INTERFACE 0x0A81
244 #define STD_SET_INTERFACE 0x0B01
245 #define STD_SYNCH_FRAME 0x0C82
247 /* CDC Class Specific Request Code */
248 #define GET_LINE_CODING 0x21A1
249 #define SET_LINE_CODING 0x2021
250 #define SET_CONTROL_LINE_STATE 0x2221
253 unsigned int dwDTERRate
;
257 } AT91S_CDC_LINE_CODING
, *AT91PS_CDC_LINE_CODING
;
259 AT91S_CDC_LINE_CODING line
= {
266 void AT91F_CDC_Enumerate();
268 AT91PS_UDP pUdp
= AT91C_BASE_UDP
;
269 byte_t btConfiguration
= 0;
270 byte_t btConnection
= 0;
271 byte_t btReceiveBank
= AT91C_UDP_RX_DATA_BK0
;
274 //*----------------------------------------------------------------------------
276 //* \brief This function deactivates the USB device
277 //*----------------------------------------------------------------------------
279 // Disconnect the USB device
280 AT91C_BASE_PIOA
->PIO_ODR
= GPIO_USB_PU
;
282 // Clear all lingering interrupts
283 if(pUdp
->UDP_ISR
& AT91C_UDP_ENDBUSRES
) {
284 pUdp
->UDP_ICR
= AT91C_UDP_ENDBUSRES
;
289 //*----------------------------------------------------------------------------
291 //* \brief This function Activates the USB device
292 //*----------------------------------------------------------------------------
294 // Set the PLL USB Divider
295 AT91C_BASE_CKGR
->CKGR_PLLR
|= AT91C_CKGR_USBDIV_1
;
297 // Specific Chip USB Initialisation
298 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
299 AT91C_BASE_PMC
->PMC_SCER
= AT91C_PMC_UDP
;
300 AT91C_BASE_PMC
->PMC_PCER
= (1 << AT91C_ID_UDP
);
302 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
303 // Set in PIO mode and Configure in Output
304 AT91C_BASE_PIOA
->PIO_PER
= GPIO_USB_PU
; // Set in PIO mode
305 AT91C_BASE_PIOA
->PIO_OER
= GPIO_USB_PU
; // Configure as Output
307 // Clear for set the Pullup resistor
308 AT91C_BASE_PIOA
->PIO_CODR
= GPIO_USB_PU
;
310 // Disconnect and reconnect USB controller for 100ms
313 // Wait for a short while
314 for (volatile size_t i
=0; i
<0x100000; i
++);
316 // Reconnect USB reconnect
317 AT91C_BASE_PIOA
->PIO_SODR
= GPIO_USB_PU
;
318 AT91C_BASE_PIOA
->PIO_OER
= GPIO_USB_PU
;
322 //*----------------------------------------------------------------------------
324 //* \brief Test if the device is configured and handle enumeration
325 //*----------------------------------------------------------------------------
327 AT91_REG isr
= pUdp
->UDP_ISR
;
329 if (isr
& AT91C_UDP_ENDBUSRES
) {
330 pUdp
->UDP_ICR
= AT91C_UDP_ENDBUSRES
;
331 // reset all endpoints
332 pUdp
->UDP_RSTEP
= (unsigned int)-1;
334 // Enable the function
335 pUdp
->UDP_FADDR
= AT91C_UDP_FEN
;
336 // Configure endpoint 0
337 pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_CTRL
);
338 } else if (isr
& AT91C_UDP_EPINT0
) {
339 pUdp
->UDP_ICR
= AT91C_UDP_EPINT0
;
340 AT91F_CDC_Enumerate();
342 return (btConfiguration
) ? true : false;
348 if (!usb_check()) return false;
349 return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
);
354 In github PR #129, some users appears to get a false positive from
355 usb_poll, which returns true, but the usb_read operation
357 This check is basically the same as above, but also checks
358 that the length available to read is non-zero, thus hopefully fixes the
361 bool usb_poll_validate_length()
363 if (!usb_check()) return false;
364 if (!(pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
)) return false;
365 return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16) > 0;
368 //*----------------------------------------------------------------------------
370 //* \brief Read available data from Endpoint OUT
371 //*----------------------------------------------------------------------------
372 uint32_t usb_read(byte_t
* data
, size_t len
) {
373 byte_t bank
= btReceiveBank
;
374 uint32_t packetSize
, nbBytesRcv
= 0;
375 uint32_t time_out
= 0;
378 if (!usb_check()) break;
380 if ( pUdp
->UDP_CSR
[AT91C_EP_OUT
] & bank
) {
381 packetSize
= MIN(pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16, len
);
384 data
[nbBytesRcv
++] = pUdp
->UDP_FDR
[AT91C_EP_OUT
];
385 UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT
, bank
);
386 if (bank
== AT91C_UDP_RX_DATA_BK0
) {
387 bank
= AT91C_UDP_RX_DATA_BK1
;
389 bank
= AT91C_UDP_RX_DATA_BK0
;
392 if (time_out
++ == 0x1fff) break;
395 btReceiveBank
= bank
;
400 //*----------------------------------------------------------------------------
402 //* \brief Send through endpoint 2
403 //*----------------------------------------------------------------------------
404 uint32_t usb_write(const byte_t
* data
, const size_t len
) {
408 if (!length
) return 0;
409 if (!usb_check()) return 0;
411 // Send the first packet
412 cpt
= MIN(length
, AT91C_EP_IN_SIZE
);
415 pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++;
417 UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
);
420 // Fill the next bank
421 cpt
= MIN(length
, AT91C_EP_IN_SIZE
);
424 pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++;
426 // Wait for the previous bank to be sent
427 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) {
428 if (!usb_check()) return length
;
430 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
);
431 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
);
432 UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
);
435 // Wait for the end of transfer
436 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) {
437 if (!usb_check()) return length
;
440 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
);
441 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
);
447 //*----------------------------------------------------------------------------
448 //* \fn AT91F_USB_SendData
449 //* \brief Send Data through the control endpoint
450 //*----------------------------------------------------------------------------
451 unsigned int csrTab
[100] = {0x00};
452 unsigned char csrIdx
= 0;
454 static void AT91F_USB_SendData(AT91PS_UDP pUdp
, const char *pData
, uint32_t length
) {
459 cpt
= MIN(length
, 8);
463 pUdp
->UDP_FDR
[0] = *pData
++;
465 if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) {
466 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
);
467 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
);
470 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
);
472 csr
= pUdp
->UDP_CSR
[AT91C_EP_CONTROL
];
474 // Data IN stage has been stopped by a status OUT
475 if (csr
& AT91C_UDP_RX_DATA_BK0
) {
476 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
);
479 } while ( !(csr
& AT91C_UDP_TXCOMP
) );
483 if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) {
484 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
);
485 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
);
490 //*----------------------------------------------------------------------------
491 //* \fn AT91F_USB_SendZlp
492 //* \brief Send zero length packet through the control endpoint
493 //*----------------------------------------------------------------------------
494 void AT91F_USB_SendZlp(AT91PS_UDP pUdp
) {
495 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
);
496 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) );
497 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
);
498 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
);
502 //*----------------------------------------------------------------------------
503 //* \fn AT91F_USB_SendStall
504 //* \brief Stall the control endpoint
505 //*----------------------------------------------------------------------------
506 void AT91F_USB_SendStall(AT91PS_UDP pUdp
) {
507 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL
);
508 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_ISOERROR
) );
509 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL
| AT91C_UDP_ISOERROR
);
510 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & (AT91C_UDP_FORCESTALL
| AT91C_UDP_ISOERROR
));
514 //*----------------------------------------------------------------------------
515 //* \fn AT91F_CDC_Enumerate
516 //* \brief This function is a callback invoked when a SETUP packet is received
517 //*----------------------------------------------------------------------------
518 void AT91F_CDC_Enumerate() {
519 byte_t bmRequestType
, bRequest
;
520 uint16_t wValue
, wIndex
, wLength
, wStatus
;
522 if ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
) )
525 bmRequestType
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
];
526 bRequest
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
];
527 wValue
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF);
528 wValue
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8);
529 wIndex
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF);
530 wIndex
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8);
531 wLength
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF);
532 wLength
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8);
534 if (bmRequestType
& 0x80) { // Data Phase Transfer Direction Device to Host
535 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_DIR
);
536 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_DIR
) );
538 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RXSETUP
);
539 while ( (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
) );
541 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
542 switch ((bRequest
<< 8) | bmRequestType
) {
543 case STD_GET_DESCRIPTOR
:
544 if (wValue
== 0x100) // Return Device Descriptor
545 AT91F_USB_SendData(pUdp
, devDescriptor
, MIN(sizeof(devDescriptor
), wLength
));
546 else if (wValue
== 0x200) // Return Configuration Descriptor
547 AT91F_USB_SendData(pUdp
, cfgDescriptor
, MIN(sizeof(cfgDescriptor
), wLength
));
548 else if ((wValue
& 0xF00) == 0x300) { // Return String Descriptor
549 const char *strDescriptor
= getStringDescriptor(wValue
& 0xff);
550 if (strDescriptor
!= NULL
) {
551 AT91F_USB_SendData(pUdp
, strDescriptor
, MIN(strDescriptor
[0], wLength
));
553 AT91F_USB_SendStall(pUdp
);
557 AT91F_USB_SendStall(pUdp
);
559 case STD_SET_ADDRESS
:
560 AT91F_USB_SendZlp(pUdp
);
561 pUdp
->UDP_FADDR
= (AT91C_UDP_FEN
| wValue
);
562 pUdp
->UDP_GLBSTATE
= (wValue
) ? AT91C_UDP_FADDEN
: 0;
564 case STD_SET_CONFIGURATION
:
565 btConfiguration
= wValue
;
566 AT91F_USB_SendZlp(pUdp
);
567 pUdp
->UDP_GLBSTATE
= (wValue
) ? AT91C_UDP_CONFG
: AT91C_UDP_FADDEN
;
568 pUdp
->UDP_CSR
[AT91C_EP_OUT
] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_OUT
) : 0;
569 pUdp
->UDP_CSR
[AT91C_EP_IN
] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_IN
) : 0;
570 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_INT_IN
) : 0;
572 case STD_GET_CONFIGURATION
:
573 AT91F_USB_SendData(pUdp
, (char *) &(btConfiguration
), sizeof(btConfiguration
));
575 case STD_GET_STATUS_ZERO
:
576 wStatus
= 0; // Device is Bus powered, remote wakeup disabled
577 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
579 case STD_GET_STATUS_INTERFACE
:
580 wStatus
= 0; // reserved for future use
581 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
583 case STD_GET_STATUS_ENDPOINT
:
586 if ((pUdp
->UDP_GLBSTATE
& AT91C_UDP_CONFG
) && (wIndex
<= AT91C_EP_NOTIFY
)) {
587 wStatus
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1;
588 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
590 else if ((pUdp
->UDP_GLBSTATE
& AT91C_UDP_FADDEN
) && (wIndex
== AT91C_EP_CONTROL
)) {
591 wStatus
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1;
592 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
595 AT91F_USB_SendStall(pUdp
);
597 case STD_SET_FEATURE_ZERO
:
598 AT91F_USB_SendStall(pUdp
);
600 case STD_SET_FEATURE_INTERFACE
:
601 AT91F_USB_SendZlp(pUdp
);
603 case STD_SET_FEATURE_ENDPOINT
:
605 if ((wValue
== 0) && (wIndex
>= AT91C_EP_OUT
) && (wIndex
<= AT91C_EP_NOTIFY
)) {
606 pUdp
->UDP_CSR
[wIndex
] = 0;
607 AT91F_USB_SendZlp(pUdp
);
610 AT91F_USB_SendStall(pUdp
);
612 case STD_CLEAR_FEATURE_ZERO
:
613 AT91F_USB_SendStall(pUdp
);
615 case STD_CLEAR_FEATURE_INTERFACE
:
616 AT91F_USB_SendZlp(pUdp
);
618 case STD_CLEAR_FEATURE_ENDPOINT
:
620 if ((wValue
== 0) && (wIndex
>= AT91C_EP_OUT
) && (wIndex
<= AT91C_EP_NOTIFY
)) {
621 if (wIndex
== AT91C_EP_OUT
)
622 pUdp
->UDP_CSR
[AT91C_EP_OUT
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_OUT
);
623 else if (wIndex
== AT91C_EP_IN
)
624 pUdp
->UDP_CSR
[AT91C_EP_IN
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_IN
);
625 else if (wIndex
== AT91C_EP_NOTIFY
)
626 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_INT_IN
);
627 AT91F_USB_SendZlp(pUdp
);
630 AT91F_USB_SendStall(pUdp
);
633 // handle CDC class requests
634 case SET_LINE_CODING
:
635 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RX_DATA_BK0
) );
636 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
);
637 AT91F_USB_SendZlp(pUdp
);
639 case GET_LINE_CODING
:
640 AT91F_USB_SendData(pUdp
, (char *) &line
, MIN(sizeof(line
), wLength
));
642 case SET_CONTROL_LINE_STATE
:
643 btConnection
= wValue
;
644 AT91F_USB_SendZlp(pUdp
);
647 AT91F_USB_SendStall(pUdp
);