Exemplo n.º 1
0
//! Task which links mouse events with the USB HID mouse device
//!
void mouse_task(void)
{
   if(Is_usb_vbus_low())
   {
      Setup_power_down_mode();
      Sleep_instruction();
   }

   if(!Is_device_enumerated())
      return;  // Device not ready

#if (USB_LOW_SPEED_DEVICE==DISABLE)
   // The SOF is used to schedule the task at the same frequency that Endpoint Interrupt frequency
   // This check allow to win a CPU time
   if(g_u8_cpt_sof<NB_IDLE_POLLING_SOF)
      return;  // Wait a delay
   g_u8_cpt_sof=0;
#endif

   if(!g_b_send_report)
   {
      // No report sending on going, then check mouse event to eventualy fill a new report
      if(is_mouse_event())
      {
         // Enable sending of report
         g_b_send_report      = TRUE;
      }
   }

   if((!g_b_send_report)&&(!g_b_send_ack_report))
      return;  // No report and ack to send

   //** A report or ack must be send
   Usb_select_endpoint(EP_MOUSE_IN);
   if(!Is_usb_write_enabled())
      return;  // Endpoint no free

   Led0_on();
   if( g_b_send_report )
   {
      g_b_send_report      = FALSE;
      // Send an ack after a "clic" report only
      g_b_send_ack_report = (0!=g_hid_mouse_report[0]);
   }
   else
   {
      Hid_mouse_report_reset();     // Reset report to have a ack report
      g_b_send_ack_report  = FALSE;
   }
   // Send report
   Usb_write_byte(g_hid_mouse_report[0]);
   Usb_write_byte(g_hid_mouse_report[1]);
   Usb_write_byte(g_hid_mouse_report[2]);
   Usb_write_byte(g_hid_mouse_report[3]);
   Usb_ack_in_ready();
   Led0_off();
}
Exemplo n.º 2
0
void usb_host_task(void)
#endif
{
  #define DEVICE_DEFAULT_MAX_ERROR_COUNT  2
  static uint8_t device_default_error_count;

#ifdef HOST_VBUS_LOW_TIMEOUT
  extern t_cpu_time timer_vbus_low;
#endif
  static bool sav_int_sof_enable;
  uint8_t pipe;

#ifdef FREERTOS_USED
  portTickType xLastWakeTime;

  xLastWakeTime = xTaskGetTickCount();
  while (true)
  {
    vTaskDelayUntil(&xLastWakeTime, configTSK_USB_HST_PERIOD);

#endif  // FREERTOS_USED
    switch (device_state)
    {
#ifdef HOST_VBUS_LOW_TIMEOUT
    case DEVICE_VBUS_LOW:
      Usb_disable_vbus();
      if (cpu_is_timeout(&timer_vbus_low))
        usb_host_task_init();
      break;
#endif

    //------------------------------------------------------
    //   DEVICE_UNATTACHED state
    //
    //   - Default init state
    //   - Try to give device power supply
    //
    case DEVICE_UNATTACHED:
      device_default_error_count = 0;
      nb_interface_supported = 0;
      Host_clear_device_status();     // Reset device status
      Usb_clear_all_event();          // Clear all software events
      Host_disable_sof();
      host_disable_all_pipes();
      Usb_enable_vbus();              // Give at least device power supply!
      // If VBus OK, wait for device connection
      if (Is_usb_vbus_high())
        device_state = DEVICE_ATTACHED;
      break;

    //------------------------------------------------------
    //   DEVICE_ATTACHED state
    //
    //   - VBus is on
    //   - Try to detect device connection
    //
    case DEVICE_ATTACHED:
      if (Is_host_device_connection() || Is_usb_event(EVT_HOST_CONNECTION) )  // Device pull-up detected
      {
device_attached_retry:
        if( Is_usb_event(EVT_HOST_CONNECTION) ) {
          Usb_ack_event(EVT_HOST_CONNECTION);
        }
        Usb_ack_bconnection_error_interrupt();
        Usb_ack_vbus_error_interrupt();
        Host_ack_device_connection();

        Host_clear_device_status();   // Reset device status
        cpu_irq_disable();
        Host_disable_device_disconnection_interrupt();
        Host_send_reset();            // First USB reset
        (void)Is_host_sending_reset();
        cpu_irq_enable();
        Usb_ack_event(EVT_HOST_SOF);
        // Active wait for end of reset send
        while (Is_host_sending_reset())
        {
          // The USB macro does not signal the end of reset when a disconnection occurs
          if (Is_host_device_disconnection())
          {
            // Stop sending USB reset
            Host_stop_sending_reset();
          }
        }
        Host_ack_reset_sent();
        Host_enable_sof();            // Start SOF generation
        Host_enable_sof_interrupt();  // SOF will be detected under interrupt
        if (!Is_host_device_disconnection())
        {
          // Workaround for some buggy devices with powerless pull-up
          // usually low-speed where data line rises slowly and can be interpreted as disconnection
          for (sof_cnt = 0; sof_cnt < 0xFFFF; sof_cnt++)  // Basic time-out counter
          {
            // If we detect SOF, device is still alive and connected, just clear false disconnect flag
            if (Is_usb_event(EVT_HOST_SOF) && Is_host_device_disconnection())
            {
              Host_ack_device_connection();
              Host_ack_device_disconnection();
              break;
            }
          }
        }
        Host_enable_device_disconnection_interrupt();
        sof_cnt = 0;
        while (sof_cnt < 100)         // Wait 100 ms after USB reset
        {
          if (Is_usb_event(EVT_HOST_SOF)) Usb_ack_event(EVT_HOST_SOF), sof_cnt++; // Count SOFs
          if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) goto device_attached_error;
        }
        device_state = DEVICE_POWERED;
        LOG_STR(log_device_connected);
        Host_device_connection_action();
        sof_cnt = 0;
      }
device_attached_error:
      // Device connection error, or VBus pb -> Retry the connection process from the beginning
      if (Is_usb_bconnection_error_interrupt() || Is_usb_vbus_error_interrupt() || Is_usb_vbus_low())
      {
        if (device_state != DEVICE_VBUS_LOW)
          device_state = DEVICE_UNATTACHED;
        Usb_ack_bconnection_error_interrupt();
        Usb_ack_vbus_error_interrupt();
        Host_disable_sof();
      }
      break;

    //------------------------------------------------------
    //   DEVICE_POWERED state
    //
    //   - Device connection (attach) has been detected,
    //   - Wait 100 ms and configure default control pipe
    //
    case DEVICE_POWERED:
      if (Is_usb_event(EVT_HOST_SOF))
      {
        Usb_ack_event(EVT_HOST_SOF);
        if (sof_cnt++ >= 100)         // Wait 100 ms
        {
          Host_enable_pipe(P_CONTROL);
          (void)Host_configure_pipe(P_CONTROL,
                                    0,
                                    EP_CONTROL,
                                    TYPE_CONTROL,
                                    TOKEN_SETUP,
                                    8,
                                    SINGLE_BANK);
          device_state = DEVICE_DEFAULT;
        }
      }
      break;

    //------------------------------------------------------
    //   DEVICE_DEFAULT state
    //
    //   - Get device descriptor
    //   - Reconfigure control pipe according to device control endpoint
    //   - Assign device address
    //
    case DEVICE_DEFAULT:
      // Get first device descriptor
      if (host_get_device_descriptor_incomplete() == CONTROL_GOOD)
      {
        sof_cnt = 0;
        while (sof_cnt < 20)          // Wait 20 ms before USB reset (special buggy devices...)
        {
          if (Is_usb_event(EVT_HOST_SOF)) Usb_ack_event(EVT_HOST_SOF), sof_cnt++;
          if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) break;
        }
        cpu_irq_disable();
        Host_disable_device_disconnection_interrupt();
        Host_send_reset();            // First USB reset
        (void)Is_host_sending_reset();
        cpu_irq_enable();
        Usb_ack_event(EVT_HOST_SOF);
        // Active wait for end of reset send
        while (Is_host_sending_reset())
        {
          // The USB macro does not signal the end of reset when a disconnection occurs
          if (Is_host_device_disconnection())
          {
            // Stop sending USB reset
            Host_stop_sending_reset();
          }
        }
        Host_ack_reset_sent();
        if (!Is_host_device_disconnection())
        {
          // Workaround for some buggy devices with powerless pull-up
          // usually low-speed where data line rises slowly and can be interpreted as disconnection
          for (sof_cnt = 0; sof_cnt < 0xFFFF; sof_cnt++)  // Basic time-out counter
          {
            // If we detect SOF, device is still alive and connected, just clear false disconnect flag
            if (Is_usb_event(EVT_HOST_SOF) && Is_host_device_disconnection())
            {
              Host_ack_device_connection();
              Host_ack_device_disconnection();
              break;
            }
          }
        }
        Host_enable_device_disconnection_interrupt();
        sof_cnt = 0;
        while (sof_cnt < 200)         // Wait 200 ms after USB reset
        {
          if (Is_usb_event(EVT_HOST_SOF)) Usb_ack_event(EVT_HOST_SOF), sof_cnt++;
          if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) break;
        }
        Host_disable_pipe(P_CONTROL);
        Host_unallocate_memory(P_CONTROL);
        Host_enable_pipe(P_CONTROL);
        // Reconfigure the control pipe according to the device control endpoint
        (void)Host_configure_pipe(P_CONTROL,
                                  0,
                                  EP_CONTROL,
                                  TYPE_CONTROL,
                                  TOKEN_SETUP,
                                  data_stage[OFFSET_FIELD_MAXPACKETSIZE],
                                  SINGLE_BANK);
        // Give an absolute device address
        if (host_set_address(DEVICE_ADDRESS) == CONTROL_GOOD)
        {
          for (pipe = 0; pipe < MAX_PEP_NB; pipe++)
            Host_configure_address(pipe, DEVICE_ADDRESS);
          device_state = DEVICE_ADDRESSED;
        }
        else if (device_state != DEVICE_VBUS_LOW)
          device_state = DEVICE_ERROR;
      }
      else
      {
        if (device_state != DEVICE_VBUS_LOW)
        {
          if (++device_default_error_count > DEVICE_DEFAULT_MAX_ERROR_COUNT)
          device_state = DEVICE_ERROR;
          else
          {
            Host_disable_sof();
            Host_disable_pipe(P_CONTROL);
            Host_unallocate_memory(P_CONTROL);
            device_state = DEVICE_ATTACHED;
            goto device_attached_retry;
          }
        }
        Usb_ack_bconnection_error_interrupt();
        Usb_ack_vbus_error_interrupt();
        Host_disable_sof();
      }
      break;

    //------------------------------------------------------
    //   DEVICE_ADDRESSED state
    //
    //   - Check if VID PID is in supported list
    //
    case DEVICE_ADDRESSED:
      if (host_get_device_descriptor() == CONTROL_GOOD)
      {
        // Detect if the device connected belongs to the supported devices table
        if (host_check_VID_PID())
        {
          Host_set_device_supported();
          Host_device_supported_action();
          device_state = DEVICE_CONFIGURED;
        }
        else
        {
#if HOST_STRICT_VID_PID_TABLE == ENABLE
          device_state = DEVICE_ERROR;
          LOG_STR(log_unsupported_device);
#else
          device_state = DEVICE_CONFIGURED;
#endif
          Host_device_not_supported_action();
        }
      }
      else if (device_state != DEVICE_VBUS_LOW)
        device_state = DEVICE_ERROR; // Can not get device descriptor
      break;

    //------------------------------------------------------
    //   DEVICE_CONFIGURED state
    //
    //   - Configure pipes for the supported interface
    //   - Send Set_configuration() request
    //   - Go to full operating mode (device ready)
    //
    case DEVICE_CONFIGURED:
      {
        uint8_t configuration_index = 0;

        if (host_get_configuration_descriptor(configuration_index) == CONTROL_GOOD)
        {
          if (host_check_class())       // Class support OK?
          {
#if HOST_AUTO_CFG_ENDPOINT == DISABLE
            User_configure_endpoint();  // User call here instead of autoconfig
            Host_set_configured();      // Assumes config is OK with user config
#endif
            if (Is_host_configured())
            {
              if (host_set_configuration(data_stage[OFFSET_FIELD_CONFIGURATION_NB]) == CONTROL_GOOD)  // Send Set_configuration
              {
                // Device and host are now fully configured
                // go to DEVICE_READY normal operation
                device_state = DEVICE_READY;
                // Monitor device disconnection under interrupt
                Host_enable_device_disconnection_interrupt();
                // If user host application requires SOF interrupt event
                // Keep SOF interrupt enabled, otherwise disable this interrupt
#if HOST_CONTINUOUS_SOF_INTERRUPT == DISABLE
                cpu_irq_disable();
                Host_disable_sof_interrupt();
                (void)Is_host_sof_interrupt_enabled();
                cpu_irq_enable();
#endif
                Host_new_device_connection_action();
                cpu_irq_enable();
                LOG_STR(log_device_enumerated);
              }
              else if (device_state != DEVICE_VBUS_LOW)
                device_state = DEVICE_ERROR; // Problem during Set_configuration request...
            }
          }
          else  // Device class not supported...
          {
            device_state = DEVICE_UNSUPPORTED;
            LOG_STR(log_unsupported_device);
            Host_device_class_not_supported_action();
          }
        }
        else if (device_state != DEVICE_VBUS_LOW)
          device_state = DEVICE_ERROR; // Can not get configuration descriptors...
      }
      break;

    //------------------------------------------------------
    //   DEVICE_READY state
    //
    //   - Full standard operating mode
    //   - Nothing to do...
    //
    case DEVICE_READY:                // Host full standard operating mode!
      break;

    //------------------------------------------------------
    //   DEVICE_UNSUPPORTED state
    //
    case DEVICE_UNSUPPORTED:
      break;

    //------------------------------------------------------
    //   DEVICE_ERROR state
    //
    //   - Error state
    //   - Do custom action call (probably go to default mode...)
    //
    case DEVICE_ERROR:                //! @todo
#if HOST_ERROR_RESTART == ENABLE
      device_state = DEVICE_UNATTACHED;
#endif
      Host_device_error_action();
      break;

    //------------------------------------------------------
    //   DEVICE_SUSPENDED state
    //
    //   - Host application request to suspend the device activity
    //   - State machine comes here thanks to Host_request_suspend()
    //
    case DEVICE_SUSPENDED:
      if (Is_device_supports_remote_wakeup()) // If the connected device supports remote wake-up
      {
        host_set_feature_remote_wakeup(); // Enable this feature...
      }
      LOG_STR(log_usb_suspended);
      sav_int_sof_enable = Is_host_sof_interrupt_enabled(); //Save current SOF interrupt enable state
      cpu_irq_disable();
      Host_disable_sof_interrupt();
      (void)Is_host_sof_interrupt_enabled();
      cpu_irq_enable();
      Host_ack_sof();
      Host_disable_sof();             // Stop SOF generation, this generates the suspend state
      Host_ack_hwup();
      Host_enable_hwup_interrupt();   // Enable host wake-up interrupt
                                      // (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
      (void)Is_host_hwup_interrupt_enabled(); // Make sure host wake-up interrupt is enabled
      Usb_freeze_clock();
      //! @todo Implement this on the silicon version
      //Stop_pll();
      Host_suspend_action();          // Custom action here! (e.g. go to power-save mode...)
      device_state = DEVICE_WAIT_RESUME;  // Wait for device resume event
      break;

    //------------------------------------------------------
    //   DEVICE_WAIT_RESUME state
    //
    //   Wait in this state till:
    //   - the host receives an upstream resume from the device
    //   - or the host software request the device to resume
    //
    case DEVICE_WAIT_RESUME:
      if (Is_usb_event(EVT_HOST_HWUP) || Is_host_request_resume())  // Remote wake-up has been detected
                                                                    // or local resume request has been received
      {
        if (Is_host_request_resume())     // Not a remote wake-up, but a host application request
        {
          // CAUTION: HWUP can be cleared only when USB clock is active
          //! @todo Implement this on the silicon version
          //Pll_start_auto();               // First Restart the PLL for USB operation
          //Wait_pll_ready();               // Make sure PLL is locked
          Usb_unfreeze_clock();           // Enable clock on USB interface
          (void)Is_usb_clock_frozen();    // Make sure USB interface clock is enabled
          cpu_irq_disable();
          Host_disable_hwup_interrupt();  // Wake-up interrupt should be disabled as host is now awoken!
          (void)Is_host_hwup_interrupt_enabled();
          cpu_irq_enable();
          Host_ack_hwup();                // Clear HWUP interrupt flag
        }
        Host_enable_sof();
        Host_send_resume();               // Send downstream resume
        while (!Is_host_down_stream_resume());  // Wait for downstream resume sent
        Host_ack_remote_wakeup();         // Ack remote wake-up reception
        Host_ack_request_resume();        // Ack software request
        Host_ack_down_stream_resume();    // Ack downstream resume sent
        Usb_ack_event(EVT_HOST_HWUP);     // Ack software event
        if (sav_int_sof_enable) Host_enable_sof_interrupt();  // Restore SOF interrupt enable state before suspend
        device_state = DEVICE_READY;      // Come back to full operating mode
        LOG_STR(log_usb_resumed);
      }
      break;

    //------------------------------------------------------
    //   default state
    //
    //   - Default case: ERROR
    //   - Go to DEVICE_UNATTACHED state
    //
    default:
      device_state = DEVICE_UNATTACHED;
      break;
    }
#ifdef FREERTOS_USED
  }
#endif
}
Exemplo 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();
   }
}
Exemplo n.º 4
0
/**
 * @brief Entry point of the USB host management
 *
 * The aim is to manage the device target connection and enumeration
 * depending on the device_state, the function performs the required operations
 * to get the device enumerated and configured
 * Once the device is operationnal, the device_state value is DEVICE_READY
 * This state should be tested by the host task application before performing
 * any applicative requests to the device.
 *
 * @param none
 *
 * @return none
 *
 * \image html host_task.gif
 */
void usb_host_task(void)
{

   switch (device_state)
   {
     //------------------------------------------------------
     //   DEVICE_UNATTACHED state
     //
     //   - Default init state
     //   - Try to give device power supply
     //
      case DEVICE_UNATTACHED:
         Host_clear_device_supported();        // Reset Device status
         Host_clear_configured();
         Host_clear_device_ready();
         Usb_clear_all_event();                // Clear all software events
         new_device_connected=FALSE;
         selected_device=0;
         
#if (USB_HUB_SUPPORT==ENABLE)
         nb_hub_present = 0;
#endif         
         
#if (SOFTWARE_VBUS_CTRL==ENABLE)
         if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt())
         {
            Usb_ack_bconnection_error_interrupt();
            Usb_ack_vbus_error_interrupt();
            Host_clear_vbus_request();
         }
         Usb_disable_vbus_pad();
         Usb_enable_manual_vbus();
         if(Is_usb_srp_interrupt())
         {
            Usb_ack_srp_interrupt();
            Usb_enable_vbus_pad();
            Usb_enable_vbus();
            device_state=DEVICE_ATTACHED;
         }
#else
         Usb_enable_vbus();                    // Give at least device power supply!!!
         if(Is_usb_vbus_high())
         { device_state=DEVICE_ATTACHED; }     // If VBUS ok goto to device connection expectation
#endif
      break;

     //------------------------------------------------------
     //   DEVICE_ATTACHED state
     //
     //   - Vbus is on
     //   - Try to detected device connection
     //
      case DEVICE_ATTACHED :
         if (Is_device_connection() || (force_enumeration==TRUE))     // Device pull-up detected
         {
            Host_ack_device_connection();
            Host_clear_device_supported();        // Reset Device status
            Host_clear_configured();
            Host_clear_device_ready();
            Usb_clear_all_event();                // Clear all software events
            new_device_connected=FALSE;
            force_enumeration=FALSE;

           // Now device is connected, enable disconnection interrupt
            Host_enable_device_disconnection_interrupt();
            Enable_interrupt();
           // Reset device status
            Host_clear_device_supported();
            Host_clear_configured();
            Host_clear_device_ready();
            Host_enable_sof();            // Start Start Of Frame generation
            Host_enable_sof_interrupt();  // SOF will be detected under interrupt
            c = 0;
            while (c<100)               // wait 100ms before USB reset
            {
               if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }// Count Start Of frame
               if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {goto device_attached_error;}
            }
            Host_disable_device_disconnection_interrupt();
            Host_send_reset();          // First USB reset
            Usb_ack_event(EVT_HOST_SOF);
            while (Is_host_reset());    // Active wait of end of reset send
            Host_ack_reset();
            //Workaround for some bugly devices with powerless pull up
            //usually low speed where data line rise slowly and can be interpretaded as disconnection
            for(c=0;c!=0xFFFF;c++)    // Basic Timeout counter
            {
               if(Is_usb_event(EVT_HOST_SOF))   //If we detect SOF, device is still alive and connected, just clear false disconnect flag
               {
                  if(Is_device_disconnection())
                  {
                      Host_ack_device_connection();
                      Host_ack_device_disconnection();
                      break;
                  }
               }
            }
            Host_enable_device_disconnection_interrupt();
            // All USB pipes must be reconfigured after a USB reset generation
            host_configure_pipe(PIPE_CONTROL, \
                                            TYPE_CONTROL, \
                                            TOKEN_SETUP,  \
                                            EP_CONTROL,   \
                                            SIZE_64,      \
                                            ONE_BANK,     \
                                            0             );            
            c = 0;
            while (c<100)               // wait 100ms after USB reset
            {
               if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }// Count Start Of frame
               if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) {goto device_attached_error;}
            }
            device_state = DEVICE_POWERED;
            c=0;
         }
         device_attached_error:
        // Device connection error, or vbus pb -> Retry the connection process from the begining
         if( Is_usb_bconnection_error_interrupt()||Is_usb_vbus_error_interrupt()||Is_usb_vbus_low())
         {
            Usb_ack_bconnection_error_interrupt();
            Usb_enable_vbus_hw_control();
            device_state=DEVICE_UNATTACHED;
            Usb_disable_vbus();
            Usb_disable_vbus_pad();
            Usb_enable_vbus_pad();
            Usb_ack_vbus_error_interrupt();
            Usb_enable_vbus();
            Usb_disable_vbus_hw_control();
            Host_disable_sof();
         }
         break;

     //------------------------------------------------------
     //   DEVICE_POWERED state
     //
     //   - Device connection (attach) as been detected,
     //   - Wait 100ms and configure default control pipe
     //
      case DEVICE_POWERED :
         LOG_STR_CODE(log_device_connected);
         Host_device_connection_action();
         if (Is_usb_event(EVT_HOST_SOF))
         {
            Usb_ack_event(EVT_HOST_SOF);
            if (c++ >= 100)                          // Wait 100ms
            {
               device_state = DEVICE_DEFAULT;
            }
         }
         break;

     //------------------------------------------------------
     //   DEVICE_DEFAULT state
     //
     //   - Get device descriptor
     //   - Reconfigure Pipe 0 according to Device EP0
     //   - Attribute device address
     //
      case DEVICE_DEFAULT :
        // Get first device descriptor
         Host_select_device(0);
         usb_tree.device[0].ep_ctrl_size=8;
         if( CONTROL_GOOD == host_get_device_descriptor_uncomplete())
         {
            c = 0;
            while(c<20)           // wait 20ms before USB reset (special buggly devices...)
            {
               if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
               if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt())  {break;}
            }
            Host_disable_device_disconnection_interrupt();
            Host_send_reset();          // First USB reset
            Usb_ack_event(EVT_HOST_SOF);
            while (Is_host_reset());    // Active wait of end of reset send
            Host_ack_reset();
            //Workaround for some bugly devices with powerless pull up
            //usually low speed where data line rise slowly and can be interpretaded as disconnection
            for(c=0;c!=0xFFFF;c++)    // Basic Timeout counter
            {
               if(Is_usb_event(EVT_HOST_SOF))   //If we detect SOF, device is still alive and connected, just clear false disconnect flag
               {
                  if(Is_device_disconnection())
                  {
                      Host_ack_device_connection();
                      Host_ack_device_disconnection();
                      break;
                  }
               }
            }
            Host_enable_device_disconnection_interrupt();
            c = 0;
            host_configure_pipe(PIPE_CONTROL, \
                                            TYPE_CONTROL, \
                                            TOKEN_SETUP,  \
                                            EP_CONTROL,   \
                                            SIZE_64,      \
                                            ONE_BANK,     \
                                            0             );            
            while(c<200)           // wait 200ms after USB reset
            {
               if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }
               if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt())  {break;}
            }
            usb_tree.device[0].ep_ctrl_size=data_stage[OFFSET_FIELD_MAXPACKETSIZE];
            
            // Give an absolute device address
            host_set_address(DEVICE_BASE_ADDRESS);
            usb_tree.device[0].device_address=DEVICE_BASE_ADDRESS;
            device_state = DEVICE_ADDRESSED;
         }
         else
         {  device_state = DEVICE_ERROR; }
         break;

     //------------------------------------------------------
     //   DEVICE_BASE_ADDRESSED state
     //
     //   - Check if VID PID is in supported list
     //
      case DEVICE_ADDRESSED :
         if (CONTROL_GOOD == host_get_device_descriptor())
         {
           // Detect if the device connected belongs to the supported devices table
            if (HOST_TRUE == host_check_VID_PID())
            {
               Host_set_device_supported();
               Host_device_supported_action();
               device_state = DEVICE_CONFIGURED;
            }
            else
            {
               #if (HOST_STRICT_VID_PID_TABLE==ENABLE)
                  Host_device_not_supported_action();
                  device_state = DEVICE_ERROR;
               #else
                  device_state = DEVICE_CONFIGURED;
               #endif
            }
         }
         else // Can not get device descriptor
         {  device_state = DEVICE_ERROR; }
         break;

     //------------------------------------------------------
     //   DEVICE_CONFIGURED state
     //
     //   - Configure pipes for the supported interface
     //   - Send Set_configuration() request
     //   - Goto full operating mode (device ready)
     //
      case DEVICE_CONFIGURED :
         if (CONTROL_GOOD == host_get_configuration_descriptor())
         {
            if (HOST_FALSE != host_check_class()) // Class support OK?
            {
               usb_tree.nb_device++;
            #if (HOST_AUTO_CFG_ENDPOINT==ENABLE)
               if(host_auto_configure_endpoint())
            #else
               Host_set_configured();     // Assumes config is OK with user config
               if(User_configure_endpoint()) // User call here instead of autoconfig
            #endif
               {
                  if (CONTROL_GOOD== host_set_configuration(1))  // Send Set_configuration
                  {
                     //host_set_interface(interface_bound,interface_bound_alt_set);
                     // device and host are now fully configured
                     // goto DEVICE READY normal operation
                      device_state = DEVICE_READY;
                      Host_set_device_ready();
                     // monitor device disconnection under interrupt
                      Host_enable_device_disconnection_interrupt();
                     // If user host application requires SOF interrupt event
                     // Keep SOF interrupt enable otherwize, disable this interrupt
                  #if (HOST_CONTINUOUS_SOF_INTERRUPT==DISABLE && USB_HUB_SUPPORT==DISABLE)
                      Host_disable_sof_interrupt();
                  #endif
                  #if (USB_HUB_SUPPORT==ENABLE)
                      // Check if the connected device is a hub
                      if(Get_class(0)==HUB_CLASS && Get_subclass(0)==0x00 && Get_protocol(0)==0x00)
                      {
                           // Get hub descriptor
                           if( Get_hub_descriptor()==CONTROL_GOOD)
                           {
                              // Power each port of the hub
                              i=data_stage[NB_PORT_OFFSET];
                              for(c=1;c<=i;c++)
                              {
                                 Set_port_feature(PORT_POWER,c);
                              }
                              nb_hub_present = 1;
                              hub_device_address[0]=DEVICE_BASE_ADDRESS;
                              hub_init(nb_hub_present-1);    
                           }
                      }
                      else
                      {
                         nb_hub_present = 0;
                         new_device_connected=TRUE;
                      }
                  #else
                      new_device_connected=TRUE;
                  #endif
                      
                      Enable_interrupt();
                      LOG_STR_CODE(log_device_enumerated);
                  }
                  else// Problem during Set_configuration request...
                  {   device_state = DEVICE_ERROR;  }
               }
            }
            else // device class not supported...
            {
                device_state = DEVICE_ERROR;
                LOG_STR_CODE(log_device_unsupported);
                Host_device_class_not_supported_action();
            }
         }
         else // Can not get configuration descriptors...
         {  device_state = DEVICE_ERROR; }
         break;

     //------------------------------------------------------
     //   DEVICE_READY state
     //
     //   - Full std operatinf mode
     //   - Nothing to do...
     //
      case DEVICE_READY:     // Host full std operating mode!
         new_device_connected=FALSE;
         
      #if (USB_HUB_SUPPORT==ENABLE)
         f_hub_port_disconnect=FALSE;
         // If one hub is present in the USB tree and the period interval
         // for the interrupt hub endpoint occurs
         if(nb_hub_present && hub_interrupt_sof==0)
         {
            saved_device=selected_device;      // Backup user selected device
            for(j=1;j<=nb_hub_present;j++)
            {
               for(i=0;i<MAX_DEVICE_IN_USB_TREE;i++)
               {
                  if(usb_tree.device[i].device_address==hub_device_address[j-1]) break;
               }
               Host_select_device(i);
               Host_select_pipe(usb_tree.device[i].interface[0].ep[0].pipe_number);
               Host_ack_nak_received();
               Host_ack_in_received();
               Host_unfreeze_pipe();
               Host_send_in();
               while(1)
               {
                   if(Is_host_nak_received())   break;
                   if(Is_host_emergency_exit()) break;
                   if(Is_host_in_received())    break;
               }
               Host_freeze_pipe();
               if(Is_host_nak_received())
               {
                  Host_ack_nak_received();
               }
               if(Is_host_in_received())
               {
                  if(Is_host_stall()==FALSE)
                  {
                     c=Host_read_byte();
                  }
                  Host_ack_in_received();
                  hub_manage_port_change_status(c,j);
               }
            } // for all hub 
            Host_select_device(saved_device);  // Restore user selected device
            #if (USER_PERIODIC_PIPE==ENABLE)
            unfreeze_user_periodic_pipe();
            #endif
         }
      #endif
         break;

     //------------------------------------------------------
     //   DEVICE_ERROR state
     //
     //   - Error state
     //   - Do custom action call (probably go to default mode...)
     //
      case DEVICE_ERROR :    // TODO !!!!
      #if (HOST_ERROR_RESTART==ENABLE)
         device_state=DEVICE_UNATTACHED;
      #endif
         Host_device_error_action();
         break;

     //------------------------------------------------------
     //   DEVICE_SUSPENDED state
     //
     //   - Host application request to suspend the device activity
     //   - State machine comes here thanks to Host_request_suspend()
     //
      case DEVICE_SUSPENDED :
         if(Is_device_supports_remote_wakeup()) // If the connected device supports remote wake up
         {
           host_set_feature_remote_wakeup();    // Enable this feature...
         }
         LOG_STR_CODE(log_going_to_suspend);
         c = Is_host_sof_interrupt_enabled(); //Save current sof interrupt enable state
         Host_disable_sof_interrupt();
         Host_ack_sof();
         Host_disable_sof();           // Stop start of frame generation, this generates the suspend state
         Host_ack_hwup();
         Host_enable_hwup_interrupt(); // Enable host wake-up interrupt
                                       // (this is the unique USB interrupt able to wake up the CPU core from power-down mode)
         Usb_freeze_clock();
         Stop_pll();
         Host_suspend_action();              // Custom action here! (for example go to power-save mode...)
         device_state=DEVICE_WAIT_RESUME;    // wait for device resume event
         break;

     //------------------------------------------------------
     //   DEVICE_WAIT_RESUME state
     //
     //   - Wait in this state till the host receives an upstream resume from the device
     //   - or the host software request the device to resume
     //
      case DEVICE_WAIT_RESUME :
         if(Is_usb_event(EVT_HOST_HWUP)|| Is_host_request_resume())// Remote wake up has been detected
                                                                 // or Local resume request has been received
         {
            if(Is_host_request_resume())       // Not a remote wakeup, but an host application request
            {
               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
               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
            }
            Host_enable_sof();
            Host_send_resume();                            // Send down stream resume
            while (Is_host_down_stream_resume()==FALSE);   // Wait Down stream resume sent
            Host_ack_remote_wakeup();        // Ack remote wake-up reception
            Host_ack_request_resume();       // Ack software request
            Host_ack_down_stream_resume();   // Ack down stream resume sent
            Usb_ack_event(EVT_HOST_HWUP);    // Ack software event
            if(c) { Host_enable_sof_interrupt(); } // Restore SOF interrupt enable state before suspend
            device_state=DEVICE_READY;       // Come back to full operating mode
            LOG_STR_CODE(log_usb_resumed);
         }
         break;

     //------------------------------------------------------
     //   DEVICE_DISCONNECTED state
     //
     //   - Device disconnection has been detected
     //   - Run scheduler in this state at least two times to get sure event is detected by all host application tasks
     //   - Go to DEVICE_DISCONNECTED_ACK state before DEVICE_UNATTACHED, to get sure scheduler calls all app tasks...
     //
      case DEVICE_DISCONNECTED :
         device_state = DEVICE_DISCONNECTED_ACK;
         break;

     //------------------------------------------------------
     //   DEVICE_DISCONNECTED_ACK state
     //
     //   - Device disconnection has been detected and managed bu applicatives tasks
     //   - Go to DEVICE_UNATTACHED state
     //
      case DEVICE_DISCONNECTED_ACK :
         device_state = DEVICE_UNATTACHED;
         break;

     //------------------------------------------------------
     //   default state
     //
     //   - Default case: ERROR
     //   - Goto no device state
     //
      default :
         device_state = DEVICE_UNATTACHED;
         break;
      }
}
Exemplo n.º 5
0
//!
//! @brief Entry point of the MMI task management
//!
void mmi_task(void)
{
  uint32_t i;
  switch( mmi_state )
  {
  case MMI_TOP_MENU_START:
    // Draw the background AVR32 logo.
    et024006_PutPixmap(avr32_logo, 320, 0, 0, 0, 0, 320, 240);

    // Display welcome string.
    et024006_PrintString("EVK1104 Demo", (const unsigned char *)&FONT8x8, 110, 220, BLACK, -1);

    mmi_state = MMI_TOP_MENU;
    break;

  case MMI_TOP_MENU:
    if( Is_usb_vbus_high() )
    {
      mmi_state = MMI_MASS_STORAGE_START;
    }
    break;

  case MMI_MASS_STORAGE_START:
    // Draw the background AVR32 logo.
    et024006_PutPixmap(avr32_logo, 320, 0, 0, 0, 0, 320, 240);

    // Display USB key logo.
    et024006_DrawFilledRect(220-1, 20-1, 80+2, 42+2, BLACK );
    et024006_PutPixmap(ms_key_logo, 80, 0, 0, 220, 20, 80, 42);

    // Display title.
    et024006_PrintString("U-Disk", (const unsigned char *)&FONT6x8, 240, 65, BLACK, -1);

    // Display Activity window.
    display_box(80, 180, 156, 16, WHITE, BLACK);

    // Display performances box.
    display_perf(120, 201, true, 0, 0);

    ms_old_cnt_read = ms_cnt_read =0;
    ms_old_cnt_write = ms_cnt_write =0;
    mmi_state = MMI_MASS_STORAGE;
    ms_cnt_screen = 0;
    for( i=0 ; i<MS_N_PROGRESS_BAR ; i++ )
    {
      ms_progress_bar_level[i] = 1;
      ms_progress_bar_type[i] = BLACK;
    }
    mmi_ms_display();

    cpu_set_timeout( cpu_ms_2_cy(TIMER_MS_PROGRESS_BAR_UPDATE, pm_freq_param.cpu_f), &ms_activity_timer);
    cpu_set_timeout( cpu_ms_2_cy(TIMER_MS_PROGRESS_BAR_CLEAR,  pm_freq_param.cpu_f), &ms_clear_timer);
    break;

  case MMI_MASS_STORAGE:
    // Manage progress-bar shading.
    //
    if( cpu_is_timeout(&ms_clear_timer) )
    {
      cpu_set_timeout( cpu_ms_2_cy(TIMER_MS_PROGRESS_BAR_CLEAR,  pm_freq_param.cpu_f), &ms_clear_timer);
      mmi_ms_display();
    }

    // Manage progress-bar box moving.
    //
    if( cpu_is_timeout(&ms_activity_timer) )
    {
      cpu_set_timeout( cpu_ms_2_cy(TIMER_MS_PROGRESS_BAR_UPDATE, pm_freq_param.cpu_f), &ms_activity_timer);
      if( ms_old_cnt_write != ms_cnt_write )
      {
        ms_cnt_screen = (unsigned char)(ms_cnt_screen-1)%MS_N_PROGRESS_BAR;
        ms_progress_bar_type[ms_cnt_screen] = RED;

        // Compute performances
        //
        perf_write = (U64)(ms_cnt_write - ms_old_cnt_write)*SD_MMC_SECTOR_SIZE/TIMER_MS_PROGRESS_BAR_UPDATE;
        display_perf(120, 201, false, perf_write, RED);
        ms_old_cnt_write = ms_cnt_write;
        ms_progress_bar_level[ms_cnt_screen] = (perf_write>10000) ? 31 :
                                               (perf_write> 7500) ? 29 :
                                               (perf_write> 5000) ? 27 : 25 ;
      }
      else if( ms_old_cnt_read != ms_cnt_read )
      {
        ms_cnt_screen = (unsigned char)(ms_cnt_screen+1)%MS_N_PROGRESS_BAR;
        ms_progress_bar_type[ms_cnt_screen] = BLUE;

        // Compute performances
        //
        perf_read = (U64)(ms_cnt_read - ms_old_cnt_read)*SD_MMC_SECTOR_SIZE/TIMER_MS_PROGRESS_BAR_UPDATE;
        display_perf(120, 201, false, perf_read, BLUE);
        ms_old_cnt_read = ms_cnt_read;
        ms_progress_bar_level[ms_cnt_screen] = (perf_read>10000) ? 31 :
                                               (perf_read> 7500) ? 29 :
                                               (perf_read> 5000) ? 27 : 25 ;
      }
      else
      {
        display_perf(120, 201, true, 0, 0);
      }
    }

    // Detect USB unplug.
    //
    if( Is_usb_vbus_low() )
    {
      mmi_state = MMI_TOP_MENU_START;
    }
    break;

  default:
    break;
  }

}