- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# 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.

- Compiler: IAR EWAVR and GNU GCC for AVR
- Supported devices: AT90USB1287, AT90USB1286, AT90USB647, AT90USB646

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().