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) 
  42 #include "at91sam7s512.h" 
  43 #include "config_gpio.h" 
  45 #define AT91C_EP_CONTROL     0 
  46 #define AT91C_EP_OUT         1 
  48 #define AT91C_EP_NOTIFY      3 
  49 #define AT91C_EP_OUT_SIZE 0x40 
  50 #define AT91C_EP_IN_SIZE  0x40 
  52 // Language must always be 0. 
  53 #define STR_LANGUAGE_CODES 0x00 
  54 #define STR_MANUFACTURER   0x01 
  55 #define STR_PRODUCT        0x02 
  58 static const char devDescriptor
[] = { 
  59         /* Device descriptor */ 
  61         0x01,      // bDescriptorType 
  62         0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.0) 
  63         0x02,      // bDeviceClass:    (Communication Device Class) 
  64         0x00,      // bDeviceSubclass: (unused at this time) 
  65         0x00,      // bDeviceProtocol: (unused at this time) 
  66         0x08,      // bMaxPacketSize0 
  67         0xc4,0x9a, // Vendor ID (0x9ac4 = J. Westhues) 
  68         0x8f,0x4b, // Product ID (0x4b8f = Proxmark-3 RFID Instrument) 
  69         0x01,0x00, // Device release number (0001) 
  70         STR_MANUFACTURER
,  // iManufacturer 
  71         STR_PRODUCT
,       // iProduct 
  72         0x00,      // iSerialNumber 
  77 static const char cfgDescriptor
[] = { 
  78         /* ============== CONFIGURATION 1 =========== */ 
  79         /* Configuration 1 descriptor */ 
  81         0x02,   // CbDescriptorType 
  82         0x43,   // CwTotalLength 2 EP + Control 
  84         0x02,   // CbNumInterfaces 
  85         0x01,   // CbConfigurationValue 
  86         0x00,   // CiConfiguration 
  87         0x80,   // CbmAttributes (Bus Powered) 
  88         0x4B,   // CMaxPower (150mA max current drawn from bus) 
  90         /* Interface 0 Descriptor: Communication Class Interface */ 
  92         0x04, // bDescriptorType 
  93         0x00, // bInterfaceNumber 
  94         0x00, // bAlternateSetting 
  95         0x01, // bNumEndpoints 
  96         0x02, // bInterfaceClass:       Communication Interface Class 
  97         0x02, // bInterfaceSubclass:    Abstract Control Model 
  98         0x01, // bInterfaceProtocol:    Common AT Commands, V.25ter 
 101         /* Header Functional Descriptor */ 
 102         0x05, // bFunction Length 
 103         0x24, // bDescriptor type:      CS_INTERFACE 
 104         0x00, // bDescriptor subtype:   Header Functional Descriptor 
 108         /* ACM Functional Descriptor */ 
 109         0x04, // bFunctionLength 
 110         0x24, // bDescriptor Type:      CS_INTERFACE 
 111         0x02, // bDescriptor Subtype:   Abstract Control Management Functional Descriptor 
 112         0x02, // bmCapabilities:        D1: Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State 
 114         /* Union Functional Descriptor */ 
 115         0x05, // bFunctionLength 
 116         0x24, // bDescriptorType:       CS_INTERFACE 
 117         0x06, // bDescriptor Subtype:   Union Functional Descriptor 
 118         0x00, // bMasterInterface:      Communication Class Interface 
 119         0x01, // bSlaveInterface0:      Data Class Interface 
 121         /* Call Management Functional Descriptor */ 
 122         0x05, // bFunctionLength 
 123         0x24, // bDescriptor Type:      CS_INTERFACE 
 124         0x01, // bDescriptor Subtype:   Call Management Functional Descriptor 
 125         0x00, // bmCapabilities:        Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself 
 126         0x01, // bDataInterface:        Data Class Interface 1 
 128         /* Endpoint 1 descriptor */ 
 130         0x05,   // bDescriptorType 
 131         0x83,   // bEndpointAddress:    Endpoint 03 - IN 
 132         0x03,   // bmAttributes:        INT 
 133         0x08,   // wMaxPacketSize:      8 
 137         /* Interface 1 Descriptor: Data Class Interface */ 
 139         0x04, // bDescriptorType 
 140         0x01, // bInterfaceNumber 
 141         0x00, // bAlternateSetting 
 142         0x02, // bNumEndpoints 
 143         0x0A, // bInterfaceClass:       Data Interface Class 
 144         0x00, // bInterfaceSubclass:    not used 
 145         0x00, // bInterfaceProtocol:    No class specific protocol required) 
 148         /* Endpoint 1 descriptor */ 
 150         0x05,   // bDescriptorType 
 151         0x01,   // bEndpointAddress:    Endpoint 01 - OUT 
 152         0x02,   // bmAttributes:        BULK 
 153         AT91C_EP_OUT_SIZE
, // wMaxPacketSize 
 157         /* Endpoint 2 descriptor */ 
 159         0x05,   // bDescriptorType 
 160         0x82,   // bEndpointAddress:    Endpoint 02 - IN 
 161         0x02,   // bmAttributes:        BULK 
 162         AT91C_EP_IN_SIZE
,   // wMaxPacketSize 
 168 static const char StrDescLanguageCodes
[] = { 
 170         0x03,       // Type is string 
 171         0x09, 0x04  // supported language Code 0 = 0x0409 (English) 
 175 // Note: ModemManager (Linux) ignores Proxmark3 devices by matching the 
 176 // manufacturer string "proxmark.org". Don't change this. 
 177 static const char StrDescManufacturer
[] = { 
 179         0x03,       // Type is string 
 195 static const char StrDescProduct
[] = { 
 197         0x03,       // Type is string 
 210 static const char* getStringDescriptor(uint8_t idx
) { 
 212                 case STR_LANGUAGE_CODES
: 
 213                         return StrDescLanguageCodes
; 
 214                 case STR_MANUFACTURER
: 
 215                         return StrDescManufacturer
; 
 217                         return StrDescProduct
; 
 224 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect 
 225 #define REG_NO_EFFECT_1_ALL      AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \ 
 226                                                                 |AT91C_UDP_STALLSENT   | AT91C_UDP_RXSETUP \ 
 230 // Clear flags in the UDP_CSR register 
 231 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \ 
 232         volatile unsigned int reg; \ 
 233         reg = pUdp->UDP_CSR[(endpoint)]; \ 
 234         reg |= REG_NO_EFFECT_1_ALL; \ 
 236         pUdp->UDP_CSR[(endpoint)] = reg; \ 
 240 // Set flags in the UDP_CSR register 
 241 #define UDP_SET_EP_FLAGS(endpoint, flags) { \ 
 242         volatile unsigned int reg; \ 
 243         reg = pUdp->UDP_CSR[(endpoint)]; \ 
 244         reg |= REG_NO_EFFECT_1_ALL; \ 
 246         pUdp->UDP_CSR[(endpoint)] = reg; \ 
 250 /* USB standard request codes */ 
 251 #define STD_GET_STATUS_ZERO           0x0080 
 252 #define STD_GET_STATUS_INTERFACE      0x0081 
 253 #define STD_GET_STATUS_ENDPOINT       0x0082 
 255 #define STD_CLEAR_FEATURE_ZERO        0x0100 
 256 #define STD_CLEAR_FEATURE_INTERFACE   0x0101 
 257 #define STD_CLEAR_FEATURE_ENDPOINT    0x0102 
 259 #define STD_SET_FEATURE_ZERO          0x0300 
 260 #define STD_SET_FEATURE_INTERFACE     0x0301 
 261 #define STD_SET_FEATURE_ENDPOINT      0x0302 
 263 #define STD_SET_ADDRESS               0x0500 
 264 #define STD_GET_DESCRIPTOR            0x0680 
 265 #define STD_SET_DESCRIPTOR            0x0700 
 266 #define STD_GET_CONFIGURATION         0x0880 
 267 #define STD_SET_CONFIGURATION         0x0900 
 268 #define STD_GET_INTERFACE             0x0A81 
 269 #define STD_SET_INTERFACE             0x0B01 
 270 #define STD_SYNCH_FRAME               0x0C82 
 272 /* CDC Class Specific Request Code */ 
 273 #define GET_LINE_CODING               0x21A1 
 274 #define SET_LINE_CODING               0x2021 
 275 #define SET_CONTROL_LINE_STATE        0x2221 
 279         unsigned int dwDTERRate
; 
 283 } AT91S_CDC_LINE_CODING
, *AT91PS_CDC_LINE_CODING
; 
 286 AT91S_CDC_LINE_CODING line 
= { 
 293 static void AT91F_CDC_Enumerate(); 
 295 AT91PS_UDP pUdp 
= AT91C_BASE_UDP
; 
 296 uint8_t btConfiguration 
= 0; 
 297 uint8_t btConnection    
= 0; 
 298 uint8_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 //*---------------------------------------------------------------------------- 
 353 static bool usb_check() { 
 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; 
 374         if (!usb_check()) return false; 
 375         return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
); 
 380         In github PR #129, some users appears to get a false positive from 
 381         usb_poll, which returns true, but the usb_read operation 
 383         This check is basically the same as above, but also checks 
 384         that the length available to read is non-zero, thus hopefully fixes the 
 387 bool usb_poll_validate_length() { 
 388         if (!usb_check()) return false; 
 389         if (!(pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
)) return false; 
 390         return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16) >  0; 
 394 //*---------------------------------------------------------------------------- 
 396 //* \brief Read available data from Endpoint OUT 
 397 //*---------------------------------------------------------------------------- 
 398 static uint32_t usb_read(uint8_t* data
, size_t len
) { 
 399         uint8_t bank 
= btReceiveBank
; 
 400         uint32_t packetSize
, nbBytesRcv 
= 0; 
 401         uint32_t time_out 
= 0; 
 404                 if (!usb_check()) break; 
 406                 if ( pUdp
->UDP_CSR
[AT91C_EP_OUT
] & bank 
) { 
 407                         packetSize 
= MIN(pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16, len
); 
 410                                 data
[nbBytesRcv
++] = pUdp
->UDP_FDR
[AT91C_EP_OUT
]; 
 411                         UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT
, bank
); 
 412                         if (bank 
== AT91C_UDP_RX_DATA_BK0
) { 
 413                                 bank 
= AT91C_UDP_RX_DATA_BK1
; 
 415                                 bank 
= AT91C_UDP_RX_DATA_BK0
; 
 418                 if (time_out
++ == 0x1fff) break; 
 421         btReceiveBank 
= bank
; 
 426 //*---------------------------------------------------------------------------- 
 428 //* \brief Send through endpoint 2 
 429 //*---------------------------------------------------------------------------- 
 430 static uint32_t usb_write(const uint8_t* data
, const size_t len
) { 
 434         if (!length
) return 0; 
 435         if (!usb_check()) return 0; 
 437         // Send the first packet 
 438         cpt 
= MIN(length
, AT91C_EP_IN_SIZE
); 
 441                 pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++; 
 443         UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
); 
 446                 // Fill the next bank 
 447                 cpt 
= MIN(length
, AT91C_EP_IN_SIZE
); 
 450                         pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++; 
 452                 // Wait for the previous bank to be sent 
 453                 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) { 
 454                         if (!usb_check()) return length
; 
 456                 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
); 
 457                 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
) 
 475 //*---------------------------------------------------------------------------- 
 476 //* \fn    AT91F_USB_SendData 
 477 //* \brief Send Data through the control endpoint 
 478 //*---------------------------------------------------------------------------- 
 479 static void AT91F_USB_SendData(AT91PS_UDP pUdp
, const char *pData
, uint32_t length
) { 
 484                 cpt 
= MIN(length
, 8); 
 488                         pUdp
->UDP_FDR
[0] = *pData
++; 
 490                 if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) { 
 491                         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
); 
 492                         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) 
 496                 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
); 
 498                         csr 
= pUdp
->UDP_CSR
[AT91C_EP_CONTROL
]; 
 500                         // Data IN stage has been stopped by a status OUT 
 501                         if (csr 
& AT91C_UDP_RX_DATA_BK0
) { 
 502                                 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
); 
 505                 } while (!(csr 
& AT91C_UDP_TXCOMP
)); 
 509         if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) { 
 510                 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
); 
 511                 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 static 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
)) 
 525         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
); 
 526         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) 
 531 //*---------------------------------------------------------------------------- 
 532 //* \fn    AT91F_USB_SendStall 
 533 //* \brief Stall the control endpoint 
 534 //*---------------------------------------------------------------------------- 
 535 static void AT91F_USB_SendStall(AT91PS_UDP pUdp
) { 
 536         UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL
); 
 537         while (!(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_ISOERROR
)) 
 539         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL 
| AT91C_UDP_ISOERROR
); 
 540         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & (AT91C_UDP_FORCESTALL 
| AT91C_UDP_ISOERROR
)) 
 545 //*---------------------------------------------------------------------------- 
 546 //* \fn    AT91F_CDC_Enumerate 
 547 //* \brief This function is a callback invoked when a SETUP packet is received 
 548 //*---------------------------------------------------------------------------- 
 549 static void AT91F_CDC_Enumerate() { 
 550         uint8_t bmRequestType
, bRequest
; 
 551         uint16_t wValue
, wIndex
, wLength
, wStatus
; 
 553         if (!(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
)) 
 556         bmRequestType 
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
]; 
 557         bRequest      
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
]; 
 558         wValue        
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF); 
 559         wValue       
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8); 
 560         wIndex        
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF); 
 561         wIndex       
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8); 
 562         wLength       
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF); 
 563         wLength      
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8); 
 565         if (bmRequestType 
& 0x80) { // Data Phase Transfer Direction Device to Host 
 566                 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_DIR
); 
 567                 while (!(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_DIR
)) 
 570         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RXSETUP
); 
 571         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
) 
 574         // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 
 575         switch ((bRequest 
<< 8) | bmRequestType
) { 
 576         case STD_GET_DESCRIPTOR
: 
 577                 if (wValue 
== 0x100)       // Return Device Descriptor 
 578                         AT91F_USB_SendData(pUdp
, devDescriptor
, MIN(sizeof(devDescriptor
), wLength
)); 
 579                 else if (wValue 
== 0x200)  // Return Configuration Descriptor 
 580                         AT91F_USB_SendData(pUdp
, cfgDescriptor
, MIN(sizeof(cfgDescriptor
), wLength
)); 
 581                 else if ((wValue 
& 0xF00) == 0x300) { // Return String Descriptor 
 582                         const char *strDescriptor 
= getStringDescriptor(wValue 
& 0xff); 
 583                         if (strDescriptor 
!= NULL
) { 
 584                                 AT91F_USB_SendData(pUdp
, strDescriptor
, MIN(strDescriptor
[0], wLength
)); 
 586                                 AT91F_USB_SendStall(pUdp
); 
 590                         AT91F_USB_SendStall(pUdp
); 
 592         case STD_SET_ADDRESS
: 
 593                 AT91F_USB_SendZlp(pUdp
); 
 594                 pUdp
->UDP_FADDR 
= (AT91C_UDP_FEN 
| wValue
); 
 595                 pUdp
->UDP_GLBSTATE  
= (wValue
) ? AT91C_UDP_FADDEN 
: 0; 
 597         case STD_SET_CONFIGURATION
: 
 598                 btConfiguration 
= wValue
; 
 599                 AT91F_USB_SendZlp(pUdp
); 
 600                 pUdp
->UDP_GLBSTATE  
= (wValue
) ? AT91C_UDP_CONFG 
: AT91C_UDP_FADDEN
; 
 601                 pUdp
->UDP_CSR
[AT91C_EP_OUT
]    = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_OUT
) : 0; 
 602                 pUdp
->UDP_CSR
[AT91C_EP_IN
]     = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_IN
)  : 0; 
 603                 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_INT_IN
)   : 0; 
 605         case STD_GET_CONFIGURATION
: 
 606                 AT91F_USB_SendData(pUdp
, (char *) &(btConfiguration
), sizeof(btConfiguration
)); 
 608         case STD_GET_STATUS_ZERO
: 
 609                 wStatus 
= 0;    // Device is Bus powered, remote wakeup disabled 
 610                 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 612         case STD_GET_STATUS_INTERFACE
: 
 613                 wStatus 
= 0;    // reserved for future use 
 614                 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 616         case STD_GET_STATUS_ENDPOINT
: 
 619                 if ((pUdp
->UDP_GLBSTATE 
& AT91C_UDP_CONFG
) && (wIndex 
<= AT91C_EP_NOTIFY
)) { 
 620                         wStatus 
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1; 
 621                         AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 622                 } else if ((pUdp
->UDP_GLBSTATE 
& AT91C_UDP_FADDEN
) && (wIndex 
== AT91C_EP_CONTROL
)) { 
 623                         wStatus 
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1; 
 624                         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
); 
 640                         AT91F_USB_SendStall(pUdp
); 
 642         case STD_CLEAR_FEATURE_ZERO
: 
 643                 AT91F_USB_SendStall(pUdp
); 
 645         case STD_CLEAR_FEATURE_INTERFACE
: 
 646                 AT91F_USB_SendZlp(pUdp
); 
 648         case STD_CLEAR_FEATURE_ENDPOINT
: 
 650                 if ((wValue 
== 0) && (wIndex 
>= AT91C_EP_OUT
) && (wIndex 
<= AT91C_EP_NOTIFY
)) { 
 651                         if (wIndex 
== AT91C_EP_OUT
) 
 652                                 pUdp
->UDP_CSR
[AT91C_EP_OUT
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_OUT
); 
 653                         else if (wIndex 
== AT91C_EP_IN
) 
 654                                 pUdp
->UDP_CSR
[AT91C_EP_IN
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_IN
); 
 655                         else if (wIndex 
== AT91C_EP_NOTIFY
) 
 656                                 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_INT_IN
); 
 657                         AT91F_USB_SendZlp(pUdp
); 
 660                         AT91F_USB_SendStall(pUdp
); 
 663         // handle CDC class requests 
 664         case SET_LINE_CODING
: 
 665                 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
); 
 684 //*************************************************************************** 
 685 // Interface to the main program 
 686 //*************************************************************************** 
 688 // The function to receive a command from the client via USB 
 689 bool cmd_receive(UsbCommand
* cmd
) { 
 691         // Check if there is a usb packet available 
 695         // Try to retrieve the available command frame 
 696         size_t rxlen 
= usb_read((uint8_t*)cmd
, sizeof(UsbCommand
)); 
 698         // Check if the transfer was complete 
 699         if (rxlen 
!= sizeof(UsbCommand
)) 
 702         // Received command successfully 
 707 // The function to send a response to the client via USB 
 708 bool cmd_send(uint16_t cmd
, uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, void* data
, uint16_t datalen
) { 
 712         // Compose the outgoing response frame 
 713         txcmd
.cmd 
= cmd 
| CMD_VARIABLE_SIZE_FLAG
; 
 718         // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE 
 720                 datalen 
= MIN(datalen
, USB_CMD_DATA_SIZE
); 
 721                 for (uint16_t i 
= 0; i 
< datalen
; i
++) { 
 722                         txcmd
.d
.asBytes
[i
] = ((uint8_t*)data
)[i
]; 
 724                 txcmd
.datalen 
= datalen
; 
 729         // Send frame and make sure all bytes are transmitted 
 730         size_t tx_size 
= offsetof(UsbResponse
, d
) + datalen
; 
 731         if (usb_write((uint8_t*)&txcmd
, tx_size
) != 0) return false; 
 737 // For compatibility only: legacy function to send a response with fixed size to the client via USB 
 738 bool cmd_send_old(uint16_t cmd
, uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, void* data
, uint16_t datalen
) { 
 742         // Compose the outgoing response frame 
 748         // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE 
 750                 datalen 
= MIN(datalen
, USB_CMD_DATA_SIZE
); 
 751                 for (uint16_t i 
= 0; i 
< datalen
; i
++) { 
 752                         txcmd
.d
.asBytes
[i
] = ((uint8_t*)data
)[i
]; 
 756         // Send frame and make sure all bytes are transmitted 
 757         if (usb_write((uint8_t*)&txcmd
, sizeof(UsbCommand
)) != 0) return false;