Ejemplo n.º 1
0
//!
//! @brief This function initializes the USB device controller
//!
//! This function enables the USB controller and init the USB interrupts.
//! The aim is to allow the USB connection detection in order to send
//! the appropriate USB event to the operating mode manager.
//! Start device function is executed once VBUS connection has been detected
//! either by the VBUS change interrupt either by the VBUS high level
//!
//! @param none
//!
//! @return none
//!
void usb_start_device (void)
{
   Pll_start_auto();
   Wait_pll_ready();
   Usb_unfreeze_clock();
   usb_init_device();         // configure the USB controller EP0
   Usb_attach();
   Usb_enable_suspend_interrupt();
   Usb_enable_reset_interrupt();
#if (USB_OTG_FEATURE == ENABLED)
   Usb_enable_id_interrupt();
#endif
}
Ejemplo n.º 2
0
__interrupt void usb_general_interrupt()
#endif
{
   #if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
   U8 i;
   U8 save_pipe_nb;
   #endif
// ---------- DEVICE events management -----------------------------------
#if (USB_DEVICE_FEATURE == ENABLED)

   // - Device start of frame received
   if (Is_usb_sof() && Is_sof_interrupt_enabled())
   {
      Usb_ack_sof();
      Usb_sof_action();
   }
#ifdef WA_USB_SUSPEND_PERTUBATION
  // - Device Suspend event (no more USB activity detected)
   if (Is_usb_suspend() && Is_suspend_interrupt_enabled())
   {
      usb_suspended=TRUE;
      Usb_ack_wake_up();                 // clear wake up to detect next event
      Usb_send_event(EVT_USB_SUSPEND);
      Usb_ack_suspend();
      Usb_enable_wake_up_interrupt();
      Usb_disable_resume_interrupt();
      Usb_freeze_clock();
      Stop_pll();
      Usb_suspend_action();
   }
  // - Wake up event (USB activity detected): Used to resume
   if (Is_usb_wake_up() && Is_wake_up_interrupt_enabled())
   {
      if(Is_pll_ready()==FALSE)
      {
         Pll_start_auto();
         Wait_pll_ready();
      }
      Usb_unfreeze_clock();
      Usb_ack_wake_up();
      if(usb_suspended)
      {
         Usb_enable_resume_interrupt();
         Usb_enable_reset_interrupt();
         while(Is_usb_wake_up())
         {
            Usb_ack_wake_up();
         }
         usb_delay_ms(2);
         if(Is_usb_sof() || Is_usb_resume() || Is_usb_reset() )
         {
            Usb_disable_wake_up_interrupt();
            Usb_wake_up_action();
            Usb_send_event(EVT_USB_WAKE_UP);
            Usb_enable_suspend_interrupt();
            Usb_enable_resume_interrupt();
            Usb_enable_reset_interrupt();
            
         }
         else // Workarround to make the USB enter power down mode again (spurious transcient detected on the USB lines)
         {
            Usb_ack_wake_up();                 // clear wake up to detect next event
            Usb_send_event(EVT_USB_SUSPEND);
            Usb_enable_wake_up_interrupt();
            Usb_disable_resume_interrupt();
            Usb_freeze_clock();
            Stop_pll();
            Usb_suspend_action();
         }
      }
   }
  // - Resume state bus detection
   if (Is_usb_resume() && Is_resume_interrupt_enabled())
   {
      usb_suspended = FALSE;
      Usb_disable_wake_up_interrupt();
      Usb_ack_resume();
      Usb_disable_resume_interrupt();
      Usb_resume_action();
      Usb_send_event(EVT_USB_RESUME);
   }
#else
  // - Device Suspend event (no more USB activity detected)
   if (Is_usb_suspend() && Is_suspend_interrupt_enabled())
   {
      // Remote wake-up handler
      if ((remote_wakeup_feature == ENABLED) && (usb_configuration_nb != 0))
      {
        Usb_disable_suspend_interrupt();
        Usb_ack_wake_up();
        Usb_enable_wake_up_interrupt();
        Stop_pll();
        Usb_freeze_clock();
        Usb_suspend_action();
        
        // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up
        // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume
        // So the SUSPE enable bit must be cleared to avoid redundant interrupt
        // ****************
        // Please note also that is Vbus is lost during an upstream resume (Host disconnection),
        // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent)
        // remains set after the event, so that a good way to handle this feature is :
        //            Usb_unfreeze_clock();
        //            Usb_initiate_remote_wake_up();
        //            while (Is_usb_pending_remote_wake_up())
        //            {
        //              if (Is_usb_vbus_low())
        //              {
        //                // Emergency action (reset macro, etc.) if Vbus lost during resuming
        //                break;
        //              }
        //            }
        //            Usb_ack_remote_wake_up_start();
        // ****************
      }
      else
      {
        // No remote wake-up supported
         Usb_ack_wake_up();                 // clear wake up to detect next event
         Usb_send_event(EVT_USB_SUSPEND);
         Usb_ack_suspend();  // must be executed last (after Usb_suspend_action()) to allow upstream resume
         Usb_enable_wake_up_interrupt();
         Usb_freeze_clock();
         Stop_pll();
         Usb_suspend_action();
      }
   }
  // - Wake up event (USB activity detected): Used to resume
   if (Is_usb_wake_up() && Is_wake_up_interrupt_enabled())
   {
      if(Is_pll_ready()==FALSE)
      {
         Pll_start_auto();
         Wait_pll_ready();
      }
      Usb_unfreeze_clock();
      Usb_ack_wake_up();
      Usb_disable_wake_up_interrupt();
      Usb_wake_up_action();
      Usb_send_event(EVT_USB_WAKE_UP);
      Usb_enable_suspend_interrupt();
   }
  // - Resume state bus detection
   if (Is_usb_resume() && Is_resume_interrupt_enabled())
   {
      Usb_disable_wake_up_interrupt();
      Usb_ack_resume();
      Usb_disable_resume_interrupt();
      Usb_resume_action();
      Usb_send_event(EVT_USB_RESUME);
   }
#endif
  // - USB bus reset detection
   if (Is_usb_reset()&& Is_reset_interrupt_enabled())
   {
      Usb_ack_reset();
      usb_init_device();
      Usb_reset_action();
      Usb_send_event(EVT_USB_RESET);
   }
#endif// End DEVICE FEATURE MODE

// ---------- HOST events management -----------------------------------
#if (USB_HOST_FEATURE == ENABLED && USB_DEVICE_FEATURE == ENABLED)
  // - ID pin change detection
   if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled())
   {
      if(Is_usb_id_device())
      { g_usb_mode=USB_MODE_DEVICE;}
      else
      { g_usb_mode=USB_MODE_HOST;}
      Usb_ack_id_transition();
      if( g_usb_mode != g_old_usb_mode) // Basic Debounce
      {
         if(Is_usb_id_device()) // Going to device mode
         {
            Usb_send_event(EVT_USB_DEVICE_FUNCTION);
         }
         else                   // Going to host mode
         {
            Usb_send_event(EVT_USB_HOST_FUNCTION);
         }
         Usb_id_transition_action();
         LOG_STR_CODE(log_id_change);
         #if ( ID_PIN_CHANGE_GENERATE_RESET == ENABLE)
         // Hot ID transition generates wdt reset
         wdtdrv_enable(WDTO_16MS);
         while(1);
         #endif
      }
   }
#endif
#if (USB_HOST_FEATURE == ENABLED)
  // - The device has been disconnected
   if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled())
   {
      host_disable_all_pipe();
      Host_ack_device_disconnection();
      device_state=DEVICE_DISCONNECTED;
      Usb_send_event(EVT_HOST_DISCONNECTION);
      init_usb_tree();      
      LOG_STR_CODE(log_device_disconnect);
      Host_device_disconnection_action();
   }
  // - Device connection
   if(Is_device_connection() && Is_host_device_connection_interrupt_enabled())
   {
      Host_ack_device_connection();
      host_disable_all_pipe();
      Host_device_connection_action();
   }
  // - Host Start of frame has been sent
   if (Is_host_sof() && Is_host_sof_interrupt_enabled())
   {
      Host_ack_sof();
      Usb_send_event(EVT_HOST_SOF);
      private_sof_counter++;
#if (USB_HUB_SUPPORT==ENABLE)
      hub_interrupt_sof++;
#endif

      // delay timeout management for interrupt tranfer mode in host mode
      #if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
      if (private_sof_counter>=250)   // Count 1/4 sec
      {
         private_sof_counter=0;
         for(i=0;i<MAX_EP_NB;i++)
         {
            if(it_pipe_str[i].enable==ENABLE)
            {
               save_pipe_nb=Host_get_selected_pipe();
               Host_select_pipe(i);
               if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT))
               {
                  it_pipe_str[i].enable=DISABLE;
                  it_pipe_str[i].status=PIPE_DELAY_TIMEOUT;
                  Host_stop_pipe_interrupt(i);
                  if (is_any_interrupt_pipe_active()==FALSE)    // If no more transfer is armed
                  {
                     if (g_sav_int_sof_enable==FALSE)
                     {
                        Host_disable_sof_interrupt();
                     }
                  }
                  it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed);
               }
               Host_select_pipe(save_pipe_nb);
            }
         }
      }
      #endif  // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
      Host_sof_action();
   }
  // - Host Wake-up has been received
   if (Is_host_hwup() && Is_host_hwup_interrupt_enabled())
   {
      Host_disable_hwup_interrupt();  // Wake up interrupt should be disable host is now wake up !
      // CAUTION HWUP can be cleared only when USB clock is active (not frozen)!
      Pll_start_auto();               // First Restart the PLL for USB operation
      Wait_pll_ready();               // Get sure pll is lock
      Usb_unfreeze_clock();           // Enable clock on USB interface
      Host_ack_hwup();                // Clear HWUP interrupt flag
      Usb_send_event(EVT_HOST_HWUP);  // Send software event
      Host_hwup_action();             // Map custom action
   }
#endif // End HOST FEATURE MODE
}
Ejemplo n.º 3
0
//! @brief Entry point of the USB device mamagement
//!
//! This function is the entry point of the USB management. Each USB
//! event is checked here in order to launch the appropriate action.
//! If a Setup request occurs on the Default Control Endpoint,
//! the usb_process_request() function is call in the usb_standard_request.c file
//!
//! @param none
//!
//! @return none
void usb_device_task(void)
{
  
#if (USB_OTG_FEATURE == ENABLED)
   // Check if a reset has been received
   if(Is_usb_event(EVT_USB_RESET))
   {
      Usb_ack_event(EVT_USB_RESET);
      Usb_reset_endpoint(0);
      usb_configuration_nb=0;
      otg_b_device_state = B_IDLE;
      Clear_otg_features_from_host();
   }

   // When OTG mode enabled, B-Device is managed thanks to its state machine
   switch (otg_b_device_state)
   {
   //------------------------------------------------------
   //   B_IDLE state
   //
   //   - waits for Vbus to rise
   //   - initiate SRP if asked by user
   //
   case B_IDLE:
     if (Is_usb_vbus_high())
     {
       // Vbus rise
       usb_connected = TRUE;
       remote_wakeup_feature = DISABLED;
       usb_start_device();
       Usb_vbus_on_action();
       Usb_attach();
       otg_b_device_state = B_PERIPHERAL;
       Ack_user_request_srp();
       Clear_otg_features_from_host();
       remote_wakeup_feature = DISABLED;
       End_session_with_srp();
       if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE))
       {
         Ack_srp_sent_and_answer();
         Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC);
       }
       Usb_enable_sof_interrupt();
       
     }
     else
     {
       if (Is_user_requested_srp() && Is_usb_id_device())
       {
         // User has requested a SRP
         Ack_user_request_srp();
         if (!Is_srp_sent_and_waiting_answer())
         {
           Pll_start_auto();  // reinit device mode
           Wait_pll_ready();
           Usb_disable();
           Usb_enable_uid_pin();
           Usb_enable();
           Usb_unfreeze_clock();
           Usb_select_device();
           Usb_attach();
           otg_b_device_state = B_SRP_INIT;
           Usb_device_initiate_srp();       // hardware waits for initial condition (SE0, Session End level)
           sof_seen_in_session = FALSE;
         }
       }
       if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow()))
       {
         // SRP failed because A-Device did not respond
         End_session_with_srp();
         Ack_srp_sent_and_answer();
         Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC);
       }
     }
     break;

     
   //------------------------------------------------------
   //   B_SRP_INIT
   //
   //   - a SRP has been initiated
   //   - B-Device waits it is finished to initialize variables
   //
   case B_SRP_INIT:
     if (!Is_usb_device_initiating_srp())
     {
       otg_b_device_state = B_IDLE;   // SRP initiated, return to Idle state (wait for Vbus to rise)
       Srp_sent_and_waiting_answer();
       Init_tb_srp_counter();
       Start_session_with_srp();
       Otg_print_new_event_message(OTGMSG_SRP_STARTED,TB_SRP_FAIL_MIN);
     }
     break;

     
   //------------------------------------------------------
     //   B_PERIPHERAL : the main state of OTG Peripheral
   //
   //   - all events are interrupt-handled
   //   - but they are saved and this function can execute alternate actions
   //   - also handle user requests (disconnect)
   //
   // ======================================================================================
   case B_PERIPHERAL:
     if (Is_otg_event(EVT_OTG_DEVICE_CONNECTED))
     {
       Otg_ack_event(EVT_OTG_DEVICE_CONNECTED); // set on a SetConfiguration descriptor reception
       Otg_print_new_event_message(OTGMSG_CONNECTED_TO_A,OTG_TEMPO_4SEC);
     }
     if (Is_usb_event(EVT_USB_SUSPEND)) // SUSPEND state
     {
        // Suspend and HNP operations are handled in the interrupt functions
     }
     if (Is_srp_sent_and_waiting_answer() && (sof_seen_in_session == TRUE))
     {
       Ack_srp_sent_and_answer();
       Otg_print_new_failure_message(OTGMSG_A_RESPONDED,OTG_TEMPO_2SEC);
     }
     if ((Is_srp_sent_and_waiting_answer()) && (Is_tb_srp_counter_overflow())) 
     {
       // SRP failed because A-Device did not respond
       End_session_with_srp();
       Ack_srp_sent_and_answer();
       Otg_print_new_failure_message(OTGMSG_SRP_A_NO_RESP,OTG_TEMPO_3SEC);
     }
     
     if (Is_usb_event(EVT_USB_RESUME) && !Is_usb_pending_remote_wake_up())  // RESUME signal detected
     {
       Usb_ack_event(EVT_USB_RESUME);
       Usb_ack_event(EVT_USB_SUSPEND);
       Usb_ack_remote_wake_up_start();
     }
     if (Is_usb_event(EVT_USB_UNPOWERED))
     {
       Usb_ack_event(EVT_USB_UNPOWERED);
       Clear_all_user_request();
       otg_b_device_state = B_IDLE;
     }
     if(Is_usb_event(EVT_USB_RESET))
     {
       Usb_ack_event(EVT_USB_RESET);
       Usb_reset_endpoint(0);
       usb_configuration_nb=0;
       Clear_otg_features_from_host();
     }
     if (Is_otg_event(EVT_OTG_HNP_ERROR))
     {
       Otg_ack_event(EVT_OTG_HNP_ERROR);
       Otg_print_new_failure_message(OTGMSG_DEVICE_NO_RESP,OTG_TEMPO_4SEC);
       PORTC &= ~0x10;
     }
     if (Is_user_requested_disc())
     {
       Ack_user_request_disc();
       if (Is_usb_id_device())
       {
         Usb_detach();
         Usb_freeze_clock();
         while (Is_usb_vbus_high());  // wait for Vbus to be under Va_vbus_valid
         otg_b_device_state = B_IDLE;
         usb_configuration_nb = 0;
         usb_connected = FALSE;
         Clear_all_user_request();
       }
     }
     break;

   //------------------------------------------------------
   //   B_HOST
   //
   //   - state entered after an HNP success
   //   - handle user requests (disconnection, suspend, hnp)
   //   - call the "host_task()" for Host level handlers
   //
   // ======================================================================================
   case B_HOST:
     if (Is_otg_event(EVT_OTG_DEV_UNSUPPORTED))
     {
       Otg_ack_event(EVT_OTG_DEV_UNSUPPORTED);
       Clear_all_user_request();
       otg_b_device_state = B_IDLE;
       device_state = DEVICE_UNATTACHED;
     }
     if (Is_user_requested_disc() || Is_user_requested_suspend() || Is_user_requested_hnp())
     {
       Ack_user_request_disc();   // suspend and hnp requests cleared in B_END_HNP_SUSPEND stage
       Host_disable_sof();        // go into suspend mode
       Usb_host_reject_hnp();
       otg_b_device_state = B_END_HNP_SUSPEND;
       Usb_ack_suspend();
       Usb_enable_suspend_interrupt();
     }
     if (Is_usb_event(EVT_USB_UNPOWERED))
     {
       Usb_ack_event(EVT_USB_UNPOWERED);
       Usb_freeze_clock();
       otg_b_device_state = B_IDLE;
       device_state = DEVICE_UNATTACHED;
     }
     usb_host_task();   // call the host task
     break;

   //------------------------------------------------------
   //   B_END_HNP_SUSPEND
   //
   //   - device enters this state after being B_HOST, on a user request to stop bus activity (suspend, disconnect or hnp request)
   //   - macro is reset to peripheral mode
   //
   // ======================================================================================
   case B_END_HNP_SUSPEND:
     if (Is_usb_event(EVT_USB_SUSPEND))
     {
       Usb_ack_event(EVT_USB_SUSPEND);
       Usb_device_stop_hnp();
       Usb_select_device();
       device_state = DEVICE_UNATTACHED;
       if (Is_user_requested_hnp() || Is_user_requested_suspend())
       {
         otg_b_device_state = B_PERIPHERAL;
         Ack_user_request_suspend();
         Ack_user_request_hnp();
       }
       else
       {
         otg_b_device_state = B_IDLE;
         Usb_detach();
         Usb_freeze_clock();
       }
     }
     break;


   default:
     otg_b_device_state = B_IDLE;
     Clear_all_user_request();
     device_state = DEVICE_UNATTACHED;
     break;
   }


#else
   
   // Non-OTG exclusives Device operations

   // VBUS state detection
   if (Is_usb_vbus_high()&& (usb_connected==FALSE))
   {
      usb_connected = TRUE;
      remote_wakeup_feature = DISABLED;
      Usb_vbus_on_action();
      Usb_send_event(EVT_USB_POWERED);
      usb_start_device();
   }
   if (Is_usb_vbus_low()&& (usb_connected==TRUE))
   {
      usb_connected = FALSE;
      usb_configuration_nb = 0;
      Usb_send_event(EVT_USB_UNPOWERED);
      Usb_detach();
      Usb_freeze_clock();
      Usb_vbus_off_action();
   }

   if(Is_usb_event(EVT_USB_RESET))
   {
      Usb_ack_event(EVT_USB_RESET);
      Usb_reset_endpoint(0);
      usb_configuration_nb=0;
   }

#endif

   
   
   // =======================================
   // Common Standard Device Control Requests
   // =======================================
   //   - device enumeration process
   //   - device control commands and features
   Usb_select_endpoint(EP_CONTROL);
   if (Is_usb_receive_setup())
   {
      usb_process_request();
   }
}
Ejemplo n.º 4
0
//------------------------------------------------------------------------------
/// USB interrupt subroutine
///
/// This function is called each time a USB interrupt occurs.
/// The following USB DEVICE events are taken in charge:
/// - VBus On / Off
/// - Start Of Frame
/// - Suspend
/// - Wake-Up
/// - Resume
/// - Reset
/// - Start of frame
///
/// The following USB HOST events are taken in charge:
/// - Device connection
/// - Device Disconnection
/// - Start Of Frame
/// - ID pin change
/// - SOF (or Keep alive in low speed) sent
/// - Wake up on USB line detected
///
/// The following USB HOST events are taken in charge:
/// - HNP success (Role Exchange)
/// - HNP failure (HNP Error)
///
/// For each event, the user can launch an action by completing
/// the associate define (See conf_usb.h file to add action upon events)
///
/// Note: Only interrupts events that are enabled are processed
//------------------------------------------------------------------------------
void usb_general_interrupt(void)
{
    //TRACE_DEBUG("usb_general_interrupt\n\r");

    // ---------- DEVICE events management -----------------------------------
    // -----------------------------------------------------------------------

    //- VBUS state detection
    // -----------------------------------------------------------------------
    /// Arbitrer
    // -----------------------------------------------------------------------
    if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled() 
        && Is_usb_id_device()) {
        Usb_ack_vbus_transition();

        if (Is_usb_vbus_high()) {
            usb_connected = TRUE;
            Usb_vbus_on_action();
            Usb_send_event(EVT_USB_POWERED);
            //jcb    Usb_enable_reset_interrupt();
            //usb_start_device();
            USBD_Connect();//Usb_attach();
        }
        else {
            TRACE_DEBUG("VBUS low\n\r");
            USBD_Disconnect();
            Usb_device_stop_hnp();
            TRACE_DEBUG("Usb_select_device4\n\r");
            Usb_select_device();
            Clear_all_user_request();
            Usb_vbus_off_action();
            usb_connected = FALSE;
            usb_configuration_nb = 0;
            Usb_send_event(EVT_USB_UNPOWERED);
        }

    }

    // -----------------------------------------------------------------------
    /// Device
    // -----------------------------------------------------------------------
    // - Device start of frame received
    if (Is_usb_sof() && Is_sof_interrupt_enabled()) {
        //  TRACE_DEBUG_WP("F");   // device
        Usb_ack_sof();
        Usb_sof_action();
        //sof_seen_in_session = TRUE;
        otg_last_sof_received = UDFNUML;  // store last frame number received
    }

    // -----------------------------------------------------------------------
    /// Device
    // -----------------------------------------------------------------------
    // - Device Suspend event (no more USB activity detected)
    if (Is_usb_suspend()) { //&& Is_suspend_interrupt_enabled()) {
        //TRACE_DEBUG_WP("D\n\r");
        // 1st : B-PERIPH mode ?
        if (Is_usb_id_device()) {
            // HNP Handler
            TRACE_DEBUG("HNP Handler\n\r");
            //TRACE_DEBUG("device_state = %d\n\r", device_state);
            //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
            if (Is_host_requested_hnp() // "b_hnp_enable" feature received
            && (Is_session_started_with_srp() || Is_user_requested_hnp() )) {
                if (otg_device_nb_hnp_retry == 0) {
                    otg_features_supported &= ~USBFeatureRequest_OTG_B_HNP_ENABLE;
                }
                else {
                    Ack_user_request_hnp();
                    Usb_ack_hnp_error_interrupt();
                    Usb_ack_role_exchange_interrupt();
                    Usb_enable_role_exchange_interrupt();
                    Usb_enable_hnp_error_interrupt();
                    Usb_device_initiate_hnp();
                    otg_device_nb_hnp_retry--;
                }
            }
            else
            {
                // Remote wake-up handler
                //TRACE_DEBUG("Remote wake-up handler\n\r");
                //TRACE_DEBUG("device_state = %d\n\r", device_state);
                //TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
                if ((remote_wakeup_feature == ENABLE) && (usb_configuration_nb != 0))
                {
                    //TRACE_DEBUG("enabled\n\r");
                    // After that user can execute "Usb_initiate_remote_wake_up()" to initiate a remote wake-up
                    // Note that the suspend interrupt flag SUSPI must still be set to enable upstream resume
                    // So the SUSPE enable bit must be cleared to avoid redundant interrupt
                    // ****************
                    // Please note also that is Vbus is lost during an upstream resume (Host disconnection),
                    // the RMWKUP bit (used to initiate remote wake up and that is normally cleared by hardware when sent)
                    // remains set after the event, so that a good way to handle this feature is :
                    //            Usb_initiate_remote_wake_up();
                    //            while (Is_usb_pending_remote_wake_up())
                    //            {
                    //              if (Is_usb_vbus_low())
                    //              {
                    //                // Emergency action (reset macro, etc.) if Vbus lost during resuming
                    //                break;
                    //              }
                    //            }
                    //            Usb_ack_remote_wake_up_start();
                    // ****************
                }
                else {
                    //TRACE_DEBUG("disabled: %d %d\n\r", usb_configuration_nb, remote_wakeup_feature);
                    // No remote wake-up supported
                    Usb_send_event(EVT_USB_SUSPEND);
                }
            }
        }
        else
        {
            //TRACE_DEBUG("ici\n\r");
            // A-PERIPH mode (will cause a session end, handled in usb_host_task.c)
            Usb_send_event(EVT_USB_SUSPEND);
            Usb_suspend_action();
            //jcb   Usb_ack_suspend();
        }
    }
   
    // -----------------------------------------------------------------------
    /// Device
    // -----------------------------------------------------------------------
    // - Wake up event (USB activity detected): Used to resume
    if (Is_usb_wake_up() && Is_swake_up_interrupt_enabled()) {
        TRACE_DEBUG("W\n\r");
        Usb_unfreeze_clock();
        Usb_send_event(EVT_USB_WAKE_UP);
    }

    // -----------------------------------------------------------------------
    /// Device
    // -----------------------------------------------------------------------
    // - Resume state bus detection
    if (Is_usb_resume() && Is_resume_interrupt_enabled()) {
        TRACE_DEBUG("Resume state bus detect\n\r");
        Usb_send_event(EVT_USB_RESUME);
    }

    // -----------------------------------------------------------------------
    /// Device
    // -----------------------------------------------------------------------
    // - USB bus reset detection
    if (Is_usb_reset()&& Is_reset_interrupt_enabled()) {
        TRACE_DEBUG_WP("B\n\r");
        if (Is_usb_id_host()) {
            //TRACE_DEBUG_WP("id_host\n\r");
            dev_configure_endpoint(EP_CONTROL,
            TYPE_CONTROL,
            DIRECTION_OUT,
            SIZE_64,
            ONE_BANK,
            NYET_DISABLED);
        }
        // First initialization is important to be synchronized
        // A reset must first have been received
        if (device_state == A_PERIPHERAL) {
            //TRACE_DEBUG_WP("r A_PERIPHERAL\n\r");
            otg_last_sof_received = UDFNUML;
            otg_last_sof_stored   = UDFNUML;
            Usb_ack_sof();
            Usb_enable_sof_interrupt();
            reset_received = TRUE;
            Timer16_set_counter(0);
        }
        Usb_reset_action();
        Usb_send_event(EVT_USB_RESET);
    }

    // ---------- OTG events management ------------------------------------
    // ---------------------------------------------------------------------

    // -----------------------------------------------------------------------
    /// Arbitrer
    // -----------------------------------------------------------------------
    // - OTG HNP Success detection
    if (Is_usb_role_exchange_interrupt() && Is_role_exchange_interrupt_enabled()) {
        //     TRACE_DEBUG("OTG HNP detect\n\r");
        Usb_ack_role_exchange_interrupt();
        Host_ack_device_connection();
        Host_ack_device_disconnection();
        Otg_send_event(EVT_OTG_HNP_SUCCESS);
        End_session_with_srp();
        Clear_otg_features_from_host();
        if (Is_usb_id_host()) {
            // HOST (A- or B-) mode
            if ((device_state != A_PERIPHERAL) && (device_state != A_END_HNP_WAIT_VFALL)) {
                static volatile unsigned int jcb;
                // Current mode is A-HOST, device will take the A-PERIPHERAL role
                b_uut_device_state = B_PERIPHERAL;
                device_state = A_PERIPHERAL;
                usb_connected = FALSE;
                usb_configuration_nb = 0;
                Usb_select_device();
                USBD_Connect();//Usb_attach();
                Usb_unfreeze_clock();
                Usb_disable_role_exchange_interrupt();
                Usb_disable_hnp_error_interrupt();
                Usb_device_stop_hnp();
                Usb_ack_reset();
                Timer16_set_counter(0);
                Usb_freeze_clock();                // USB clock can be freezed to slow down events and condition detection
                //jcb       while (Timer16_get_counter_low() != 20);
                jcb=0;
                while( jcb <100000){ jcb++; }

                Usb_unfreeze_clock();
                reset_received = FALSE;
                Usb_disable_sof_interrupt();       // will be set in the next OTG Timer IT (mandatory)

                Usb_enable_suspend_interrupt();
                Usb_enable_reset_interrupt();
                dev_configure_endpoint(EP_CONTROL,
                    TYPE_CONTROL,
                    DIRECTION_OUT,
                    SIZE_64,
                    ONE_BANK,
                    NYET_DISABLED);
            }
        }
        else {
            // In B_HOST mode, the HNPREQ bit must not be cleared because it releases the bus in suspend mode (and sof can't start)
            if ((b_uut_device_state != B_HOST) && (b_uut_device_state != B_END_HNP_SUSPEND)) {
                static volatile unsigned int jcb2;
                // Current mode is B-PERIPHERAL, device will go into B-HOST role
                End_session_with_srp();
                Clear_otg_features_from_host();
                b_uut_device_state = B_HOST;
                device_state = DEVICE_ATTACHED;
                usb_connected = FALSE;
                usb_configuration_nb = 0;
                TRACE_DEBUG("Select host 3\n\r");
                Usb_select_host();

                TRACE_DEBUG("Send reset\n\r");
                Host_send_reset();     // send the first RESET
                while (Host_is_reset());
                TRACE_DEBUG("Reset passed\n\r");

                jcb2=0;
                while( jcb2 <1000000){ jcb2++; }
                Host_enable_sof();     // start Host (sof)
                Usb_disable_role_exchange_interrupt();
                Usb_disable_hnp_error_interrupt();
                Clear_all_user_request();

                TRACE_DEBUG("Select host 3\n\r");
            }
        }
    }

    // -----------------------------------------------------------------------
    /// Arbitrer
    // -----------------------------------------------------------------------
    // - OTG HNP Failure detection
    if (Is_usb_hnp() && Is_usb_hnp_error_interrupt()&& Is_hnp_error_interrupt_enabled()) {
        TRACE_DEBUG("OTG HNP failure\n\r");
        Usb_device_stop_hnp();
        Usb_disable_role_exchange_interrupt();
        Usb_disable_hnp_error_interrupt();
        Usb_ack_hnp_error_interrupt();
        if (Is_usb_id_device()) {
            Otg_send_event(EVT_OTG_HNP_ERROR);
            Clear_all_user_request();
        }
    }   

    // ---------- HOST events management -----------------------------------
    // ---------------------------------------------------------------------

    // -----------------------------------------------------------------------
    /// Arbitrer
    // -----------------------------------------------------------------------
    // - ID pin change detection
    if(Is_usb_id_transition()&&Is_usb_id_interrupt_enabled()) {
        TRACE_DEBUG("ID pin change\n\r");
        TRACE_DEBUG("device_state = %d\n\r", device_state);
        TRACE_DEBUG("b_uut_device_state = %d\n\r", b_uut_device_state);
        Usb_device_stop_hnp();
        Clear_all_user_request();
        if(Is_usb_id_device()) { 
            g_usb_mode = USB_MODE_DEVICE;
        }
        else {
            g_usb_mode = USB_MODE_HOST;
        }
        Usb_ack_id_transition();
        if( g_usb_mode != g_old_usb_mode) { // Basic Debounce
            if(Is_usb_id_device()) { // Going into device mode
                Usb_send_event(EVT_USB_DEVICE_FUNCTION);
                b_uut_device_state = B_IDLE;
                device_state = DEVICE_UNATTACHED;
                id_changed_to_host_event = DISABLE;
            }
            else {                  // Going into host mode
                b_uut_device_state = B_IDLE;
                device_state = DEVICE_UNATTACHED;
                Usb_send_event(EVT_USB_HOST_FUNCTION);
                id_changed_to_host_event = ENABLE;
            }
            Usb_id_transition_action();
            TRACE_INFO("Pin Id changed\n\r");
        }
    }
   
    // -----------------------------------------------------------------------
    /// Host
    // -----------------------------------------------------------------------
    // - The device has been disconnected
    // JCB to be fix
    if(Is_device_disconnection() && Is_host_device_disconnection_interrupt_enabled()) {
        TRACE_DEBUG("device disconnect\n\r");
        host_disable_all_pipe();
        Host_ack_device_disconnection();
        device_state=DEVICE_DISCONNECTED;
        Usb_send_event(EVT_HOST_DISCONNECTION);
        TRACE_INFO("Device disconnected\n\r");
        Host_device_disconnection_action();
        Clear_all_user_request();
    }

    // -----------------------------------------------------------------------
    /// Host
    // -----------------------------------------------------------------------
    // - Device connection
    if(Is_device_connection() && Is_host_device_connection_interrupt_enabled()) {
        TRACE_DEBUG("device connect\n\r");
        Host_ack_device_connection();
        host_disable_all_pipe();
        Host_device_connection_action();
    }

    // -----------------------------------------------------------------------
    /// Host
    // -----------------------------------------------------------------------
    // - Host Start of frame has been sent
    if (Is_host_sof() && Is_host_sof_interrupt_enabled()) {
        //TRACE_DEBUG_WP("_");  // host
        Host_ack_sof();
        Usb_send_event(EVT_HOST_SOF);
        private_sof_counter++;

        // delay timeout management for interrupt tranfer mode in host mode
#if ((USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
        if (private_sof_counter>=250) {  // Count 1/4 sec
            private_sof_counter=0;
            for(i=0;i<MAX_EP_NB;i++) {
                if(it_pipe_str[i].enable==ENABLE) {
                    save_pipe_nb=Host_get_selected_pipe();
                    Host_select_pipe(i);
                    if((++it_pipe_str[i].timeout>TIMEOUT_DELAY) && (Host_get_pipe_type()!=TYPE_INTERRUPT)) {
                        it_pipe_str[i].enable=DISABLE;
                        it_pipe_str[i].status=PIPE_DELAY_TIMEOUT;
                        Host_stop_pipe_interrupt(i);
                        if (is_any_interrupt_pipe_active()==FALSE) {   // If no more transfer is armed
                            if (g_sav_int_sof_enable==FALSE) {
                                Host_disable_sof_interrupt();
                            }
                        }
                        it_pipe_str[i].handle(PIPE_DELAY_TIMEOUT,it_pipe_str[i].nb_byte_processed);
                    }
                    Host_select_pipe(save_pipe_nb);
                }
            }
        }
#endif  // (USB_HOST_PIPE_INTERRUPT_TRANSFER==ENABLE) && (TIMEOUT_DELAY_ENABLE==ENABLE))
        Host_sof_action();
    }

    // -----------------------------------------------------------------------
    /// Host
    // -----------------------------------------------------------------------
    // - Host Wake-up has been received
    if (Is_host_hwup() && Is_host_hwup_interrupt_enabled()) {
        TRACE_DEBUG("Host wake up\n\r");
        Host_disable_hwup_interrupt();  // Wake up interrupt should be disable host is now wake up !
        Host_disable_remote_wakeup_interrupt();
        // CAUTION HWUP can be cleared only when USB clock is active (not frozen)!
        Usb_unfreeze_clock();           // Enable clock on USB interface
        Host_enable_sof();              // start sending SOF
        Host_ack_hwup();                // Clear HWUP interrupt flag
        Host_ack_remote_wakeup();
        Usb_send_event(EVT_HOST_HWUP);  // Send software event
        Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
        Host_hwup_action();             // Map custom action
        if (Is_usb_hnp()) {
            Usb_host_reject_hnp();
            Usb_disable_hnp_error_interrupt();
            Usb_disable_role_exchange_interrupt();
        }
        Host_send_resume();
    }

    // -----------------------------------------------------------------------
    /// Host
    // -----------------------------------------------------------------------
    // Remote Wake Up has been received
    if (Is_host_remote_wakeup_interrupt_enabled() && Is_host_remote_wakeup()) {
        TRACE_DEBUG("Remote wake up\n\r");
        Host_disable_remote_wakeup_interrupt();
        Host_disable_hwup_interrupt();
        Host_ack_remote_wakeup();
        Host_ack_hwup();                // Clear HWUP interrupt flag
        Usb_unfreeze_clock();           // Enable clock on USB interface
        Host_enable_sof();     // start sending SOF
        Usb_send_event(EVT_HOST_REMOTE_WAKEUP);
        Usb_send_event(EVT_HOST_HWUP);  // Send software event
        if (Is_usb_hnp()) {
            Usb_host_reject_hnp();
            Usb_disable_hnp_error_interrupt();
            Usb_disable_role_exchange_interrupt();
        }
        Host_send_resume();
    }
}