usb_host_task.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00016 
00017 /* Copyright (c) 2007, Atmel Corporation All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms, with or without
00020  * modification, are permitted provided that the following conditions are met:
00021  *
00022  * 1. Redistributions of source code must retain the above copyright notice,
00023  * this list of conditions and the following disclaimer.
00024  *
00025  * 2. Redistributions in binary form must reproduce the above copyright notice,
00026  * this list of conditions and the following disclaimer in the documentation
00027  * and/or other materials provided with the distribution.
00028  *
00029  * 3. The name of ATMEL may not be used to endorse or promote products derived
00030  * from this software without specific prior written permission.
00031  *
00032  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00034  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00042  */
00043 
00044 //_____  I N C L U D E S ___________________________________________________
00045 
00046 #include "config.h"
00047 #include "conf_usb.h"
00048 #include "modules/usb/usb_task.h"
00049 #include "usb_host_task.h"
00050 #include "lib_mcu/usb/usb_drv.h"
00051 #include "lib_mcu/pll/pll_drv.h"
00052 #include "modules/usb/host_chap9/usb_host_enum.h"
00053 
00054 #if (USB_HUB_SUPPORT == ENABLE)
00055 #include "modules/usb/host_chap9/usb_host_hub.h"
00056 #endif
00057 
00058 #if (USB_HOST_FEATURE == DISABLED)
00059    #warning trying to compile a file used with the USB HOST without USB_HOST_FEATURE enabled
00060 #endif
00061 
00062 #if (USB_HOST_FEATURE == ENABLED)
00063 
00064 #ifndef DEVICE_BASE_ADDRESS
00065    #error DEVICE_BASE_ADDRESS should be defined somewhere in config files (conf_usb.h)
00066 #endif
00067 
00068 #ifndef SIZEOF_DATA_STAGE
00069    #error SIZEOF_DATA_STAGE should be defined in conf_usb.h
00070 #endif
00071 
00072 #ifndef HOST_CONTINUOUS_SOF_INTERRUPT
00073    #error HOST_CONTINUOUS_SOF_INTERRUPT should be defined as ENABLE or DISABLE in conf_usb.h
00074 #endif
00075 
00076 #ifndef USB_HOST_PIPE_INTERRUPT_TRANSFER
00077    #error USB_HOST_PIPE_INTERRUPT_TRANSFER should be defined as ENABLE or DISABLE in conf_usb.h
00078 #endif
00079 
00080 #ifndef Usb_id_transition_action
00081    #define Usb_id_transition_action()
00082 #endif
00083 #ifndef  Host_device_disconnection_action
00084    #define Host_device_disconnection_action()
00085 #endif
00086 #ifndef  Host_device_connection_action
00087    #define Host_device_connection_action()
00088 #endif
00089 #ifndef  Host_sof_action
00090    #define Host_sof_action()
00091 #endif
00092 #ifndef  Host_suspend_action
00093    #define Host_suspend_action()
00094 #endif
00095 #ifndef  Host_hwup_action
00096    #define Host_hwup_action()
00097 #endif
00098 #ifndef  Host_device_not_supported_action
00099    #define Host_device_not_supported_action()
00100 #endif
00101 #ifndef  Host_device_class_not_supported_action
00102    #define Host_device_class_not_supported_action()
00103 #endif
00104 #ifndef  Host_device_supported_action
00105    #define Host_device_supported_action()
00106 #endif
00107 #ifndef  Host_device_error_action
00108    #define Host_device_error_action()
00109 #endif
00110 
00111 
00112 //_____ M A C R O S ________________________________________________________
00113 
00114 #ifndef LOG_STR_CODE
00115 #define LOG_STR_CODE(str)
00116 #else
00117 U8 code log_device_connected[]="Device Connection";
00118 U8 code log_device_enumerated[]="Device Enumerated";
00119 U8 code log_device_unsupported[]="Unsupported Device";
00120 U8 code log_going_to_suspend[]="Usb suspend";
00121 U8 code log_usb_resumed[]="Usb resumed";
00122 #endif
00123 
00124 //_____ D E F I N I T I O N S ______________________________________________
00125 
00126 //_____ D E C L A R A T I O N S ____________________________________________
00127 
00128 #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
00129    volatile S_pipe_int   it_pipe_str[MAX_EP_NB];
00130    volatile U8 pipe_nb_save;
00131    U8 g_sav_int_sof_enable;
00132 #endif
00133 
00152 U8 device_state;
00153 
00155 S_usb_setup_data usb_request;
00156 
00166 U8 data_stage[SIZEOF_DATA_STAGE];
00167 
00168 U8 device_status;
00169 U8 request_resume = FALSE;
00170 U8 force_enumeration = FALSE;
00171 U8 new_device_connected = 0;
00172 
00173 
00174 static U16  c;                // As internal host start of frame counter
00175 
00176 
00177 #if (USB_HUB_SUPPORT == ENABLE)
00178    static U8 i,j;
00179    volatile U8 hub_interrupt_sof=0;
00180    U8 saved_device;
00181 #endif
00182 
00194 void usb_host_task_init(void)
00195 {
00196    Pll_start_auto();
00197    Wait_pll_ready();
00198    Usb_disable();
00199    Usb_enable();
00200    Usb_unfreeze_clock();
00201    Usb_attach();
00202    Usb_enable_uvcon_pin();
00203    Usb_select_host();
00204    Usb_disable_vbus_hw_control();   // Force Vbus generation without timeout
00205    Host_enable_device_disconnection_interrupt();
00206    device_state=DEVICE_UNATTACHED;
00207    init_usb_tree();
00208 }
00209 
00226 void usb_host_task(void)
00227 {
00228 
00229    switch (device_state)
00230    {
00231      //------------------------------------------------------
00232      //   DEVICE_UNATTACHED state
00233      //
00234      //   - Default init state
00235      //   - Try to give device power supply
00236      //
00237       case DEVICE_UNATTACHED:
00238          Host_clear_device_supported();        // Reset Device status
00239          Host_clear_configured();
00240          Host_clear_device_ready();
00241          Usb_clear_all_event();                // Clear all software events
00242          new_device_connected=0;
00243          selected_device=0;
00244          
00245 #if (USB_HUB_SUPPORT==ENABLE)
00246          nb_hub_present = 0;
00247 #endif         
00248          
00249 #if (SOFTWARE_VBUS_CTRL==ENABLE)
00250          if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt())
00251          {
00252             Usb_ack_bconnection_error_interrupt();
00253             Usb_ack_vbus_error_interrupt();
00254             Host_clear_vbus_request();
00255          }
00256          Usb_disable_vbus_pad();
00257          Usb_enable_manual_vbus();
00258          if(Is_usb_srp_interrupt())
00259          {
00260             Usb_ack_srp_interrupt();
00261             Usb_enable_vbus_pad();
00262             Usb_enable_vbus();
00263             device_state=DEVICE_ATTACHED;
00264          }
00265 #else
00266          Usb_enable_vbus();                    // Give at least device power supply!!!
00267          if(Is_usb_vbus_high())
00268          { device_state=DEVICE_ATTACHED; }     // If VBUS ok goto to device connection expectation
00269 #endif
00270       break;
00271 
00272      //------------------------------------------------------
00273      //   DEVICE_ATTACHED state
00274      //
00275      //   - Vbus is on
00276      //   - Try to detected device connection
00277      //
00278       case DEVICE_ATTACHED :
00279          if (Is_device_connection() || (force_enumeration==TRUE))     // Device pull-up detected
00280          {
00281             Host_ack_device_connection();
00282             Host_clear_device_supported();        // Reset Device status
00283             Host_clear_configured();
00284             Host_clear_device_ready();
00285             Usb_clear_all_event();                // Clear all software events
00286             new_device_connected=0;
00287             force_enumeration=FALSE;
00288 
00289            // Now device is connected, enable disconnection interrupt
00290             Host_enable_device_disconnection_interrupt();
00291             Enable_interrupt();
00292            // Reset device status
00293             Host_clear_device_supported();
00294             Host_clear_configured();
00295             Host_clear_device_ready();
00296             Host_enable_sof();            // Start Start Of Frame generation
00297             Host_enable_sof_interrupt();  // SOF will be detected under interrupt
00298             c = 0;
00299             while (c<100)               // wait 100ms before USB reset
00300             {
00301                if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }// Count Start Of frame
00302                if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {goto device_attached_error;}
00303             }
00304             Host_disable_device_disconnection_interrupt();
00305             Host_send_reset();          // First USB reset
00306             Usb_ack_event(EVT_HOST_SOF);
00307             while (Is_host_reset());    // Active wait of end of reset send
00308             Host_ack_reset();
00309             //Workaround for some bugly devices with powerless pull up
00310             //usually low speed where data line rise slowly and can be interpretaded as disconnection
00311             for(c=0;c!=0xFFFF;c++)    // Basic Timeout counter
00312             {
00313                if(Is_usb_event(EVT_HOST_SOF))   //If we detect SOF, device is still alive and connected, just clear false disconnect flag
00314                {
00315                   if(Is_device_disconnection())
00316                   {
00317                       Host_ack_device_connection();
00318                       Host_ack_device_disconnection();
00319                       break;
00320                   }
00321                }
00322             }
00323             Host_enable_device_disconnection_interrupt();
00324             // All USB pipes must be reconfigured after a USB reset generation
00325             host_configure_pipe(PIPE_CONTROL, \
00326                                             TYPE_CONTROL, \
00327                                             TOKEN_SETUP,  \
00328                                             EP_CONTROL,   \
00329                                             SIZE_64,      \
00330                                             ONE_BANK,     \
00331                                             0             );            
00332             c = 0;
00333             while (c<100)               // wait 100ms after USB reset
00334             {
00335                if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }// Count Start Of frame
00336                if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {goto device_attached_error;}
00337             }
00338             device_state = DEVICE_POWERED;
00339             c=0;
00340          }
00341          device_attached_error:
00342         // Device connection error, or vbus pb -> Retry the connection process from the begining
00343          if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt()||Is_usb_vbus_low())
00344          {
00345             Usb_ack_bconnection_error_interrupt();
00346             Usb_enable_vbus_hw_control();
00347             device_state=DEVICE_UNATTACHED;
00348             Usb_disable_vbus();
00349             Usb_disable_vbus_pad();
00350             Usb_enable_vbus_pad();
00351             Usb_ack_vbus_error_interrupt();
00352             Usb_enable_vbus();
00353             Usb_disable_vbus_hw_control();
00354             Host_disable_sof();
00355          }
00356          break;
00357 
00358      //------------------------------------------------------
00359      //   DEVICE_POWERED state
00360      //
00361      //   - Device connection (attach) as been detected,
00362      //   - Wait 100ms and configure default control pipe
00363      //
00364       case DEVICE_POWERED :
00365          LOG_STR_CODE(log_device_connected);
00366          Host_device_connection_action();
00367          if (Is_usb_event(EVT_HOST_SOF))
00368          {
00369             Usb_ack_event(EVT_HOST_SOF);
00370             if (c++ >= 100)                          // Wait 100ms
00371             {
00372                device_state = DEVICE_DEFAULT;
00373             }
00374          }
00375          break;
00376 
00377      //------------------------------------------------------
00378      //   DEVICE_DEFAULT state
00379      //
00380      //   - Get device descriptor
00381      //   - Reconfigure Pipe 0 according to Device EP0
00382      //   - Attribute device address
00383      //
00384       case DEVICE_DEFAULT :
00385         // Get first device descriptor
00386          Host_select_device(0);
00387          usb_tree.device[0].ep_ctrl_size=8;
00388          if( CONTROL_GOOD == host_get_device_descriptor_uncomplete())
00389          {
00390             c = 0;
00391             while(c<20)           // wait 20ms before USB reset (special buggly devices...)
00392             {
00393                if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
00394                if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt())  {break;}
00395             }
00396             Host_disable_device_disconnection_interrupt();
00397             Host_send_reset();          // First USB reset
00398             Usb_ack_event(EVT_HOST_SOF);
00399             while (Is_host_reset());    // Active wait of end of reset send
00400             Host_ack_reset();
00401             //Workaround for some bugly devices with powerless pull up
00402             //usually low speed where data line rise slowly and can be interpretaded as disconnection
00403             for(c=0;c!=0xFFFF;c++)    // Basic Timeout counter
00404             {
00405                if(Is_usb_event(EVT_HOST_SOF))   //If we detect SOF, device is still alive and connected, just clear false disconnect flag
00406                {
00407                   if(Is_device_disconnection())
00408                   {
00409                       Host_ack_device_connection();
00410                       Host_ack_device_disconnection();
00411                       break;
00412                   }
00413                }
00414             }
00415             Host_enable_device_disconnection_interrupt();
00416             c = 0;
00417             host_configure_pipe(PIPE_CONTROL, \
00418                                             TYPE_CONTROL, \
00419                                             TOKEN_SETUP,  \
00420                                             EP_CONTROL,   \
00421                                             SIZE_64,      \
00422                                             ONE_BANK,     \
00423                                             0             );            
00424             while(c<200)           // wait 200ms after USB reset
00425             {
00426                if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
00427                if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt())  {break;}
00428             }
00429             usb_tree.device[0].ep_ctrl_size=data_stage[OFFSET_FIELD_MAXPACKETSIZE];
00430             
00431             // Give an absolute device address
00432             host_set_address(DEVICE_BASE_ADDRESS);
00433             usb_tree.device[0].device_address=DEVICE_BASE_ADDRESS;
00434             device_state = DEVICE_ADDRESSED;
00435          }
00436          else
00437          {  device_state = DEVICE_ERROR; }
00438          break;
00439 
00440      //------------------------------------------------------
00441      //   DEVICE_BASE_ADDRESSED state
00442      //
00443      //   - Check if VID PID is in supported list
00444      //
00445       case DEVICE_ADDRESSED :
00446          if (CONTROL_GOOD == host_get_device_descriptor())
00447          {
00448            // Detect if the device connected belongs to the supported devices table
00449             if (HOST_TRUE == host_check_VID_PID())
00450             {
00451                Host_set_device_supported();
00452                Host_device_supported_action();
00453                device_state = DEVICE_CONFIGURED;
00454             }
00455             else
00456             {
00457                #if (HOST_STRICT_VID_PID_TABLE==ENABLE)
00458                   Host_device_not_supported_action();
00459                   device_state = DEVICE_ERROR;
00460                #else
00461                   device_state = DEVICE_CONFIGURED;
00462                #endif
00463             }
00464          }
00465          else // Can not get device descriptor
00466          {  device_state = DEVICE_ERROR; }
00467          break;
00468 
00469      //------------------------------------------------------
00470      //   DEVICE_CONFIGURED state
00471      //
00472      //   - Configure pipes for the supported interface
00473      //   - Send Set_configuration() request
00474      //   - Goto full operating mode (device ready)
00475      //
00476       case DEVICE_CONFIGURED :
00477          if (CONTROL_GOOD == host_get_configuration_descriptor())
00478          {
00479             if (HOST_FALSE != host_check_class()) // Class support OK?
00480             {
00481                usb_tree.nb_device++;
00482             #if (HOST_AUTO_CFG_ENDPOINT==ENABLE)
00483                if(host_auto_configure_endpoint())
00484             #else
00485                Host_set_configured();     // Assumes config is OK with user config
00486                if(User_configure_endpoint()) // User call here instead of autoconfig
00487             #endif
00488                {
00489                   if (CONTROL_GOOD== host_set_configuration(1))  // Send Set_configuration
00490                   {
00491                      //host_set_interface(interface_bound,interface_bound_alt_set);
00492                      // device and host are now fully configured
00493                      // goto DEVICE READY normal operation
00494                       device_state = DEVICE_READY;
00495                      // monitor device disconnection under interrupt
00496                       Host_enable_device_disconnection_interrupt();
00497                      // If user host application requires SOF interrupt event
00498                      // Keep SOF interrupt enable otherwize, disable this interrupt
00499                   #if (HOST_CONTINUOUS_SOF_INTERRUPT==DISABLE && USB_HUB_SUPPORT==DISABLE)
00500                       Host_disable_sof_interrupt();
00501                   #endif
00502                   #if (USB_HUB_SUPPORT==ENABLE)
00503                       // Check if the connected device is a hub
00504                       if(Get_class(0)==HUB_CLASS && Get_subclass(0)==0x00 && Get_protocol(0)==0x00)
00505                       {
00506                            // Get hub descriptor
00507                            if( Get_hub_descriptor()==CONTROL_GOOD)
00508                            {
00509                               // Power each port of the hub
00510                               i=data_stage[NB_PORT_OFFSET];
00511                               for(c=1;c<=i;c++)
00512                               {
00513                                  Set_port_feature(PORT_POWER,c);
00514                               }
00515                               nb_hub_present = 1;
00516                               hub_device_address[0]=DEVICE_BASE_ADDRESS;
00517                               hub_init(nb_hub_present-1);    
00518                            }
00519                       }
00520                       else
00521                       {
00522                          nb_hub_present = 0;
00523                          new_device_connected=TRUE;
00524                       }
00525                   #else
00526                       new_device_connected=TRUE;
00527                   #endif
00528                       
00529                       Enable_interrupt();
00530                       LOG_STR_CODE(log_device_enumerated);
00531                   }
00532                   else// Problem during Set_configuration request...
00533                   {   device_state = DEVICE_ERROR;  }
00534                }
00535             }
00536             else // device class not supported...
00537             {
00538                 device_state = DEVICE_ERROR;
00539                 LOG_STR_CODE(log_device_unsupported);
00540                 Host_device_class_not_supported_action();
00541             }
00542          }
00543          else // Can not get configuration descriptors...
00544          {  device_state = DEVICE_ERROR; }
00545          break;
00546 
00547      //------------------------------------------------------
00548      //   DEVICE_READY state
00549      //
00550      //   - Full std operatinf mode
00551      //   - Nothing to do...
00552      //
00553       case DEVICE_READY:     // Host full std operating mode!
00554          new_device_connected=FALSE;
00555          
00556       #if (USB_HUB_SUPPORT==ENABLE)
00557          f_hub_port_disconnect=FALSE;
00558          // If one hub is present in the USB tree and the period interval
00559          // for the interrupt hub endpoint occurs
00560          if(nb_hub_present && hub_interrupt_sof==0)
00561          {
00562             saved_device=selected_device;      // Backup user selected device
00563             for(j=1;j<=nb_hub_present;j++)
00564             {
00565                for(i=0;i<MAX_DEVICE_IN_USB_TREE;i++)
00566                {
00567                   if(usb_tree.device[i].device_address==hub_device_address[j-1]) break;
00568                }
00569                Host_select_device(i);
00570                Host_select_pipe(usb_tree.device[i].interface[0].ep[0].pipe_number);
00571                Host_ack_nak_received();
00572                Host_ack_in_received();
00573                Host_unfreeze_pipe();
00574                Host_send_in();
00575                while(1)
00576                {
00577                    if(Is_host_nak_received())   break;
00578                    if(Is_host_emergency_exit()) break;
00579                    if(Is_host_in_received())    break;
00580                }
00581                Host_freeze_pipe();
00582                if(Is_host_nak_received())
00583                {
00584                   Host_ack_nak_received();
00585                }
00586                if(Is_host_in_received())
00587                {
00588                   if(Is_host_stall()==FALSE)
00589                   {
00590                      c=Host_read_byte();
00591                   }
00592                   Host_ack_in_received();
00593                   hub_manage_port_change_status(c,j);
00594                }
00595             } // for all hub 
00596             Host_select_device(saved_device);  // Restore user selected device
00597             #if (USER_PERIODIC_PIPE==ENABLE)
00598             unfreeze_user_periodic_pipe();
00599             #endif
00600          }
00601       #endif
00602          break;
00603 
00604      //------------------------------------------------------
00605      //   DEVICE_ERROR state
00606      //
00607      //   - Error state
00608      //   - Do custom action call (probably go to default mode...)
00609      //
00610       case DEVICE_ERROR :    // TODO !!!!
00611       #if (HOST_ERROR_RESTART==ENABLE)
00612          device_state=DEVICE_UNATTACHED;
00613       #endif
00614          Host_device_error_action();
00615          break;
00616 
00617      //------------------------------------------------------
00618      //   DEVICE_SUSPENDED state
00619      //
00620      //   - Host application request to suspend the device activity
00621      //   - State machine comes here thanks to Host_request_suspend()
00622      //
00623       case DEVICE_SUSPENDED :
00624          if(Is_device_supports_remote_wakeup()) // If the connected device supports remote wake up
00625          {
00626            host_set_feature_remote_wakeup();    // Enable this feature...
00627          }
00628          LOG_STR_CODE(log_going_to_suspend);
00629          c = Is_host_sof_interrupt_enabled(); //Save current sof interrupt enable state
00630          Host_disable_sof_interrupt();
00631          Host_ack_sof();
00632          Host_disable_sof();           // Stop start of frame generation, this generates the suspend state
00633          Host_ack_hwup();
00634          Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
00635                                        // (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
00636          Usb_freeze_clock();
00637          Stop_pll();
00638          Host_suspend_action();              // Custom action here! (for example go to power-save mode...)
00639          device_state=DEVICE_WAIT_RESUME;    // wait for device resume event
00640          break;
00641 
00642      //------------------------------------------------------
00643      //   DEVICE_WAIT_RESUME state
00644      //
00645      //   - Wait in this state till the host receives an upstream resume from the device
00646      //   - or the host software request the device to resume
00647      //
00648       case DEVICE_WAIT_RESUME :
00649          if(Is_usb_event(EVT_HOST_HWUP)|| Is_host_request_resume())// Remote wake up has been detected
00650                                                                  // or Local resume request has been received
00651          {
00652             if(Is_host_request_resume())       // Not a remote wakeup, but an host application request
00653             {
00654                Host_disable_hwup_interrupt();  // Wake up interrupt should be disable host is now wake up !
00655               // CAUTION HWUP can be cleared only when USB clock is active
00656                Pll_start_auto();               // First Restart the PLL for USB operation
00657                Wait_pll_ready();               // Get sure pll is lock
00658                Usb_unfreeze_clock();           // Enable clock on USB interface
00659                Host_ack_hwup();                // Clear HWUP interrupt flag
00660             }
00661             Host_enable_sof();
00662             Host_send_resume();                            // Send down stream resume
00663             while (Is_host_down_stream_resume()==FALSE);   // Wait Down stream resume sent
00664             Host_ack_remote_wakeup();        // Ack remote wake-up reception
00665             Host_ack_request_resume();       // Ack software request
00666             Host_ack_down_stream_resume();   // Ack down stream resume sent
00667             Usb_ack_event(EVT_HOST_HWUP);    // Ack software event
00668             if(c) { Host_enable_sof_interrupt(); } // Restore SOF interrupt enable state before suspend
00669             device_state=DEVICE_READY;       // Come back to full operating mode
00670             LOG_STR_CODE(log_usb_resumed);
00671          }
00672          break;
00673 
00674      //------------------------------------------------------
00675      //   DEVICE_DISCONNECTED state
00676      //
00677      //   - Device disconnection has been detected
00678      //   - Run scheduler in this state at least two times to get sure event is detected by all host application tasks
00679      //   - Go to DEVICE_DISCONNECTED_ACK state before DEVICE_UNATTACHED, to get sure scheduler calls all app tasks...
00680      //
00681       case DEVICE_DISCONNECTED :
00682          device_state = DEVICE_DISCONNECTED_ACK;
00683          break;
00684 
00685      //------------------------------------------------------
00686      //   DEVICE_DISCONNECTED_ACK state
00687      //
00688      //   - Device disconnection has been detected and managed bu applicatives tasks
00689      //   - Go to DEVICE_UNATTACHED state
00690      //
00691       case DEVICE_DISCONNECTED_ACK :
00692          device_state = DEVICE_UNATTACHED;
00693          break;
00694 
00695      //------------------------------------------------------
00696      //   default state
00697      //
00698      //   - Default case: ERROR
00699      //   - Goto no device state
00700      //
00701       default :
00702          device_state = DEVICE_UNATTACHED;
00703          break;
00704       }
00705 }
00706 
00707 //___ F U N C T I O N S   F O R   P O L L I N G   M A N A G E D   D A T A  F L O W S  _________________________
00708 
00721 U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf)
00722 {
00723    U8 c;
00724    U8 status=PIPE_GOOD;
00725    U8 sav_int_sof_enable;
00726    U8 nak_timeout;
00727    U16 cpt_nak;
00728    U8 nb_data_loaded;
00729    U8 cpt_err_timeout=0;
00730 
00731 #if (USER_PERIODIC_PIPE==ENABLE)
00732    freeze_user_periodic_pipe();
00733 #endif
00734    sav_int_sof_enable=Is_host_sof_interrupt_enabled();  // Save state of enable sof interrupt
00735    Host_enable_sof_interrupt();
00736    Host_select_pipe(pipe);
00737    Host_set_token_out();
00738    Host_ack_out_sent();
00739    Host_unfreeze_pipe();
00740    
00741    while (nb_data != 0)         // While there is something to send...
00742    {
00743      // Prepare data to be sent
00744       c = Host_get_pipe_length();
00745       if ( (U16)c > nb_data)
00746       {
00747          nb_data_loaded = (U8)nb_data;
00748          c = nb_data;
00749       }
00750       else
00751       {  nb_data_loaded = c; }
00752       while (c!=0)              // Load Pipe buffer
00753       {
00754          Host_write_byte(*buf++);
00755          c--;
00756       }
00757       private_sof_counter=0;    // Reset the counter in SOF detection sub-routine
00758       cpt_nak=0;
00759       nak_timeout=0;
00760       Host_ack_out_sent();
00761       Host_send_out();
00762       while (!Is_host_out_sent())
00763       {
00764          if (Is_host_emergency_exit())// Async disconnection or role change detected under interrupt
00765          {
00766             status=PIPE_DELAY_TIMEOUT;
00767             Host_reset_pipe(pipe);
00768             goto host_send_data_end;
00769          }
00770          #if (TIMEOUT_DELAY_ENABLE==ENABLE)
00771          if (private_sof_counter>=250)            // Count 250ms (250sof)
00772          {
00773             private_sof_counter=0;
00774             if (nak_timeout++>=TIMEOUT_DELAY) // Inc timeout and check for overflow
00775             {
00776                status=PIPE_DELAY_TIMEOUT;
00777                Host_reset_pipe(pipe);
00778                goto host_send_data_end;
00779             }
00780          }
00781          #endif
00782          if (Is_host_pipe_error()) // Any error ?
00783          {
00784             status = Host_error_status();
00785             Host_ack_all_errors();
00786             if(status == PIPE_TIMEOUT)
00787             {
00788                if(cpt_err_timeout++>100)
00789                {
00790                   goto host_send_data_end;
00791                }
00792                else
00793                {
00794                   c=0;
00795                   while(c<2)           // wait  2 ms
00796                   {
00797                      if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
00798                      if (Is_host_emergency_exit() )  {break;}
00799                   }
00800 
00801                   Host_unfreeze_pipe();
00802                }
00803             }
00804          }
00805          if (Is_host_stall())      // Stall management
00806          {
00807             status =PIPE_STALL;
00808             Host_ack_stall();
00809             goto host_send_data_end;
00810          }
00811          #if (NAK_TIMEOUT_ENABLE==ENABLE)
00812          if(Is_host_nak_received())  //NAK received
00813          {
00814             Host_ack_nak_received();
00815             if (cpt_nak++>NAK_SEND_TIMEOUT)
00816             {
00817                status = PIPE_NAK_TIMEOUT;
00818                Host_reset_pipe(pipe);
00819                goto host_send_data_end;
00820             }
00821          }
00822          #endif
00823       }
00824       // Here OUT sent
00825       nb_data -= nb_data_loaded;
00826       status=PIPE_GOOD;         // Frame correctly sent
00827       Host_ack_out_sent();
00828    }
00829    while(0!=Host_number_of_busy_bank());
00830    
00831 host_send_data_end:
00832    Host_freeze_pipe();
00833   // Restore sof interrupt enable state
00834    if (sav_int_sof_enable==FALSE)   {Host_disable_sof_interrupt();}
00835    #if (USER_PERIODIC_PIPE==ENABLE)
00836    unfreeze_user_periodic_pipe();
00837    #endif   
00838   // And return...
00839    return ((U8)status);
00840 }
00841 
00842 
00843 
00856 U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf)
00857 {
00858    U8 status=PIPE_GOOD;
00859    U8 sav_int_sof_enable;
00860    U8 nak_timeout;
00861    U16 n,i;
00862    U16 cpt_nak;
00863    
00864    #if (USER_PERIODIC_PIPE==ENABLE)
00865    freeze_user_periodic_pipe();   
00866    #endif
00867    n=*nb_data;
00868    *nb_data=0;
00869    sav_int_sof_enable=Is_host_sof_interrupt_enabled();
00870    Host_enable_sof_interrupt();
00871    Host_select_pipe(pipe);
00872    Host_continuous_in_mode();
00873    Host_set_token_in();
00874    Host_ack_in_received();
00875    while (n)              // While missing data...
00876    {
00877       Host_unfreeze_pipe();
00878       Host_send_in();
00879       private_sof_counter=0; // Reset the counter in SOF detection sub-routine
00880       nak_timeout=0;
00881       cpt_nak=0;
00882       while (!Is_host_in_received())
00883       {
00884          if (Is_host_emergency_exit())   // Async disconnection or role change detected under interrupt
00885          {
00886             status=PIPE_DELAY_TIMEOUT;
00887             Host_reset_pipe(pipe);
00888             goto host_get_data_end;
00889          }
00890          #if (TIMEOUT_DELAY_ENABLE==ENABLE)
00891          if (private_sof_counter>=250)   // Timeout management
00892          {
00893             private_sof_counter=0;       // Done in host SOF interrupt
00894             if (nak_timeout++>=TIMEOUT_DELAY)// Check for local timeout
00895             {
00896                status=PIPE_DELAY_TIMEOUT;
00897                Host_reset_pipe(pipe);
00898                goto host_get_data_end;
00899             }
00900          }
00901          #endif
00902          if(Is_host_pipe_error())        // Error management
00903          {
00904             status = Host_error_status();
00905             Host_ack_all_errors();
00906             goto host_get_data_end;
00907          }
00908          if(Is_host_stall())             // STALL management
00909          {
00910             status =PIPE_STALL;
00911             Host_reset_pipe(pipe);
00912             Host_ack_stall();
00913             goto host_get_data_end;
00914          }
00915          #if (NAK_TIMEOUT_ENABLE==ENABLE)
00916          if(Is_host_nak_received())  //NAK received
00917          {
00918             Host_ack_nak_received();
00919             if (cpt_nak++>NAK_RECEIVE_TIMEOUT)
00920             {
00921                status = PIPE_NAK_TIMEOUT;
00922                Host_reset_pipe(pipe);
00923                goto host_get_data_end;
00924             }
00925          }
00926          #endif
00927       }
00928       status=PIPE_GOOD;
00929       Host_freeze_pipe();
00930       if (Host_byte_counter()<=n)
00931       {
00932          if ((Host_byte_counter() < n)&&(Host_byte_counter()<Host_get_pipe_length()))
00933          { n=0;}
00934          else
00935          { n-=Host_byte_counter();}
00936          (*nb_data)+=Host_byte_counter();  // Update nb of byte received
00937          for (i=Host_byte_counter();i;i--)
00938          { *buf=Host_read_byte(); buf++;}
00939       }
00940       else  // more bytes received than expected
00941       {     // TODO error code management
00942          *nb_data+=n;
00943          for (i=n;i;i--)                  // Byte number limited to the initial request (limit tab over pb)
00944          {  *buf=Host_read_byte(); buf++; }
00945          n=0;
00946       }
00947       Host_ack_in_received();
00948    }
00949    Host_freeze_pipe();
00950 host_get_data_end:
00951    if (sav_int_sof_enable==FALSE)
00952    {
00953       Host_disable_sof_interrupt();
00954    }
00955    #if (USER_PERIODIC_PIPE==ENABLE)
00956    unfreeze_user_periodic_pipe();
00957    #endif   
00958    return ((U8)status);
00959 }
00960 
00961 
00962 //___ F U N C T I O N S   F O R   I N T E R R U P T   M A N A G E D   D A T A   F L O W S  _________________________
00963 
00964 #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
00965 
00966 void reset_it_pipe_str(void)
00967 {
00968    U8 i;
00969    for(i=0;i<MAX_EP_NB;i++)
00970    {
00971       it_pipe_str[i].enable=DISABLE;
00972       it_pipe_str[i].timeout=0;
00973    }
00974 }
00975 
00976 U8 is_any_interrupt_pipe_active(void)
00977 {
00978    U8 i;
00979    for(i=0;i<MAX_EP_NB;i++)
00980    {
00981       if(it_pipe_str[i].enable==ENABLE) return TRUE;
00982    }
00983    return FALSE;
00984 }
00985 
00999 U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf,void(*handle)(U8 status, U16 nb_byte))
01000 {
01001    Host_select_pipe(pipe);
01002    if(it_pipe_str[pipe].enable==ENABLE)
01003    {
01004       return HOST_FALSE;
01005    }
01006    else
01007    {
01008       if(is_any_interrupt_pipe_active()==FALSE)
01009       {
01010          g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
01011          Host_enable_sof_interrupt();
01012       }
01013       it_pipe_str[pipe].enable=ENABLE;
01014       it_pipe_str[pipe].nb_byte_to_process=nb_data;
01015       it_pipe_str[pipe].nb_byte_processed=0;
01016       it_pipe_str[pipe].ptr_buf=buf;
01017       it_pipe_str[pipe].handle=handle;
01018       it_pipe_str[pipe].timeout=0;
01019       it_pipe_str[pipe].nak_timeout=NAK_RECEIVE_TIMEOUT;
01020 
01021       private_sof_counter=0;           // Reset the counter in SOF detection sub-routine
01022       Host_reset_pipe(pipe);
01023       Host_enable_stall_interrupt();
01024       #if (NAK_TIMEOUT_ENABLE==ENABLE)
01025       Host_enable_nak_interrupt();
01026       #endif
01027       Host_enable_error_interrupt();
01028       Host_enable_receive_interrupt();
01029       Host_ack_stall();
01030       Host_ack_nak_received();
01031 
01032       Host_continuous_in_mode();
01033       Host_set_token_in();
01034       Host_unfreeze_pipe();
01035       return HOST_TRUE;
01036    }
01037 }
01038 
01050 U8 host_send_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void(*handle)(U8 status, U16 nb_byte))
01051 {
01052    U8 i;
01053    U8 *ptr_buf=buf;
01054 
01055    Host_select_pipe(pipe);
01056    if(it_pipe_str[pipe].enable==ENABLE)
01057    {
01058       return HOST_FALSE;
01059    }
01060    else
01061    {
01062       if(is_any_interrupt_pipe_active()==FALSE)
01063       {
01064          g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
01065          Host_enable_sof_interrupt();
01066       }
01067       it_pipe_str[pipe].enable=ENABLE;
01068       it_pipe_str[pipe].nb_byte_to_process=nb_data;
01069       it_pipe_str[pipe].nb_byte_processed=0;
01070       it_pipe_str[pipe].ptr_buf=buf;
01071       it_pipe_str[pipe].handle=handle;
01072       it_pipe_str[pipe].timeout=0;
01073       it_pipe_str[pipe].nak_timeout=NAK_SEND_TIMEOUT;
01074       it_pipe_str[pipe].nb_byte_on_going=0;
01075 
01076       Host_reset_pipe(pipe);
01077       Host_unfreeze_pipe();
01078       // Prepare data to be sent
01079       i = Host_get_pipe_length();
01080       if ( i > nb_data)                // Pipe size> remaining data
01081       {
01082          i = nb_data;
01083          nb_data = 0;
01084       }
01085       else                             // Pipe size < remaining data
01086       {
01087          nb_data -= i;
01088       }
01089       it_pipe_str[pipe].nb_byte_on_going+=i;   // Update nb data processed
01090       while (i!=0)                    // Load Pipe buffer
01091       {  Host_write_byte(*ptr_buf++); i--;
01092       }
01093       private_sof_counter=0;          // Reset the counter in SOF detection sub-routine
01094       it_pipe_str[pipe].timeout=0;    // Refresh timeout counter
01095       Host_ack_out_sent();
01096       Host_ack_stall();
01097       Host_ack_nak_received();
01098 
01099       Host_enable_stall_interrupt();
01100       Host_enable_error_interrupt();
01101       #if (NAK_TIMEOUT_ENABLE==ENABLE)
01102       Host_enable_nak_interrupt();
01103       #endif
01104       Host_enable_transmit_interrupt();
01105       Host_send_out();                // Send the USB frame
01106       return HOST_TRUE;
01107    }
01108 }
01109 
01115 #ifdef __GNUC__
01116  ISR(USB_COM_vect)
01117 #else
01118 #pragma vector = USB_Endpoint_Pipe_vect
01119 __interrupt void usb_pipe_interrupt()
01120 #endif
01121 {
01122    U8 pipe_nb;
01123    U8 *ptr_buf;
01124    void  (*fct_handle)(U8 status,U16 nb_byte);
01125    U16 n;
01126    U8 i;
01127    U8 do_call_back=FALSE;
01128 
01129    pipe_nb_save = Host_get_selected_pipe();       // Important! Save here working pipe number
01130    pipe_nb=usb_get_nb_pipe_interrupt();  // work with the correct pipe number that generates the interrupt
01131    Host_select_pipe(pipe_nb);                        // Select this pipe
01132    fct_handle=*(it_pipe_str[pipe_nb].handle);
01133 
01134    // Now try to detect what event generate an interrupt...
01135 
01136    if (Is_host_pipe_error())             // Any error ?
01137    {
01138       it_pipe_str[pipe_nb].status = Host_error_status();
01139       it_pipe_str[pipe_nb].enable=DISABLE;
01140       Host_stop_pipe_interrupt(pipe_nb);
01141       Host_ack_all_errors();
01142       do_call_back=TRUE;
01143       goto usb_pipe_interrupt_end;
01144    }
01145 
01146    if (Is_host_stall())                  // Stall handshake received ?
01147    {
01148       it_pipe_str[pipe_nb].status=PIPE_STALL;
01149       it_pipe_str[pipe_nb].enable=DISABLE;
01150       Host_stop_pipe_interrupt(pipe_nb);
01151       do_call_back=TRUE;
01152       goto usb_pipe_interrupt_end;
01153    }
01154 
01155    #if (NAK_TIMEOUT_ENABLE==ENABLE)
01156    if (Is_host_nak_received())           // NAK ?
01157    {
01158       Host_ack_nak_received();
01159       // check if number of NAK timeout error occurs (not for interrupt type pipe)
01160       if((--it_pipe_str[pipe_nb].nak_timeout==0) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
01161       {
01162          it_pipe_str[pipe_nb].status=PIPE_NAK_TIMEOUT;
01163          it_pipe_str[pipe_nb].enable=DISABLE;
01164          Host_stop_pipe_interrupt(pipe_nb);
01165          do_call_back=TRUE;
01166          goto usb_pipe_interrupt_end;
01167       }
01168    }
01169    #endif
01170 
01171    if (Is_host_in_received())            // Pipe IN reception ?
01172    {
01173       ptr_buf=it_pipe_str[pipe_nb].ptr_buf+it_pipe_str[pipe_nb].nb_byte_processed;       // Build pointer to data buffer
01174       n=it_pipe_str[pipe_nb].nb_byte_to_process-it_pipe_str[pipe_nb].nb_byte_processed;  // Remaining data bytes
01175       Host_freeze_pipe();
01176       if (Host_byte_counter()<=n)
01177       {
01178          if ((Host_byte_counter() < n)&&(Host_byte_counter()<Host_get_pipe_length())) //Received less than remaining, but less than pipe capacity
01179                                                                                       //TODO: error code
01180          {
01181             n=0;
01182          }
01183          else
01184          {
01185             n-=Host_byte_counter();
01186          }
01187          it_pipe_str[pipe_nb].nb_byte_processed+=Host_byte_counter();  // Update nb of byte received
01188          for (i=Host_byte_counter();i;i--)
01189          { *ptr_buf=Host_read_byte(); ptr_buf++;}
01190       }
01191       else  // more bytes received than expected
01192       {     // TODO error code management
01193          it_pipe_str[pipe_nb].nb_byte_processed+=n;
01194          for (i=n;i;i--)                  // Byte number limited to the initial request (limit tab over pb)
01195          { *ptr_buf=Host_read_byte(); ptr_buf++;}
01196          n=0;
01197       }
01198       Host_ack_in_received();
01199       if(n>0) //still something to process
01200       {
01201          Host_unfreeze_pipe();            // Request another IN transfer
01202          Host_send_in();
01203          private_sof_counter=0;           // Reset the counter in SOF detection sub-routine
01204          it_pipe_str[pipe_nb].timeout=0;  // Reset timeout
01205          it_pipe_str[pipe_nb].nak_timeout=NAK_RECEIVE_TIMEOUT;
01206 
01207       }
01208       else //end of transfer
01209       {
01210          it_pipe_str[pipe_nb].enable=DISABLE;
01211          it_pipe_str[pipe_nb].status=PIPE_GOOD;
01212          Host_stop_pipe_interrupt(pipe_nb);
01213          do_call_back=TRUE;
01214       }
01215    }
01216 
01217    if(Is_host_out_sent())                  // Pipe OUT sent ?
01218    {
01219       Host_ack_out_sent();
01220       it_pipe_str[pipe_nb].nb_byte_processed+=it_pipe_str[pipe_nb].nb_byte_on_going;
01221       it_pipe_str[pipe_nb].nb_byte_on_going=0;
01222       ptr_buf=it_pipe_str[pipe_nb].ptr_buf+it_pipe_str[pipe_nb].nb_byte_processed;       // Build pointer to data buffer
01223       n=it_pipe_str[pipe_nb].nb_byte_to_process-it_pipe_str[pipe_nb].nb_byte_processed;  // Remaining data bytes
01224       if(n>0)   // Still data to process...
01225       {
01226          Host_unfreeze_pipe();
01227         // Prepare data to be sent
01228          i = Host_get_pipe_length();
01229          if ( i > n)     // Pipe size> remaining data
01230          {
01231             i = n;
01232             n = 0;
01233          }
01234          else                // Pipe size < remaining data
01235          {  n -= i; }
01236          it_pipe_str[pipe_nb].nb_byte_on_going+=i;   // Update nb data processed
01237          while (i!=0)                     // Load Pipe buffer
01238          {
01239             Host_write_byte(*ptr_buf++); i--;
01240          }
01241          private_sof_counter=0;           // Reset the counter in SOF detection sub-routine
01242          it_pipe_str[pipe_nb].timeout=0;  // Refresh timeout counter
01243          it_pipe_str[pipe_nb].nak_timeout=NAK_SEND_TIMEOUT;
01244          Host_send_out();                 // Send the USB frame
01245       }
01246       else                                //n==0 Transfer is finished
01247       {
01248          it_pipe_str[pipe_nb].enable=DISABLE;    // Tranfer end
01249          it_pipe_str[pipe_nb].status=PIPE_GOOD;  // Status OK
01250          Host_stop_pipe_interrupt(pipe_nb);
01251          do_call_back=TRUE;
01252       }
01253    }
01254 
01255 usb_pipe_interrupt_end:
01256    Host_select_pipe(pipe_nb_save);   // Restore pipe number !!!!
01257    if (is_any_interrupt_pipe_active()==FALSE)    // If no more transfer is armed
01258    {
01259       if (g_sav_int_sof_enable==FALSE)
01260       {
01261          Host_disable_sof_interrupt();
01262       }
01263    }
01264    if(do_call_back)      // Any callback functions to perform ?
01265    {
01266       fct_handle(it_pipe_str[pipe_nb].status,it_pipe_str[pipe_nb].nb_byte_processed);
01267    }
01268 }
01269 #endif
01270 
01271 
01272 #endif // USB_HOST_FEATURE ENABLE
01273 

Generated on Mon Nov 3 10:08:24 2008 for ATMEL by  doxygen 1.5.3