⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_host_task.c

📁 ATMEL 90usb128 USB source,include USB protocol stack.
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 * @file usb_host_task.c,v
 *
 * Copyright (c) 2004 Atmel.
 *
 * Please read file license.txt for copyright notice.
 *
 * @brief This file manages the USB Host controller, the host enumeration process
 *        and suspend resume host requests.
 *
 * This task dos not belongs to the scheduler tasks but is called directly from the general usb_task
 *
 * @version 1.19 at90usb128-usbkey-demo-3enum-host-mouse-1_0_4 $Id: usb_host_task.c,v 1.19 2006/10/13 13:34:12 rletendu Exp $
 *
 *
 * @todo
 * @bug
 */

//_____  I N C L U D E S ___________________________________________________

#include "config.h"
#include "conf_usb.h"
#include "modules/usb/usb_task.h"
#include "usb_host_task.h"
#include "lib_mcu/usb/usb_drv.h"
#include "lib_mcu/pll/pll_drv.h"
#include "modules/usb/host_chap9/usb_host_enum.h"


#if (USB_HOST_FEATURE == DISABLED)
   #warning trying to compile a file used with the USB HOST without USB_HOST_FEATURE enabled
#endif

#if (USB_HOST_FEATURE == ENABLED)

#ifndef DEVICE_ADDRESS
   #error DEVICE_ADDRESS should be defined somewhere in config files (conf_usb.h)
#endif

#ifndef SIZEOF_DATA_STAGE
   #error SIZEOF_DATA_STAGE should be defined in conf_usb.h
#endif

#ifndef HOST_CONTINUOUS_SOF_INTERRUPT
   #error HOST_CONTINUOUS_SOF_INTERRUPT should be defined as ENABLE or DISABLE in conf_usb.h
#endif

#ifndef USB_HOST_PIPE_INTERRUPT_TRANSFER
   #error USB_HOST_PIPE_INTERRUPT_TRANSFER should be defined as ENABLE or DISABLE in conf_usb.h
#endif

#ifndef Usb_id_transition_action
   #define Usb_id_transition_action()
#endif
#ifndef  Host_device_disconnection_action
   #define Host_device_disconnection_action()
#endif
#ifndef  Host_device_connection_action
   #define Host_device_connection_action()
#endif
#ifndef  Host_sof_action
   #define Host_sof_action()
#endif
#ifndef  Host_suspend_action
   #define Host_suspend_action()
#endif
#ifndef  Host_hwup_action
   #define Host_hwup_action()
#endif
#ifndef  Host_device_not_supported_action
   #define Host_device_not_supported_action()
#endif
#ifndef  Host_device_class_not_supported_action
   #define Host_device_class_not_supported_action()
#endif
#ifndef  Host_device_supported_action
   #define Host_device_supported_action()
#endif
#ifndef  Host_device_error_action
   #define Host_device_error_action()
#endif


//_____ M A C R O S ________________________________________________________

#ifndef LOG_STR_CODE
#define LOG_STR_CODE(str)
#else
U8 code log_device_connected[]="Device Connection";
U8 code log_device_enumerated[]="Device Enumerated";
U8 code log_device_unsupported[]="Unsupported Device";
U8 code log_going_to_suspend[]="Usb suspend";
U8 code log_usb_resumed[]="Usb resumed";
#endif

//_____ D E F I N I T I O N S ______________________________________________

//_____ D E C L A R A T I O N S ____________________________________________

#if (USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE)
   volatile S_pipe_int   it_pipe_str[MAX_EP_NB];
   volatile U8 pipe_nb_save;
   U8 g_sav_int_sof_enable;
#endif

//!
//! Public : U8 device_state
//! Its value represent the current state of the
//! device connected to the usb host controller
//! Value can be:
//! - DEVICE_ATTACHED
//! - DEVICE_POWERED
//! - DEVICE_SUSPENDED
//! - DEVICE_DEFAULT
//! - DEVICE_ADDRESSED
//! - DEVICE_CONFIGURED
//! - DEVICE_ERROR
//! - DEVICE_UNATTACHED
//! - DEVICE_READY
//! - DEVICE_WAIT_RESUME
//! - DEVICE_DISCONNECTED
//! - DEVICE_DISCONNECTED_ACK
//!/
U8 device_state;

//! For control requests management over pipe 0
S_usb_setup_data usb_request;

//!
//! Public : U8 data_stage[SIZEOF_DATA_STAGE];
//! Internal RAM buffer for USB data stage content
//! This buffer is required to setup host enumeration process
//! Its contains the device descriptors received.
//! Depending on the device descriptors lenght, its size can be optimized
//! with the SIZEOF_DATA_STAGE define of conf_usb.h file
//!
//!/
U8 data_stage[SIZEOF_DATA_STAGE];


U8 device_status;
U8 request_resume;
U8 force_enumeration=FALSE;


static U16  c;                // As internal host start of frame counter

U8 new_device_connected=0;


/**
 * @brief This function initializes the USB controller in host mode and
 *        the associated variables.
 *
 * This function enables the USB controller for host mode operation.
 *
 * @param none
 *
 * @return none
 *
 */
void usb_host_task_init(void)
{
   Pll_start_auto();
   Wait_pll_ready();
   Usb_disable();
   Usb_enable();
   Usb_unfreeze_clock();
   Usb_attach();
   Usb_enable_uvcon_pin();
   Usb_select_host();
   Usb_disable_vbus_hw_control();   // Force Vbus generation without timeout
   Host_enable_device_disconnection_interrupt();
   device_state=DEVICE_UNATTACHED;
}

/**
 * @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:
         for (c=0;c<MAX_EP_NB;c++) {ep_table[c]=0;}// Reset PIPE lookup table with device EP addr
         nb_interface_supported=0;
         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=0;
#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();
            for (c=0;c<MAX_EP_NB;c++) {ep_table[c]=0;}// Reset PIPE lookup table with device EP addr
            nb_interface_supported=0;
            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=0;
            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();
            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;
               Host_select_pipe(PIPE_CONTROL);
               Host_enable_pipe();
               host_configure_pipe(PIPE_CONTROL, \
                                   TYPE_CONTROL, \
                                   TOKEN_SETUP,  \
                                   EP_CONTROL,   \
                                   SIZE_8,      \
                                   ONE_BANK,     \
                                   0             );
               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
         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;
                  }
               }
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -