USB Device HID Class

This section describes the Human Interface Device (HID) class supported by Silicon Labs USB Device.

The HID class encompasses devices used by humans to control computer operations, such as keyboards, mice, pointing devices, and game devices.

The HID class can also be used in a composite device that contains controls such as knobs, switches, buttons, and sliders. For example, mute and volume controls in an audio headset are controlled by the HID function of the headset. HID class can exchange data for any purpose using only control and interrupt transfers.

The HID class is one of the oldest and most widely-used USB classes. All the major host operating systems provide a native driver to manage HID devices, which is why a variety of vendor-specific devices work with the HID class. This class also includes various types of output items such as LEDs, audio, tactile feedback, etc.

The HID implementation complies with the following specifications:

USB Device HID Class Overview

Overview

A HID device is composed of the following endpoints:

The table below describes the usage of the different endpoints:

Table - HID Class Endpoints Usage
EndpointDirectionUsage
Control INDevice-to-hostStandard requests for enumeration, class-specific requests, and data communication (Input, Feature reports sent to the host with GET_REPORT request).
Control OUTHost-to-deviceStandard requests for enumeration, class-specific requests and data communication (Output, Feature reports received from the host with SET_REPORT request).
Interrupt INDevice-to-hostData communication (Input and Feature reports).
Interrupt OUTHost-to-deviceData communication (Output and Feature reports).

Report

A host and a HID device exchange data using reports. A report contains formatted data giving information about controls and other physical entities of the HID device. A control is manipulable by the user and operates an aspect of the device. For example, a control can be a button on a mouse or a keyboard, a switch, etc. Other entities inform the user about the state of certain device’s features. For example, LEDs on a keyboard notify the user about the caps lock on, the numeric keypad active, etc.

The format and the use of a report data is understood by the host by analyzing the content of a Report descriptor. Analyzing the content is done by a parser. The Report descriptor describes data provided by each control in a device. It is composed of items which are pieces of information about the device and consist of a 1-byte prefix and variable-length data. For more details about the item format, refer to “Device Class Definition for Human Interface Devices (HID) Version 1.11”, section 5.6 and 6.2.2.

There are three principal types of items:

Each item type is defined by different functions. An item function can also be called a tag. An item function can be seen as a sub-item that belongs to one of the three principal item types. The table below provides a brief overview of the item’s functions in each item type. For a complete description of the items in each category, see “Device Class Definition for Human Interface Devices (HID) Version 1.11”, section 6.2.2.

Table - Item’s Function Description for Each Item Type
Item TypeItem FunctionDescription
MainInputDescribes information about the data provided by one or more physical controls.
MainOutputDescribes data sent to the device.
MainFeatureDescribes device configuration information sent to or received from the device which influences the overall behavior of the device or one of its components.
MainCollectionGroup related items (Input, Output or Feature).
MainEnd of CollectionCloses a collection.
GlobalUsage PageIdentifies a function available within the device.
GlobalLogical MinimumDefines the lower limit of the reported values in logical units.
GlobalLogical MaximumDefines the upper limit of the reported values in logical units.
GlobalPhysical MinimumDefines the lower limit of the reported values in physical units, that is the Logical Minimum expressed in physical units.
GlobalPhysical MaximumDefines the upper limit of the reported values in physical units, that is the Logical Maximum expressed in physical units.
GlobalUnit ExponentIndicates the unit exponent in base 10. The exponent ranges from -8 to +7.
GlobalUnitIndicates the unit of the reported values. For instance, length, mass, temperature units, etc.
GlobalReport SizeIndicates the size of the report fields in bits.
GlobalReport IDIndicates the prefix added to a particular report.
GlobalReport CountIndicates the number of data fields for an item.
GlobalPushPlaces a copy of the global item state table on the CPU stack.
GlobalPopReplaces the item state table with the last structure from the stack.
LocalUsageRepresents an index to designate a specific Usage within a Usage Page. It indicates the vendor’s suggested use for a specific control or group of controls. A usage supplies information to an application developer about what a control is actually measuring.
LocalUsage MinimumDefines the starting usage associated with an array or bitmap.
LocalUsage MaximumDefines the ending usage associated with an array or bitmap.
LocalDesignator IndexDetermines the body part used for a control. Index points to a designator in the Physical descriptor.
LocalDesignator MinimumDefines the index of the starting designator associated with an array or bitmap.
LocalDesignator MaximumDefines the index of the ending designator associated with an array or bitmap.
LocalString IndexString index for a String descriptor. It allows a string to be associated with a particular item or control.
LocalString MinimumSpecifies the first string index when assigning a group of sequential strings to controls in an array or bitmap.
LocalString MaximumSpecifies the last string index when assigning a group of sequential strings to controls in an array or bitmap.
LocalDelimiterDefines the beginning or end of a set of local items.

A control’s data must define at least the following items:

The table below shows the representation of a Mouse Report descriptor content from a host HID parser perspective. The mouse has three buttons (left, right, and wheel). The code presented in the example below is a code implementation corresponding to this mouse Report descriptor representation.

Figure - Report Descriptor Content from a Host HID Parser View

Figure 9 Report Descriptor Content from a Host HID Parser View

(1) The Usage Page item function specifies the general function of the device. In this example, the HID device belongs to a generic desktop control.

(2) The Collection Application groups Main items that have a common purpose and may be familiar to applications. In the diagram, the group is composed of three Input Main items. For this collection, the suggested use for the controls is a mouse as indicated by the Usage item.

(3) Nested collections may be used to give more details about the use of a single control or group of controls to applications. In this example, the Collection Physical, nested into the Collection Application, is composed of the same three Input items forming the Collection Application. The Collection Physical is used for a set of data items that represent data points collected at one geometric point. In the example, the suggested use is a pointer as indicated by the Usage item. Here the pointer usage refers to the mouse position coordinates and the system software will translate the mouse coordinates in movement of the screen cursor.

(4) Nested usage pages are also possible and give more details about a certain aspect within the general function of the device. In this case, two Inputs items are grouped and correspond to the buttons of the mouse. One Input item defines the three buttons of the mouse (right, left and wheel) in terms of number of data fields for the item (Report Count item), size of a data field (Report Size item) and possible values for each data field (Usage Minimum and Maximum, Logical Minimum and Maximum items). The other Input item is a 13-bit constant allowing the Input report data to be aligned on a byte boundary. This Input item is used only for padding purpose.

(5) Another nested usage page referring to a generic desktop control is defined for the mouse position coordinates. For this usage page, the Input item describes the data fields corresponding to the x- and y-axis as specified by the two Usage items.

After analyzing the previous mouse Report descriptor content, the host’s HID parser is able to interpret the Input report data sent by the device with an interrupt IN transfer or in response to a GET_REPORT request. The Input report data corresponding to the mouse Report descriptor shown in Figure - Report Descriptor Content from a Host HID Parser View is shown in the table below. The total size of the report data is 4 bytes. Different types of reports may be sent over the same endpoint. For the purpose of distinguishing the different types of reports, a 1-byte report ID prefix is added to the data report. If a report ID was used in the example of the mouse report, the total size of the report data would be 5 bytes.

Table - Input Report Sent to Host and Corresponding to the State of a 3-Buttons Mouse
Bit OffsetBit CountDescription
01Button 1 (left button).
11Button 2 (right button).
21Button 3 (wheel button).
313Not used.
168Position on axis X.
248Position on axis Y.

A Physical descriptor indicates the part or parts of the body intended to activate a control or controls. An application may use this information to assign a functionality to the control of a device. A Physical descriptor is an optional class-specific descriptor and most devices have little gain for using it. Refer to “Device Class Definition for Human Interface Devices (HID) Version 1.11” section 6.2.3 for more details about this descriptor.

USB Device HID Class Resource Needs from Core

Each time you add a HID class instance to a USB configuration via a call to the function sl_usbd_hid_add_to_configuration(), the following resources will be allocated from the core.

ResourceQuantity
Interfaces1
Alternate interfaces1
Endpoints1 (2 if interrupt OUT endpoint is enabled)
Interface groups0

Note that those numbers are per configuration. When setting up your SL_USBD_INTERFACE_QUANTITY, SL_USBD_ALT_INTERFACE_QUANTITY, SL_USBD_INTERFACE_GROUP_QUANTITY and SL_USBD_DESCRIPTOR_QUANTITY configuration values, don't forget to take into account on how many configurations the class will be added. For the SL_USBD_OPEN_ENDPOINTS_QUANTITY configuration value, since endpoints are opened only when a configuration is set by the host, you just need to take into account the number of needed endpoints for a class instance.

USB Device HID Class Configuration

Two groups of configuration parameters are used to configure the HID class:

USB Device HID Class Application-Specific Configurations

First, to use the Silicon Labs USB device HID class module, adjust the HID compile-time configuration defines according to your application needs. They are regrouped inside the sl_usbd_core_config.h header file under the HID section. They can be divided into two sections, the quantity configurations and the HID task configurations. The quantity configurations purpose is to inform the USB device module about how many USB HID objects to allocate.

The table below describes each configuration define.

Table - USB Device HID Configuration Defines
Configuration NameDescriptionDefault Value
SL_USBD_HID_CLASS_INSTANCE_QUANTITYNumber of class instances you will allocate via a call to the function sl_usbd_hid_create_instance().2
SL_USBD_HID_CONFIGURATION_QUANTITYNumber of configurations. HID class instances can be added to one or more configurations via a call to the function sl_usbd_hid_add_to_configuration().1
SL_USBD_HID_REPORT_ID_QUANTITYConfigures the total number of report IDs to allocate.2
SL_USBD_HID_PUSH_POP_ITEM_QUANTITYConfigures the total number of Push/Pop items to allocate.0
SL_USBD_HID_TIMER_TASK_STACK_SIZEThe timer task handles all the timer-based HID operations. This configuration allows you to set the stack size (in number of bytes).2048
SL_USBD_HID_TIMER_TASK_PRIORITYPriority of HID task. his is a CMSIS-RTOS2 priority.osPriorityHigh

USB Device HID Class Instance Configurations

This section defines the configurations related to the HID class instances.

Class Instance Creation

Creating a HID class instance is done by calling the function sl_usbd_hid_create_instance(), which takes several configuration arguments that are described below.

subclass

Code of the HID subclass. Possible values are:

A HID device that uses the boot subclass must use standard report formats. For more information on the subclass codes, see section 4.2 of HID specification revision 1.11.

protocol

Protocol used by the HID device. Possible values are:

If your HID function is a mouse, the protocol should be set to SL_USBD_HID_PROTOCOL_MOUSE. If it is a keyboard, it should be set to SL_USBD_HID_PROTOCOL_KBD. Otherwise, the protocol should be set to SL_USBD_HID_PROTOCOL_NONE. For more information on the subclass codes, see section 4.3 of HID specification revision 1.11.

country_code

ID of the country code. Possible values are:

The country code identifies which country the hardware is localized for. Most hardware is not localized and therefore this value would be SL_USBD_HID_COUNTRY_CODE_NOT_SUPPORTED(0). However, keyboards may use the field to indicate the language of the key caps.

For more information on the country codes, see section 6.2.1 of HID specification revision 1.11.

interval_in and interval_out

interval_in and interval_out represent the polling interval of the IN interrupt endpoint and the OUT interrupt endpoint.

This represents the polling interval of the endpoint, in milliseconds. Setting this value depends on how frequently your device is susceptible to generate a new report for the host. For instance, if a report is generated every 16 milliseconds, the interval should be 16 or less.

The value must be a power of 2 (1, 2, 4, 8, 16, etc.).

interval_out value is ignored if ctrl_rd_en is set to true.

p_hid_callback

p_hid_callback is a pointer to a structure of type sl_usbd_hid_callbacks_t. Its purpose is to give the HID Class a set of callback functions to be called when a HID event occurs.

Not all callbacks are mandatory and a null pointer (NULL) can be passed in the callbacks structure variable when the callback is not needed.

The table below describes each configuration field available in this configuration structure.

Table - sl_usbd_hid_callbacks_t Configuration Structure
Fields Description Function signature
.enable Called when the USB class instance is enabled succesfully. void app_usbd_hid_enable(uint8_t class_nbr);
.disable Called when the USB class instance is disabled. void app_usbd_hid_disable(uint8_t class_nbr);
.get_report_desc Called during the HID Instance creation to pass your report descriptor. For each of your HID functions, you must provide a report descriptor. The report descriptor indicates to the host how the periodic report that will be sent by the device should be parsed. Writing your own report descriptor can be challenging, and that is why there are some resources to help. This is the only mandatory callback function. void app_usbd_hid_get_report_desc(uint8_t class_nbr, const uint8_t **p_report_ptr, uint16_t *p_report_len);
.get_phy_desc Called during the HID Instance creation to pass your physical descriptor. The physical descriptor is a descriptor that provides information about the specific part or parts of the human body that are activating a control or controls. For more information on physical descriptors, see section 6.2.3 of HID specification revision 1.11. The physical descriptor is optional and most of the time ignored. The buffer passed here can be set to NULL and the length set to 0. void app_usbd_hid_get_phy_desc(uint8_t class_nbr, const uint8_t **p_report_ptr, uint16_t *p_report_len);
.set_output_report Called when the host sets a report as described in your report descriptor (when it sends a report). void app_usbd_hid_set_output_report(uint8_t class_nbr, uint8_t report_id, uint8_t *p_report_buf, uint16_t report_len);
.get_feature_report Called when the host requests a feature report as described in your report descriptor. void app_usbd_hid_get_feature_report(uint8_t class_nbr, uint8_t report_id, uint8_t *p_report_buf, uint16_t report_len);
.set_feature_report Called when the host sets a feature report as described in your report descriptor. void app_usbd_hid_set_feature_report(uint8_t class_nbr, uint8_t report_id, uint8_t *p_report_buf, uint16_t report_len);
.get_protocol Retrieves current active protocol. void app_usbd_hid_get_protocol(uint8_t class_nbr, uint8_t *p_protocol);
.set_protocol Sets current active protocol. void app_usbd_hid_set_protocol(uint8_t class_nbr, uint8_t protocol);

HID Class Report Descriptor Example

Silicon Labs' HID class sample application provides an example of a report descriptor for a simple mouse. The example below shows a mouse report descriptor.

Example - Mouse Report Descriptor
static  uint8_t  app_usbd_hid_report_desc[] = {                                          (1) (2)
  SL_USBD_HID_GLOBAL_USAGE_PAGE    + 1, SL_USBD_HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS,
  SL_USBD_HID_LOCAL_USAGE          + 1, SL_USBD_HID_CA_MOUSE,                            (3)
  SL_USBD_HID_MAIN_COLLECTION      + 1, SL_USBD_HID_COLLECTION_APPLICATION,              (4)
  SL_USBD_HID_LOCAL_USAGE          + 1, SL_USBD_HID_CP_POINTER,                          (5)
  SL_USBD_HID_MAIN_COLLECTION      + 1, SL_USBD_HID_COLLECTION_PHYSICAL,                 (6)
  SL_USBD_HID_GLOBAL_USAGE_PAGE    + 1, SL_USBD_HID_USAGE_PAGE_BUTTON,                   (7)
  SL_USBD_HID_LOCAL_USAGE_MIN      + 1, 0x01,
  SL_USBD_HID_LOCAL_USAGE_MAX      + 1, 0x03,
  SL_USBD_HID_GLOBAL_LOG_MIN       + 1, 0x00,
  SL_USBD_HID_GLOBAL_LOG_MAX       + 1, 0x01,
  SL_USBD_HID_GLOBAL_REPORT_COUNT  + 1, 0x03,
  SL_USBD_HID_GLOBAL_REPORT_SIZE   + 1, 0x01,
  SL_USBD_HID_MAIN_INPUT           + 1, SL_USBD_HID_MAIN_DATA     |
                                        SL_USBD_HID_MAIN_VARIABLE |
                                        SL_USBD_HID_MAIN_ABSOLUTE,
  SL_USBD_HID_GLOBAL_REPORT_COUNT  + 1, 0x01,                                            (8)
  SL_USBD_HID_GLOBAL_REPORT_SIZE   + 1, 0x0D,
  SL_USBD_HID_MAIN_INPUT           + 1, SL_USBD_HID_MAIN_CONSTANT,
                                                                                         (9)
  SL_USBD_HID_GLOBAL_USAGE_PAGE    + 1, SL_USBD_HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS,
  SL_USBD_HID_LOCAL_USAGE          + 1, SL_USBD_HID_DV_X,
  SL_USBD_HID_LOCAL_USAGE          + 1, SL_USBD_HID_DV_Y,
  SL_USBD_HID_GLOBAL_LOG_MIN       + 1, 0x81,
  SL_USBD_HID_GLOBAL_LOG_MAX       + 1, 0x7F,
  SL_USBD_HID_GLOBAL_REPORT_SIZE   + 1, 0x08,
  SL_USBD_HID_GLOBAL_REPORT_COUNT  + 1, 0x02,
  SL_USBD_HID_MAIN_INPUT           + 1, SL_USBD_HID_MAIN_DATA     |
                                        SL_USBD_HID_MAIN_VARIABLE |
                                        SL_USBD_HID_MAIN_RELATIVE,
  SL_USBD_HID_MAIN_ENDCOLLECTION,                                                        (10)
  SL_USBD_HID_MAIN_ENDCOLLECTION                                                         (11)
};

(1) The table representing a mouse report descriptor is initialized in such way that each line corresponds to a short item. The latter is formed from a 1-byte prefix and a 1-byte data. Refer to “Device Class Definition for Human Interface Devices (HID) Version 1.11”, sections 5.3 and 6.2.2.2 for more details about short items format. This table content corresponds to the mouse report descriptor content viewed by a host HID parser in Figure - Report Descriptor Content from a Host HID Parser View.

(2) The Generic Desktop Usage Page is used.

(3) Within the Generic Desktop Usage Page, the usage tag suggests that the group of controls is for controlling a mouse. A mouse collection typically consists of two axes (X and Y) and one, two, or three buttons.

(4) The mouse collection is started.

(5) Within the mouse collection, a usage tag suggests more specifically that the mouse controls belong to the pointer collection. A pointer collection is a collection of axes that generates a value to direct, indicate, or point user intentions to an application.

(6) The pointer collection is started.

(7) The Buttons Usage Page defines an Input item composed of three 1-bit fields. Each 1-bit field represents the mouse’s button 1, 2 and 3 respectively and can return a value of 0 or 1.

(8) The Input Item for the Buttons Usage Page is padded with 13 other bits.

(9) Another Generic Desktop Usage Page is indicated for describing the mouse position with the axes X and Y. The Input item is composed of two 8-bit fields whose value can be between -127 and 127.

(10) The pointer collection is closed.

(11) The mouse collection is closed.

USB.org HID Page

The USB Implementers Forum (USB-IF) provides a tool called "HID Descriptor Tool" along with other information on the report descriptor format. Seehttp://www.usb.org/developers/hidpage/ for more information.

USB Device HID Class Programming Guide

This section explains how to use the HID class.

Initializing the USB Device HID Class

To add HID Class functionality to your device, you must first initialize the class by calling the function sl_usbd_hid_init().

The example below shows how to call sl_usbd_hid_init() using default arguments. For more information on the configuration arguments to pass to sl_usbd_hid_init(), see USB Device HID Class Application Specific Configurations .

Example - Calling sl_usbd_hid_init()
sl_status_t  status;

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

Adding a USB Device HID Class Instance to Your Device

To add HID class functionality to your device, you must create an instance, then add it to your device's configuration(s).

Creating a HID Class Instance

Create a HID class instance by calling the function sl_usbd_hid_create_instance().

The example below shows how to create a simple mouse function via sl_usbd_hid_create_instance() using default arguments. For more information on the configuration arguments to pass to sl_usbd_hid_create_instance(), see USB Device HID Class Instance Configurations .

Example - Adding a Mouse Function via sl_usbd_hid_create_instance()
/* Global constants.  */
static  const  uint8_t  app_usbd_hid_mouse_report_desc[] = {
    SL_USBD_HID_GLOBAL_USAGE_PAGE   + 1, SL_USBD_HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS,
    SL_USBD_HID_LOCAL_USAGE         + 1, SL_USBD_HID_CA_MOUSE,
    SL_USBD_HID_MAIN_COLLECTION     + 1, SL_USBD_HID_COLLECTION_APPLICATION,
    SL_USBD_HID_LOCAL_USAGE         + 1, SL_USBD_HID_CP_POINTER,
    SL_USBD_HID_MAIN_COLLECTION     + 1, SL_USBD_HID_COLLECTION_PHYSICAL,
    SL_USBD_HID_GLOBAL_USAGE_PAGE   + 1, SL_USBD_HID_USAGE_PAGE_BUTTON,
    SL_USBD_HID_LOCAL_USAGE_MIN     + 1, 0x01,
    SL_USBD_HID_LOCAL_USAGE_MAX     + 1, 0x03,
    SL_USBD_HID_GLOBAL_LOG_MIN      + 1, 0x00,
    SL_USBD_HID_GLOBAL_LOG_MAX      + 1, 0x01,
    SL_USBD_HID_GLOBAL_REPORT_COUNT + 1, 0x03,
    SL_USBD_HID_GLOBAL_REPORT_SIZE  + 1, 0x01,
    SL_USBD_HID_MAIN_INPUT          + 1, SL_USBD_HID_MAIN_DATA | SL_USBD_HID_MAIN_VARIABLE | SL_USBD_HID_MAIN_ABSOLUTE,
    SL_USBD_HID_GLOBAL_REPORT_COUNT + 1, 0x01,
    SL_USBD_HID_GLOBAL_REPORT_SIZE  + 1, 0x0D,
    SL_USBD_HID_MAIN_INPUT          + 1, SL_USBD_HID_MAIN_CONSTANT,
    SL_USBD_HID_GLOBAL_USAGE_PAGE   + 1, SL_USBD_HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS,
    SL_USBD_HID_LOCAL_USAGE         + 1, SL_USBD_HID_DV_X,
    SL_USBD_HID_LOCAL_USAGE         + 1, SL_USBD_HID_DV_Y,
    SL_USBD_HID_GLOBAL_LOG_MIN      + 1, 0x81,
    SL_USBD_HID_GLOBAL_LOG_MAX      + 1, 0x7F,
    SL_USBD_HID_GLOBAL_REPORT_SIZE  + 1, 0x08,
    SL_USBD_HID_GLOBAL_REPORT_COUNT + 1, 0x02,
    SL_USBD_HID_MAIN_INPUT          + 1, SL_USBD_HID_MAIN_DATA | SL_USBD_HID_MAIN_VARIABLE | SL_USBD_HID_MAIN_RELATIVE,
    SL_USBD_HID_MAIN_ENDCOLLECTION,
    SL_USBD_HID_MAIN_ENDCOLLECTION
};

/* Local variables.*/
uint8_t      class_nbr;
sl_status_t  status;

sl_usbd_hid_callbacks_t app_usbd_hid_callbacks = {
  NULL,
  NULL,
  app_usbd_hid_get_report_desc,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL
};

void app_usbd_hid_get_report_desc(uint8_t       class_nbr,
                                  const uint8_t **p_report_ptr,
                                  uint16_t      *p_report_len)
{
  (void)class_nbr;

  *p_report_ptr = app_usbd_hid_mouse_report_desc;
  *p_report_len = sizeof(app_usbd_hid_mouse_report_desc);
}

status = sl_usbd_hid_create_instance(SL_USBD_HID_SUBCLASS_BOOT,
                                     SL_USBD_HID_PROTOCOL_MOUSE,
                                     SL_USBD_HID_COUNTRY_CODE_NOT_SUPPORTED,
                                     Ex_USBD_HID_Mouse_ReportDesc,
                                     sizeof(Ex_USBD_HID_Mouse_ReportDesc),
                                     2u,
                                     2u,
                                     true,
                                     &app_usbd_hid_callbacks,
                                     &class_nbr);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

Adding the HID Class Instance to Your Device's Configuration(s)

After you have created a HID class instance, you can add it to a configuration by calling the function sl_usbd_hid_add_to_configuration().

The example below shows how to call sl_usbd_hid_add_to_configuration().

Example - Calling sl_usbd_hid_add_to_configuration()
sl_status_t  status;

sl_usbd_hid_add_to_configuration(class_nbr,           (1)
                                 config_nbr_fs);      (2)
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

(1) Class number to add to the configuration returned by sl_usbd_hid_create_instance().

(2) Configuration number (here adding it to a Full-Speed configuration).

Communicating Using the USB Device HID Class

Class Instance Communication

The HID class offers the following functions to communicate with the host.

Table - HID Communication API Summary
Function nameOperation
sl_usbd_hid_read_sync()Receives data from the host through interrupt OUT endpoint. This function is blocking.
sl_usbd_hid_write_sync()Sends data to the host through interrupt IN endpoint. This function is blocking.

Synchronous Communication

Synchronous communication means that the transfer is blocking. Upon the function call, the applications blocks until the transfer is completed with or without an error. A timeout can be specified to avoid waiting forever.

The example below shows a read and write that receives data from the host using the interrupt OUT endpoint and sends data to the host using the interrupt IN endpoint.

Example - Synchronous HID Read and Write
__ALIGNED(4) uint8_t  rx_buf[2];
__ALIGNED(4) uint8_t  tx_buf[2];
uint32_t              xfer_len;
sl_status_t           status;

status = sl_usbd_hid_read_sync(class_nbr,                                         (1)
                               (void *)rx_buf,                                    (2)
                               2u,
                               0u,                                                (3)
                               &xfer_len);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

status = sl_usbd_hid_write_sync(class_nbr,                                         (1)
                                (void *)tx_buf,                                    (4)
                                2u,
                                0u,                                                (3)
                                &xfer_len);
if (status != SL_STATUS_OK) {
  /* An error occurred. Error handling should be added here. */
}

(1) The class instance number created from sl_usbd_hid_create_instance() provides an internal reference for the HID class to route the transfer to the proper interrupt OUT or IN endpoint.

(2) The application must ensure that the buffer provided to the function is large enough to accommodate all the data. Otherwise, synchronization issues might happen. Internally, the read operation is done either with the control endpoint or with the interrupt endpoint, depending on the control read flag set when calling sl_usbd_hid_create_instance().

(3) To avoid an infinite blocking situation, a timeout expressed in milliseconds can be specified. A value of ‘0’ makes the application task wait forever.

(4) The application provides the initialized transmit buffer.

HID Periodic Input Reports Task

To save bandwidth, the host has the ability to silence reports from an interrupt IN endpoint by limiting the reporting frequency. To do so, the host must send the SET_IDLE request. The HID class implemented by Silicon Labs contains an internal task that respects the reporting frequency limitation that you can apply to one or several input reports. Figure - Periodic Input Reports Task shows the functioning of the periodic input reports tasks.

Figure - Periodic Input Reports Task

Figure 11 Periodic Input Reports Task

(1) The device receives a SET_IDLE request. This request specifies an idle duration for a given report ID. For more details about the SET_IDLE request, see “Device Class Definition for Human Interface Devices (HID) Version 1.11”, section 7.2.4. A report ID allows you to distinguish among the different types of reports sent from the same endpoint.

(2) A report ID structure (allocated during the HID class initialization phase) is updated with the idle duration. An idle duration counter is initialized with the idle duration value. The report ID structure is inserted at the end of a linked list containing input reports ID structures. The idle duration value is expressed in 4-ms unit which gives a range of 4 to 1020 ms. If the idle duration is less than the polling interval of the interrupt IN endpoint, the reports are generated at the polling interval.

(3) Every 4 ms, the periodic input report task browses the input reports ID list. For each input report ID, the task performs one of two possible operations. The duration of the task period matches the 4-ms unit used for the idle duration. If no SET_IDLE requests have been sent by the host, the input reports ID list is empty and the task has nothing to process. The task processes only report IDs that are different from 0 and with an idle duration greater than 0.

(4) For a given input report ID, the task verifies if the idle duration has elapsed. If the idle duration has not elapsed, the counter is decremented and no input report is sent to the host.

(5) If the idle duration has elapsed (that is, the idle duration counter has reached zero), an input report is sent to the host by calling the sl_usbd_hid_write_sync() function via the interrupt IN endpoint.

(6) The input report data sent by the task comes from an internal data buffer allocated for each input report described in the Report descriptor. An application task can call the sl_usbd_hid_write_sync() function to send an input report. After sending the input report data, sl_usbd_hid_write_sync() updates the internal buffer associated to an input report ID with the data just sent. Then, the periodic input reports task always sends the same input report data after each idle duration elapsed and until the application task updates the data in the internal buffer. There is some locking mechanism to avoid corruption of the input report ID data in the event of a modification happening at the exact time of transmission done by the periodic input report task.