HID Class Configuration

Generic Configuration

Some constants are available to customize the class. These constants are located in the USB device configuration file, usbd_cfg.hTable - HID Class Configuration Constants shows their description.

Table - HID Class Configuration Constants
ConstantDescriptionPossible Values
USBD_HID_CFG_MAX_NBR_DEVConfigures the maximum number of class instances. Unless you plan on having multiple configurations or interfaces using different class instances, this can be set to the default value.From 1 to 254. Default value is 1.
USBD_HID_CFG_MAX_NBR_CFGConfigures the maximum number of configurations in which HID class is used. Keep in mind that if you use a high-speed device, two configurations will be built, one for full-speed and another for high-speed.From 1 (low- and full-speed) or 2 (high-speed) to 254. Default value is 2.
USBD_HID_CFG_MAX_NBR_REPORT_IDConfigures the maximum number of report IDs allowed in a report. The value should be set properly to accommodate the number of report ID to be used in the report.From 1 to 65535. Default value is 1.
USBD_HID_CFG_MAX_NBR_REPORT_PUSHPOPConfigures the maximum number of Push and Pop items used in a report. If the constant is set to 0, no Push and Pop items are present in the report.From 0 to 254. Default value is 0.

The HID class uses an internal task to manage periodic input reports. The task priority and stack size shown in Table - HID Internal Task’s Configuration Constants are defined in the application configuration file, app_cfg.h. Refer to the HID Periodic Input Reports Task page for more details about the HID internal task.

Table - HID Internal Task’s Configuration Constants
ConstantDescriptionPossible Values
USBD_HID_OS_CFG_TMR_TASK_PRIOConfigures the priority of the HID periodic input reports task.From the lowest to the highest priority supported by the OS used.
USBD_HID_OS_CFG_TMR_TASK_STK_SIZE
Configures the stack size of the HID periodic input reports task. The required size of the stack can greatly vary depending on the OS used, the CPU architecture, the type of application, etc. Refer to the documentation of the OS for more details about tasks and stack size calculation.From the minimal to the maximal stack size supported by the OS used.


Class Instance Configuration

Before starting the communication phase, your application needs to initialize and configure the class to suit its needs. Table - HID Class Initialization API Summary summarizes the initialization functions provided by the HID class. For more details about the functions parameters, refer to the HID API Reference.

Table - HID Class Initialization API Summary
Function nameOperation
USBD_HID_Init()Initializes HID class internal structures, variables and the OS layer.
USBD_HID_Add()Creates a new instance of HID class.
USBD_HID_CfgAdd()Adds an existing HID instance to the specified device configuration.


You need to call these functions in the order shown below to successfully initialize the HID class:

  1. Call USBD_HID_Init() 
    This is the first function you should call and you should do it only once even if you use multiple class instances. This function initializes all internal structures and variables that the class needs and also the HID OS layer.
  2. Call USBD_HID_Add() 
    This function allocates an HID class instance. It also allows you to specify the following instance characteristics:
    • The country code of the localized HID hardware.
    • The Report descriptor content and size.
    • The Physical descriptor content and size.
    • The polling internal for the interrupt IN endpoint.
    • The polling internal for the interrupt OUT endpoint.
    • A flag enabling or disabling the Output reports reception with the control endpoint. When the control endpoint is not used, the interrupt OUT endpoint is used instead to receive Output reports.
    • A structure that contains 4 application callbacks used for class-specific requests processing.
  3. Call USBD_HID_CfgAdd()

Finally, once the HID class instance has been created, you must add it to a specific configuration.

Listing - HID Class Initialization Example illustrates the use of the previous functions for initializing the HID class.

static  USBD_HID_CALLBACK  App_USBD_HID_Callback = {                          (3)
    App_USBD_HID_GetFeatureReport,
    App_USBD_HID_SetFeatureReport,
    App_USBD_HID_GetProtocol,
    App_USBD_HID_SetProtocol,
    App_USBD_HID_ReportSet
};

CPU_BOOLEAN  App_USBD_HID_Init (CPU_INT08U  dev_nbr,
                                CPU_INT08U  cfg_hs,
                                CPU_INT08U  cfg_fs)
{
    USBD_ERR    err;
    CPU_INT08U  class_nbr;


    USBD_HID_Init(&err);                                                      (1)
    if (err != USBD_ERR_NONE) {
        /* Handle the error. */
    }


    class_nbr = USBD_HID_Add(              USBD_HID_SUBCLASS_BOOT,            (2)
                                           USBD_HID_PROTOCOL_MOUSE,
                                           USBD_HID_COUNTRY_CODE_NOT_SUPPORTED,
                                          &App_USBD_HID_ReportDesc[0],
                                           sizeof(App_USBD_HID_ReportDesc),
                             (CPU_INT08U *)0,
                                           0u,
                                           2u,
                                           2u,
                                           DEF_YES,
                                          &App_USBD_HID_Callback,             (3)
                                          &err);
    if (err != USBD_ERR_NONE) {
        /* Handle the error. */
    }

    if (cfg_hs != USBD_CFG_NBR_NONE) {
        USBD_HID_CfgAdd(class_nbr, dev_nbr, cfg_hs, &err);                    (4)
        if (err != USBD_ERR_NONE) {
            /* Handle the error. */
        }
    }
    if (cfg_fs != USBD_CFG_NBR_NONE) {
        USBD_HID_CfgAdd(class_nbr, dev_nbr, cfg_fs, &err);                    (5)
        if (err != USBD_ERR_NONE) {
            /* Handle the error. */
        }
    }
}

(1) Initialize HID internal structures, variables and OS layer.

(2) Create a new HID class instance. In this example, the subclass is “Boot”, the protocol is “Mouse” and the country code is unknown. A table, App_USBD_HID_ReportDesc[], representing the Report descriptor is passed to the function (refer to Listing - Mouse Report Descriptor Example for an example of Report descriptor content and to the Report section for more details about the Report descriptor format). No Physical descriptor is provided by the application. The interrupt IN endpoint is used and has a 2 frames or microframes polling interval. The use of the control endpoint to receive Output reports is enabled. The interrupt OUT endpoint will not be used. And therefore, the interrupt OUT polling interval of 2 is ignored by the class. The structure App_USBD_HID_Callback is also passed and references 4 application callbacks which will be called by the HID class upon processing of the class-specific requests.

(3) There are 5 application callbacks for class-specific requests processing. There is one callback for each of the following requests: GET_REPORT, SET_REPORT, GET_PROTOCOL and SET_PROTOCOL. Refer to “Device Class Definition for Human Interface Devices (HID) Version 1.11”, section 7.2 for more details about these class-specific requests.

(4) Check if the high-speed configuration is active and proceed to add the HID instance previously created to this configuration.

(5) Check if the full-speed configuration is active and proceed to add the HID instance to this configuration.


Listing - HID Class Initialization Example also illustrates an example of multiple configurations. The functions USBD_HID_Add() and USBD_HID_CfgAdd() allow you to create multiple configurations and multiple instances architecture. Refer to Table - Constants and Functions Related to the Concept of Multiple Class Instances for more details about multiple class instances.

Listing - Mouse Report Descriptor Example presents an example of table declaration defining a Report descriptor corresponding to a mouse. The example matches the mouse report descriptor viewed by the host HID parser in Figure - Report Descriptor Content from a Host HID Parser View. The mouse report represents an Input report. Refer to the Report section for more details about the Report descriptor format. The items inside a collection are intentionally indented for code clarity.

static  CPU_INT08U  App_USBD_HID_ReportDesc[] = {                             (1) (2)
  USBD_HID_GLOBAL_USAGE_PAGE        + 1, USBD_HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS,
  USBD_HID_LOCAL_USAGE              + 1, USBD_HID_CA_MOUSE,                   (3)
  USBD_HID_MAIN_COLLECTION          + 1, USBD_HID_COLLECTION_APPLICATION,     (4)
    USBD_HID_LOCAL_USAGE            + 1, USBD_HID_CP_POINTER,                 (5)
    USBD_HID_MAIN_COLLECTION        + 1, USBD_HID_COLLECTION_PHYSICAL,        (6)
      USBD_HID_GLOBAL_USAGE_PAGE    + 1, USBD_HID_USAGE_PAGE_BUTTON,          (7)
      USBD_HID_LOCAL_USAGE_MIN      + 1, 0x01,
      USBD_HID_LOCAL_USAGE_MAX      + 1, 0x03,
      USBD_HID_GLOBAL_LOG_MIN       + 1, 0x00,
      USBD_HID_GLOBAL_LOG_MAX       + 1, 0x01,
      USBD_HID_GLOBAL_REPORT_COUNT  + 1, 0x03,
      USBD_HID_GLOBAL_REPORT_SIZE   + 1, 0x01,
      USBD_HID_MAIN_INPUT           + 1, USBD_HID_MAIN_DATA     | 
                                         USBD_HID_MAIN_VARIABLE | 
                                         USBD_HID_MAIN_ABSOLUTE,
      USBD_HID_GLOBAL_REPORT_COUNT  + 1, 0x01,                                (8)
      USBD_HID_GLOBAL_REPORT_SIZE   + 1, 0x0D,
      USBD_HID_MAIN_INPUT           + 1, USBD_HID_MAIN_CONSTANT,
                                                                              (9)
      USBD_HID_GLOBAL_USAGE_PAGE    + 1, USBD_HID_USAGE_PAGE_GENERIC_DESKTOP_CONTROLS,
      USBD_HID_LOCAL_USAGE          + 1, USBD_HID_DV_X,
      USBD_HID_LOCAL_USAGE          + 1, USBD_HID_DV_Y,
      USBD_HID_GLOBAL_LOG_MIN       + 1, 0x81,
      USBD_HID_GLOBAL_LOG_MAX       + 1, 0x7F,
      USBD_HID_GLOBAL_REPORT_SIZE   + 1, 0x08,
      USBD_HID_GLOBAL_REPORT_COUNT  + 1, 0x02,
      USBD_HID_MAIN_INPUT           + 1, USBD_HID_MAIN_DATA     | 
                                         USBD_HID_MAIN_VARIABLE | 
                                         USBD_HID_MAIN_RELATIVE,
    USBD_HID_MAIN_ENDCOLLECTION,                                             (10)
  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.


Class Instance Communication

The HID class offers the following functions to communicate with the host. For more details about the functions parameters, refer to the HID API Reference.

Table - HID Communication API Summary
Function nameOperation
USBD_HID_Rd()Receives data from host through interrupt OUT endpoint. This function is blocking.
USBD_HID_Wr()Sends data to host through interrupt IN endpoint. This function is blocking.
USBD_HID_RdAsync()Receives data from host through interrupt OUT endpoint. This function is non-blocking.
USBD_HID_WrAsync()Sends data to host through interrupt IN endpoint. This function is non-blocking.


Synchronous Communication

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

Listing - Synchronous Bulk Read and Write Example presents a read and write example to receive data from the host using the interrupt OUT endpoint and to send data to the host using the interrupt IN endpoint.

CPU_INT08U  rx_buf[2];
CPU_INT08U  tx_buf[2];
USBD_ERR    err;


(void)USBD_HID_Rd(         class_nbr,                                         (1)
                  (void *)&rx_buf[0],                                         (2)
                           2u,
                           0u,                                                (3)
                          &err);
if (err != USBD_ERR_NONE) {
    /* $$$$ Handle the error. */
}

(void)USBD_HID_Wr(         class_nbr,                                         (1)
                  (void *)&tx_buf[0],                                         (4)
                           2u,
                           0u,                                                (3)
                          &err);
if (err != USBD_ERR_NONE) {
    /* $$$$ Handle the error. */
}

(1) The class instance number created from USBD_HID_Add() will serve internally 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 USBD_HID_Add().

(3) In order 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.


Asynchronous Communication

Asynchronous communication means that the transfer is non-blocking. Upon function call, the application passes the transfer information to the device stack and does not block. Other application processing can be done while the transfer is in progress over the USB bus. Once the transfer is completed, a callback is called by the device stack to inform the application about the transfer completion.

Listing - Asynchronous Bulk Read and Write Example shows an example of an asynchronous read and write.

void App_USBD_HID_Comm (CPU_INT08U  class_nbr)
{
    CPU_INT08U  rx_buf[2];
    CPU_INT08U  tx_buf[2];
    USBD_ERR    err;


    USBD_HID_RdAsync(         class_nbr,                                      (1)
                     (void *)&rx_buf[0],                                      (2)
                              2u,
                              App_USBD_HID_RxCmpl,                            (3)
                     (void *) 0u,                                             (4)
                             &err);
    if (err != USBD_ERR_NONE) {
        /* Handle the error. */
    }

    USBD_HID_WrAsync(         class_nbr,                                      (1)
                     (void *)&tx_buf[0],                                      (5)
                              2u,
                              App_USBD_HID_TxCmpl,                            (3)
                     (void *) 0u,                                             (4)
                             &err);
    if (err != USBD_ERR_NONE) {
        /* $$$$ Handle the error. */
    }
}

static  void  App_USBD_HID_RxCmpl (CPU_INT08U   class_nbr,                    (3)
                                   void        *p_buf,
                                   CPU_INT32U   buf_len,
                                   CPU_INT32U   xfer_len,
                                   void        *p_callback_arg,
                                   USBD_ERR     err)
{
    (void)class_nbr;
    (void)p_buf;
    (void)buf_len;
    (void)xfer_len;
    (void)p_callback_arg;                                                     (4)
 
    if (err == USBD_ERR_NONE) {
        /* $$$$ Do some processing. */
    } else {
        /* $$$$ Handle the error. */
    }
}


static  void  App_USBD_HID_TxCmpl (CPU_INT08U   class_nbr,                    (3)
                                   void        *p_buf,
                                   CPU_INT32U   buf_len,
                                   CPU_INT32U   xfer_len,
                                   void        *p_callback_arg,
                                   USBD_ERR     err)
{
    (void)class_nbr;
    (void)p_buf;
    (void)buf_len;
    (void)xfer_len;
    (void)p_callback_arg;                                                     (4)
 
    if (err == USBD_ERR_NONE) {
        /* $$$$ Do some processing. */
    } else {
        /* $$$$ Handle the error. */
    }
}

(1) The class instance number serves internally 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 USBD_HID_Add().

(3) The application provides a callback passed as a parameter. Upon completion of the transfer, the device stack calls this callback so that the application can finalize the transfer by analyzing the transfer result. For instance, upon read operation completion, the application may do a certain processing with the received data. Upon write completion, the application may indicate if the write was successful and how many bytes were sent.

(4) An argument associated to the callback can be also passed. Then in the callback context, some private information can be retrieved.

(5) The application provides the initialized transmit buffer.