This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

HID output report size and count

Hello,

I am developing a simple HID device with output report to receive data from PC. I took keyboard example as base project and I want to increase output report size (count) up to 64 bytes. 

I can successfully send data from PC to device when output report is not larger than 1 byte. If I change size or count in descriptor, data transmission is not working.

I use c# code to connect to device and send byte buffer. It does not show any errors, I have just "success" or "fail".

Device is recognized by the PC correctly.

Here is my descriptor

#define HID_CONTROL_REPORT_DESCRIPTOR() {                \
    0x05, 0x01,                    /* USAGE_PAGE (Generic Desktop)*/	\
    0x09, 0x00,                    /* USAGE (Undefined)*/	\
    0xa1, 0x01,                    /* COLLECTION (Application)*/	\
    0x75, 0x08,                    /*   REPORT_SIZE (1)*/	\
    0x95, 0x01,                    /*   REPORT_COUNT (1)*/	\
    0x15, 0x00,                    /*   LOGICAL_MINIMUM (0)*/	\
    0x25, 0x7F,                    /*   LOGICAL_MAXIMUM (127)*/	\
    0x09, 0x01,                    /*   USAGE (Consumer Control)*/	\
    0x91, 0x02,                    /*   OUTPUT (Data,Ary,Abs)*/	\
    0xc0                           /* END_COLLECTION*/	\
}

It works perfectly. But if I increase REPORT_COUNT, or REPORT_SIZE, it stops receiving data from PC

Parents
  • Ok, I found what causes such behavior.

    Apparently, changing REPORT_COUNT in HID descriptor is not enough. For example, there is a app_usbd_hid_kbd_internal.h file for keyboard descriptor. In this file there is global definition of app_usbd_hid_kbd_t class:

    #define APP_USBD_HID_KBD_GLOBAL_DEF_INTERNAL(instance_name,                                        \
                                                 interface_number,                                     \
                                                 endpoint,                                             \
                                                 user_ev_handler,                                      \
                                                 subclass_boot)                                        \
        static app_usbd_hid_report_buffer_t CONCAT_2(instance_name, _in)[1];                           \
        static uint8_t CONCAT_2(instance_name, _ep) = {MACRO_MAP(APP_USBD_HID_KBD_INTERVAL,endpoint)}; \
        APP_USBD_HID_GENERIC_GLOBAL_OUT_REP_DEF(CONCAT_2(instance_name, _out), 1 + 1);                 \
        APP_USBD_CLASS_INST_GLOBAL_DEF(                                                                \
            instance_name,                                                                             \
            app_usbd_hid_kbd,                                                                          \
            &app_usbd_hid_kbd_class_methods,                                                           \
            APP_USBD_HID_KBD_CONFIG(interface_number, endpoint),                                       \
            (APP_USBD_HID_KBD_INST_CONFIG(CONCAT_2(instance_name, _in),                                \
                                          &CONCAT_2(instance_name, _out),                              \
                                          user_ev_handler,                                             \
                                          subclass_boot,                                               \
                                          &CONCAT_2(instance_name, _ep)))                              \
        )

    The following line looks like definition of the output report:

    APP_USBD_HID_GENERIC_GLOBAL_OUT_REP_DEF(CONCAT_2(instance_name, _out), 1 + 1); 

    That "1 + 1" looks like size of this output report: 1 byte for Report_ID + 1 byte for data that was defined in descriptor.

    Thus, when I change Report_Count in descriptor, I can't receive more data because I specified here only 2 byte buffer. And I also can't receive same 1 byte data because my descriptor requires larger byte count.

    So, in the global definition for my custom hid class I changed that "1 + 1" to "1 + 64" and updated my descriptor with 64 bytes output report count. And it works.

Reply
  • Ok, I found what causes such behavior.

    Apparently, changing REPORT_COUNT in HID descriptor is not enough. For example, there is a app_usbd_hid_kbd_internal.h file for keyboard descriptor. In this file there is global definition of app_usbd_hid_kbd_t class:

    #define APP_USBD_HID_KBD_GLOBAL_DEF_INTERNAL(instance_name,                                        \
                                                 interface_number,                                     \
                                                 endpoint,                                             \
                                                 user_ev_handler,                                      \
                                                 subclass_boot)                                        \
        static app_usbd_hid_report_buffer_t CONCAT_2(instance_name, _in)[1];                           \
        static uint8_t CONCAT_2(instance_name, _ep) = {MACRO_MAP(APP_USBD_HID_KBD_INTERVAL,endpoint)}; \
        APP_USBD_HID_GENERIC_GLOBAL_OUT_REP_DEF(CONCAT_2(instance_name, _out), 1 + 1);                 \
        APP_USBD_CLASS_INST_GLOBAL_DEF(                                                                \
            instance_name,                                                                             \
            app_usbd_hid_kbd,                                                                          \
            &app_usbd_hid_kbd_class_methods,                                                           \
            APP_USBD_HID_KBD_CONFIG(interface_number, endpoint),                                       \
            (APP_USBD_HID_KBD_INST_CONFIG(CONCAT_2(instance_name, _in),                                \
                                          &CONCAT_2(instance_name, _out),                              \
                                          user_ev_handler,                                             \
                                          subclass_boot,                                               \
                                          &CONCAT_2(instance_name, _ep)))                              \
        )

    The following line looks like definition of the output report:

    APP_USBD_HID_GENERIC_GLOBAL_OUT_REP_DEF(CONCAT_2(instance_name, _out), 1 + 1); 

    That "1 + 1" looks like size of this output report: 1 byte for Report_ID + 1 byte for data that was defined in descriptor.

    Thus, when I change Report_Count in descriptor, I can't receive more data because I specified here only 2 byte buffer. And I also can't receive same 1 byte data because my descriptor requires larger byte count.

    So, in the global definition for my custom hid class I changed that "1 + 1" to "1 + 64" and updated my descriptor with 64 bytes output report count. And it works.

Children
No Data
Related