📄 usb_host_enum.c
字号:
//! @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 + -