USB Host Programming Guide#

This section explains how to use the USB Host module.

Initial Setup of USB Host Module#

This section describes the basic steps required to initialize the USB Host module and to add and start a host controller.

Initializing the USB Host Module#

Initializing the USB Host Core#

The first step is to initialize the USB host module core. This is done by calling the function USBH_Init().

Listing - Example of call to USBH_Init() in the Initial Setup of USB Host Module page shows an example of a call to USBH_Init() that will create a single host. For more information on the configuration arguments to pass to USBH_Init(), see USB Host Run-Time Application Specific Configurations .

Listing - Example of call to USBH_Init()#
RTOS_ERR  err;

USBH_Init(1u,
         &err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

Initializing the USB Host PBHCI Module (not always necessary)#

If at least one of the drivers you use is of type PBHCD (Pipe-Based Host Controller Driver), you must initialize the Pipe-Based Host Controller Interface (PBHCI). This is done by calling the function USBH_PBHCI_Init().

For more information on the PBHCI, and to learn how to determine the type of your driver(s), refer to USB Host Hardware Porting Guide .

Listing - Example of call to USBH_PBHCI_Init() in the Initial Setup of USB Host Module page gives an example of a call to USBH_PBHCI_Init().

Listing - Example of call to USBH_PBHCI_Init()#
RTOS_ERR  err;

USBH_PBHCI_Init(&err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

Initializing the Class(es)#

Once the USB host module core has been initialized, you must initialize each class you intend to use. See the programming guide of your class(es) for more information.

Adding Your Host Controller(s)#

Once you successfully initialized the USB host module, you can start adding your host controller(s). This is done by calling the function USBH_HC_Add(). This function must be called for each host controller you want to add.

Listing - Example of call to USBH_HC_Add() in the Initial Setup of USB Host Module page shows an example of a call to USBH_HC_Add() using default arguments. In this example, USB host controller "usb0" is added to the USB host module. For more information about the configuration arguments to pass to USBH_HC_Add(), see USB Host Controller Driver Configuration . For more information on how to register a USB controller (if you have to write your own BSP), see USB Host Hardware Porting Guide .

Listing - Example of call to USBH_HC_Add()#
RTOS_ERR        err;
USBH_HC_HANDLE  hc_handle;

hc_handle = USBH_HC_Add("usb0",
                         DEF_NULL,
                        &err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

If your platform uses companion controller(s) (for example, an OHCI controller that is a companion of an EHCI controller), the main controller must always be added before the companion controller(s).

Starting Your Host Controller(s)#

Once you successfully added your host controller(s), you should start it/them. This is done by calling the function USBH_HC_Start(). This function must be called for each host controller you added.

Listing - Example of call to USBH_HC_Start() in the Initial Setup of USB Host Module page gives an example of call to USBH_HC_Start().

Listing - Example of call to USBH_HC_Start()#
RTOS_ERR  err;

USBH_HC_Start(hc_handle,
             &err);
if (err.Code != RTOS_ERR_NONE) {
    /* An error occurred. Error handling should be added here. */
}

If your platform uses companion controller(s) (for example, an OHCI controller that is a companion of an EHCI controller), the main controller must always be started after the companion controller(s).

A Note on the Usage of Companion Controllers#

When a USB host controller uses one or more companion controller(s), each controller must be added separately. However, the order is very important for the add and start procedures.

Add#

When adding the USB controllers (via the function USBH_HC_Add()), you must always add the main controller first. Then you can add the companion controller(s) in no particular order.

Start#

When starting the USB controllers (via the function USBH_HC_Start()), you must always start the companion controller(s) first. Then you can start the main controller once its companion controller(s) are started.

USB Host Event Callbacks Usage#

The USB Host module offers a set of callbacks that are called when certain events occur. These callbacks are given to the USB host module via a configuration structure of type USBH_EVENT_FNCTS. Note that these callbacks are optional and you can define only the ones you actually need. Any callbacks in this structure can be set to null (DEF_NULL). Listing - Example of USBH_EVENT_FNCTS declaration in the USB Host Event Callbacks Usage page gives an example of how to create the structure of type USBH_EVENT_FNCTS. In the following sections, each callback function will be explained.

Listing - Example of USBH_EVENT_FNCTS declaration#
USBH_EVENT_FNCTS  App_USBH_EventFncts = {
    .DevConnAccept   = App_USBH_DevConnAccept,
    .DevConfigAccept = App_USBH_DevConfigAccept,
    .DevConfig       = App_USBH_DevConfig,
    .FnctConnFail    = App_USBH_FnctConnFail,
    .DevConnFail     = App_USBH_DevConnFail,
    .DevResume       = DEF_NULL,              /* Device remote wake-up functionality not yet implemented. */
    .DevDisconn      = App_USBH_DevDisconn
};

DevConnAccept#

This function will be called when a device is connected. When this function is called, the device is still in the addressed state (configuration information have not yet been retrieved). This is useful to deny specific device connections (for example, if too many devices are connected, or to filter device connections based on their vendor and product IDs).

If, while in this function, you call core functions that take a USBH_DEV_HANDLE as argument, the special value USBH_DEV_HANDLE_NOTIFICATION must be used.

This function returns a boolean. You must return DEF_YES if you accept the device connection, you must return DEF_NO otherwise. Note that if you set the .DevConnAccept field of your USBH_EVENT_FNCTS structure to DEF_NULL, all the device connections will be accepted.

Listing - Example of DevConnAccept callback function in the USB Host Event Callbacks Usage page shows an example of implementation of a DevConnAccept() function where a device that has a particular vendor ID will be denied.

Listing - Example of DevConnAccept callback function#
CPU_BOOLEAN  App_USBH_DevConnAccept ()
{
    CPU_BOOLEAN  accept    = DEF_YES;
    CPU_INT16U   vendor_id;
    RTOS_ERR     err;

    vendor_id = USBH_DevVendorID_Get(USBH_DEV_HANDLE_NOTIFICATION,
                                    &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* An error occurred. Error handling should be added here. */
    }

    if (vendor_id == <some denied vendor>) {
        accept = DEF_NO;
    }

    return (accept);
}

DevConfigAccept#

This function will be called when a device is connected, just before setting the configuration. At this moment, all the configuration information has been retrieved. This is useful to deny enabling the configuration (for example, if the configuration will draw too much power).

If, while in this function, you call core functions that take a USBH_DEV_HANDLE as argument, the special value USBH_DEV_HANDLE_NOTIFICATION must be used.

This function returns a boolean. You must return DEF_YES if you accept the configuration, and you must return DEF_NO otherwise. Note that if you set the .DevConfigAccept field of your USBH_EVENT_FNCTS structure to DEF_NULL, all the configurations will be accepted.

Also note that if you deny the configuration, you can request another configuration to be set for this device later or before returning from this function by calling the function USBH_DevConfigSet().

Listing - Example of DevConfigAccept callback function in the USB Host Event Callbacks Usage page shows an example of implementation of a DevConfigAccept() function where a configuration that draws more than 250 mA will be denied.

Listing - Example of DevConfigAccept callback function#
CPU_BOOLEAN  App_USBH_DevConfigAccept ()
{
    CPU_BOOLEAN  accept  = DEF_YES;
    CPU_INT16U   max_pwr;
    RTOS_ERR     err;

    max_pwr = USBH_ConfigMaxPwrGet(USBH_DEV_HANDLE_NOTIFICATION,
                                  &err);
    if (err.Code != RTOS_ERR_NONE) {
        /* An error occurred. Error handling should be added here. */
    }

    if ((max_pwr * 2u) > 250u) {
        accept = DEF_NO;
    }

    return (accept);
}

DevConfig#

This function will be called when a device configuration has been set. At this moment, the device is ready for communication.

This function will also be called if the configuration set has failed. In this case, the argument err will give more information about the cause of the failure.

This function will provide a device handle to your application that can be saved for later use. From this point on (and within this function), the special value USBH_DEV_HANDLE_NOTIFICATION should not be used.

Listing - Example of DevConfig callback function in the USB Host Event Callbacks Usage page shows an example of implementation of a DevConfig() function where the application ensures that the configuration set was successful and saves the device handle if it was.

Listing - Example of DevConfig callback function#
USBH_DEV_HANDLE  latest_dev_handle;

void  App_USBH_DevConfig (USBH_DEV_HANDLE  dev_handle,
                          CPU_INT08U       config_nbr,
                          RTOS_ERR         err)
{
    if (err.Code == RTOS_ERR_NONE) {
        latest_dev_handle = dev_handle;
    } else {
        /* Configuration set has failed. Error handling should be added here. */
    }
}

FnctConnFail#

This function will be called when a function connection within a USB configuration has failed. This is useful to retrieve the cause of the failure. Also consider that if a multi-function device is connected, the configuration will be set as long as at least one function connected successfully.

Typical cause of failures are:

  • Cannot allocate the required resources

  • No class driver can handle the function

  • Not enough bandwidth

The argument err should be checked to get more information on the cause of the failure.

Listing - Example of FnctConnFail callback function in the USB Host Event Callbacks Usage page shows an example of implementation of a FnctConnFail() function where the application retrieves the error code associated with the failure.

Listing - Example of FnctConnFail callback function#
void  App_USBH_FnctConnFail (USBH_FNCT_HANDLE  fnct_handle,
                             RTOS_ERR          err)
{
    /* Function connection has failed. Error handling should be added here. */
}

DevConnFail#

This function will be called when a device connection has failed. It can be use to retrieve the cause of the failure.

Typical cause of failures are:

  • Cannot allocate the required resources

  • No class driver can handle the device

  • All the device's functions connection have failed

  • Not enough bandwidth

The argument err should be checked to get more information on the cause of the failure.

Listing - Example of DevConnFail callback function in the USB Host Event Callbacks Usage page shows an example of implementation of a DevConnFail() function where the application retrieves the error code associated with the failure.

Listing - Example of DevConnFail callback function#
void  App_USBH_DevConnFail (CPU_INT08U  hub_addr,
                            CPU_INT08U  port_nbr,
                            RTOS_ERR    err)
{
    /* Device connection has failed. Error handling should be added here. */
}

DevDisconn#

This function will be called when a device is disconnected.

Listing - Example of DevDisconn callback function in the USB Host Event Callbacks Usage page shows an example of implementation of a DevDisconn() function.

Listing - Example of DevDisconn callback function#
void  App_USBH_DevDisconn (USBH_DEV_HANDLE  dev_handle)
{
    /* Device was disconnected. All saved references to the device should be cleared. */
}