usb_standard_request.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00021 
00022 /* Copyright (c) 2007, 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  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00038  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00039  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00040  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00041  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00042  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00043  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00044  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00045  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00046  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00047  */
00048 
00049 //_____ I N C L U D E S ____________________________________________________
00050 
00051 #include "config.h"
00052 #include "conf_usb.h"
00053 #include "lib_mcu/usb/usb_drv.h"
00054 #include "usb_descriptors.h"
00055 #include "modules/usb/device_chap9/usb_standard_request.h"
00056 #include "lib_mcu/pll/pll_drv.h"
00057 #include "usb_specific_request.h"
00058 
00059 
00060 //_____ M A C R O S ________________________________________________________
00061 
00062 
00063 //_____ D E F I N I T I O N ________________________________________________
00064 
00065 //_____ P R I V A T E   D E C L A R A T I O N ______________________________
00066 
00067 static  void    usb_get_descriptor(   void);
00068 static  void    usb_set_address(      void);
00069 static  void    usb_set_configuration(void);
00070 static  void    usb_clear_feature(    void);
00071 static  void    usb_set_feature(      void);
00072 static  void    usb_get_status(       void);
00073 static  void    usb_get_configuration(void);
00074 static  void    usb_get_interface (void);
00075 static  void    usb_set_interface (void);
00076 
00077 
00078 #ifndef USB_REMOTE_WAKEUP_FEATURE
00079    #error USB_REMOTE_WAKEUP_FEATURE should be defined as ENABLE or DISABLE in conf_usb.h
00080 #endif
00081 
00082 
00083 
00084 
00085 //_____ D E C L A R A T I O N ______________________________________________
00086 
00087 static  bit  zlp;
00088 static  U8   endpoint_status[NB_ENDPOINTS];
00089 static  U8   device_status=DEVICE_STATUS;
00090 
00091 #ifdef __GNUC__
00092         PGM_VOID_P pbuffer;
00093 #else
00094         U8   code *pbuffer;
00095 #endif
00096         U8   data_to_transfer;
00097 
00098         U16  wInterface;
00099 
00100 static  U8   bmRequestType;
00101         U8      remote_wakeup_feature=DISABLE; 
00102         U8   usb_configuration_nb;
00103 extern  bit     usb_connected;
00104 extern  code    S_usb_device_descriptor             usb_user_device_descriptor;
00105 extern  code    S_usb_user_configuration_descriptor usb_user_configuration_descriptor;
00106 
00107 U8      usb_remote_wup_feature;  // Store ENABLED value if a SetFeature(RemoteWakeUp) has been received
00108 
00109 
00128 void usb_process_request(void)
00129 {
00130    U8  bmRequest;
00131 
00132    Usb_ack_control_out();
00133    bmRequestType = Usb_read_byte();
00134    bmRequest     = Usb_read_byte();
00135 
00136    switch (bmRequest)
00137    {
00138     case GET_DESCRIPTOR:
00139          if (0x80 == bmRequestType) { usb_get_descriptor(); }
00140          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00141          break;
00142 
00143     case GET_CONFIGURATION:
00144          if (0x80 == bmRequestType) { usb_get_configuration(); }
00145          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00146          break;
00147 
00148     case SET_ADDRESS:
00149          if (0x00 == bmRequestType) { usb_set_address(); }
00150          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00151          break;
00152 
00153     case SET_CONFIGURATION:
00154          if (0x00 == bmRequestType) { usb_set_configuration(); }
00155          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00156          break;
00157 
00158     case CLEAR_FEATURE:
00159          if (0x02 >= bmRequestType) { usb_clear_feature(); }
00160          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00161          break;
00162 
00163     case SET_FEATURE:
00164          if (0x02 >= bmRequestType) { usb_set_feature(); }
00165          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00166          break;
00167 
00168     case GET_STATUS:
00169          if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
00170                                     { usb_get_status(); }
00171          else                       { usb_user_read_request(bmRequestType, bmRequest); }
00172          break;
00173 
00174     case GET_INTERFACE:
00175           if (bmRequestType == 0x81) { usb_get_interface(); }
00176           else { usb_user_read_request(bmRequestType, bmRequest); }
00177           break;
00178 
00179 
00180     case SET_INTERFACE:
00181       if (bmRequestType == 0x01) {usb_set_interface();}
00182       break;
00183 
00184     case SET_DESCRIPTOR:
00185     case SYNCH_FRAME:
00186     default: 
00187          if(usb_user_read_request(bmRequestType, bmRequest) == FALSE)
00188          {
00189             Usb_enable_stall_handshake();
00190             Usb_ack_receive_setup();
00191             return;
00192          }
00193          break;
00194   }
00195 }
00196 
00197 
00209 void usb_set_address(void)
00210 {
00211    U8 addr = Usb_read_byte();
00212    Usb_configure_address(addr);
00213 
00214    Usb_ack_receive_setup();
00215 
00216    Usb_send_control_in();                    
00217    while(!Is_usb_in_ready());                
00218 
00219    Usb_enable_address();
00220 }
00221 
00222 
00236 void usb_set_configuration( void )
00237 {
00238 U8 configuration_number;
00239 
00240    configuration_number = Usb_read_byte();
00241 
00242    if (configuration_number <= NB_CONFIGURATION)
00243    {
00244       Usb_ack_receive_setup();
00245       usb_configuration_nb = configuration_number;
00246    }
00247    else
00248    {
00251       Usb_enable_stall_handshake();
00252       Usb_ack_receive_setup();
00253       return;
00254    }
00255 
00256    Usb_send_control_in();                    
00257 
00258    usb_user_endpoint_init(usb_configuration_nb);  
00259    Usb_set_configuration_action();
00260 }
00261 
00262 
00277 void usb_get_descriptor(void)
00278 {
00279 U16  wLength;
00280 U8   descriptor_type ;
00281 U8   string_type;
00282 U8   dummy;
00283 U8   nb_byte;
00284 
00285    zlp             = FALSE;                  /* no zero length packet */
00286    string_type     = Usb_read_byte();        /* read LSB of wValue    */
00287    descriptor_type = Usb_read_byte();        /* read MSB of wValue    */
00288 
00289    switch (descriptor_type)
00290    {
00291     case DEVICE_DESCRIPTOR:
00292       data_to_transfer = Usb_get_dev_desc_length(); 
00293       pbuffer          = Usb_get_dev_desc_pointer();
00294       break;
00295     case CONFIGURATION_DESCRIPTOR:
00296       data_to_transfer = Usb_get_conf_desc_length(); 
00297       pbuffer          = Usb_get_conf_desc_pointer();
00298       break;
00299     default:
00300       if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE )
00301       {
00302          Usb_enable_stall_handshake();
00303          Usb_ack_receive_setup();
00304          return;
00305       }
00306       break;
00307    }
00308 
00309    dummy = Usb_read_byte();                     
00310    dummy = Usb_read_byte();
00311    LSB(wLength) = Usb_read_byte();              
00312    MSB(wLength) = Usb_read_byte();
00313    Usb_ack_receive_setup() ;                  
00314 
00315    if (wLength > data_to_transfer)
00316    {
00317       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00318       else { zlp = FALSE; }                   
00319    }
00320    else
00321    {
00322       data_to_transfer = (U8)wLength;         
00323    }
00324 
00325    Usb_ack_nak_out();
00326 
00327    while((data_to_transfer != 0) && (!Is_usb_nak_out_sent()))
00328    {
00329       while(!Is_usb_read_control_enabled())
00330       {
00331         if (Is_usb_nak_out_sent())
00332           break;    // don't clear the flag now, it will be cleared after
00333       }
00334 
00335       nb_byte=0;
00336       while(data_to_transfer != 0)        
00337       {
00338          if(nb_byte++==EP_CONTROL_LENGTH) 
00339          {
00340             break;
00341          }
00342 
00343 #ifndef __GNUC__
00344          Usb_write_byte(*pbuffer++);
00345 #else    // AVRGCC does not support point to PGM space
00346          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00347 #endif
00348          data_to_transfer --;
00349       }
00350 
00351       if (Is_usb_nak_out_sent())
00352         break;
00353       else
00354         Usb_send_control_in();
00355    }
00356 
00357    if((zlp == TRUE) && (!Is_usb_nak_out_sent()))
00358    {
00359      while(!Is_usb_read_control_enabled());
00360      Usb_send_control_in();
00361    }
00362 
00363    while (!(Is_usb_nak_out_sent()));
00364    Usb_ack_nak_out();       // clear NAKOUTI
00365    Usb_ack_control_out();   // clear RXOUTI
00366 
00367 
00368 
00369 }
00370 
00371 
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() );
00391    Usb_ack_receive_out();
00392 }
00393 
00405 void usb_get_status(void)
00406 {
00407 U8 wIndex;
00408 U8 dummy;
00409 
00410    dummy    = Usb_read_byte();                 
00411    dummy    = Usb_read_byte();                 
00412    wIndex = Usb_read_byte();
00413 
00414    switch(bmRequestType)
00415    {
00416     case REQUEST_DEVICE_STATUS:    Usb_ack_receive_setup();
00417                                    Usb_write_byte(device_status);
00418                                    break;
00419 
00420     case REQUEST_INTERFACE_STATUS: Usb_ack_receive_setup();
00421                                    Usb_write_byte(INTERFACE_STATUS);
00422                                    break;
00423 
00424     case REQUEST_ENDPOINT_STATUS:  Usb_ack_receive_setup();
00425                                    wIndex = wIndex & MSK_EP_DIR;
00426                                    Usb_write_byte(endpoint_status[wIndex]);
00427                                    break;
00428     default:
00429                                    Usb_enable_stall_handshake();
00430                                    Usb_ack_receive_setup();
00431                                    return;
00432    }
00433 
00434    Usb_write_byte(0x00);
00435    Usb_send_control_in();
00436 
00437    while( !Is_usb_receive_out() );
00438    Usb_ack_receive_out();
00439 }
00440 
00441 
00453 void usb_set_feature(void)
00454 {
00455 U8 wValue;
00456 U8 wIndex;
00457 U8 dummy;
00458 
00459   switch (bmRequestType)
00460    {
00461     case ZERO_TYPE:
00462       wValue = Usb_read_byte();
00463       switch (wValue)
00464       {
00465          case USB_REMOTE_WAKEUP:
00466             if ((wValue == FEATURE_DEVICE_REMOTE_WAKEUP) && (USB_REMOTE_WAKEUP_FEATURE == ENABLED))
00467             {
00468                 device_status |= USB_STATUS_REMOTEWAKEUP;
00469                 remote_wakeup_feature = ENABLED;
00470                 Usb_ack_receive_setup();
00471                 Usb_send_control_in();
00472             }
00473             else
00474             {
00475                Usb_enable_stall_handshake();
00476                Usb_ack_receive_setup();
00477             }
00478             break;
00479             
00480             
00481             
00482          default:
00483          Usb_enable_stall_handshake();
00484          Usb_ack_receive_setup();
00485          break;
00486       }
00487       break;
00488 
00489   case INTERFACE_TYPE:
00492       Usb_enable_stall_handshake();
00493       Usb_ack_receive_setup();
00494     break;
00495 
00496   case ENDPOINT_TYPE:
00497       wValue = Usb_read_byte();
00498       dummy    = Usb_read_byte();                
00499 
00500       if (wValue == FEATURE_ENDPOINT_HALT)
00501       {
00502          wIndex = (Usb_read_byte() & MSK_EP_DIR);
00503 
00504          if (wIndex == EP_CONTROL)
00505          {
00506             Usb_enable_stall_handshake();
00507             Usb_ack_receive_setup();
00508          }
00509 
00510          Usb_select_endpoint(wIndex);
00511          if(Is_usb_endpoint_enabled())
00512          {
00513             Usb_enable_stall_handshake();
00514             Usb_select_endpoint(EP_CONTROL);
00515             endpoint_status[wIndex] = 0x01;
00516             Usb_ack_receive_setup();
00517             Usb_send_control_in();
00518          }
00519          else
00520          {
00521             Usb_select_endpoint(EP_CONTROL);
00522             Usb_enable_stall_handshake();
00523             Usb_ack_receive_setup();
00524          }
00525       }
00526       else
00527       {
00528          Usb_enable_stall_handshake();
00529          Usb_ack_receive_setup();
00530       }
00531     break;
00532 
00533   default:
00534     Usb_enable_stall_handshake();
00535     Usb_ack_receive_setup();
00536     break;
00537    }
00538 }
00539 
00540 
00551 void usb_clear_feature(void)
00552 {
00553 U8 wValue;
00554 U8 wIndex;
00555 U8 dummy;
00556 
00557    if (bmRequestType == ZERO_TYPE)
00558    {
00559      wValue = Usb_read_byte();
00560       if ((wValue == FEATURE_DEVICE_REMOTE_WAKEUP) && (USB_REMOTE_WAKEUP_FEATURE == ENABLED))
00561      {
00562        device_status &= ~USB_STATUS_REMOTEWAKEUP;
00563          remote_wakeup_feature = DISABLED;
00564        Usb_ack_receive_setup();
00565        Usb_send_control_in();
00566      }
00567      else
00568      {
00569       Usb_enable_stall_handshake();
00570       Usb_ack_receive_setup();
00571      }
00572       return;
00573    }
00574    else if (bmRequestType == INTERFACE_TYPE)
00575    {
00578       Usb_enable_stall_handshake();
00579       Usb_ack_receive_setup();
00580       return;
00581    }
00582    else if (bmRequestType == ENDPOINT_TYPE)
00583    {
00584       wValue = Usb_read_byte();
00585       dummy  = Usb_read_byte();                
00586 
00587       if (wValue == FEATURE_ENDPOINT_HALT)
00588       {
00589          wIndex = (Usb_read_byte() & MSK_EP_DIR);
00590 
00591          Usb_select_endpoint(wIndex);
00592          if(Is_usb_endpoint_enabled())
00593          {
00594             if(wIndex != EP_CONTROL)
00595             {
00596                Usb_disable_stall_handshake();
00597                Usb_reset_endpoint(wIndex);
00598                Usb_reset_data_toggle();
00599             }
00600             Usb_select_endpoint(EP_CONTROL);
00601             endpoint_status[wIndex] = 0x00;
00602             Usb_ack_receive_setup();
00603             Usb_send_control_in();
00604          }
00605          else
00606          {
00607             Usb_select_endpoint(EP_CONTROL);
00608             Usb_enable_stall_handshake();
00609             Usb_ack_receive_setup();
00610             return;
00611          }
00612       }
00613       else
00614       {
00615          Usb_enable_stall_handshake();
00616          Usb_ack_receive_setup();
00617          return;
00618       }
00619    }
00620 }
00621 
00622 
00623 
00634 void usb_get_interface (void)
00635 {
00636    Usb_ack_receive_setup();
00637    Usb_send_control_in();
00638 
00639    while( !Is_usb_receive_out() );
00640    Usb_ack_receive_out();
00641 }
00642 
00653 void usb_set_interface (void)
00654 {
00655   Usb_ack_receive_setup();
00656   Usb_send_control_in();                    
00657   while(!Is_usb_in_ready());
00658 }
00659 
00668 void usb_generate_remote_wakeup(void)
00669 {
00670    if(Is_pll_ready()==FALSE)
00671    {
00672       Pll_start_auto();
00673       Wait_pll_ready();
00674    }
00675    Usb_unfreeze_clock();
00676    if (remote_wakeup_feature == ENABLED)
00677    {
00678       Usb_initiate_remote_wake_up();
00679       remote_wakeup_feature = DISABLED;
00680    }
00681 }  

Generated on Mon May 5 15:57:55 2008 for ATMEL by  doxygen 1.5.1-p1