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"
39 #define AT91C_EP_IN_SIZE 0x40
40 #define AT91C_EP_OUT 1
41 #define AT91C_EP_OUT_SIZE 0x40
44 static const char devDescriptor
[] = {
45 /* Device descriptor */
47 0x01, // bDescriptorType
48 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0)
49 0x02, // bDeviceClass: CDC class code
50 0x00, // bDeviceSubclass: CDC class sub code
51 0x00, // bDeviceProtocol: CDC Device protocol
52 0x08, // bMaxPacketSize0
53 0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues)
54 0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument)
55 0x01,0x00, // Device release number (0001)
56 0x01, // iManufacturer
58 0x00, // iSerialNumber
62 static const char cfgDescriptor
[] = {
63 /* ============== CONFIGURATION 1 =========== */
64 /* Configuration 1 descriptor */
66 0x02, // CbDescriptorType
67 0x43, // CwTotalLength 2 EP + Control
69 0x02, // CbNumInterfaces
70 0x01, // CbConfigurationValue
71 0x00, // CiConfiguration
72 0xC0, // CbmAttributes 0xA0
75 /* Communication Class Interface Descriptor Requirement */
77 0x04, // bDescriptorType
78 0x00, // bInterfaceNumber
79 0x00, // bAlternateSetting
80 0x01, // bNumEndpoints
81 0x02, // bInterfaceClass
82 0x02, // bInterfaceSubclass
83 0x01, // bInterfaceProtocol
86 /* Header Functional Descriptor */
87 0x05, // bFunction Length
88 0x24, // bDescriptor type: CS_INTERFACE
89 0x00, // bDescriptor subtype: Header Func Desc
93 /* ACM Functional Descriptor */
94 0x04, // bFunctionLength
95 0x24, // bDescriptor Type: CS_INTERFACE
96 0x02, // bDescriptor Subtype: ACM Func Desc
97 0x02, // bmCapabilities
99 /* Union Functional Descriptor */
100 0x05, // bFunctionLength
101 0x24, // bDescriptorType: CS_INTERFACE
102 0x06, // bDescriptor Subtype: Union Func Desc
103 0x00, // bMasterInterface: Communication Class Interface
104 0x01, // bSlaveInterface0: Data Class Interface
106 /* Call Management Functional Descriptor */
107 0x05, // bFunctionLength
108 0x24, // bDescriptor Type: CS_INTERFACE
109 0x01, // bDescriptor Subtype: Call Management Func Desc
110 0x00, // bmCapabilities: D1 + D0
111 0x01, // bDataInterface: Data Class Interface 1
113 /* Endpoint 1 descriptor */
115 0x05, // bDescriptorType
116 0x83, // bEndpointAddress, Endpoint 03 - IN
117 0x03, // bmAttributes INT
118 0x08, // wMaxPacketSize
122 /* Data Class Interface Descriptor Requirement */
124 0x04, // bDescriptorType
125 0x01, // bInterfaceNumber
126 0x00, // bAlternateSetting
127 0x02, // bNumEndpoints
128 0x0A, // bInterfaceClass
129 0x00, // bInterfaceSubclass
130 0x00, // bInterfaceProtocol
133 /* First alternate setting */
134 /* Endpoint 1 descriptor */
136 0x05, // bDescriptorType
137 0x01, // bEndpointAddress, Endpoint 01 - OUT
138 0x02, // bmAttributes BULK
139 AT91C_EP_OUT_SIZE
, // wMaxPacketSize
143 /* Endpoint 2 descriptor */
145 0x05, // bDescriptorType
146 0x82, // bEndpointAddress, Endpoint 02 - IN
147 0x02, // bmAttributes BULK
148 AT91C_EP_IN_SIZE
, // wMaxPacketSize
153 static const char StrDescLanguageCodes
[] = {
155 0x03, // Type is string
156 0x09, 0x04 // supported language Code 0 = 0x0409 (English)
159 static const char StrDescManufacturer
[] = {
161 0x03, // Type is string
176 static const char StrDescProduct
[] = {
178 0x03, // Type is string
184 static const char* const pStrings
[] =
186 StrDescLanguageCodes
,
191 const char* getStringDescriptor(uint8_t idx
)
193 if(idx
>= (sizeof(pStrings
) / sizeof(pStrings
[0]))) {
196 return(pStrings
[idx
]);
200 /* USB standard request code */
201 #define STD_GET_STATUS_ZERO 0x0080
202 #define STD_GET_STATUS_INTERFACE 0x0081
203 #define STD_GET_STATUS_ENDPOINT 0x0082
205 #define STD_CLEAR_FEATURE_ZERO 0x0100
206 #define STD_CLEAR_FEATURE_INTERFACE 0x0101
207 #define STD_CLEAR_FEATURE_ENDPOINT 0x0102
209 #define STD_SET_FEATURE_ZERO 0x0300
210 #define STD_SET_FEATURE_INTERFACE 0x0301
211 #define STD_SET_FEATURE_ENDPOINT 0x0302
213 #define STD_SET_ADDRESS 0x0500
214 #define STD_GET_DESCRIPTOR 0x0680
215 #define STD_SET_DESCRIPTOR 0x0700
216 #define STD_GET_CONFIGURATION 0x0880
217 #define STD_SET_CONFIGURATION 0x0900
218 #define STD_GET_INTERFACE 0x0A81
219 #define STD_SET_INTERFACE 0x0B01
220 #define STD_SYNCH_FRAME 0x0C82
222 /* CDC Class Specific Request Code */
223 #define GET_LINE_CODING 0x21A1
224 #define SET_LINE_CODING 0x2021
225 #define SET_CONTROL_LINE_STATE 0x2221
228 unsigned int dwDTERRate
;
232 } AT91S_CDC_LINE_CODING
, *AT91PS_CDC_LINE_CODING
;
234 AT91S_CDC_LINE_CODING line
= {
240 void AT91F_CDC_Enumerate();
242 AT91PS_UDP pUdp
= AT91C_BASE_UDP
;
243 byte_t btConfiguration
= 0;
244 byte_t btConnection
= 0;
245 byte_t btReceiveBank
= AT91C_UDP_RX_DATA_BK0
;
247 //*----------------------------------------------------------------------------
249 //* \brief This function deactivates the USB device
250 //*----------------------------------------------------------------------------
252 // Disconnect the USB device
253 AT91C_BASE_PIOA
->PIO_ODR
= GPIO_USB_PU
;
255 // Clear all lingering interrupts
256 if(pUdp
->UDP_ISR
& AT91C_UDP_ENDBUSRES
) {
257 pUdp
->UDP_ICR
= AT91C_UDP_ENDBUSRES
;
261 //*----------------------------------------------------------------------------
263 //* \brief This function Activates the USB device
264 //*----------------------------------------------------------------------------
266 // Set the PLL USB Divider
267 AT91C_BASE_CKGR
->CKGR_PLLR
|= AT91C_CKGR_USBDIV_1
;
269 // Specific Chip USB Initialisation
270 // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock
271 AT91C_BASE_PMC
->PMC_SCER
= AT91C_PMC_UDP
;
272 AT91C_BASE_PMC
->PMC_PCER
= (1 << AT91C_ID_UDP
);
274 // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO
275 // Set in PIO mode and Configure in Output
276 AT91C_BASE_PIOA
->PIO_PER
= GPIO_USB_PU
; // Set in PIO mode
277 AT91C_BASE_PIOA
->PIO_OER
= GPIO_USB_PU
; // Configure as Output
279 // Clear for set the Pullup resistor
280 AT91C_BASE_PIOA
->PIO_CODR
= GPIO_USB_PU
;
282 // Disconnect and reconnect USB controller for 100ms
285 // Wait for a short while
286 for (volatile size_t i
=0; i
<0x100000; i
++);
288 // Reconnect USB reconnect
289 AT91C_BASE_PIOA
->PIO_SODR
= GPIO_USB_PU
;
290 AT91C_BASE_PIOA
->PIO_OER
= GPIO_USB_PU
;
293 //*----------------------------------------------------------------------------
295 //* \brief Test if the device is configured and handle enumeration
296 //*----------------------------------------------------------------------------
298 AT91_REG isr
= pUdp
->UDP_ISR
;
300 if (isr
& AT91C_UDP_ENDBUSRES
) {
301 pUdp
->UDP_ICR
= AT91C_UDP_ENDBUSRES
;
302 // reset all endpoints
303 pUdp
->UDP_RSTEP
= (unsigned int)-1;
305 // Enable the function
306 pUdp
->UDP_FADDR
= AT91C_UDP_FEN
;
307 // Configure endpoint 0
308 pUdp
->UDP_CSR
[0] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_CTRL
);
310 else if (isr
& AT91C_UDP_EPINT0
) {
311 pUdp
->UDP_ICR
= AT91C_UDP_EPINT0
;
312 AT91F_CDC_Enumerate();
314 return (btConfiguration
) ? true : false;
320 if (!usb_check()) return false;
321 return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
);
325 In github PR #129, some users appears to get a false positive from
326 usb_poll, which returns true, but the usb_read operation
328 This check is basically the same as above, but also checks
329 that the length available to read is non-zero, thus hopefully fixes the
332 bool usb_poll_validate_length()
335 if (!usb_check()) return false;
336 if (!(pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
)) return false;
337 return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16) > 0;
340 //*----------------------------------------------------------------------------
342 //* \brief Read available data from Endpoint OUT
343 //*----------------------------------------------------------------------------
344 uint32_t usb_read(byte_t
* data
, size_t len
) {
345 byte_t bank
= btReceiveBank
;
346 uint32_t packetSize
, nbBytesRcv
= 0;
347 uint32_t time_out
= 0;
350 if (!usb_check()) break;
352 if ( pUdp
->UDP_CSR
[AT91C_EP_OUT
] & bank
) {
353 packetSize
= MIN(pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16, len
);
356 data
[nbBytesRcv
++] = pUdp
->UDP_FDR
[AT91C_EP_OUT
];
357 pUdp
->UDP_CSR
[AT91C_EP_OUT
] &= ~(bank
);
358 if (bank
== AT91C_UDP_RX_DATA_BK0
) {
359 bank
= AT91C_UDP_RX_DATA_BK1
;
361 bank
= AT91C_UDP_RX_DATA_BK0
;
364 if (time_out
++ == 0x1fff) break;
367 btReceiveBank
= bank
;
371 //*----------------------------------------------------------------------------
373 //* \brief Send through endpoint 2
374 //*----------------------------------------------------------------------------
375 uint32_t usb_write(const byte_t
* data
, const size_t len
) {
379 if (!length
) return 0;
380 if (!usb_check()) return 0;
382 // Send the first packet
383 cpt
= MIN(length
, AT91C_EP_IN_SIZE
-1);
385 while (cpt
--) pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++;
386 pUdp
->UDP_CSR
[AT91C_EP_IN
] |= AT91C_UDP_TXPKTRDY
;
389 // Fill the second bank
390 cpt
= MIN(length
, AT91C_EP_IN_SIZE
-1);
392 while (cpt
--) pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++;
393 // Wait for the first bank to be sent
394 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) {
395 if (!usb_check()) return length
;
397 pUdp
->UDP_CSR
[AT91C_EP_IN
] &= ~(AT91C_UDP_TXCOMP
);
398 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
);
399 pUdp
->UDP_CSR
[AT91C_EP_IN
] |= AT91C_UDP_TXPKTRDY
;
402 // Wait for the end of transfer
403 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) {
404 if (!usb_check()) return length
;
407 pUdp
->UDP_CSR
[AT91C_EP_IN
] &= ~(AT91C_UDP_TXCOMP
);
408 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
);
413 //*----------------------------------------------------------------------------
414 //* \fn AT91F_USB_SendData
415 //* \brief Send Data through the control endpoint
416 //*----------------------------------------------------------------------------
417 unsigned int csrTab
[100] = {0x00};
418 unsigned char csrIdx
= 0;
420 static void AT91F_USB_SendData(AT91PS_UDP pUdp
, const char *pData
, uint32_t length
) {
425 cpt
= MIN(length
, 8);
429 pUdp
->UDP_FDR
[0] = *pData
++;
431 if (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
) {
432 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_TXCOMP
);
433 while (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
);
436 pUdp
->UDP_CSR
[0] |= AT91C_UDP_TXPKTRDY
;
438 csr
= pUdp
->UDP_CSR
[0];
440 // Data IN stage has been stopped by a status OUT
441 if (csr
& AT91C_UDP_RX_DATA_BK0
) {
442 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_RX_DATA_BK0
);
445 } while ( !(csr
& AT91C_UDP_TXCOMP
) );
449 if (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
) {
450 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_TXCOMP
);
451 while (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
);
455 //*----------------------------------------------------------------------------
456 //* \fn AT91F_USB_SendZlp
457 //* \brief Send zero length packet through the control endpoint
458 //*----------------------------------------------------------------------------
459 void AT91F_USB_SendZlp(AT91PS_UDP pUdp
) {
460 pUdp
->UDP_CSR
[0] |= AT91C_UDP_TXPKTRDY
;
461 while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
) );
462 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_TXCOMP
);
463 while (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
);
466 //*----------------------------------------------------------------------------
467 //* \fn AT91F_USB_SendStall
468 //* \brief Stall the control endpoint
469 //*----------------------------------------------------------------------------
470 void AT91F_USB_SendStall(AT91PS_UDP pUdp
) {
471 pUdp
->UDP_CSR
[0] |= AT91C_UDP_FORCESTALL
;
472 while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_ISOERROR
) );
473 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_FORCESTALL
| AT91C_UDP_ISOERROR
);
474 while (pUdp
->UDP_CSR
[0] & (AT91C_UDP_FORCESTALL
| AT91C_UDP_ISOERROR
));
477 //*----------------------------------------------------------------------------
478 //* \fn AT91F_CDC_Enumerate
479 //* \brief This function is a callback invoked when a SETUP packet is received
480 //*----------------------------------------------------------------------------
481 void AT91F_CDC_Enumerate() {
482 byte_t bmRequestType
, bRequest
;
483 uint16_t wValue
, wIndex
, wLength
, wStatus
;
485 if ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_RXSETUP
) )
488 bmRequestType
= pUdp
->UDP_FDR
[0];
489 bRequest
= pUdp
->UDP_FDR
[0];
490 wValue
= (pUdp
->UDP_FDR
[0] & 0xFF);
491 wValue
|= (pUdp
->UDP_FDR
[0] << 8);
492 wIndex
= (pUdp
->UDP_FDR
[0] & 0xFF);
493 wIndex
|= (pUdp
->UDP_FDR
[0] << 8);
494 wLength
= (pUdp
->UDP_FDR
[0] & 0xFF);
495 wLength
|= (pUdp
->UDP_FDR
[0] << 8);
497 if (bmRequestType
& 0x80) {
498 pUdp
->UDP_CSR
[0] |= AT91C_UDP_DIR
;
499 while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_DIR
) );
501 pUdp
->UDP_CSR
[0] &= ~AT91C_UDP_RXSETUP
;
502 while ( (pUdp
->UDP_CSR
[0] & AT91C_UDP_RXSETUP
) );
504 // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
505 switch ((bRequest
<< 8) | bmRequestType
) {
506 case STD_GET_DESCRIPTOR
:
507 if (wValue
== 0x100) // Return Device Descriptor
508 AT91F_USB_SendData(pUdp
, devDescriptor
, MIN(sizeof(devDescriptor
), wLength
));
509 else if (wValue
== 0x200) // Return Configuration Descriptor
510 AT91F_USB_SendData(pUdp
, cfgDescriptor
, MIN(sizeof(cfgDescriptor
), wLength
));
511 else if ((wValue
& 0xF00) == 0x300) { // Return String Descriptor
512 const char *strDescriptor
= getStringDescriptor(wValue
& 0xff);
513 if (strDescriptor
!= NULL
) {
514 AT91F_USB_SendData(pUdp
, strDescriptor
, MIN(strDescriptor
[0], wLength
));
516 AT91F_USB_SendStall(pUdp
);
520 AT91F_USB_SendStall(pUdp
);
522 case STD_SET_ADDRESS
:
523 AT91F_USB_SendZlp(pUdp
);
524 pUdp
->UDP_FADDR
= (AT91C_UDP_FEN
| wValue
);
525 pUdp
->UDP_GLBSTATE
= (wValue
) ? AT91C_UDP_FADDEN
: 0;
527 case STD_SET_CONFIGURATION
:
528 btConfiguration
= wValue
;
529 AT91F_USB_SendZlp(pUdp
);
530 pUdp
->UDP_GLBSTATE
= (wValue
) ? AT91C_UDP_CONFG
: AT91C_UDP_FADDEN
;
531 pUdp
->UDP_CSR
[1] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_OUT
) : 0;
532 pUdp
->UDP_CSR
[2] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_IN
) : 0;
533 pUdp
->UDP_CSR
[3] = (wValue
) ? (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_INT_IN
) : 0;
535 case STD_GET_CONFIGURATION
:
536 AT91F_USB_SendData(pUdp
, (char *) &(btConfiguration
), sizeof(btConfiguration
));
538 case STD_GET_STATUS_ZERO
:
540 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
542 case STD_GET_STATUS_INTERFACE
:
544 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
546 case STD_GET_STATUS_ENDPOINT
:
549 if ((pUdp
->UDP_GLBSTATE
& AT91C_UDP_CONFG
) && (wIndex
<= 3)) {
550 wStatus
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1;
551 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
553 else if ((pUdp
->UDP_GLBSTATE
& AT91C_UDP_FADDEN
) && (wIndex
== 0)) {
554 wStatus
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1;
555 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
));
558 AT91F_USB_SendStall(pUdp
);
560 case STD_SET_FEATURE_ZERO
:
561 AT91F_USB_SendStall(pUdp
);
563 case STD_SET_FEATURE_INTERFACE
:
564 AT91F_USB_SendZlp(pUdp
);
566 case STD_SET_FEATURE_ENDPOINT
:
568 if ((wValue
== 0) && wIndex
&& (wIndex
<= 3)) {
569 pUdp
->UDP_CSR
[wIndex
] = 0;
570 AT91F_USB_SendZlp(pUdp
);
573 AT91F_USB_SendStall(pUdp
);
575 case STD_CLEAR_FEATURE_ZERO
:
576 AT91F_USB_SendStall(pUdp
);
578 case STD_CLEAR_FEATURE_INTERFACE
:
579 AT91F_USB_SendZlp(pUdp
);
581 case STD_CLEAR_FEATURE_ENDPOINT
:
583 if ((wValue
== 0) && wIndex
&& (wIndex
<= 3)) {
585 pUdp
->UDP_CSR
[1] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_OUT
);
586 else if (wIndex
== 2)
587 pUdp
->UDP_CSR
[2] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_BULK_IN
);
588 else if (wIndex
== 3)
589 pUdp
->UDP_CSR
[3] = (AT91C_UDP_EPEDS
| AT91C_UDP_EPTYPE_ISO_IN
);
590 AT91F_USB_SendZlp(pUdp
);
593 AT91F_USB_SendStall(pUdp
);
596 // handle CDC class requests
597 case SET_LINE_CODING
:
598 while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_RX_DATA_BK0
) );
599 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_RX_DATA_BK0
);
600 AT91F_USB_SendZlp(pUdp
);
602 case GET_LINE_CODING
:
603 AT91F_USB_SendData(pUdp
, (char *) &line
, MIN(sizeof(line
), wLength
));
605 case SET_CONTROL_LINE_STATE
:
606 btConnection
= wValue
;
607 AT91F_USB_SendZlp(pUdp
);
610 AT91F_USB_SendStall(pUdp
);