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

📄 usb_host_enum.c

📁 ATMEL 90usb128 USB source,include USB protocol stack.
💻 C
📖 第 1 页 / 共 2 页
字号:
//! @file usb_host_enum.c,v
//!
//! Copyright (c) 2004 Atmel.
//!
//! Use of this program is subject to Atmel's End User License Agreement.
//! Please read file license.txt for copyright notice.
//!
//! @brief This file manages the host enumeration process.
//!
//!
//! @version 1.12 at90usb128-usbkey-demo-3enum-host-mouse-1_0_4 $Id: usb_host_enum.c,v 1.12 2006/07/24 15:03:23 rletendu Exp $
//!
//! @todo
//! @bug

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

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

//_____ M A C R O S ________________________________________________________


//_____ D E F I N I T I O N ________________________________________________

//_____ P R I V A T E   D E C L A R A T I O N ______________________________

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

#if (MAX_INTERFACE_SUPPORTED<1)
#error MAX_INTERFACE_SUPPORTED<1 : The host controller should support at least one interface...
#endif

#if (USB_HOST_FEATURE == ENABLED)
extern S_usb_setup_data usb_request;



#ifndef VID_PID_TABLE
   #error VID_PID_TABLE shoud be defined somewhere (conf_usb.h)
  /*   VID_PID_TABLE format definition:
  //   #define VID_PID_TABLE      {VID1, number_of_pid_for_this_VID1, PID11_value,..., PID1X_Value \
  //                              ...\
  //                              ,VIDz, number_of_pid_for_this_VIDz, PIDz1_value,..., PIDzX_Value}
  */
#endif

#ifndef CLASS_SUBCLASS_PROTOCOL
   #error CLASS_SUBCLASS_PROTOCOL shoud be defined somewhere (conf_usb.h)
  /*   CLASS_SUBCLASS_PROTOCOL format definition:
  //   #define CLASS_SUBCLASS_PROTOCOL  {CLASS1, SUB_CLASS1,PROTOCOL1, \
  //                                     ...\
  //                                     CLASSz, SUB_CLASSz,PROTOCOLz}
  */
#endif


//! Const table of known devices (see conf_usb.h for table content)
U16 registered_VID_PID[]   = VID_PID_TABLE;

//! Const table of known class (see conf_usb.h for table content)
U8  registered_class[]     = CLASS_SUBCLASS_PROTOCOL;

//! Physical EP to address device endpoints look-up table
//  This table is dynamically built with the "host_configure_endpoint_class" function
U8 ep_table[MAX_EP_NB]={0,0,0,0,0,0,0};

//! The number of interface the host is able to support in the device connected
U8 nb_interface_supported=0;

S_interface interface_supported[MAX_INTERFACE_SUPPORTED];

//! PID of device connected
U16 device_PID;
//! VID of device connected
U16 device_VID;
//! bmAttributes byte of the connected device
U8 bmattributes;
//! maxpower byte of the connected device (Caution, unit is 2mA)
U8 maxpower;



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

/**
 * host_check_VID_PID
 *
 * @brief This function checks if the VID and the PID are supported
 * (if the VID/PID belongs to the VID_PID table)
 *
 * @param none
 *
 * @return status
 */
U8 host_check_VID_PID(void)
{
U8  c,d;

   // Rebuild VID PID from data stage
   LSB(device_VID) = data_stage[OFFSET_FIELD_LSB_VID];
   MSB(device_VID) = data_stage[OFFSET_FIELD_MSB_VID];
   LSB(device_PID) = data_stage[OFFSET_FIELD_LSB_PID];
   MSB(device_PID) = data_stage[OFFSET_FIELD_MSB_PID];

   // Compare detected VID PID with supported table
   c=0;
   while (c< sizeof(registered_VID_PID)/2)   // /2 because registered_VID_PID table is U16...
   {
      if (registered_VID_PID[c] == device_VID)   // VID is correct
      {
         d = (U8)registered_VID_PID[c+1];    // store nb of PID for this VID
         while (d != 0)
         {
            if (registered_VID_PID[c+d+1] == device_PID)
            {
               return HOST_TRUE;
            }
            d--;
         }
      }
      c+=registered_VID_PID[c+1]+2;
   }
   return HOST_FALSE;
}

/**
 * host_check_class
 *
 * @brief This function checks if the device class is supported.
 * The function looks in all interface declared in the received dewcriptors, if
 * one of them match with the CLASS/SUB_CLASS/PROTOCOL table
 *
 * @param none
 *
 * @return status
 */
U8 host_check_class(void)
{
U8  c;
T_DESC_OFFSET  descriptor_offset;
T_DESC_OFFSET  conf_offset_end;
U16  config_size;
U8  device_class;
U8  device_subclass;
U8  device_protocol;

   nb_interface_supported=0;   //First asumes ,no interface is supported!
   if (data_stage[OFFSET_FIELD_DESCRIPTOR_TYPE] != CONFIGURATION_DESCRIPTOR)           // check if configuration descriptor
   { return HOST_FALSE;}
   LSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT];
   MSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT+1];
   bmattributes = data_stage[OFFSET_FIELD_BMATTRIBUTES];
   maxpower = data_stage[OFFSET_FIELD_MAXPOWER];
   descriptor_offset = 0;
   conf_offset_end = descriptor_offset + config_size;

   // Look in all interfaces declared in the configuration
   while(descriptor_offset < conf_offset_end)
   {
      // Find next interface descriptor
      while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != INTERFACE_DESCRIPTOR)
      {
         descriptor_offset += data_stage[descriptor_offset];
         if(descriptor_offset >= conf_offset_end)
         {
            if(nb_interface_supported)
            {return HOST_TRUE;}
            else return HOST_FALSE;
         }
      }
      // Found an interface descriptor
      // Get charateristics of this interface
      device_class    = data_stage[descriptor_offset + OFFSET_FIELD_CLASS];
      device_subclass = data_stage[descriptor_offset + OFFSET_FIELD_SUB_CLASS];
      device_protocol = data_stage[descriptor_offset + OFFSET_FIELD_PROTOCOL];
      // Look in registered class table for match
      c=0;
      while (c< sizeof(registered_class))
      {
         if (registered_class[c] == device_class)                 // class is correct!
         {
            if (registered_class[c+1] == device_subclass)         // sub class is correct!
            {
               if (registered_class[c+2] == device_protocol)      // protocol is correct!
               {
                  // Prepare for another item CLASS/SUB_CLASS/PROTOCOL in table
                  c+=3;
                  // Store this interface as supported interface
                  // Memorize its interface nb
                  interface_supported[nb_interface_supported].interface_nb=data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB];
                  //          its alternate setting
                  interface_supported[nb_interface_supported].altset_nb=data_stage[descriptor_offset+OFFSET_FIELD_ALT];
                  //          its USB class
                  interface_supported[nb_interface_supported].class=device_class;
                  //          its USB subclass
                  interface_supported[nb_interface_supported].subclass=device_subclass;
                  //          its USB protocol
                  interface_supported[nb_interface_supported].protocol=device_protocol;
                  //          the number of endpoints associated to this interface
                  //          Note: The associated endpoints addresses are stored during pipe attribution...
                  interface_supported[nb_interface_supported].nb_ep=data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
                  // Update the number of interface supported
                  nb_interface_supported++;
                  // Check the maximum number of interfaces we can support
                  if(nb_interface_supported>=MAX_INTERFACE_SUPPORTED)
                  {
                     return HOST_TRUE;
                  }
               }
            }
         }
         c+=3; // Check other item CLASS/SUB_CLASS/PROTOCOL in table
      }
      descriptor_offset += data_stage[descriptor_offset]; // Next descriptor
      if(descriptor_offset > SIZEOF_DATA_STAGE)           // Check overflow
      {
         if(nb_interface_supported)
         {return HOST_TRUE;}
         else return HOST_FALSE;
      }
   }
   if(nb_interface_supported)
   { return HOST_TRUE; }
   else return HOST_FALSE;
}

 /**
 * @brief This function configures the pipe according to the device class of the
 * interface selected
 *
 * @return status
 */
U8 host_auto_configure_endpoint()
{
U8  nb_endpoint_to_configure;
T_DESC_OFFSET  descriptor_offset;
U8  physical_pipe=1;   // =1 cause lookup table assumes that physiacl pipe 0 is reserved for control
U8 i;
U8 ep_index;

   // For all interfaces to configure...
   for(i=0;i<nb_interface_supported;i++)
   {
      ep_index=0;
      // First look for the target interface descriptor offset
      descriptor_offset = get_interface_descriptor_offset(interface_supported[i].interface_nb,interface_supported[i].altset_nb);
      // Get the number of endpoint to configure for this interface
      nb_endpoint_to_configure = data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
      // Get the first Endpoint descriptor offset to configure
      descriptor_offset += data_stage[descriptor_offset+OFFSET_DESCRIPTOR_LENGHT];  // pointing on endpoint descriptor

      // While there is at least one pipe to configure
      while (nb_endpoint_to_configure)
      {
         // Check and look for an Endpoint descriptor
         while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != ENDPOINT_DESCRIPTOR)
         {
            descriptor_offset += data_stage[descriptor_offset];
            if(descriptor_offset > SIZEOF_DATA_STAGE)   // No more endpoint descriptor found -> Errror !
            {  return HOST_FALSE; }
         }

        // Select the new physical pipe to configure and get ride of any previous configuration for this physical pipe
         Host_select_pipe(physical_pipe);
         Host_disable_pipe();
         Usb_unallocate_memory();
         Host_enable_pipe();

         // Build the pipe configuration according to the endpoint descriptors fields received
         //
         // host_configure_pipe(
         //    physical_pipe,                                                                    // pipe nb in USB interface
         //    data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                               // pipe type (interrupt/BULK/ISO)
         //    Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),               // pipe addr
         //    (data_stage[descriptor_offset+2] & MSK_EP_DIR),                                   // pipe dir (IN/OUT)
         //    host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),// pipe size
         //    ONE_BANK,                                                                         // bumber of bank to allocate for pipe
         //    data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                            // interrupt period (for interrupt pipe)
         //  );
         host_configure_pipe(                                                          \
            physical_pipe,                                                             \
            data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                        \
            Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),        \
            (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),                            \
            host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),\
            ONE_BANK,                                                                  \
            data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                     \
         );

         // Update Physical Pipe lookup table with device enpoint address
         ep_table[physical_pipe]=data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
         physical_pipe++;
         // Update endpoint addr table in supported interface structure
         interface_supported[i].ep_addr[ep_index++]=data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
         descriptor_offset += data_stage[descriptor_offset];             // pointing on next descriptor

         // All target endpoints configured ?
         nb_endpoint_to_configure--;
      } //for(i=0;i<nb_interface_supported;i++)
   }
   Host_set_configured();
   return HOST_TRUE;
}

/**
 * get_interface_descriptor_offset
 *
 * @brief This function returns the offset in data_stage where to find the interface descriptor
 * whose number and alternate setting values are passed as parameters

⌨️ 快捷键说明

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