usb_standard_request.c

Go to the documentation of this file.
00001 /*This file is prepared for Doxygen automatic documentation generation.*/
00021 
00022 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
00023  *
00024  * Redistribution and use in source and binary forms, with or without
00025  * modification, are permitted provided that the following conditions are met:
00026  *
00027  * 1. Redistributions of source code must retain the above copyright notice,
00028  * this list of conditions and the following disclaimer.
00029  *
00030  * 2. Redistributions in binary form must reproduce the above copyright notice,
00031  * this list of conditions and the following disclaimer in the documentation
00032  * and/or other materials provided with the distribution.
00033  *
00034  * 3. The name of Atmel may not be used to endorse or promote products derived
00035  * from this software without specific prior written permission.
00036  *
00037  * 4. This software may only be redistributed and used in connection with an Atmel
00038  * AVR product.
00039  *
00040  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00041  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00042  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00043  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00044  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00045  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00046  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00047  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00048  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00049  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00050  */
00051 
00052 //_____ I N C L U D E S ____________________________________________________
00053 
00054 #include "config.h"
00055 #include "conf_usb.h"
00056 #include "lib_mcu/usb/usb_drv.h"
00057 #include "lib_mcu/pll/pll_drv.h"
00058 #include "usb_descriptors.h"
00059 #include "modules/usb/device_chap9/usb_standard_request.h"
00060 #include "usb_specific_request.h"
00061 
00062 #if ((USB_DEVICE_SN_USE==ENABLE) && (USE_DEVICE_SN_UNIQUE==ENABLE))
00063 #include "lib_mcu/flash/flash_drv.h"
00064 static  U8   bin_to_ascii (U8 b);
00065 #endif
00066 
00067 //_____ D E F I N I T I O N ________________________________________________
00068 
00069 static   Bool  usb_get_descriptor   ( void );
00070 static   void  usb_set_address      ( void );
00071 static   Bool  usb_set_configuration( void );
00072 static   void  usb_get_configuration( void );
00073 static   Bool  usb_get_status       ( U8 bmRequestType );
00074 static   Bool  usb_set_feature      ( U8 bmRequestType );
00075 static   Bool  usb_clear_feature    ( U8 bmRequestType );
00076 static   Bool  usb_get_interface    ( void );
00077 static   Bool  usb_set_interface    ( void );
00078 
00079 #ifndef USB_REMOTE_WAKEUP_FEATURE
00080    #error USB_REMOTE_WAKEUP_FEATURE should be defined as ENABLE or DISABLE in conf_usb.h
00081 #endif
00082 
00083 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00084     U8   f_get_serial_string=FALSE;
00085 #endif
00086 
00087 
00088 //_____ D E C L A R A T I O N ______________________________________________
00089 
00090 #ifdef __GNUC__                          // AVRGCC does not support point to PGM space
00091    PGM_VOID_P pbuffer;
00092    #define Usb_write_PGM_byte(byte) (Usb_write_byte(pgm_read_byte_near((unsigned int)byte))) 
00093 #else
00094    U8   code *pbuffer;
00095    #define Usb_write_PGM_byte(byte) (Usb_write_byte(*byte))
00096 #endif
00097 
00098 U8    endpoint_status[MAX_EP_NB];
00099 U8    data_to_transfer;
00100 U8    usb_configuration_nb;
00101 U8    remote_wakeup_feature = DISABLE; 
00102 static U8    device_status = DEVICE_STATUS;
00103 
00104 
00109 void usb_process_request(void)
00110 {
00111    U8 bmRequestType;
00112    U8 bmRequest;
00113 
00114    Usb_ack_control_out();
00115    bmRequestType = Usb_read_byte();
00116    bmRequest     = Usb_read_byte();
00117 
00118    switch (bmRequest)
00119    {
00120       case SETUP_GET_DESCRIPTOR:
00121       if (USB_SETUP_GET_STAND_DEVICE == bmRequestType)
00122       {     
00123          if( usb_get_descriptor() )
00124             return;
00125       }
00126       break;
00127 
00128       case SETUP_GET_CONFIGURATION:
00129       if (USB_SETUP_GET_STAND_DEVICE == bmRequestType)
00130       {
00131          usb_get_configuration();
00132          return;
00133       }
00134       break;
00135 
00136       case SETUP_SET_ADDRESS:
00137       if (USB_SETUP_SET_STAND_DEVICE == bmRequestType)
00138       {
00139          usb_set_address();
00140          return;
00141       }
00142       break;
00143 
00144       case SETUP_SET_CONFIGURATION:
00145       if (USB_SETUP_SET_STAND_DEVICE == bmRequestType)
00146       { 
00147          if( usb_set_configuration() )
00148             return;
00149       }
00150       break;
00151 
00152       case SETUP_CLEAR_FEATURE:
00153       if (usb_clear_feature(bmRequestType))
00154          return;
00155       break;
00156 
00157       case SETUP_SET_FEATURE:
00158       if (usb_set_feature(bmRequestType))
00159          return;
00160       break;
00161 
00162       case SETUP_GET_STATUS:
00163       if (usb_get_status(bmRequestType))
00164          return;
00165       break;
00166 
00167       case SETUP_GET_INTERFACE:
00168       if (USB_SETUP_GET_STAND_INTERFACE == bmRequestType)
00169       {
00170          if( usb_get_interface() )
00171             return;
00172       }
00173       break;
00174 
00175       case SETUP_SET_INTERFACE:
00176       if (bmRequestType == USB_SETUP_SET_STAND_INTERFACE)
00177       {
00178          if( usb_set_interface() )
00179             return;
00180       }
00181       break;
00182 
00183       default:
00184       break;
00185    }
00186 
00187    // un-supported like standard request => call to user read request
00188    if( !usb_user_read_request(bmRequestType, bmRequest) )
00189    {
00190       // Request unknow in the specific request list from interface
00191       // keep that order (set StallRq/clear RxSetup) or a
00192       // OUT request following the SETUP may be acknowledged
00193       Usb_enable_stall_handshake();
00194       Usb_ack_receive_setup();
00195       endpoint_status[(EP_CONTROL & MSK_EP_DIR)] = 0x01;
00196    }
00197 }
00198 
00199 
00203 void usb_set_address(void)
00204 {
00205    U8 addr = Usb_read_byte();
00206    Usb_configure_address(addr);
00207 
00208    Usb_ack_receive_setup();
00209 
00210    Usb_send_control_in();                    // send a ZLP for STATUS phase
00211    while(!Is_usb_in_ready()) {if(Is_usb_vbus_low())break;} // waits for status phase done
00212                                              // before using the new address
00213    Usb_enable_address();
00214 }
00215 
00216 
00222 Bool usb_set_configuration( void )
00223 {
00224    U8 configuration_number;
00225 
00226    // Get/Check new configuration
00227    configuration_number = Usb_read_byte();
00228    if (configuration_number > NB_CONFIGURATION)
00229       return FALSE;  //  Bad configuration number then stall request
00230    Usb_ack_receive_setup();
00231    usb_configuration_nb = configuration_number;
00232    
00233    Usb_send_control_in();                          // send a ZLP for STATUS phase
00234    usb_user_endpoint_init(usb_configuration_nb);   // endpoint configuration
00235    Usb_set_configuration_action();
00236    return TRUE;
00237 }
00238 
00239 
00246 Bool usb_get_descriptor(void)
00247 {
00248    Bool zlp;
00249    U16  wLength;
00250    U8   descriptor_type ;
00251    U8   string_type;
00252    U8   dummy;
00253    U8   nb_byte;
00254    U8   byte_to_send;
00255 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00256    U16  sn_index=0;
00257    U8   initial_data_to_transfer;
00258 #endif
00259     
00260    zlp             = FALSE;                  /* no zero length packet */
00261    string_type     = Usb_read_byte();        /* read LSB of wValue    */
00262    descriptor_type = Usb_read_byte();        /* read MSB of wValue    */
00263 
00264    switch (descriptor_type)
00265    {
00266       case DESCRIPTOR_DEVICE:
00267       data_to_transfer = Usb_get_dev_desc_length(); 
00268       pbuffer          = Usb_get_dev_desc_pointer();
00269       break;
00270       
00271       case DESCRIPTOR_CONFIGURATION:
00272       data_to_transfer = Usb_get_conf_desc_length(); 
00273       pbuffer          = Usb_get_conf_desc_pointer();
00274       break;
00275       
00276       default:
00277       if( !usb_user_get_descriptor(descriptor_type, string_type))
00278          return FALSE;  // Unknow descriptor then stall request
00279       break;
00280    }
00281 
00282    dummy = Usb_read_byte();                     
00283    dummy = Usb_read_byte();
00284    LSB(wLength) = Usb_read_byte();              
00285    MSB(wLength) = Usb_read_byte();
00286    Usb_ack_receive_setup() ;                  
00287 
00288    if (wLength > data_to_transfer)
00289    {
00290       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00291       else { zlp = FALSE; }                   
00292    }
00293    else
00294    {
00295       data_to_transfer = (U8)wLength;         
00296    }
00297 
00298    Usb_ack_nak_out();
00299     
00300    byte_to_send=0;
00301 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00302    initial_data_to_transfer = data_to_transfer;
00303 #endif
00304    while((data_to_transfer != 0) && (!Is_usb_nak_out_sent()))
00305    {
00306       while(!Is_usb_read_control_enabled())
00307       {
00308          if (Is_usb_nak_out_sent())
00309             break;    // don't clear the flag now, it will be cleared after
00310          if (Is_usb_vbus_low())
00311             break;          
00312       }
00313               
00314       nb_byte=0;
00315       while(data_to_transfer != 0)        
00316       {
00317          if(nb_byte++==EP_CONTROL_LENGTH) 
00318             break;         
00319          
00320 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00321 
00322          if(f_get_serial_string && (data_to_transfer < (initial_data_to_transfer-1)))    //if we are sending the signature characters (third byte and more...)
00323          {                                                                              //(The first two bytes are the length and the descriptor)
00324             
00325             switch (byte_to_send)
00326             {
00327                case 0:
00328                Usb_write_byte(bin_to_ascii((Flash_read_sn(sn_index)>>4) & 0x0F)); //sends the fist part (MSB) of the signature hex number, converted in ascii
00329                break;
00330               
00331                case 1:
00332                Usb_write_byte(0);                                                   //then, sends a null character (Usb_unicode)                    
00333                break;
00334     
00335                case 2:
00336                Usb_write_byte(bin_to_ascii(Flash_read_sn(sn_index) & 0x0F));      //sends the second part (LSB) of the signature hex number, converted in ascii 
00337                break;
00338     
00339                case 3:
00340                Usb_write_byte(0);                                                   //then, sends a null character (Usb_unicode)  
00341                sn_index++;                                                         //increments the signature address pointer.
00342                break;
00343             }
00344             byte_to_send = (byte_to_send+1)%4;     
00345          }
00346          else
00347          {
00348             Usb_write_PGM_byte(pbuffer++);                                                 //Write a flash byte to USB        
00349          }        
00350 #else          
00351          Usb_write_PGM_byte(pbuffer++);          
00352 #endif
00353          data_to_transfer --;                                                             //decrements the number of bytes to transmit.
00354       }
00355       
00356       if (Is_usb_nak_out_sent())
00357          break;
00358       if (Is_usb_vbus_low())
00359          break;
00360       Usb_send_control_in();
00361    }
00362    
00363 #if (USE_DEVICE_SN_UNIQUE==ENABLE)      
00364    f_get_serial_string=FALSE;                                                   //end of signature transmission    
00365 #endif   
00366 
00367    if((zlp == TRUE) && (!Is_usb_nak_out_sent()))
00368    {
00369       while(!Is_usb_read_control_enabled()) {if(Is_usb_vbus_low())break;}
00370       Usb_send_control_in();
00371    }
00372 
00373    while (!(Is_usb_nak_out_sent())) {if(Is_usb_vbus_low())break;}
00374    Usb_ack_nak_out();
00375    Usb_ack_control_out();
00376    return TRUE;
00377 }
00378 
00379 
00383 void usb_get_configuration(void)
00384 {
00385    Usb_ack_receive_setup();
00386 
00387    Usb_write_byte(usb_configuration_nb);
00388    Usb_ack_in_ready();
00389 
00390    while( !Is_usb_receive_out() ){if(Is_usb_vbus_low())break;}
00391    Usb_ack_receive_out();
00392 }
00393 
00394 
00398 Bool usb_get_status( U8 bmRequestType )
00399 {
00400    U8 wIndex;
00401    U8 dummy;
00402 
00403    dummy    = Usb_read_byte();                 
00404    dummy    = Usb_read_byte();                 
00405    wIndex   = Usb_read_byte();
00406 
00407    switch(bmRequestType)
00408    {
00409       case USB_SETUP_GET_STAND_DEVICE:
00410       Usb_ack_receive_setup();
00411       Usb_write_byte(device_status);
00412       break;
00413 
00414       case USB_SETUP_GET_STAND_INTERFACE:
00415       Usb_ack_receive_setup();
00416       Usb_write_byte(0);      // Reserved - always 0
00417       break;
00418 
00419       case USB_SETUP_GET_STAND_ENDPOINT:
00420       Usb_ack_receive_setup();
00421       wIndex = wIndex & MSK_EP_DIR;
00422       Usb_write_byte( endpoint_status[wIndex] );
00423       break;
00424     
00425       default:
00426       return FALSE;
00427    }
00428    Usb_write_byte(0);
00429 
00430    Usb_send_control_in();
00431    while( !Is_usb_receive_out() ){if(Is_usb_vbus_low())break;}
00432    Usb_ack_receive_out();
00433    return TRUE;
00434 }
00435 
00436 
00440 Bool usb_set_feature( U8 bmRequestType )
00441 {
00442    U8 wValue;
00443    U8 wIndex;
00444    U8 dummy;
00445 
00446    switch (bmRequestType)
00447    {
00448       case USB_SETUP_SET_STAND_DEVICE:
00449       wValue = Usb_read_byte();
00450       switch (wValue)
00451       {
00452          case USB_REMOTE_WAKEUP:
00453          if ((wValue != FEATURE_DEVICE_REMOTE_WAKEUP)
00454          ||  (USB_REMOTE_WAKEUP_FEATURE != ENABLED))
00455             return FALSE;              // Invalid request
00456          device_status |= USB_DEVICE_STATUS_REMOTEWAKEUP;
00457          remote_wakeup_feature = ENABLED;
00458          Usb_ack_receive_setup();
00459          Usb_send_control_in();
00460          break;
00461 
00462 #if (USB_OTG_FEATURE == ENABLED)
00463          case OTG_B_HNP_ENABLE:
00464          if (((OTG_BMATTRIBUTES&HNP_SUPPORT) == 0) || (USB_OTG_FEATURE == DISABLED))   // see usb_descriptors.h
00465             return FALSE;              // Invalid request
00466          otg_features_supported |= OTG_B_HNP_ENABLE;
00467          otg_device_nb_hnp_retry = BDEV_HNP_NB_RETRY;
00468          Usb_ack_receive_setup();
00469          Usb_send_control_in();
00470          break;
00471 
00472          case OTG_A_HNP_SUPPORT:
00473          if (((OTG_BMATTRIBUTES&HNP_SUPPORT) == 0) || (USB_OTG_FEATURE == DISABLED))
00474             return FALSE;              // Invalid request
00475          otg_features_supported |= OTG_A_HNP_SUPPORT;
00476          Usb_ack_receive_setup();
00477          Usb_send_control_in();
00478          break;
00479 
00480          case OTG_A_ALT_HNP_SUPPORT:
00481          if (((OTG_BMATTRIBUTES&HNP_SUPPORT) == 0) || (USB_OTG_FEATURE == DISABLED))
00482             return FALSE;              // Invalid request
00483          otg_features_supported |= OTG_A_ALT_HNP_SUPPORT;
00484          Usb_ack_receive_setup();
00485          Usb_send_control_in();
00486          break;
00487 #endif
00488             
00489          default:
00490          return FALSE;                 // Unknow request
00491          break;
00492       }
00493       break;
00494 
00495       case USB_SETUP_SET_STAND_INTERFACE:
00496       return FALSE;                    // Unknow request
00497       break;
00498 
00499       case USB_SETUP_SET_STAND_ENDPOINT:
00500       wValue   = Usb_read_byte();
00501       dummy    = Usb_read_byte();                
00502       if (wValue != FEATURE_ENDPOINT_HALT)
00503          return FALSE;                 // Unknow request
00504       wIndex = (Usb_read_byte() & MSK_EP_DIR);
00505       if (wIndex == EP_CONTROL)
00506       {
00507          Usb_enable_stall_handshake();
00508          Usb_ack_receive_setup();
00509       }
00510       Usb_select_endpoint(wIndex);
00511       if( !Is_usb_endpoint_enabled())
00512       {
00513          Usb_select_endpoint(EP_CONTROL);
00514          return FALSE;              // Invalid request
00515       }
00516       Usb_enable_stall_handshake();
00517       Usb_select_endpoint(EP_CONTROL);
00518       endpoint_status[wIndex] = 0x01;
00519       Usb_ack_receive_setup();
00520       Usb_send_control_in();
00521       break;
00522 
00523       default:
00524       return FALSE;                    // Unknow request
00525       break;
00526    }
00527    return TRUE;
00528 }
00529 
00530 
00533 Bool usb_clear_feature( U8 bmRequestType )
00534 {
00535    U8 wValue;
00536    U8 wIndex;
00537    U8 dummy;
00538 
00539    switch (bmRequestType)
00540    {
00541       case  USB_SETUP_SET_STAND_DEVICE:
00542       wValue = Usb_read_byte();
00543       if ((wValue != FEATURE_DEVICE_REMOTE_WAKEUP) || (USB_REMOTE_WAKEUP_FEATURE != ENABLED))
00544          return FALSE;              // Invalid request
00545       device_status &= ~USB_DEVICE_STATUS_REMOTEWAKEUP;
00546       remote_wakeup_feature = DISABLED;
00547       Usb_ack_receive_setup();
00548       Usb_send_control_in();
00549       break;
00550    
00551       case USB_SETUP_SET_STAND_INTERFACE:
00552       return FALSE;                    // Unknow request
00553       break;
00554       
00555       case USB_SETUP_SET_STAND_ENDPOINT:
00556       wValue = Usb_read_byte();
00557       dummy  = Usb_read_byte();
00558       if (wValue != FEATURE_ENDPOINT_HALT)
00559          return FALSE;                 // Unknow request
00560       wIndex = (Usb_read_byte() & MSK_EP_DIR);
00561       Usb_select_endpoint(wIndex);
00562       if( !Is_usb_endpoint_enabled())
00563       {
00564          Usb_select_endpoint(EP_CONTROL);
00565          return FALSE;              // Invalid request
00566       } 
00567       if(wIndex != EP_CONTROL)
00568       {
00569          Usb_disable_stall_handshake();
00570          Usb_reset_endpoint(wIndex);
00571          Usb_reset_data_toggle();
00572       }
00573       Usb_select_endpoint(EP_CONTROL);
00574       endpoint_status[wIndex] = 0x00;
00575       Usb_ack_receive_setup();
00576       Usb_send_control_in();
00577       break;
00578    
00579       default:
00580       return FALSE;                    // Unknow request
00581       break;
00582    }
00583    return TRUE;
00584 }
00585 
00586 
00589 Bool usb_get_interface (void)
00590 {
00591    U16   wInterface;
00592    U8    wValue_msb;
00593    U8    wValue_lsb;
00594 
00595    // Read wValue
00596    wValue_lsb = Usb_read_byte();
00597    wValue_msb = Usb_read_byte();
00598    // wValue = Alternate Setting
00599    // wIndex = Interface
00600    LSB(wInterface)=Usb_read_byte();
00601    MSB(wInterface)=Usb_read_byte();
00602    if( (0!=wValue_msb) || (0!=wValue_msb) )
00603       return FALSE;
00604    Usb_ack_receive_setup();
00605    
00606    Usb_write_byte( usb_user_interface_get(wInterface) );
00607    Usb_send_control_in();
00608 
00609    while( !Is_usb_receive_out() ){if(Is_usb_vbus_low())break;}
00610    Usb_ack_receive_out();
00611    return TRUE;
00612 }
00613 
00614 
00617 Bool usb_set_interface (void)
00618 {
00619    U16   wInterface;
00620    U8    wValue_msb;
00621    U8    wValue_lsb;
00622 
00623    // Read wValue
00624    wValue_lsb = Usb_read_byte();
00625    wValue_msb = Usb_read_byte();
00626    // wValue = Alternate Setting
00627    // wIndex = Interface
00628    LSB(wInterface)=Usb_read_byte();
00629    MSB(wInterface)=Usb_read_byte();
00630    if( 0!=wValue_msb )
00631       return FALSE;
00632    Usb_ack_receive_setup();
00633    
00634    usb_user_interface_reset(wInterface, wValue_lsb);
00635    Usb_select_endpoint(EP_CONTROL);
00636             
00637    Usb_send_control_in();
00638    while(!Is_usb_in_ready()) {if(Is_usb_vbus_low())break;}
00639    return TRUE;
00640 }
00641 
00642 
00645 void usb_generate_remote_wakeup(void)
00646 {
00647    if(Is_pll_ready()==FALSE)
00648    {
00649       Pll_start_auto();
00650       Wait_pll_ready();
00651    }
00652    Usb_unfreeze_clock();
00653    if (remote_wakeup_feature == ENABLED)
00654    {
00655       Usb_initiate_remote_wake_up();
00656       remote_wakeup_feature = DISABLED;
00657    }
00658 }  
00659 
00660 
00661 #if ((USB_DEVICE_SN_USE==ENABLE) && (USE_DEVICE_SN_UNIQUE==ENABLE))
00669 U8 bin_to_ascii (U8 b)
00670 {
00671 return ( (b <= 0x09) ? (b+'0') : (b+'A'-10) );
00672 }
00673 #endif
00674 

Generated on Mon Sep 14 13:51:27 2009 for ATMEL by  doxygen 1.5.3