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, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 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 = FALSE;
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=FALSE;
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=FALSE;
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                       Host_set_device_ready();
00496                      // monitor device disconnection under interrupt
00497                       Host_enable_device_disconnection_interrupt();
00498                      // If user host application requires SOF interrupt event
00499                      // Keep SOF interrupt enable otherwize, disable this interrupt
00500                   #if (HOST_CONTINUOUS_SOF_INTERRUPT==DISABLE && USB_HUB_SUPPORT==DISABLE)
00501                       Host_disable_sof_interrupt();
00502                   #endif
00503                   #if (USB_HUB_SUPPORT==ENABLE)
00504                       // Check if the connected device is a hub
00505                       if(Get_class(0)==HUB_CLASS && Get_subclass(0)==0x00 && Get_protocol(0)==0x00)
00506                       {
00507                            // Get hub descriptor
00508                            if( Get_hub_descriptor()==CONTROL_GOOD)
00509                            {
00510                               // Power each port of the hub
00511                               i=data_stage[NB_PORT_OFFSET];
00512                               for(c=1;c<=i;c++)
00513                               {
00514                                  Set_port_feature(PORT_POWER,c);
00515                               }
00516                               nb_hub_present = 1;
00517                               hub_device_address[0]=DEVICE_BASE_ADDRESS;
00518                               hub_init(nb_hub_present-1);    
00519                            }
00520                       }
00521                       else
00522                       {
00523                          nb_hub_present = 0;
00524                          new_device_connected=TRUE;
00525                       }
00526                   #else
00527                       new_device_connected=TRUE;
00528                   #endif
00529                       
00530                       Enable_interrupt();
00531                       LOG_STR_CODE(log_device_enumerated);
00532                   }
00533                   else// Problem during Set_configuration request...
00534                   {   device_state = DEVICE_ERROR;  }
00535                }
00536             }
00537             else // device class not supported...
00538             {
00539                 device_state = DEVICE_ERROR;
00540                 LOG_STR_CODE(log_device_unsupported);
00541                 Host_device_class_not_supported_action();
00542             }
00543          }
00544          else // Can not get configuration descriptors...
00545          {  device_state = DEVICE_ERROR; }
00546          break;
00547 
00548      //------------------------------------------------------
00549      //   DEVICE_READY state
00550      //
00551      //   - Full std operatinf mode
00552      //   - Nothing to do...
00553      //
00554       case DEVICE_READY:     // Host full std operating mode!
00555          new_device_connected=FALSE;
00556          
00557       #if (USB_HUB_SUPPORT==ENABLE)
00558          f_hub_port_disconnect=FALSE;
00559          // If one hub is present in the USB tree and the period interval
00560          // for the interrupt hub endpoint occurs
00561          if(nb_hub_present && hub_interrupt_sof==0)
00562          {
00563             saved_device=selected_device;      // Backup user selected device
00564             for(j=1;j<=nb_hub_present;j++)
00565             {
00566                for(i=0;i<MAX_DEVICE_IN_USB_TREE;i++)
00567                {
00568                   if(usb_tree.device[i].device_address==hub_device_address[j-1]) break;
00569                }
00570                Host_select_device(i);
00571                Host_select_pipe(usb_tree.device[i].interface[0].ep[0].pipe_number);
00572                Host_ack_nak_received();
00573                Host_ack_in_received();
00574                Host_unfreeze_pipe();
00575                Host_send_in();
00576                while(1)
00577                {
00578                    if(Is_host_nak_received())   break;
00579                    if(Is_host_emergency_exit()) break;
00580                    if(Is_host_in_received())    break;
00581                }
00582                Host_freeze_pipe();
00583                if(Is_host_nak_received())
00584                {
00585                   Host_ack_nak_received();
00586                }
00587                if(Is_host_in_received())
00588                {
00589                   if(Is_host_stall()==FALSE)
00590                   {
00591                      c=Host_read_byte();
00592                   }
00593                   Host_ack_in_received();
00594                   hub_manage_port_change_status(c,j);
00595                }
00596             } // for all hub 
00597             Host_select_device(saved_device);  // Restore user selected device
00598             #if (USER_PERIODIC_PIPE==ENABLE)
00599             unfreeze_user_periodic_pipe();
00600             #endif
00601          }
00602       #endif
00603          break;
00604 
00605      //------------------------------------------------------
00606      //   DEVICE_ERROR state
00607      //
00608      //   - Error state
00609      //   - Do custom action call (probably go to default mode...)
00610      //
00611       case DEVICE_ERROR :    // TODO !!!!
00612       #if (HOST_ERROR_RESTART==ENABLE)
00613          device_state=DEVICE_UNATTACHED;
00614       #endif
00615          Host_device_error_action();
00616          break;
00617 
00618      //------------------------------------------------------
00619      //   DEVICE_SUSPENDED state
00620      //
00621      //   - Host application request to suspend the device activity
00622      //   - State machine comes here thanks to Host_request_suspend()
00623      //
00624       case DEVICE_SUSPENDED :
00625          if(Is_device_supports_remote_wakeup()) // If the connected device supports remote wake up
00626          {
00627            host_set_feature_remote_wakeup();    // Enable this feature...
00628          }
00629          LOG_STR_CODE(log_going_to_suspend);
00630          c = Is_host_sof_interrupt_enabled(); //Save current sof interrupt enable state
00631          Host_disable_sof_interrupt();
00632          Host_ack_sof();
00633          Host_disable_sof();           // Stop start of frame generation, this generates the suspend state
00634          Host_ack_hwup();
00635          Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
00636                                        // (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
00637          Usb_freeze_clock();
00638          Stop_pll();
00639          Host_suspend_action();              // Custom action here! (for example go to power-save mode...)
00640          device_state=DEVICE_WAIT_RESUME;    // wait for device resume event
00641          break;
00642 
00643      //------------------------------------------------------
00644      //   DEVICE_WAIT_RESUME state
00645      //
00646      //   - Wait in this state till the host receives an upstream resume from the device
00647      //   - or the host software request the device to resume
00648      //
00649       case DEVICE_WAIT_RESUME :
00650          if(Is_usb_event(EVT_HOST_HWUP)|| Is_host_request_resume())// Remote wake up has been detected
00651                                                                  // or Local resume request has been received
00652          {
00653             if(Is_host_request_resume())       // Not a remote wakeup, but an host application request
00654             {
00655                Host_disable_hwup_interrupt();  // Wake up interrupt should be disable host is now wake up !
00656               // CAUTION HWUP can be cleared only when USB clock is active
00657                Pll_start_auto();               // First Restart the PLL for USB operation
00658                Wait_pll_ready();               // Get sure pll is lock
00659                Usb_unfreeze_clock();           // Enable clock on USB interface
00660                Host_ack_hwup();                // Clear HWUP interrupt flag
00661             }
00662             Host_enable_sof();
00663             Host_send_resume();                            // Send down stream resume
00664             while (Is_host_down_stream_resume()==FALSE);   // Wait Down stream resume sent
00665             Host_ack_remote_wakeup();        // Ack remote wake-up reception
00666             Host_ack_request_resume();       // Ack software request
00667             Host_ack_down_stream_resume();   // Ack down stream resume sent
00668             Usb_ack_event(EVT_HOST_HWUP);    // Ack software event
00669             if(c) { Host_enable_sof_interrupt(); } // Restore SOF interrupt enable state before suspend
00670             device_state=DEVICE_READY;       // Come back to full operating mode
00671             LOG_STR_CODE(log_usb_resumed);
00672          }
00673          break;
00674 
00675      //------------------------------------------------------
00676      //   DEVICE_DISCONNECTED state
00677      //
00678      //   - Device disconnection has been detected
00679      //   - Run scheduler in this state at least two times to get sure event is detected by all host application tasks
00680      //   - Go to DEVICE_DISCONNECTED_ACK state before DEVICE_UNATTACHED, to get sure scheduler calls all app tasks...
00681      //
00682       case DEVICE_DISCONNECTED :
00683          device_state = DEVICE_DISCONNECTED_ACK;
00684          break;
00685 
00686      //------------------------------------------------------
00687      //   DEVICE_DISCONNECTED_ACK state
00688      //
00689      //   - Device disconnection has been detected and managed bu applicatives tasks
00690      //   - Go to DEVICE_UNATTACHED state
00691      //
00692       case DEVICE_DISCONNECTED_ACK :
00693          device_state = DEVICE_UNATTACHED;
00694          break;
00695 
00696      //------------------------------------------------------
00697      //   default state
00698      //
00699      //   - Default case: ERROR
00700      //   - Goto no device state
00701      //
00702       default :
00703          device_state = DEVICE_UNATTACHED;
00704          break;
00705       }
00706 }
00707 
00708 //___ 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  _________________________
00709 
00722 U8 host_send_data(U8 pipe, U16 nb_data, U8 *buf)
00723 {
00724    U8 c;
00725    U8 status=PIPE_GOOD;
00726    U8 sav_int_sof_enable;
00727    U8 nak_timeout;
00728    U16 cpt_nak;
00729    U8 nb_data_loaded;
00730    U8 cpt_err_timeout=0;
00731 
00732 #if (USER_PERIODIC_PIPE==ENABLE)
00733    freeze_user_periodic_pipe();
00734 #endif
00735    sav_int_sof_enable=Is_host_sof_interrupt_enabled();  // Save state of enable sof interrupt
00736    Host_enable_sof_interrupt();
00737    Host_select_pipe(pipe);
00738    Host_set_token_out();
00739    Host_ack_out_sent();
00740    Host_unfreeze_pipe();
00741    
00742    while (nb_data != 0)         // While there is something to send...
00743    {
00744      // Prepare data to be sent
00745       c = Host_get_pipe_length();
00746       if ( (U16)c > nb_data)
00747       {
00748          nb_data_loaded = (U8)nb_data;
00749          c = nb_data;
00750       }
00751       else
00752       {  nb_data_loaded = c; }
00753       while (c!=0)              // Load Pipe buffer
00754       {
00755          Host_write_byte(*buf++);
00756          c--;
00757       }
00758       private_sof_counter=0;    // Reset the counter in SOF detection sub-routine
00759       cpt_nak=0;
00760       nak_timeout=0;
00761       Host_ack_out_sent();
00762       Host_send_out();
00763       while (!Is_host_out_sent())
00764       {
00765          if (Is_host_emergency_exit())// Async disconnection or role change detected under interrupt
00766          {
00767             status=PIPE_DELAY_TIMEOUT;
00768             Host_reset_pipe(pipe);
00769             goto host_send_data_end;
00770          }
00771          #if (TIMEOUT_DELAY_ENABLE==ENABLE)
00772          if (private_sof_counter>=250)            // Count 250ms (250sof)
00773          {
00774             private_sof_counter=0;
00775             if (nak_timeout++>=TIMEOUT_DELAY) // Inc timeout and check for overflow
00776             {
00777                status=PIPE_DELAY_TIMEOUT;
00778                Host_reset_pipe(pipe);
00779                goto host_send_data_end;
00780             }
00781          }
00782          #endif
00783          if (Is_host_pipe_error()) // Any error ?
00784          {
00785             status = Host_error_status();
00786             Host_ack_all_errors();
00787             if(status == PIPE_TIMEOUT)
00788             {
00789                if(cpt_err_timeout++>100)
00790                {
00791                   goto host_send_data_end;
00792                }
00793                else
00794                {
00795                   c=0;
00796                   while(c<2)           // wait  2 ms
00797                   {
00798                      if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
00799                      if (Is_host_emergency_exit() )  {break;}
00800                   }
00801 
00802                   Host_unfreeze_pipe();
00803                }
00804             }
00805          }
00806          if (Is_host_stall())      // Stall management
00807          {
00808             status =PIPE_STALL;
00809             Host_ack_stall();
00810             goto host_send_data_end;
00811          }
00812          #if (NAK_TIMEOUT_ENABLE==ENABLE)
00813          if(Is_host_nak_received())  //NAK received
00814          {
00815             Host_ack_nak_received();
00816             if (cpt_nak++>NAK_SEND_TIMEOUT)
00817             {
00818                status = PIPE_NAK_TIMEOUT;
00819                Host_reset_pipe(pipe);
00820                goto host_send_data_end;
00821             }
00822          }
00823          #endif
00824       }
00825       // Here OUT sent
00826       nb_data -= nb_data_loaded;
00827       status=PIPE_GOOD;         // Frame correctly sent
00828       Host_ack_out_sent();
00829    }
00830    while(0!=Host_number_of_busy_bank());
00831    
00832 host_send_data_end:
00833    Host_freeze_pipe();
00834   // Restore sof interrupt enable state
00835    if (sav_int_sof_enable==FALSE)   {Host_disable_sof_interrupt();}
00836    #if (USER_PERIODIC_PIPE==ENABLE)
00837    unfreeze_user_periodic_pipe();
00838    #endif   
00839   // And return...
00840    return ((U8)status);
00841 }
00842 
00843 
00844 
00857 U8 host_get_data(U8 pipe, U16 *nb_data, U8 *buf)
00858 {
00859    U8 status=PIPE_GOOD;
00860    U8 sav_int_sof_enable;
00861    U8 nak_timeout;
00862    U16 n,i;
00863    U16 cpt_nak;
00864    
00865    #if (USER_PERIODIC_PIPE==ENABLE)
00866    freeze_user_periodic_pipe();   
00867    #endif
00868    n=*nb_data;
00869    *nb_data=0;
00870    sav_int_sof_enable=Is_host_sof_interrupt_enabled();
00871    Host_enable_sof_interrupt();
00872    Host_select_pipe(pipe);
00873    Host_continuous_in_mode();
00874    Host_set_token_in();
00875    Host_ack_in_received();
00876    while (n)              // While missing data...
00877    {
00878       Host_unfreeze_pipe();
00879       Host_send_in();
00880       private_sof_counter=0; // Reset the counter in SOF detection sub-routine
00881       nak_timeout=0;
00882       cpt_nak=0;
00883       while (!Is_host_in_received())
00884       {
00885          if (Is_host_emergency_exit())   // Async disconnection or role change detected under interrupt
00886          {
00887             status=PIPE_DELAY_TIMEOUT;
00888             Host_reset_pipe(pipe);
00889             goto host_get_data_end;
00890          }
00891          #if (TIMEOUT_DELAY_ENABLE==ENABLE)
00892          if (private_sof_counter>=250)   // Timeout management
00893          {
00894             private_sof_counter=0;       // Done in host SOF interrupt
00895             if (nak_timeout++>=TIMEOUT_DELAY)// Check for local timeout
00896             {
00897                status=PIPE_DELAY_TIMEOUT;
00898                Host_reset_pipe(pipe);
00899                goto host_get_data_end;
00900             }
00901          }
00902          #endif
00903          if(Is_host_pipe_error())        // Error management
00904          {
00905             status = Host_error_status();
00906             Host_ack_all_errors();
00907             goto host_get_data_end;
00908          }
00909          if(Is_host_stall())             // STALL management
00910          {
00911             if( Is_host_in_received() )
00912               break;
00913             status =PIPE_STALL;
00914             Host_reset_pipe(pipe);
00915             Host_ack_stall();
00916             goto host_get_data_end;
00917          }
00918          #if (NAK_TIMEOUT_ENABLE==ENABLE)
00919          if(Is_host_nak_received())  //NAK received
00920          {
00921             Host_ack_nak_received();
00922             if (cpt_nak++>NAK_RECEIVE_TIMEOUT)
00923             {
00924                status = PIPE_NAK_TIMEOUT;
00925                Host_reset_pipe(pipe);
00926                goto host_get_data_end;
00927             }
00928          }
00929          #endif
00930       }
00931       status=PIPE_GOOD;
00932       Host_freeze_pipe();
00933       if (Host_byte_counter()<=n)
00934       {
00935          if ((Host_byte_counter() < n)&&(Host_byte_counter()<Host_get_pipe_length()))
00936          { n=0;}
00937          else
00938          { n-=Host_byte_counter();}
00939          (*nb_data)+=Host_byte_counter();  // Update nb of byte received
00940          if( NULL != buf )
00941          {
00942            for (i=Host_byte_counter();i;i--)
00943            { *buf=Host_read_byte(); buf++;}
00944          }
00945       }
00946       else  // more bytes received than expected
00947       {     // TODO error code management
00948          *nb_data+=n;
00949          if( NULL != buf )
00950          {
00951             for (i=n;i;i--)                  // Byte number limited to the initial request (limit tab over pb)
00952             {  *buf=Host_read_byte(); buf++; }
00953          }
00954          n=0;
00955       }
00956       Host_ack_in_received();
00957    }
00958    Host_freeze_pipe();
00959 host_get_data_end:
00960    if (sav_int_sof_enable==FALSE)
00961    {
00962       Host_disable_sof_interrupt();
00963    }
00964    #if (USER_PERIODIC_PIPE==ENABLE)
00965    unfreeze_user_periodic_pipe();
00966    #endif   
00967    return ((U8)status);
00968 }
00969 
00970 
00971 //___ 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  _________________________
00972 
00973 #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
00974 
00975 void reset_it_pipe_str(void)
00976 {
00977    U8 i;
00978    for(i=0;i<MAX_EP_NB;i++)
00979    {
00980       it_pipe_str[i].enable=DISABLE;
00981       it_pipe_str[i].timeout=0;
00982    }
00983 }
00984 
00985 U8 is_any_interrupt_pipe_active(void)
00986 {
00987    U8 i;
00988    for(i=0;i<MAX_EP_NB;i++)
00989    {
00990       if(it_pipe_str[i].enable==ENABLE) return TRUE;
00991    }
00992    return FALSE;
00993 }
00994 
01008 U8 host_get_data_interrupt(U8 pipe, U16 nb_data, U8 *buf,void(*handle)(U8 status, U16 nb_byte))
01009 {
01010    Host_select_pipe(pipe);
01011    if(it_pipe_str[pipe].enable==ENABLE)
01012    {
01013       return HOST_FALSE;
01014    }
01015    else
01016    {
01017       if(is_any_interrupt_pipe_active()==FALSE)
01018       {
01019          g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
01020          Host_enable_sof_interrupt();
01021       }
01022       it_pipe_str[pipe].enable=ENABLE;
01023       it_pipe_str[pipe].nb_byte_to_process=nb_data;
01024       it_pipe_str[pipe].nb_byte_processed=0;
01025       it_pipe_str[pipe].ptr_buf=buf;
01026       it_pipe_str[pipe].handle=handle;
01027       it_pipe_str[pipe].timeout=0;
01028       it_pipe_str[pipe].nak_timeout=NAK_RECEIVE_TIMEOUT;
01029 
01030       private_sof_counter=0;           // Reset the counter in SOF detection sub-routine
01031       Host_reset_pipe(pipe);
01032       Host_enable_stall_interrupt();
01033       #if (NAK_TIMEOUT_ENABLE==ENABLE)
01034       Host_enable_nak_interrupt();
01035       #endif
01036       Host_enable_error_interrupt();
01037       Host_enable_receive_interrupt();
01038       Host_ack_stall();
01039       Host_ack_nak_received();
01040 
01041       Host_continuous_in_mode();
01042       Host_set_token_in();
01043       Host_ack_in_received();
01044       Host_unfreeze_pipe();
01045       return HOST_TRUE;
01046    }
01047 }
01048 
01060 U8 host_send_data_interrupt(U8 pipe, U16 nb_data, U8 *buf, void(*handle)(U8 status, U16 nb_byte))
01061 {
01062    U8 i;
01063    U8 *ptr_buf=buf;
01064 
01065    Host_select_pipe(pipe);
01066    if(it_pipe_str[pipe].enable==ENABLE)
01067    {
01068       return HOST_FALSE;
01069    }
01070    else
01071    {
01072       if(is_any_interrupt_pipe_active()==FALSE)
01073       {
01074          g_sav_int_sof_enable=Is_host_sof_interrupt_enabled();
01075          Host_enable_sof_interrupt();
01076       }
01077       it_pipe_str[pipe].enable=ENABLE;
01078       it_pipe_str[pipe].nb_byte_to_process=nb_data;
01079       it_pipe_str[pipe].nb_byte_processed=0;
01080       it_pipe_str[pipe].ptr_buf=buf;
01081       it_pipe_str[pipe].handle=handle;
01082       it_pipe_str[pipe].timeout=0;
01083       it_pipe_str[pipe].nak_timeout=NAK_SEND_TIMEOUT;
01084       it_pipe_str[pipe].nb_byte_on_going=0;
01085 
01086       Host_reset_pipe(pipe);
01087       Host_unfreeze_pipe();
01088       // Prepare data to be sent
01089       i = Host_get_pipe_length();
01090       if ( i > nb_data)                // Pipe size> remaining data
01091       {
01092          i = nb_data;
01093          nb_data = 0;
01094       }
01095       else                             // Pipe size < remaining data
01096       {
01097          nb_data -= i;
01098       }
01099       it_pipe_str[pipe].nb_byte_on_going+=i;   // Update nb data processed
01100       while (i!=0)                    // Load Pipe buffer
01101       {  Host_write_byte(*ptr_buf++); i--;
01102       }
01103       private_sof_counter=0;          // Reset the counter in SOF detection sub-routine
01104       it_pipe_str[pipe].timeout=0;    // Refresh timeout counter
01105       Host_ack_out_sent();
01106       Host_ack_stall();
01107       Host_ack_nak_received();
01108 
01109       Host_enable_stall_interrupt();
01110       Host_enable_error_interrupt();
01111       #if (NAK_TIMEOUT_ENABLE==ENABLE)
01112       Host_enable_nak_interrupt();
01113       #endif
01114       Host_enable_transmit_interrupt();
01115       Host_send_out();                // Send the USB frame
01116       return HOST_TRUE;
01117    }
01118 }
01119 
01125 #ifdef __GNUC__
01126  ISR(USB_COM_vect)
01127 #else
01128 #pragma vector = USB_Endpoint_Pipe_vect
01129 __interrupt void usb_pipe_interrupt()
01130 #endif
01131 {
01132    U8 pipe_nb;
01133    U8 *ptr_buf;
01134    void  (*fct_handle)(U8 status,U16 nb_byte);
01135    U16 n;
01136    U8 i;
01137    U8 do_call_back=FALSE;
01138 
01139    pipe_nb_save = Host_get_selected_pipe();       // Important! Save here working pipe number
01140    pipe_nb=usb_get_nb_pipe_interrupt();  // work with the correct pipe number that generates the interrupt
01141    Host_select_pipe(pipe_nb);                        // Select this pipe
01142    fct_handle=*(it_pipe_str[pipe_nb].handle);
01143 
01144    // Now try to detect what event generate an interrupt...
01145 
01146    if (Is_host_pipe_error())             // Any error ?
01147    {
01148       it_pipe_str[pipe_nb].status = Host_error_status();
01149       it_pipe_str[pipe_nb].enable=DISABLE;
01150       Host_stop_pipe_interrupt(pipe_nb);
01151       Host_ack_all_errors();
01152       do_call_back=TRUE;
01153       goto usb_pipe_interrupt_end;
01154    }
01155 
01156    if (Is_host_stall())                  // Stall handshake received ?
01157    {
01158       it_pipe_str[pipe_nb].status=PIPE_STALL;
01159       it_pipe_str[pipe_nb].enable=DISABLE;
01160       Host_stop_pipe_interrupt(pipe_nb);
01161       do_call_back=TRUE;
01162       goto usb_pipe_interrupt_end;
01163    }
01164 
01165    #if (NAK_TIMEOUT_ENABLE==ENABLE)
01166    if (Is_host_nak_received())           // NAK ?
01167    {
01168       Host_ack_nak_received();
01169       // check if number of NAK timeout error occurs (not for interrupt type pipe)
01170       if((--it_pipe_str[pipe_nb].nak_timeout==0) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
01171       {
01172          it_pipe_str[pipe_nb].status=PIPE_NAK_TIMEOUT;
01173          it_pipe_str[pipe_nb].enable=DISABLE;
01174          Host_stop_pipe_interrupt(pipe_nb);
01175          do_call_back=TRUE;
01176          goto usb_pipe_interrupt_end;
01177       }
01178    }
01179    #endif
01180 
01181    if (Is_host_in_received())            // Pipe IN reception ?
01182    {
01183       ptr_buf=it_pipe_str[pipe_nb].ptr_buf+it_pipe_str[pipe_nb].nb_byte_processed;       // Build pointer to data buffer
01184       n=it_pipe_str[pipe_nb].nb_byte_to_process-it_pipe_str[pipe_nb].nb_byte_processed;  // Remaining data bytes
01185       Host_freeze_pipe();
01186       if (Host_byte_counter()<=n)
01187       {
01188          if ((Host_byte_counter() < n)&&(Host_byte_counter()<Host_get_pipe_length())) //Received less than remaining, but less than pipe capacity
01189                                                                                       //TODO: error code
01190          {
01191             n=0;
01192          }
01193          else
01194          {
01195             n-=Host_byte_counter();
01196          }
01197          it_pipe_str[pipe_nb].nb_byte_processed+=Host_byte_counter();  // Update nb of byte received
01198          for (i=Host_byte_counter();i;i--)
01199          { *ptr_buf=Host_read_byte(); ptr_buf++;}
01200       }
01201       else  // more bytes received than expected
01202       {     // TODO error code management
01203          it_pipe_str[pipe_nb].nb_byte_processed+=n;
01204          for (i=n;i;i--)                  // Byte number limited to the initial request (limit tab over pb)
01205          { *ptr_buf=Host_read_byte(); ptr_buf++;}
01206          n=0;
01207       }
01208       Host_ack_in_received();
01209       if(n>0) //still something to process
01210       {
01211          Host_unfreeze_pipe();            // Request another IN transfer
01212          Host_send_in();
01213          private_sof_counter=0;           // Reset the counter in SOF detection sub-routine
01214          it_pipe_str[pipe_nb].timeout=0;  // Reset timeout
01215          it_pipe_str[pipe_nb].nak_timeout=NAK_RECEIVE_TIMEOUT;
01216 
01217       }
01218       else //end of transfer
01219       {
01220          it_pipe_str[pipe_nb].enable=DISABLE;
01221          it_pipe_str[pipe_nb].status=PIPE_GOOD;
01222          Host_stop_pipe_interrupt(pipe_nb);
01223          do_call_back=TRUE;
01224       }
01225    }
01226 
01227    if(Is_host_out_sent())                  // Pipe OUT sent ?
01228    {
01229       Host_ack_out_sent();
01230       it_pipe_str[pipe_nb].nb_byte_processed+=it_pipe_str[pipe_nb].nb_byte_on_going;
01231       it_pipe_str[pipe_nb].nb_byte_on_going=0;
01232       ptr_buf=it_pipe_str[pipe_nb].ptr_buf+it_pipe_str[pipe_nb].nb_byte_processed;       // Build pointer to data buffer
01233       n=it_pipe_str[pipe_nb].nb_byte_to_process-it_pipe_str[pipe_nb].nb_byte_processed;  // Remaining data bytes
01234       if(n>0)   // Still data to process...
01235       {
01236          Host_unfreeze_pipe();
01237         // Prepare data to be sent
01238          i = Host_get_pipe_length();
01239          if ( i > n)     // Pipe size> remaining data
01240          {
01241             i = n;
01242             n = 0;
01243          }
01244          else                // Pipe size < remaining data
01245          {  n -= i; }
01246          it_pipe_str[pipe_nb].nb_byte_on_going+=i;   // Update nb data processed
01247          while (i!=0)                     // Load Pipe buffer
01248          {
01249             Host_write_byte(*ptr_buf++); i--;
01250          }
01251          private_sof_counter=0;           // Reset the counter in SOF detection sub-routine
01252          it_pipe_str[pipe_nb].timeout=0;  // Refresh timeout counter
01253          it_pipe_str[pipe_nb].nak_timeout=NAK_SEND_TIMEOUT;
01254          Host_send_out();                 // Send the USB frame
01255       }
01256       else                                //n==0 Transfer is finished
01257       {
01258          it_pipe_str[pipe_nb].enable=DISABLE;    // Tranfer end
01259          it_pipe_str[pipe_nb].status=PIPE_GOOD;  // Status OK
01260          Host_stop_pipe_interrupt(pipe_nb);
01261          do_call_back=TRUE;
01262       }
01263    }
01264 
01265 usb_pipe_interrupt_end:
01266    Host_select_pipe(pipe_nb_save);   // Restore pipe number !!!!
01267    if (is_any_interrupt_pipe_active()==FALSE)    // If no more transfer is armed
01268    {
01269       if (g_sav_int_sof_enable==FALSE)
01270       {
01271          Host_disable_sof_interrupt();
01272       }
01273    }
01274    if(do_call_back)      // Any callback functions to perform ?
01275    {
01276       fct_handle(it_pipe_str[pipe_nb].status,it_pipe_str[pipe_nb].nb_byte_processed);
01277    }
01278 }
01279 #endif
01280 
01281 
01282 #endif // USB_HOST_FEATURE ENABLE
01283 

Generated on Fri May 15 15:41:36 2009 for ATMEL by  doxygen 1.5.3