usb_host_hub.c File Reference

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

Include dependency graph for usb_host_hub.c:

Go to the source code of this file.

Defines

#define HUB_MAX_NB_PORT   4

Functions

void hub_init (U8 hub_number)
U32 get_port_status (U8 port_number)
void hub_manage_port_change_status (U8 port_change_status, U8 hub_number)
void enumerate_hub_port_device (U8 hub_port, U8 port_ev, U8 hub_number)

Variables

U8 hub_port_state [USB_MAX_HUB_NUMBER][4]
 Enumeration state machine for each port of each hub.
U8 hub_device_address [USB_MAX_HUB_NUMBER]
 Table to store the device address of the hub connected in the USB tree.
U8 f_hub_port_disconnect = FALSE
 Flag to store device connection event.
U8 nb_hub_present
 The number of hub connected in the USB tree.


Detailed Description

This file manages the usb host hub requests and enumeration of the devices connected to the hub.

Author:
Atmel Corporation: http://www.atmel.com
Support and FAQ: http://support.atmel.no/

Definition in file usb_host_hub.c.


Define Documentation

#define HUB_MAX_NB_PORT   4

Definition at line 57 of file usb_host_hub.c.


Function Documentation

void hub_init ( U8  hub_number  ) 

This function initializes the enumeration state machines for each hub port

Parameters:
U8 hub_number
Returns:
void

Definition at line 88 of file usb_host_hub.c.

Referenced by enumerate_hub_port_device(), init_usb_tree(), and usb_host_task().

00089 {
00090    U8 i;
00091 
00092    for(i=0;i<HUB_MAX_NB_PORT;i++)
00093    {
00094       hub_port_state[hub_number][i]=HUB_DEVICE_POWERED;
00095    }
00096 }

Here is the caller graph for this function:

U32 get_port_status ( U8  port_number  ) 

This function returns the status of the specified usb hub port

Parameters:
U8 port_number
Returns:
status

Definition at line 108 of file usb_host_hub.c.

Referenced by hub_manage_port_change_status().

00109 {
00110    U32 to_return;
00111    
00112    Get_port_status(port_number);
00113    LSB3(to_return)=data_stage[3];
00114    LSB2(to_return)=data_stage[2];
00115    LSB1(to_return)=data_stage[1];
00116    LSB0(to_return)=data_stage[0];
00117    return to_return;
00118 }

Here is the caller graph for this function:

void hub_manage_port_change_status ( U8  port_change_status,
U8  hub_number 
)

This function decodes the change status repport from the hub interrupt pipe.

The function decodes hub port event and call the "enumerate_hub_port_device" function to manage the enumeration of the device connected to the hub port.

Parameters:
U8 port_change_status
U8 hub_number the number of the hub taht detects the event
Returns:
void

Definition at line 134 of file usb_host_hub.c.

Referenced by usb_host_task().

00135 {
00136    U8 i,c;
00137    U32 port_status;
00138    U8 port_addr_0_in_use=0;
00139    
00140    // There should be one and only one device on the bus responding to device address 0
00141    // Look in the hub_port_state state machine if one device is currently using this address
00142    // If another hub is currently using address zero, the function returns imediately
00143    for(i=0;i<USB_MAX_HUB_NUMBER;i++)
00144    {
00145       for(c=1;c<=HUB_MAX_NB_PORT;c++)
00146       {
00147          if((hub_port_state[i][c-1] != HUB_DEVICE_POWERED) && (hub_port_state[i][c-1] != HUB_DEVICE_READY))
00148          {
00149             //Found one port with one device using the address 0
00150             // memorize this port number
00151             if(i!=(hub_number-1)) 
00152             {  return; } //Other hub currently using address zero
00153             // ok the hub using the device address zero is the hub that currently generates the event (port_change_status)
00154             port_addr_0_in_use=c; 
00155             break;        
00156          }
00157       }
00158    }
00159    
00160    // For all ports 
00161    for(c=1;c<=HUB_MAX_NB_PORT;c++)
00162    {
00163       // One device connected to one port is using device address zero
00164       // Skip all other port activity management
00165       if((port_addr_0_in_use!=0) && (c!=port_addr_0_in_use) )
00166       {
00167          continue;
00168       }
00169       
00170       // Does this port generates port change status ?
00171       if(port_change_status & (1<<c))
00172       {
00173          // Get port status bytes
00174          port_status=get_port_status(c);
00175          // For each port event, send this event to the function that manage the 
00176          // state of the device connected to the hub port
00177          if( port_status & ((U32)1<<C_PORT_CONNECTION))
00178          {
00179             Clear_port_feature(C_PORT_CONNECTION,c);
00180             if(port_status&((U32)1<<PORT_CONNECTION))
00181             {
00182                // Port connection low speed -> Unsupported (no PRE token in current OTG interface implementation)
00183                if(port_status&((U32)1<<PORT_LOW_SPEED))
00184                {
00185 
00186                }
00187                else // Port Connection full speed : OK
00188                {
00189                   enumerate_hub_port_device(c,HUB_PORT_CONNECTION,hub_number);
00190                }
00191             }
00192             else
00193             {
00194                // Port disconnection
00195                enumerate_hub_port_device(c,HUB_PORT_DISCONNECT,hub_number);
00196             }
00197          }
00198          else if( port_status & ((U32)1<<C_PORT_SUSPEND))
00199          {
00200             // Port Suspend state
00201             Clear_port_feature(C_PORT_SUSPEND,c);
00202          }
00203          else if( port_status & ((U32)1<<C_PORT_RESET))
00204          {
00205             // Port Reset sent
00206             Clear_port_feature(C_PORT_RESET,c);
00207             enumerate_hub_port_device(c,HUB_PORT_RESET,hub_number);            
00208          }
00209       }
00210 
00211       // Previous port using device address zero abort all port device management  
00212       // (There should be one and only device with adddress zero on the USB tree)
00213       if((hub_port_state[hub_number-1][c-1] != HUB_DEVICE_POWERED) && (hub_port_state[hub_number-1][c-1] != HUB_DEVICE_READY))
00214       {
00215          break;  // Break port loop and exit from function      
00216       }
00217    }
00218 }

Here is the caller graph for this function:

void enumerate_hub_port_device ( U8  hub_port,
U8  port_ev,
U8  hub_number 
)

Manage the enumeration process of the device connected to the hub port number specified

Parameters:
U8 hub_port: the usb hub downstream port number
U8 port_ev: the hub port event detected
Returns:
none

Definition at line 229 of file usb_host_hub.c.

Referenced by hub_manage_port_change_status().

00230 {
00231    U8 device_index=0;
00232    U8 hub_device_index=0;
00233    U8 nb_port,c;
00234    
00235    // Find the device index of the hub_number
00236    for(c=0;c<MAX_DEVICE_IN_USB_TREE;c++)
00237    {
00238       if(usb_tree.device[c].device_address==hub_device_address[hub_number-1])
00239       {
00240          hub_device_index=c;         
00241       }
00242    }
00243    
00244    // Find the device index in linked to the specified hub port    
00245    // -> look in the usb_tree structure
00246    for(c=0;c<MAX_DEVICE_IN_USB_TREE;c++)
00247    {
00248       if((usb_tree.device[c].hub_port_nb == hub_port) && (usb_tree.device[c].parent_hub_number==hub_number))
00249       {
00250          device_index=c;
00251          break;
00252       }
00253    }
00254 
00255    // Port disconnection detected -> delete device entry and RAZ state machine
00256    // and return ...
00257    if(port_ev==HUB_PORT_DISCONNECT)
00258    {
00259       remove_device_entry(device_index);  // Remove device entry in usb tree
00260       usb_tree.nb_device--; 
00261       hub_port_state[hub_number-1][hub_port-1]=HUB_DEVICE_POWERED; // RAZ state machine 
00262       f_hub_port_disconnect = TRUE;   // Flag for device disconnection signaling
00263       return;
00264    }
00265    
00266    // Device enumeration state machine for hub port
00267    switch(hub_port_state[hub_number-1][hub_port-1])
00268    {
00269       // New device connection
00270       // -> Generate first USB reset for the device
00271       case HUB_DEVICE_POWERED:
00272          if(port_ev==HUB_PORT_CONNECTION)
00273          {
00274             device_index=usb_tree.nb_device++;
00275             usb_tree.device[device_index].hub_port_nb=hub_port;
00276             usb_tree.device[device_index].parent_hub_number=hub_number;
00277             Host_select_device(hub_device_index);
00278             Set_port_reset(hub_port);
00279             hub_port_state[hub_number-1][hub_port-1]=HUB_DEVICE_WAIT_RST_1;
00280          }
00281          break;
00282          
00283       // Wait First reset successfully generated then:
00284       // -> Get device descriptor to get endpoint zero lenght
00285       // -> Generate second USB reset for the device
00286       case HUB_DEVICE_WAIT_RST_1:
00287          if(port_ev==HUB_PORT_RESET)
00288          {
00289             c = 0;
00290             while (c<250)               // wait 250ms after USB reset
00291             {
00292                if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }// Count Start Of frame
00293                if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) 
00294                {hub_port_state[hub_number-1][hub_port-1]=HUB_DEVICE_POWERED; return;}
00295             }
00296             Host_select_device(device_index);
00297             // By default assumes its ctrl endpoint is 8 bytes only
00298             usb_tree.device[device_index].ep_ctrl_size=8;
00299             // Get its device descriptor to get ctrl endpoint size 
00300             if( CONTROL_GOOD == host_get_device_descriptor_uncomplete())
00301             {
00302                Host_select_device(hub_device_index);
00303                usb_tree.device[device_index].ep_ctrl_size=data_stage[OFFSET_FIELD_MAXPACKETSIZE];
00304                Set_port_reset(hub_port);         // Second USB reset
00305                hub_port_state[hub_number-1][hub_port-1]=HUB_DEVICE_WAIT_RST_2;
00306             }
00307          }
00308          break;
00309 
00310       // Wait Second USB reset successfully generated then:
00311       // -> Enumerate the new device
00312       case HUB_DEVICE_WAIT_RST_2:
00313          if(port_ev==HUB_PORT_RESET)
00314          {
00315             c = 0;
00316             while (c<250)               // wait 250ms after USB reset
00317             {
00318                if (Is_usb_event(EVT_HOST_SOF)) { Usb_ack_event(EVT_HOST_SOF); c++; }// Count Start Of frame
00319                if (Is_host_emergency_exit() || Is_usb_bconnection_error_interrupt()) 
00320                {hub_port_state[hub_number-1][hub_port-1]=HUB_DEVICE_POWERED; return;}
00321             }
00322             // Select this new device
00323             Host_select_device(device_index);
00324 
00325             // Give an absolute device address
00326             host_set_address(DEVICE_BASE_ADDRESS+device_index);
00327             usb_tree.device[+device_index].device_address=DEVICE_BASE_ADDRESS+device_index;
00328 
00329             // Select this new address
00330             Host_select_device(device_index); 
00331 
00332             // Get the device descriptor 
00333             if (CONTROL_GOOD == host_get_device_descriptor())
00334             {
00335                // Check if the device connected belongs to the supported devices table
00336                if (HOST_TRUE == host_check_VID_PID())
00337                {
00338                   Host_set_device_supported();
00339                   Host_device_supported_action();
00340                }
00341                else
00342                {
00343                #if (HOST_STRICT_VID_PID_TABLE==ENABLE)
00344                   Host_device_not_supported_action();
00345                   return
00346                #endif
00347                }
00348                // Get Confiuration descriptor
00349                if (CONTROL_GOOD == host_get_configuration_descriptor())
00350                {
00351                   if (HOST_FALSE != host_check_class()) // Class support OK?
00352                   {
00353                   #if (HOST_AUTO_CFG_ENDPOINT==ENABLE)
00354                      if (host_auto_configure_endpoint())
00355                   #else
00356                      if(User_configure_endpoint()) // User call here instead of autoconfig
00357                   #endif
00358                      {
00359                         if (CONTROL_GOOD == host_set_configuration(1))  // Send Set_configuration
00360                         {
00361                            hub_port_state[hub_number-1][hub_port-1] = HUB_DEVICE_READY;
00362                             // Check if the connected device is a HUB
00363                            if(Get_class(0)==HUB_CLASS )
00364                            {
00365                                  // Get hub descriptor
00366                                  if( Get_hub_descriptor()==CONTROL_GOOD)
00367                                  {
00368                                     // Power each port of the hub
00369                                     nb_port=data_stage[NB_PORT_OFFSET];
00370                                     for(c=1;c<=nb_port;c++)
00371                                     {
00372                                        Set_port_feature(PORT_POWER,c);
00373                                     }
00374                                     nb_hub_present++;
00375                                     hub_init(nb_hub_present-1);
00376                                     hub_device_address[nb_hub_present-1]=usb_tree.device[device_index].device_address;
00377                                  }
00378                            }
00379                            else // New device is not a hub -> Signals device connection
00380                            {
00381                               new_device_connected=TRUE;
00382                            }
00383                         }
00384                      }
00385                   }
00386                }
00387             }
00388          }
00389          break;
00390          
00391       case HUB_DEVICE_READY:
00392          break;
00393       default:
00394          break;
00395    }
00396 }

Here is the caller graph for this function:


Variable Documentation

U8 hub_port_state[USB_MAX_HUB_NUMBER][4]

Enumeration state machine for each port of each hub.

Definition at line 68 of file usb_host_hub.c.

Referenced by enumerate_hub_port_device(), hub_init(), hub_manage_port_change_status(), and remove_device_entry().

U8 hub_device_address[USB_MAX_HUB_NUMBER]

Table to store the device address of the hub connected in the USB tree.

Definition at line 71 of file usb_host_hub.c.

Referenced by enumerate_hub_port_device(), init_usb_tree(), remove_device_entry(), and usb_host_task().

U8 f_hub_port_disconnect = FALSE

Flag to store device connection event.

Definition at line 74 of file usb_host_hub.c.

Referenced by enumerate_hub_port_device(), and usb_host_task().

U8 nb_hub_present

The number of hub connected in the USB tree.

Definition at line 77 of file usb_host_hub.c.

Referenced by enumerate_hub_port_device(), host_auto_configure_endpoint(), remove_device_entry(), and usb_host_task().


Generated on Fri May 15 15:41:46 2009 for ATMEL by  doxygen 1.5.3