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 "config_gpio.h" 
  38 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) 
  39 #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 
  40 #define AT91C_EP_IN_SIZE  0x40 
  41 #define AT91C_EP_OUT         1 
  42 #define AT91C_EP_OUT_SIZE 0x40 
  45 const char devDescriptor
[] = { 
  46         /* Device descriptor */ 
  48         0x01,      // bDescriptorType 
  49         0x10,0x01, // Complies with USB Spec. Release (0110h = release 1.10) 
  50         0x02,      // bDeviceClass:    CDC class code 
  51         0x00,      // bDeviceSubclass: CDC class sub code 
  52         0x00,      // bDeviceProtocol: CDC Device protocol 
  53         0x08,      // bMaxPacketSize0 
  54         0x2d,0x2d, // Vendor ID (--) 
  55         0x4d,0x50, // Product ID (PM), transmitted in reverse 
  56         0x01,0x00, // Device release number (0001) 
  57         0x01,      // iManufacturer    // 0x01 
  63 const char cfgDescriptor
[] = { 
  64         /* ============== CONFIGURATION 1 =========== */ 
  65         /* Configuration 1 descriptor */ 
  67         0x02,   // CbDescriptorType 
  68         0x43,   // CwTotalLength 2 EP + Control 
  70         0x02,   // CbNumInterfaces 
  71         0x01,   // CbConfigurationValue 
  72         0x00,   // CiConfiguration 
  73         0xC0,   // CbmAttributes 0xA0 
  76         /* Communication Class Interface Descriptor Requirement */ 
  78         0x04, // bDescriptorType 
  79         0x00, // bInterfaceNumber 
  80         0x00, // bAlternateSetting 
  81         0x01, // bNumEndpoints 
  82         0x02, // bInterfaceClass 
  83         0x02, // bInterfaceSubclass 
  84         0x00, // bInterfaceProtocol 
  87         /* Header Functional Descriptor */ 
  88         0x05, // bFunction Length 
  89         0x24, // bDescriptor type: CS_INTERFACE 
  90         0x00, // bDescriptor subtype: Header Func Desc 
  94         /* ACM Functional Descriptor */ 
  95         0x04, // bFunctionLength 
  96         0x24, // bDescriptor Type: CS_INTERFACE 
  97         0x02, // bDescriptor Subtype: ACM Func Desc 
  98         0x00, // bmCapabilities 
 100         /* Union Functional Descriptor */ 
 101         0x05, // bFunctionLength 
 102         0x24, // bDescriptorType: CS_INTERFACE 
 103         0x06, // bDescriptor Subtype: Union Func Desc 
 104         0x00, // bMasterInterface: Communication Class Interface 
 105         0x01, // bSlaveInterface0: Data Class Interface 
 107         /* Call Management Functional Descriptor */ 
 108         0x05, // bFunctionLength 
 109         0x24, // bDescriptor Type: CS_INTERFACE 
 110         0x01, // bDescriptor Subtype: Call Management Func Desc 
 111         0x00, // bmCapabilities: D1 + D0 
 112         0x01, // bDataInterface: Data Class Interface 1 
 114         /* Endpoint 1 descriptor */ 
 116         0x05,   // bDescriptorType 
 117         0x83,   // bEndpointAddress, Endpoint 03 - IN 
 118         0x03,   // bmAttributes      INT 
 119         0x08,   // wMaxPacketSize 
 123         /* Data Class Interface Descriptor Requirement */ 
 125         0x04, // bDescriptorType 
 126         0x01, // bInterfaceNumber 
 127         0x00, // bAlternateSetting 
 128         0x02, // bNumEndpoints 
 129         0x0A, // bInterfaceClass 
 130         0x00, // bInterfaceSubclass 
 131         0x00, // bInterfaceProtocol 
 134         /* First alternate setting */ 
 135         /* Endpoint 1 descriptor */ 
 137         0x05,   // bDescriptorType 
 138         0x01,   // bEndpointAddress, Endpoint 01 - OUT 
 139         0x02,   // bmAttributes      BULK 
 140         AT91C_EP_OUT_SIZE
,   // wMaxPacketSize 
 144         /* Endpoint 2 descriptor */ 
 146         0x05,   // bDescriptorType 
 147         0x82,   // bEndpointAddress, Endpoint 02 - IN 
 148         0x02,   // bmAttributes      BULK 
 149         AT91C_EP_IN_SIZE
,   // wMaxPacketSize 
 154 const char strDescriptor
[] = { 
 156   0x03,                 // Type is string 
 172 /* USB standard request code */ 
 173 #define STD_GET_STATUS_ZERO           0x0080 
 174 #define STD_GET_STATUS_INTERFACE      0x0081 
 175 #define STD_GET_STATUS_ENDPOINT       0x0082 
 177 #define STD_CLEAR_FEATURE_ZERO        0x0100 
 178 #define STD_CLEAR_FEATURE_INTERFACE   0x0101 
 179 #define STD_CLEAR_FEATURE_ENDPOINT    0x0102 
 181 #define STD_SET_FEATURE_ZERO          0x0300 
 182 #define STD_SET_FEATURE_INTERFACE     0x0301 
 183 #define STD_SET_FEATURE_ENDPOINT      0x0302 
 185 #define STD_SET_ADDRESS               0x0500 
 186 #define STD_GET_DESCRIPTOR            0x0680 
 187 #define STD_SET_DESCRIPTOR            0x0700 
 188 #define STD_GET_CONFIGURATION         0x0880 
 189 #define STD_SET_CONFIGURATION         0x0900 
 190 #define STD_GET_INTERFACE             0x0A81 
 191 #define STD_SET_INTERFACE             0x0B01 
 192 #define STD_SYNCH_FRAME               0x0C82 
 194 /* CDC Class Specific Request Code */ 
 195 #define GET_LINE_CODING               0x21A1 
 196 #define SET_LINE_CODING               0x2021 
 197 #define SET_CONTROL_LINE_STATE        0x2221 
 200         unsigned int dwDTERRate
; 
 204 } AT91S_CDC_LINE_CODING
, *AT91PS_CDC_LINE_CODING
; 
 206 AT91S_CDC_LINE_CODING line 
= { 
 212 void AT91F_CDC_Enumerate(); 
 214 AT91PS_UDP pUdp 
= AT91C_BASE_UDP
; 
 215 byte_t btConfiguration 
= 0; 
 216 byte_t btConnection    
= 0; 
 217 byte_t btReceiveBank   
= AT91C_UDP_RX_DATA_BK0
; 
 219 //*---------------------------------------------------------------------------- 
 221 //* \brief This function deactivates the USB device 
 222 //*---------------------------------------------------------------------------- 
 224   // Disconnect the USB device 
 225   AT91C_BASE_PIOA
->PIO_ODR 
= GPIO_USB_PU
; 
 227   // Clear all lingering interrupts 
 228   if(pUdp
->UDP_ISR 
& AT91C_UDP_ENDBUSRES
) { 
 229     pUdp
->UDP_ICR 
= AT91C_UDP_ENDBUSRES
; 
 233 //*---------------------------------------------------------------------------- 
 235 //* \brief This function Activates the USB device 
 236 //*---------------------------------------------------------------------------- 
 238         // Set the PLL USB Divider 
 239         AT91C_BASE_CKGR
->CKGR_PLLR 
|= AT91C_CKGR_USBDIV_1 
; 
 241         // Specific Chip USB Initialisation 
 242         // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock 
 243         AT91C_BASE_PMC
->PMC_SCER 
= AT91C_PMC_UDP
; 
 244         AT91C_BASE_PMC
->PMC_PCER 
= (1 << AT91C_ID_UDP
); 
 246         // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO 
 247         // Set in PIO mode and Configure in Output 
 248         AT91C_BASE_PIOA
->PIO_PER 
= GPIO_USB_PU
; // Set in PIO mode 
 249         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_USB_PU
; // Configure as Output 
 251         // Clear for set the Pullup resistor 
 252         AT91C_BASE_PIOA
->PIO_CODR 
= GPIO_USB_PU
; 
 254         // Disconnect and reconnect USB controller for 100ms 
 257         // Wait for a short while 
 258         for (volatile size_t i
=0; i
<0x100000; i
++); 
 261         // Reconnect USB reconnect 
 262         AT91C_BASE_PIOA
->PIO_SODR 
= GPIO_USB_PU
; 
 263         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_USB_PU
; 
 266 //*---------------------------------------------------------------------------- 
 268 //* \brief Test if the device is configured and handle enumeration 
 269 //*---------------------------------------------------------------------------- 
 271         AT91_REG isr 
= pUdp
->UDP_ISR
; 
 273         if (isr 
& AT91C_UDP_ENDBUSRES
) { 
 274                 pUdp
->UDP_ICR 
= AT91C_UDP_ENDBUSRES
; 
 275                 // reset all endpoints 
 276                 pUdp
->UDP_RSTEP  
= (unsigned int)-1; 
 278                 // Enable the function 
 279                 pUdp
->UDP_FADDR 
= AT91C_UDP_FEN
; 
 280                 // Configure endpoint 0 
 281                 pUdp
->UDP_CSR
[0] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_CTRL
); 
 283         else if (isr 
& AT91C_UDP_EPINT0
) { 
 284                 pUdp
->UDP_ICR 
= AT91C_UDP_EPINT0
; 
 285                 AT91F_CDC_Enumerate(); 
 287         return (btConfiguration
) ? true : false; 
 293   if (!usb_check()) return false; 
 294   return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
); 
 298         In github PR #129, some users appears to get a false positive from 
 299         usb_poll, which returns true, but the usb_read operation 
 301         This check is basically the same as above, but also checks 
 302         that the length available to read is non-zero, thus hopefully fixes the 
 305 bool usb_poll_validate_length() 
 307         if (!usb_check()) return false; 
 308         if (!(pUdp
->UDP_CSR
[AT91C_EP_OUT
] & btReceiveBank
)) return false; 
 309         return (pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16) >  0; 
 312 //*---------------------------------------------------------------------------- 
 314 //* \brief Read available data from Endpoint OUT 
 315 //*---------------------------------------------------------------------------- 
 316 uint32_t usb_read(byte_t
* data
, size_t len
) { 
 317         byte_t bank 
= btReceiveBank
; 
 318         uint32_t packetSize
, nbBytesRcv 
= 0; 
 319         uint32_t time_out 
= 0; 
 322                 if (!usb_check()) break; 
 324                 if ( pUdp
->UDP_CSR
[AT91C_EP_OUT
] & bank 
) { 
 325                         packetSize 
= MIN(pUdp
->UDP_CSR
[AT91C_EP_OUT
] >> 16, len
); 
 328                                 data
[nbBytesRcv
++] = pUdp
->UDP_FDR
[AT91C_EP_OUT
]; 
 330                         pUdp
->UDP_CSR
[AT91C_EP_OUT
] &= ~(bank
); 
 332                         if (bank 
== AT91C_UDP_RX_DATA_BK0
) 
 333                                 bank 
= AT91C_UDP_RX_DATA_BK1
; 
 335                                 bank 
= AT91C_UDP_RX_DATA_BK0
;            
 337                 if (time_out
++ == 0x1fff) break; 
 340         btReceiveBank 
= bank
; 
 344 //*---------------------------------------------------------------------------- 
 346 //* \brief Send through endpoint 2 
 347 //*---------------------------------------------------------------------------- 
 348 uint32_t usb_write(const byte_t
* data
, const size_t len
) { 
 352         if (!length
) return 0; 
 353         if (!usb_check()) return 0; 
 355         // Send the first packet 
 356         cpt 
= MIN(length
, AT91C_EP_IN_SIZE
-1); 
 358         while (cpt
--) pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++; 
 359         pUdp
->UDP_CSR
[AT91C_EP_IN
] |= AT91C_UDP_TXPKTRDY
; 
 362                 // Fill the second bank 
 363                 cpt 
= MIN(length
, AT91C_EP_IN_SIZE
-1); 
 365                 while (cpt
--) pUdp
->UDP_FDR
[AT91C_EP_IN
] = *data
++; 
 366                 // Wait for the the first bank to be sent 
 367                 while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) { 
 368                         if (!usb_check()) return length
; 
 370                 pUdp
->UDP_CSR
[AT91C_EP_IN
] &= ~(AT91C_UDP_TXCOMP
); 
 372                 while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
); 
 374                 pUdp
->UDP_CSR
[AT91C_EP_IN
] |= AT91C_UDP_TXPKTRDY
; 
 377         // Wait for the end of transfer 
 378         while (!(pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
)) { 
 379                 if (!usb_check()) return length
; 
 382         pUdp
->UDP_CSR
[AT91C_EP_IN
] &= ~(AT91C_UDP_TXCOMP
); 
 383         while (pUdp
->UDP_CSR
[AT91C_EP_IN
] & AT91C_UDP_TXCOMP
); 
 388 //*---------------------------------------------------------------------------- 
 389 //* \fn    AT91F_USB_SendData 
 390 //* \brief Send Data through the control endpoint 
 391 //*---------------------------------------------------------------------------- 
 392 unsigned int csrTab
[100] = {0x00}; 
 393 unsigned char csrIdx 
= 0; 
 395 static void AT91F_USB_SendData(AT91PS_UDP pUdp
, const char *pData
, uint32_t length
) { 
 400                 cpt 
= MIN(length
, 8); 
 404                         pUdp
->UDP_FDR
[0] = *pData
++; 
 406                 if (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
) { 
 407                         pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_TXCOMP
); 
 408                         while (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
); 
 411                 pUdp
->UDP_CSR
[0] |= AT91C_UDP_TXPKTRDY
; 
 413                         csr 
= pUdp
->UDP_CSR
[0]; 
 415                         // Data IN stage has been stopped by a status OUT 
 416                         if (csr 
& AT91C_UDP_RX_DATA_BK0
) { 
 417                                 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_RX_DATA_BK0
); 
 420                 } while ( !(csr 
& AT91C_UDP_TXCOMP
) ); 
 424         if (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
) { 
 425                 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_TXCOMP
); 
 426                 while (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
); 
 430 //*---------------------------------------------------------------------------- 
 431 //* \fn    AT91F_USB_SendZlp 
 432 //* \brief Send zero length packet through the control endpoint 
 433 //*---------------------------------------------------------------------------- 
 434 void AT91F_USB_SendZlp(AT91PS_UDP pUdp
) { 
 435         pUdp
->UDP_CSR
[0] |= AT91C_UDP_TXPKTRDY
; 
 436         while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
) ); 
 437         pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_TXCOMP
); 
 438         while (pUdp
->UDP_CSR
[0] & AT91C_UDP_TXCOMP
); 
 441 //*---------------------------------------------------------------------------- 
 442 //* \fn    AT91F_USB_SendStall 
 443 //* \brief Stall the control endpoint 
 444 //*---------------------------------------------------------------------------- 
 445 void AT91F_USB_SendStall(AT91PS_UDP pUdp
) { 
 446         pUdp
->UDP_CSR
[0] |= AT91C_UDP_FORCESTALL
; 
 447         while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_ISOERROR
) ); 
 448         pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_FORCESTALL 
| AT91C_UDP_ISOERROR
); 
 449         while (pUdp
->UDP_CSR
[0] & (AT91C_UDP_FORCESTALL 
| AT91C_UDP_ISOERROR
)); 
 452 //*---------------------------------------------------------------------------- 
 453 //* \fn    AT91F_CDC_Enumerate 
 454 //* \brief This function is a callback invoked when a SETUP packet is received 
 455 //*---------------------------------------------------------------------------- 
 456 void AT91F_CDC_Enumerate() { 
 457         byte_t bmRequestType
, bRequest
; 
 458         uint16_t wValue
, wIndex
, wLength
, wStatus
; 
 460         if ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_RXSETUP
) ) 
 463         bmRequestType 
= pUdp
->UDP_FDR
[0]; 
 464         bRequest      
= pUdp
->UDP_FDR
[0]; 
 465         wValue        
= (pUdp
->UDP_FDR
[0] & 0xFF); 
 466         wValue       
|= (pUdp
->UDP_FDR
[0] << 8); 
 467         wIndex        
= (pUdp
->UDP_FDR
[0] & 0xFF); 
 468         wIndex       
|= (pUdp
->UDP_FDR
[0] << 8); 
 469         wLength       
= (pUdp
->UDP_FDR
[0] & 0xFF); 
 470         wLength      
|= (pUdp
->UDP_FDR
[0] << 8); 
 472         if (bmRequestType 
& 0x80) { 
 473                 pUdp
->UDP_CSR
[0] |= AT91C_UDP_DIR
; 
 474                 while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_DIR
) ); 
 476         pUdp
->UDP_CSR
[0] &= ~AT91C_UDP_RXSETUP
; 
 477         while ( (pUdp
->UDP_CSR
[0]  & AT91C_UDP_RXSETUP
)  ); 
 479         // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 
 480         switch ((bRequest 
<< 8) | bmRequestType
) { 
 481         case STD_GET_DESCRIPTOR
: 
 482                 if (wValue 
== 0x100)       // Return Device Descriptor 
 483                         AT91F_USB_SendData(pUdp
, devDescriptor
, MIN(sizeof(devDescriptor
), wLength
)); 
 484                 else if (wValue 
== 0x200)  // Return Configuration Descriptor 
 485                         AT91F_USB_SendData(pUdp
, cfgDescriptor
, MIN(sizeof(cfgDescriptor
), wLength
)); 
 486                 else if ((wValue 
& 0x300) == 0x300)  // Return String Descriptor 
 487                         AT91F_USB_SendData(pUdp
, strDescriptor
, MIN(sizeof(strDescriptor
), wLength
)); 
 489                         AT91F_USB_SendStall(pUdp
); 
 491         case STD_SET_ADDRESS
: 
 492                 AT91F_USB_SendZlp(pUdp
); 
 493                 pUdp
->UDP_FADDR 
= (AT91C_UDP_FEN 
| wValue
); 
 494                 pUdp
->UDP_GLBSTATE  
= (wValue
) ? AT91C_UDP_FADDEN 
: 0; 
 496         case STD_SET_CONFIGURATION
: 
 497                 btConfiguration 
= wValue
; 
 498                 AT91F_USB_SendZlp(pUdp
); 
 499                 pUdp
->UDP_GLBSTATE  
= (wValue
) ? AT91C_UDP_CONFG 
: AT91C_UDP_FADDEN
; 
 500                 pUdp
->UDP_CSR
[1] = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_OUT
) : 0; 
 501                 pUdp
->UDP_CSR
[2] = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_IN
)  : 0; 
 502                 pUdp
->UDP_CSR
[3] = (wValue
) ? (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_INT_IN
)   : 0; 
 504         case STD_GET_CONFIGURATION
: 
 505                 AT91F_USB_SendData(pUdp
, (char *) &(btConfiguration
), sizeof(btConfiguration
)); 
 507         case STD_GET_STATUS_ZERO
: 
 509                 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 511         case STD_GET_STATUS_INTERFACE
: 
 513                 AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 515         case STD_GET_STATUS_ENDPOINT
: 
 518                 if ((pUdp
->UDP_GLBSTATE 
& AT91C_UDP_CONFG
) && (wIndex 
<= 3)) { 
 519                         wStatus 
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1; 
 520                         AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 522                 else if ((pUdp
->UDP_GLBSTATE 
& AT91C_UDP_FADDEN
) && (wIndex 
== 0)) { 
 523                         wStatus 
= (pUdp
->UDP_CSR
[wIndex
] & AT91C_UDP_EPEDS
) ? 0 : 1; 
 524                         AT91F_USB_SendData(pUdp
, (char *) &wStatus
, sizeof(wStatus
)); 
 527                         AT91F_USB_SendStall(pUdp
); 
 529         case STD_SET_FEATURE_ZERO
: 
 530                 AT91F_USB_SendStall(pUdp
); 
 532         case STD_SET_FEATURE_INTERFACE
: 
 533                 AT91F_USB_SendZlp(pUdp
); 
 535         case STD_SET_FEATURE_ENDPOINT
: 
 537                 if ((wValue 
== 0) && wIndex 
&& (wIndex 
<= 3)) { 
 538                         pUdp
->UDP_CSR
[wIndex
] = 0; 
 539                         AT91F_USB_SendZlp(pUdp
); 
 542                         AT91F_USB_SendStall(pUdp
); 
 544         case STD_CLEAR_FEATURE_ZERO
: 
 545                 AT91F_USB_SendStall(pUdp
); 
 547         case STD_CLEAR_FEATURE_INTERFACE
: 
 548                 AT91F_USB_SendZlp(pUdp
); 
 550         case STD_CLEAR_FEATURE_ENDPOINT
: 
 552                 if ((wValue 
== 0) && wIndex 
&& (wIndex 
<= 3)) { 
 554                                 pUdp
->UDP_CSR
[1] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_OUT
); 
 555                         else if (wIndex 
== 2) 
 556                                 pUdp
->UDP_CSR
[2] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_BULK_IN
); 
 557                         else if (wIndex 
== 3) 
 558                                 pUdp
->UDP_CSR
[3] = (AT91C_UDP_EPEDS 
| AT91C_UDP_EPTYPE_ISO_IN
); 
 559                         AT91F_USB_SendZlp(pUdp
); 
 562                         AT91F_USB_SendStall(pUdp
); 
 565         // handle CDC class requests 
 566         case SET_LINE_CODING
: 
 567                 while ( !(pUdp
->UDP_CSR
[0] & AT91C_UDP_RX_DATA_BK0
) ); 
 568                 pUdp
->UDP_CSR
[0] &= ~(AT91C_UDP_RX_DATA_BK0
); 
 569                 AT91F_USB_SendZlp(pUdp
); 
 571         case GET_LINE_CODING
: 
 572                 AT91F_USB_SendData(pUdp
, (char *) &line
, MIN(sizeof(line
), wLength
)); 
 574         case SET_CONTROL_LINE_STATE
: 
 575                 btConnection 
= wValue
; 
 576                 AT91F_USB_SendZlp(pUdp
); 
 579                 AT91F_USB_SendStall(pUdp
);