ATMEL: usb_host_hub.c File Reference

- 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 60 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 91 of file usb_host_hub.c.

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

    00092 {
    00093    U8 i;
    00094
    00095    for(i=0;i<HUB_MAX_NB_PORT;i++)
    00096    {
    00097       hub_port_state[hub_number][i]=HUB_DEVICE_POWERED;
    00098    }
    00099 }

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 111 of file usb_host_hub.c.

Referenced by hub_manage_port_change_status().

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

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 137 of file usb_host_hub.c.

Referenced by usb_host_task().

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

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 232 of file usb_host_hub.c.

Referenced by hub_manage_port_change_status().

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

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 71 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 74 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 77 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 80 of file usb_host_hub.c.

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