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 
 160 static const char StrDescLanguageCodes
[] = { 
 162   0x03,                 // Type is string 
 163   0x09, 0x04    // supported language Code 0 = 0x0409 (English) 
 166 // Note: ModemManager (Linux) ignores Proxmark3 devices by matching the 
 167 // manufacturer string "proxmark.org". Don't change this. 
 168 static const char StrDescManufacturer
[] = { 
 170   0x03,                 // Type is string 
 185 static const char StrDescProduct
[] = { 
 187   0x03,                 // Type is string 
 194 const char* getStringDescriptor(uint8_t idx
) 
 197                 case STR_LANGUAGE_CODES
: 
 198                         return StrDescLanguageCodes
; 
 199                 case STR_MANUFACTURER
: 
 200                         return StrDescManufacturer
; 
 202                         return StrDescProduct
; 
 208 // Bitmap for all status bits in CSR which must be written as 1 to cause no effect 
 209 #define REG_NO_EFFECT_1_ALL      AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \ 
 210                                 |AT91C_UDP_STALLSENT   | AT91C_UDP_RXSETUP \ 
 213 // Clear flags in the UDP_CSR register 
 214 #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \ 
 215         volatile unsigned int reg; \ 
 216         reg = pUdp->UDP_CSR[(endpoint)]; \ 
 217         reg |= REG_NO_EFFECT_1_ALL; \ 
 219         pUdp->UDP_CSR[(endpoint)] = reg; \ 
 222 // Set flags in the UDP_CSR register 
 223 #define UDP_SET_EP_FLAGS(endpoint, flags) { \ 
 224         volatile unsigned int reg; \ 
 225         reg = pUdp->UDP_CSR[(endpoint)]; \ 
 226         reg |= REG_NO_EFFECT_1_ALL; \ 
 228         pUdp->UDP_CSR[(endpoint)] = reg; \ 
 231 /* USB standard request codes */ 
 232 #define STD_GET_STATUS_ZERO           0x0080 
 233 #define STD_GET_STATUS_INTERFACE      0x0081 
 234 #define STD_GET_STATUS_ENDPOINT       0x0082 
 236 #define STD_CLEAR_FEATURE_ZERO        0x0100 
 237 #define STD_CLEAR_FEATURE_INTERFACE   0x0101 
 238 #define STD_CLEAR_FEATURE_ENDPOINT    0x0102 
 240 #define STD_SET_FEATURE_ZERO          0x0300 
 241 #define STD_SET_FEATURE_INTERFACE     0x0301 
 242 #define STD_SET_FEATURE_ENDPOINT      0x0302 
 244 #define STD_SET_ADDRESS               0x0500 
 245 #define STD_GET_DESCRIPTOR            0x0680 
 246 #define STD_SET_DESCRIPTOR            0x0700 
 247 #define STD_GET_CONFIGURATION         0x0880 
 248 #define STD_SET_CONFIGURATION         0x0900 
 249 #define STD_GET_INTERFACE             0x0A81 
 250 #define STD_SET_INTERFACE             0x0B01 
 251 #define STD_SYNCH_FRAME               0x0C82 
 253 /* CDC Class Specific Request Code */ 
 254 #define GET_LINE_CODING               0x21A1 
 255 #define SET_LINE_CODING               0x2021 
 256 #define SET_CONTROL_LINE_STATE        0x2221 
 259         unsigned int dwDTERRate
; 
 263 } AT91S_CDC_LINE_CODING
, *AT91PS_CDC_LINE_CODING
; 
 265 AT91S_CDC_LINE_CODING line 
= { 
 272 void AT91F_CDC_Enumerate(); 
 274 AT91PS_UDP pUdp 
= AT91C_BASE_UDP
; 
 275 byte_t btConfiguration 
= 0; 
 276 byte_t btConnection    
= 0; 
 277 byte_t btReceiveBank   
= AT91C_UDP_RX_DATA_BK0
; 
 280 //*---------------------------------------------------------------------------- 
 282 //* \brief This function deactivates the USB device 
 283 //*---------------------------------------------------------------------------- 
 285         // Disconnect the USB device 
 286         AT91C_BASE_PIOA
->PIO_ODR 
= GPIO_USB_PU
; 
 288         // Clear all lingering interrupts 
 289         if(pUdp
->UDP_ISR 
& AT91C_UDP_ENDBUSRES
) { 
 290                 pUdp
->UDP_ICR 
= AT91C_UDP_ENDBUSRES
; 
 295 //*---------------------------------------------------------------------------- 
 297 //* \brief This function Activates the USB device 
 298 //*---------------------------------------------------------------------------- 
 300         // Set the PLL USB Divider 
 301         AT91C_BASE_CKGR
->CKGR_PLLR 
|= AT91C_CKGR_USBDIV_1 
; 
 303         // Specific Chip USB Initialisation 
 304         // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock 
 305         AT91C_BASE_PMC
->PMC_SCER 
= AT91C_PMC_UDP
; 
 306         AT91C_BASE_PMC
->PMC_PCER 
= (1 << AT91C_ID_UDP
); 
 308         // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO 
 309         // Set in PIO mode and Configure in Output 
 310         AT91C_BASE_PIOA
->PIO_PER 
= GPIO_USB_PU
; // Set in PIO mode 
 311         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_USB_PU
; // Configure as Output 
 313         // Clear for set the Pullup resistor 
 314         AT91C_BASE_PIOA
->PIO_CODR 
= GPIO_USB_PU
; 
 316         // Disconnect and reconnect USB controller for 100ms 
 319         // Wait for a short while 
 320         for (volatile size_t i
=0; i
<0x100000; i
++); 
 322         // Reconnect USB reconnect 
 323         AT91C_BASE_PIOA
->PIO_SODR 
= GPIO_USB_PU
; 
 324         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_USB_PU
; 
 328 //*---------------------------------------------------------------------------- 
 330 //* \brief Test if the device is configured and handle enumeration 
 331 //*---------------------------------------------------------------------------- 
 333         AT91_REG isr 
= pUdp
->UDP_ISR
; 
 335         if (isr 
& AT91C_UDP_ENDBUSRES
) { 
 336                 pUdp
->UDP_ICR 
= AT91C_UDP_ENDBUSRES
; 
 337                 // reset all endpoints 
 338                 pUdp
->UDP_RSTEP  
= (unsigned int)-1; 
 340                 // Enable the function 
 341                 pUdp
->UDP_FADDR 
= AT91C_UDP_FEN
; 
 342                 // Configure endpoint 0 
 343                 pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_CTRL
); 
 344         } else if (isr 
& AT91C_UDP_EPINT0
) { 
 345                 pUdp
->UDP_ICR 
= AT91C_UDP_EPINT0
; 
 346                 AT91F_CDC_Enumerate(); 
 348         return (btConfiguration
) ? true : false; 
 354         if (!usb_check()) return false; 
 355         return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
); 
 360         In github PR #129, some users appears to get a false positive from 
 361         usb_poll, which returns true, but the usb_read operation 
 363         This check is basically the same as above, but also checks 
 364         that the length available to read is non-zero, thus hopefully fixes the 
 367 bool usb_poll_validate_length() 
 369         if (!usb_check()) return false; 
 370         if (!(pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
)) return false; 
 371         return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16) >  0; 
 374 //*---------------------------------------------------------------------------- 
 376 //* \brief Read available data from Endpoint OUT 
 377 //*---------------------------------------------------------------------------- 
 378 uint32_t usb_read(byte_t
* data
, size_t len
) { 
 379         byte_t bank 
= btReceiveBank
; 
 380         uint32_t packetSize
, nbBytesRcv 
= 0; 
 381         uint32_t time_out 
= 0; 
 384                 if (!usb_check()) break; 
 386                 if ( pUdp
->UDP_CSR
[AT91C_EP_OUT
] & bank 
) { 
 387                         packetSize 
= MIN(pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16, len
); 
 390                                 data
[nbBytesRcv
++] = pUdp
->UDP_FDR
[AT91C_EP_OUT
]; 
 391                         UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT
, bank
); 
 392                         if (bank 
== AT91C_UDP_RX_DATA_BK0
) { 
 393                                 bank 
= AT91C_UDP_RX_DATA_BK1
; 
 395                                 bank 
= AT91C_UDP_RX_DATA_BK0
; 
 398                 if (time_out
++ == 0x1fff) break; 
 401         btReceiveBank 
= bank
; 
 406 //*---------------------------------------------------------------------------- 
 408 //* \brief Send through endpoint 2 
 409 //*---------------------------------------------------------------------------- 
 410 uint32_t usb_write(const byte_t
* data
, const size_t len
) { 
 414         if (!length
) return 0; 
 415         if (!usb_check()) return 0; 
 417         // Send the first packet 
 418         cpt 
= MIN(length
, AT91C_EP_IN_SIZE
); 
 421                 pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++; 
 423         UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
); 
 426                 // Fill the next bank 
 427                 cpt 
= MIN(length
, AT91C_EP_IN_SIZE
); 
 430                         pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++; 
 432                 // Wait for the previous bank to be sent 
 433                 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) { 
 434                         if (!usb_check()) return length
; 
 436                 UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
); 
 437                 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
); 
 438                 UDP_SET_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXPKTRDY
); 
 441         // Wait for the end of transfer 
 442         while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) { 
 443                 if (!usb_check()) return length
; 
 446         UDP_CLEAR_EP_FLAGS(AT91C_EP_IN
, AT91C_UDP_TXCOMP
); 
 447         while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
); 
 453 //*---------------------------------------------------------------------------- 
 454 //* \fn    AT91F_USB_SendData 
 455 //* \brief Send Data through the control endpoint 
 456 //*---------------------------------------------------------------------------- 
 457 unsigned int csrTab
[100] = {0x00}; 
 458 unsigned char csrIdx 
= 0; 
 460 static void AT91F_USB_SendData(AT91PS_UDP pUdp
, const char *pData
, uint32_t length
) { 
 465                 cpt 
= MIN(length
, 8); 
 469                         pUdp
->UDP_FDR
[0] = *pData
++; 
 471                 if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) { 
 472                         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
); 
 473                         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
); 
 476                 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
); 
 478                         csr 
= pUdp
->UDP_CSR
[AT91C_EP_CONTROL
]; 
 480                         // Data IN stage has been stopped by a status OUT 
 481                         if (csr 
& AT91C_UDP_RX_DATA_BK0
) { 
 482                                 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
); 
 485                 } while ( !(csr 
& AT91C_UDP_TXCOMP
) ); 
 489         if (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) { 
 490                 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
); 
 491                 while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
); 
 496 //*---------------------------------------------------------------------------- 
 497 //* \fn    AT91F_USB_SendZlp 
 498 //* \brief Send zero length packet through the control endpoint 
 499 //*---------------------------------------------------------------------------- 
 500 void AT91F_USB_SendZlp(AT91PS_UDP pUdp
) { 
 501         UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXPKTRDY
); 
 502         while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
) ); 
 503         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_TXCOMP
); 
 504         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_TXCOMP
); 
 508 //*---------------------------------------------------------------------------- 
 509 //* \fn    AT91F_USB_SendStall 
 510 //* \brief Stall the control endpoint 
 511 //*---------------------------------------------------------------------------- 
 512 void AT91F_USB_SendStall(AT91PS_UDP pUdp
) { 
 513         UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL
); 
 514         while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_ISOERROR
) ); 
 515         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_FORCESTALL 
| AT91C_UDP_ISOERROR
); 
 516         while (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & (AT91C_UDP_FORCESTALL 
| AT91C_UDP_ISOERROR
)); 
 520 //*---------------------------------------------------------------------------- 
 521 //* \fn    AT91F_CDC_Enumerate 
 522 //* \brief This function is a callback invoked when a SETUP packet is received 
 523 //*---------------------------------------------------------------------------- 
 524 void AT91F_CDC_Enumerate() { 
 525         byte_t bmRequestType
, bRequest
; 
 526         uint16_t wValue
, wIndex
, wLength
, wStatus
; 
 528         if ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
) ) 
 531         bmRequestType 
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
]; 
 532         bRequest      
= pUdp
->UDP_FDR
[AT91C_EP_CONTROL
]; 
 533         wValue        
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF); 
 534         wValue       
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8); 
 535         wIndex        
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF); 
 536         wIndex       
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8); 
 537         wLength       
= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] & 0xFF); 
 538         wLength      
|= (pUdp
->UDP_FDR
[AT91C_EP_CONTROL
] << 8); 
 540         if (bmRequestType 
& 0x80) {     // Data Phase Transfer Direction Device to Host 
 541                 UDP_SET_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_DIR
); 
 542                 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_DIR
) ); 
 544         UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RXSETUP
); 
 545         while ( (pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RXSETUP
)  ); 
 547         // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 
 548         switch ((bRequest 
<< 8) | bmRequestType
) { 
 549         case STD_GET_DESCRIPTOR
: 
 550                 if (wValue 
== 0x100)       // Return Device Descriptor 
 551                         AT91F_USB_SendData(pUdp
, devDescriptor
, MIN(sizeof(devDescriptor
), wLength
)); 
 552                 else if (wValue 
== 0x200)  // Return Configuration Descriptor 
 553                         AT91F_USB_SendData(pUdp
, cfgDescriptor
, MIN(sizeof(cfgDescriptor
), wLength
)); 
 554                 else if ((wValue 
& 0xF00) == 0x300) { // Return String Descriptor 
 555                         const char *strDescriptor 
= getStringDescriptor(wValue 
& 0xff); 
 556                         if (strDescriptor 
!= NULL
) { 
 557                                 AT91F_USB_SendData(pUdp
, strDescriptor
, MIN(strDescriptor
[0], wLength
)); 
 559                                 AT91F_USB_SendStall(pUdp
); 
 563                         AT91F_USB_SendStall(pUdp
); 
 565         case STD_SET_ADDRESS
: 
 566                 AT91F_USB_SendZlp(pUdp
); 
 567                 pUdp
->UDP_FADDR 
= (AT91C_UDP_FEN 
| wValue
); 
 568                 pUdp
->UDP_GLBSTATE  
= (wValue
) ? AT91C_UDP_FADDEN 
: 0; 
 570         case STD_SET_CONFIGURATION
: 
 571                 btConfiguration 
= wValue
; 
 572                 AT91F_USB_SendZlp(pUdp
); 
 573                 pUdp
->UDP_GLBSTATE  
= (wValue
) ? AT91C_UDP_CONFG 
: AT91C_UDP_FADDEN
; 
 574                 pUdp
->UDP_CSR
[AT91C_EP_OUT
]    = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_OUT
) : 0; 
 575                 pUdp
->UDP_CSR
[AT91C_EP_IN
]     = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_IN
)  : 0; 
 576                 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_INT_IN
)   : 0; 
 578         case STD_GET_CONFIGURATION
: 
 579                 AT91F_USB_SendData(pUdp
, (char *) &(btConfiguration
), sizeof(btConfiguration
)); 
 581         case STD_GET_STATUS_ZERO
: 
 582                 wStatus 
= 0;    // Device is Bus powered, remote wakeup disabled 
 583                 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 585         case STD_GET_STATUS_INTERFACE
: 
 586                 wStatus 
= 0;    // reserved for future use 
 587                 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 589         case STD_GET_STATUS_ENDPOINT
: 
 592                 if ((pUdp
->UDP_GLBSTATE 
& AT91C_UDP_CONFG
) && (wIndex 
<= AT91C_EP_NOTIFY
)) { 
 593                         wStatus 
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1; 
 594                         AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 596                 else if ((pUdp
->UDP_GLBSTATE 
& AT91C_UDP_FADDEN
) && (wIndex 
== AT91C_EP_CONTROL
)) { 
 597                         wStatus 
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1; 
 598                         AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 601                         AT91F_USB_SendStall(pUdp
); 
 603         case STD_SET_FEATURE_ZERO
: 
 604                 AT91F_USB_SendStall(pUdp
); 
 606         case STD_SET_FEATURE_INTERFACE
: 
 607                 AT91F_USB_SendZlp(pUdp
); 
 609         case STD_SET_FEATURE_ENDPOINT
: 
 611                 if ((wValue 
== 0) && (wIndex 
>= AT91C_EP_OUT
) && (wIndex 
<= AT91C_EP_NOTIFY
)) { 
 612                         pUdp
->UDP_CSR
[wIndex
] = 0; 
 613                         AT91F_USB_SendZlp(pUdp
); 
 616                         AT91F_USB_SendStall(pUdp
); 
 618         case STD_CLEAR_FEATURE_ZERO
: 
 619                 AT91F_USB_SendStall(pUdp
); 
 621         case STD_CLEAR_FEATURE_INTERFACE
: 
 622                 AT91F_USB_SendZlp(pUdp
); 
 624         case STD_CLEAR_FEATURE_ENDPOINT
: 
 626                 if ((wValue 
== 0) && (wIndex 
>= AT91C_EP_OUT
) && (wIndex 
<= AT91C_EP_NOTIFY
)) { 
 627                         if (wIndex 
== AT91C_EP_OUT
) 
 628                                 pUdp
->UDP_CSR
[AT91C_EP_OUT
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_OUT
); 
 629                         else if (wIndex 
== AT91C_EP_IN
) 
 630                                 pUdp
->UDP_CSR
[AT91C_EP_IN
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_IN
); 
 631                         else if (wIndex 
== AT91C_EP_NOTIFY
) 
 632                                 pUdp
->UDP_CSR
[AT91C_EP_NOTIFY
] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_INT_IN
); 
 633                         AT91F_USB_SendZlp(pUdp
); 
 636                         AT91F_USB_SendStall(pUdp
); 
 639         // handle CDC class requests 
 640         case SET_LINE_CODING
: 
 641                 while ( !(pUdp
->UDP_CSR
[AT91C_EP_CONTROL
] & AT91C_UDP_RX_DATA_BK0
) ); 
 642                 UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL
, AT91C_UDP_RX_DATA_BK0
); 
 643                 AT91F_USB_SendZlp(pUdp
); 
 645         case GET_LINE_CODING
: 
 646                 AT91F_USB_SendData(pUdp
, (char *) &line
, MIN(sizeof(line
), wLength
)); 
 648         case SET_CONTROL_LINE_STATE
: 
 649                 btConnection 
= wValue
; 
 650                 AT91F_USB_SendZlp(pUdp
); 
 653                 AT91F_USB_SendStall(pUdp
);