usb_host_task.c

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

Generated on Mon Sep 14 13:24:11 2009 for ATMEL by  doxygen 1.5.3