USB Device Programming Guide

This section explains how to use the USB Device module.

Initial Setup of USB Device Module

This section describes the basic steps required to initialize the USB Device module and to add, prepare, and start a device.

Initializing the USB Device Module

Initializing the USB Device Core

Begin by initializing the USB device module core by calling the function sl_usbd_core_init().

The example below shows calling sl_usbd_core_init().

Example - Calling sl_usbd_core_init()
sl_status_t status;

status = sl_usbd_core_init();
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Initializing the Class(es)

After the USB device module core has been initialized, you must initialize each class you intend to use. See section "Programming Guide" of your class(es) for more information.

Building Your USB Device

Adding Configuration(s)

After you successfully initialize your device, you can start adding the USB functions to it, starting with a new configuration. A device must have at least one configuration. To add configuration(s), call the function sl_usbd_core_add_configuration() function. This function must be called for each configuration you want to add.

The example below shows how to add a Full-speed.

Example - Adding Configuration(s) to Your Device
sl_status_t  status;
uint8_t      config_nbr_fs;

/* Adding a full-speed configuration to the device.   */
status = sl_usbd_core_add_configuration(0,                                      /* No special attributes to the configuration. */
                                        100u,                                   /* Max power consumption: 100mA.               */
                                        SL_USBD_DEVICE_SPEED_FULL,              /* Full-Speed configuration.                   */
                                        "Config Add Example Full-Speed config",
                                        &config_nbr_fs);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Adding USB Function(s)

After you have successfully added at least one configuration to your device, you can add the interfaces and endpoints to your device. Each USB class has its own needs in terms of interface and endpoints type, quantity, and other parameters. Silicon Labs USB Device adds interfaces and endpoints in the classes it offers.

From your application, you can instantiate a USB class and add it to a configuration. For more information on the concept of USB device class instances, see USB Device Classes. Note that you can instantiate and add many different class instances to a configuration to create a multi-function (composite) device.

The example below shows how to create a class instance and add it to a configuration.

Example - Adding a Class Instance to Your Device
sl_status_t  status;
uint8_t      class_nbr;

/* Create an instance of the class you want to use.*/
/* Note that depending on the class this function can have more arguments. */
status = sl_usbd_<class>_create_instance(&class_nbr);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

/* Add the class instance to the Full-Speed configuration. */
status = sl_usbd_<class>_add_to_configuration(class_nbr,       /* Class number returned by sl_usbd_<class>_create_instance.          */
                                              config_nbr_fs);  /* Configuration number returned by sl_usbd_core_add_configuration(). */
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Starting Your USB Device

By default, the device will be started automatically by the USB device core task after the device initialization is completed and the kernel started. To control when the device is started and becomes visible by the USB host, use the configuration define SL_USBD_AUTO_START_USB_DEVICE to disable the auto-start feature. When disabled, after you have built/prepared your device, you can start it and make it visible to the USB host by calling the function sl_usbd_core_start_device().

The example below shows how to start your device using the sl_usbd_core_start_device() function.

Example - Starting Your Device
sl_status_t  status;

status = sl_usbd_core_start_device();
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Event Hook Functions

The USB Device core module offers two weak hook functions that you can re-defined in your application. Their purpose is to notify when bus and configuration events occur.

Table - USB Event Hook Functions
Event Description Function Signature
Bus Called when USB Bus event occurs void sl_usbd_on_bus_event(sl_usbd_bus_event_t event);
Configuration Called when USB Configuration event occurs void sl_usbd_on_config_event(sl_usbd_config_event_t event, uint8_t config_nbr);
Example - Event Hook Functions
void sl_usbd_on_bus_event(sl_usbd_bus_event_t event) {
  switch (event) {
    case SL_USBD_EVENT_BUS_CONNECT:
      // called when USB cable is inserted in a host controller
      break;

    case SL_USBD_EVENT_BUS_DISCONNECT:
      // called when USB cable is removed from a host controller
      break;

    case SL_USBD_EVENT_BUS_RESET:
      // called when the host sends reset command
      break;

    case SL_USBD_EVENT_BUS_SUSPEND:
      // called when the host sends suspend command
      break;

    case SL_USBD_EVENT_BUS_RESUME:
      // called when the host sends wake up command
      break;

    default:
      break;
  }
}

void sl_usbd_on_config_event(sl_usbd_config_event_t event, uint8_t config_nbr) {
  switch (event) {
    case SL_USBD_EVENT_CONFIG_SET:
      // called when the host sets a configuration
      break;

    case SL_USBD_EVENT_CONFIG_UNSET:
      // called when a configuration is unset
      break;

    default:
      break;
  }
}