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:
Device Class Definition for Human Interface Devices (HID), 6/27/01, Version 1.11.
Universal Serial Bus HID Usage Tables, 10/28/2004, Version 1.12.
USB Device HID Class Overview#
Overview#
A HID device is composed of the following endpoints:
A pair of control IN and OUT endpoints called the default endpoint
An interrupt IN endpoint
An optional interrupt OUT endpoint
The table below describes the usage of the different endpoints:
Table - HID Class Endpoints Usage#
Endpoint | Direction | Usage |
---|---|---|
Control IN | Device-to-host | Standard requests for enumeration, class-specific requests, and data communication (Input, Feature reports sent to the host with GET_REPORT request). |
Control OUT | Host-to-device | Standard requests for enumeration, class-specific requests and data communication (Output, Feature reports received from the host with SET_REPORT request). |
Interrupt IN | Device-to-host | Data communication (Input and Feature reports). |
Interrupt OUT | Host-to-device | Data 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:
Main item defines or groups certain types of data fields.
Global item describes data characteristics of a control.
Local item describes data characteristics of a control.
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 Type | Item Function | Description | |
---|---|---|---|
Main | Input | Describes information about the data provided by one or more physical controls. | |
Main | Output | Describes data sent to the device. | |
Main | Feature | Describes device configuration information sent to or received from the device which influences the overall behavior of the device or one of its components. | |
Main | Collection | Group related items (Input, Output or Feature). | |
Main | End of Collection | Closes a collection. | |
Global | Usage Page | Identifies a function available within the device. | |
Global | Logical Minimum | Defines the lower limit of the reported values in logical units. | |
Global | Logical Maximum | Defines the upper limit of the reported values in logical units. | |
Global | Physical Minimum | Defines the lower limit of the reported values in physical units, that is the Logical Minimum expressed in physical units. | |
Global | Physical Maximum | Defines the upper limit of the reported values in physical units, that is the Logical Maximum expressed in physical units. | |
Global | Unit Exponent | Indicates the unit exponent in base 10. The exponent ranges from -8 to +7. | |
Global | Unit | Indicates the unit of the reported values. For instance, length, mass, temperature units, etc. | |
Global | Report Size | Indicates the size of the report fields in bits. | |
Global | Report ID | Indicates the prefix added to a particular report. | |
Global | Report Count | Indicates the number of data fields for an item. | |
Global | Push | Places a copy of the global item state table on the CPU stack. | |
Global | Pop | Replaces the item state table with the last structure from the stack. | |
Local | Usage | Represents 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. | |
Local | Usage Minimum | Defines the starting usage associated with an array or bitmap. | |
Local | Usage Maximum | Defines the ending usage associated with an array or bitmap. | |
Local | Designator Index | Determines the body part used for a control. Index points to a designator in the Physical descriptor. | |
Local | Designator Minimum | Defines the index of the starting designator associated with an array or bitmap. | |
Local | Designator Maximum | Defines the index of the ending designator associated with an array or bitmap. | |
Local | String Index | String index for a String descriptor. It allows a string to be associated with a particular item or control. | |
Local | String Minimum | Specifies the first string index when assigning a group of sequential strings to controls in an array or bitmap. | |
Local | String Maximum | Specifies the last string index when assigning a group of sequential strings to controls in an array or bitmap. | |
Local | Delimiter | Defines the beginning or end of a set of local items. |
A control’s data must define at least the following items:
Input, Output or Feature Main items
Usage Local item
Usage Page Global item
Logical Minimum Global item
Logical Maximum Global item
Report Size Global item
Report Count Global item
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#
(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 Offset | Bit Count | Description |
---|---|---|
0 | 1 | Button 1 (left button). |
1 | 1 | Button 2 (right button). |
2 | 1 | Button 3 (wheel button). |
3 | 13 | Not used. |
16 | 8 | Position on axis X. |
24 | 8 | Position 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.
Resource | Quantity |
---|---|
Interfaces | 1 |
Alternate interfaces | 1 |
Endpoints | 1 (2 if interrupt OUT endpoint is enabled) |
Interface groups | 0 |
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 Name | Description | Default Value |
---|---|---|
| Number of class instances you will allocate via a call to the function | 2 |
| Number of configurations. HID class instances can be added to one or more configurations via a call to the function | 1 |
| Configures the total number of report IDs to allocate. | 2 |
| Configures the total number of Push/Pop items to allocate. | 0 |
| The timer task handles all the timer-based HID operations. This configuration allows you to set the stack size (in number of bytes). | 2048 |
| Priority 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:
SL_USBD_HID_SUBCLASS_NONE
SL_USBD_HID_SUBCLASS_BOOT
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:
SL_USBD_HID_PROTOCOL_NONE
SL_USBD_HID_PROTOCOL_KBD
SL_USBD_HID_PROTOCOL_MOUSE
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:
SL_USBD_HID_COUNTRY_CODE_NOT_SUPPORTED
SL_USBD_HID_COUNTRY_CODE_ARABIC
SL_USBD_HID_COUNTRY_CODE_BELGIAN
SL_USBD_HID_COUNTRY_CODE_CANADIAN_BILINGUAL
SL_USBD_HID_COUNTRY_CODE_CANADIAN_FRENCH
SL_USBD_HID_COUNTRY_CODE_CZECH_REPUBLIC
SL_USBD_HID_COUNTRY_CODE_DANISH
SL_USBD_HID_COUNTRY_CODE_FINNISH
SL_USBD_HID_COUNTRY_CODE_FRENCH
SL_USBD_HID_COUNTRY_CODE_GERMAN
SL_USBD_HID_COUNTRY_CODE_GREEK
SL_USBD_HID_COUNTRY_CODE_HEBREW
SL_USBD_HID_COUNTRY_CODE_HUNGARY
SL_USBD_HID_COUNTRY_CODE_INTERNATIONAL
SL_USBD_HID_COUNTRY_CODE_ITALIAN
SL_USBD_HID_COUNTRY_CODE_JAPAN_KATAKANA
SL_USBD_HID_COUNTRY_CODE_KOREAN
SL_USBD_HID_COUNTRY_CODE_LATIN_AMERICAN
SL_USBD_HID_COUNTRY_CODE_NETHERLANDS_DUTCH
SL_USBD_HID_COUNTRY_CODE_NORWEGIAN
SL_USBD_HID_COUNTRY_CODE_PERSIAN_FARSI
SL_USBD_HID_COUNTRY_CODE_POLAND
SL_USBD_HID_COUNTRY_CODE_PORTUGUESE
SL_USBD_HID_COUNTRY_CODE_RUSSIA
SL_USBD_HID_COUNTRY_CODE_SLOVAKIA
SL_USBD_HID_COUNTRY_CODE_SPANISH
SL_USBD_HID_COUNTRY_CODE_SWEDISH
SL_USBD_HID_COUNTRY_CODE_SWISS_FRENCH
SL_USBD_HID_COUNTRY_CODE_SWISS_GERMAN
SL_USBD_HID_COUNTRY_CODE_SWITZERLAND
SL_USBD_HID_COUNTRY_CODE_TAIWAN
SL_USBD_HID_COUNTRY_CODE_TURKISH_Q
SL_USBD_HID_COUNTRY_CODE_UK
SL_USBD_HID_COUNTRY_CODE_US
SL_USBD_HID_COUNTRY_CODE_YUGOSLAVIA
SL_USBD_HID_COUNTRY_CODE_TURKISH_F
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 successfully. | 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_tp_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_tp_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 name | Operation |
---|---|
| Receives data from the host through interrupt OUT endpoint. This function is blocking. |
| 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#
(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.