ATMEL: usb_host_task.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# 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