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

HID endpoint clarification (feature reports)

I'm trying to wrap my head around the APP_USBD driver, but I'm running into a mental block.  I am implementing a report descriptor for the Battery System usage page, and all of the characteristics are features.  So would I use an in or out endpoint? or both?  I'm in the middle of trying this now and I'm not getting an error, but I'm not seeing the endpoint on the host either - so I'm not sure if this is caused by the endpoint definition or the report.

It has also lead me down a bit of a rabbit hole.  I actually have a composite device with two endpoints working nicely (joystick and keyboard).  When I was adding on this third piece, I remembered that the default keyboard descriptor from the example has an output in it, but there is only an in endpoint.  So this has me feeling like I don't understand what's going on.  Shouldn't there also have to be an out endpoint for the keyboard to get the output from the host?  I thought I would try it, but when I added an out endpoint, the GLOBAL_DEF macro didn't like it and I'm not sure why:

#define HID_KEYBOARD_EPIN       NRF_DRV_USBD_EPIN(2)
#define HID_KEYBOARD_EPOUT       NRF_DRV_USBD_EPOUT(1)

#define ENDPOINT_LIST_KEYBOARD() \
(                           \
        HID_KEYBOARD_EPIN,  \
        HID_KEYBOARD_EPOUT  \
)

APP_USBD_HID_KBD_GLOBAL_DEF(m_app_hid_keyboard,
                            HID_KEYBOARD_INTERFACE,
                            ENDPOINT_LIST_KEYBOARD(),
                            hid_kbd_user_ev_handler,
                            APP_USBD_HID_SUBCLASS_NONE);

gives an "initializer element is not constant" error:

7> Compiling ‘main.c’
7> In file included from ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd.h:58,
7>                  from C:\some_path\main.c:96:
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd_internal.h:116:1: error: initializer element is not constant
7> ../../../../../../components/libraries/util/app_util.h:712:37: note: in expansion of macro 'APP_USBD_HID_KBD_INTERVAL'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'MACRO_MAP_1'
7> ../../../../../../components/libraries/util/app_util.h:700:29: note: in expansion of macro 'MACRO_MAP_N_'
7> ../../../../../../components/libraries/util/app_util.h:679:25: note: in expansion of macro 'MACRO_MAP_N'
7> ../../../../../../components/libraries/util/app_util.h:678:24: note: in expansion of macro 'MACRO_MAP_'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd_internal.h:167:52: note: in expansion of macro 'MACRO_MAP'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd.h:233:9: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF_INTERNAL'
7> C:\some_path\main.c:619:1: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd_internal.h:116:1: note: (near initialization for 'm_app_hid_keyboard_ep')
7> ../../../../../../components/libraries/util/app_util.h:712:37: note: in expansion of macro 'APP_USBD_HID_KBD_INTERVAL'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'MACRO_MAP_1'
7> ../../../../../../components/libraries/util/app_util.h:700:29: note: in expansion of macro 'MACRO_MAP_N_'
7> ../../../../../../components/libraries/util/app_util.h:679:25: note: in expansion of macro 'MACRO_MAP_N'
7> ../../../../../../components/libraries/util/app_util.h:678:24: note: in expansion of macro 'MACRO_MAP_'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd_internal.h:167:52: note: in expansion of macro 'MACRO_MAP'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd.h:233:9: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF_INTERNAL'
7> C:\some_path\main.c:619:1: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF'
7> In file included from ../../../../../../components/libraries/usbd/app_usbd.h:46,
7>                  from C:\some_path\main.c:92:
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:463:18: error: initializer element is not constant
7> ../../../../../../components/libraries/util/app_util.h:747:41: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_1__'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'MACRO_MAP_REC_1'
7> ../../../../../../components/libraries/util/app_util.h:708:33: note: in expansion of macro 'MACRO_MAP_REC_N_'
7> ../../../../../../components/libraries/util/app_util.h:687:29: note: in expansion of macro 'MACRO_MAP_REC_N'
7> ../../../../../../components/libraries/util/app_util.h:686:28: note: in expansion of macro 'MACRO_MAP_REC_'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:460:17: note: in expansion of macro 'MACRO_MAP_REC'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:457:17: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_1_'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_1'
7> ../../../../../../components/libraries/util/nordic_common.h:116:31: note: in expansion of macro 'CONCAT_2_'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:440:9: note: in expansion of macro 'CONCAT_2'
7> ../../../../../../components/libraries/util/app_util.h:712:37: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'MACRO_MAP_1'
7> ../../../../../../components/libraries/util/app_util.h:700:29: note: in expansion of macro 'MACRO_MAP_N_'
7> ../../../../../../components/libraries/util/app_util.h:679:25: note: in expansion of macro 'MACRO_MAP_N'
7> ../../../../../../components/libraries/util/app_util.h:678:24: note: in expansion of macro 'MACRO_MAP_'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:583:5: note: in expansion of macro 'MACRO_MAP'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:811:29: note: in expansion of macro 'APP_USBD_CLASS_IFACES_EP_EXTRACT'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:946:9: note: in expansion of macro 'APP_USBD_CLASS_INSTANCE_INITVAL'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd_internal.h:169:5: note: in expansion of macro 'APP_USBD_CLASS_INST_GLOBAL_DEF'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd.h:233:9: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF_INTERNAL'
7> C:\some_path\main.c:619:1: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:463:18: note: (near initialization for 'm_app_hid_keyboard.specific.iface.ep[0].address')
7> ../../../../../../components/libraries/util/app_util.h:747:41: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_1__'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'MACRO_MAP_REC_1'
7> ../../../../../../components/libraries/util/app_util.h:708:33: note: in expansion of macro 'MACRO_MAP_REC_N_'
7> ../../../../../../components/libraries/util/app_util.h:687:29: note: in expansion of macro 'MACRO_MAP_REC_N'
7> ../../../../../../components/libraries/util/app_util.h:686:28: note: in expansion of macro 'MACRO_MAP_REC_'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:460:17: note: in expansion of macro 'MACRO_MAP_REC'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:457:17: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_1_'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_1'
7> ../../../../../../components/libraries/util/nordic_common.h:116:31: note: in expansion of macro 'CONCAT_2_'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:440:9: note: in expansion of macro 'CONCAT_2'
7> ../../../../../../components/libraries/util/app_util.h:712:37: note: in expansion of macro 'APP_USBD_CLASS_IFACE_EP_EXTRACT_'
7> ../../../../../../components/libraries/util/nordic_common.h:118:31: note: in expansion of macro 'MACRO_MAP_1'
7> ../../../../../../components/libraries/util/app_util.h:700:29: note: in expansion of macro 'MACRO_MAP_N_'
7> ../../../../../../components/libraries/util/app_util.h:679:25: note: in expansion of macro 'MACRO_MAP_N'
7> ../../../../../../components/libraries/util/app_util.h:678:24: note: in expansion of macro 'MACRO_MAP_'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:583:5: note: in expansion of macro 'MACRO_MAP'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:811:29: note: in expansion of macro 'APP_USBD_CLASS_IFACES_EP_EXTRACT'
7> ../../../../../../components/libraries/usbd/app_usbd_class_base.h:946:9: note: in expansion of macro 'APP_USBD_CLASS_INSTANCE_INITVAL'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd_internal.h:169:5: note: in expansion of macro 'APP_USBD_CLASS_INST_GLOBAL_DEF'
7> ../../../../../../components/libraries/usbd/class/hid/kbd/app_usbd_hid_kbd.h:233:9: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF_INTERNAL'
7> C:\some_path\main.c:619:1: note: in expansion of macro 'APP_USBD_HID_KBD_GLOBAL_DEF'
Build failed

which I don't understand.  How could it not be constant?  I got the endpoints the same way I did when there was only one of them.

Anyway, I think maybe I have asked too many questions here, but I'm not 100% if I'm asking the right things so I'm hoping that there is an answer that kind of gets everything since they are related.  If this is wrong, I can always break this into different questions.  Then I can also make another one for my confusion about what the interface parameter does... :-P

  • Hi

    What does your report descriptor look like?

    Is it based on the one in the USB HID Usage Table document?

    Feature and out reports can use either an output interrupt endpoint or the control endpoint. The control endpoint is always present, so technically no OUT endpoint is needed, which is why the keyboard descriptor can support output reports without configuring an OUT endpoint. 

    Best regards
    Torbjørn

  • The report is based on the usage table doc for HID power devices (cf. the chapter on Battery System and the example in Appendix A here, especially section A.6.9).  Generally, I am doing okay with creating descriptors I think.  I'm just a little fuzzy on getting and setting them using the app_usbd driver, and what the interplay is between endpoints, interfaces, and descriptors in the actual implementation.  Here is the descriptor, I can either use it at its own endpoint, or include it as a on the joystick or keyboard descriptor (I think, no?):

    #define HID_BATT_REPORT_DESC() {  \
        0x05, 0x85,                    /* USAGE_PAGE (Battery System) */ \
     \
        0x09, 0x18,                    /* USAGE (BatteryInsertion) */ \
        0x75, 0x01,                    /* REPORT_SIZE (1) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0x15, 0x00,                    /* LOGICAL_MINIMUM (0) */ \
        0x25, 0x01,                    /* LOGICAL_MAXIMUM (1) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs) */ \
     \
        0x09, 0x2c,                    /* USAGE (CapacityMode) */ \
        0x75, 0x01,                    /* REPORT_SIZE (1) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs) */ \
     \
        0x75, 0x06,                    /* REPORT_SIZE (6) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs)  ; end byte 1 */ \
     \
        0x09, 0x83,                    /* USAGE (DesignCapacity) */ \
        0x75, 0x18,                    /* REPORT_SIZE (24) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0x67, 0x01, 0x10, 0x10, 0x00,  /* UNIT (SI Lin:Battery Capacity) */ \
        0x55, 0x00,                    /* UNIT_EXPONENT (0) */ \
        0x15, 0x00,                    /* LOGICAL_MINIMUM (0) */ \
        0x27, 0xfe, 0xff, 0xff, 0x00,  /* LOGICAL_MAXIMUM (16777214) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs)  ; end byte 1 + 3 = 4 */ \
     \
        0x09, 0x66,                    /* USAGE (RemainingCapacity) */ \
        0x75, 0x24,                    /* REPORT_SIZE (36) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0x67, 0x01, 0x10, 0x10, 0x00,  /* UNIT (SI Lin:Battery Capacity) */ \
        0x55, 0x00,                    /* UNIT_EXPONENT (0) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs)  ; end byte 4 + 4 = 8, start byte 9 with 4 bits */ \
     \
        0x75, 0x04,                    /* REPORT_SIZE (4) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs)  ; end byte 9 */ \
     \
        0x09, 0x42,                    /* USAGE (BelowRemainingCapacityLimit) */ \
        0x09, 0x44,                    /* USAGE (Charging) */ \
        0x09, 0x45,                    /* USAGE (Discharging) */ \
        0x75, 0x01,                    /* REPORT_SIZE (1) */ \
        0x95, 0x03,                    /* REPORT_COUNT (3) */ \
        0x15, 0x00,                    /* LOGICAL_MINIMUM (0) */ \
        0x25, 0x01,                    /* LOGICAL_MAXIMUM (1) */ \
        0x65, 0x00,                    /* UNIT (None) */ \
        0xb1, 0x03,                    /* FEATURE (Cnst,Var,Abs)  ; start byte 10 with 3 bits */ \
     \
        0x75, 0x05,                    /* REPORT_SIZE (5) */ \
        0x95, 0x01,                    /* REPORT_COUNT (1) */ \
        0xb1, 0x03                     /* FEATURE (Cnst,Var,Abs)  ; +5bits = end byte 10 */ \
    }

    As I said before, I try to give it it's own endpoint, but I get an error using the macro APP_USBD_HID_KBD_GLOBAL_DEF.  The most important information first is to know what is the preferred way to set up a report descriptor like this one?

    Then, once I get it setup without throwing errors, I have no idea how to set the feature reports (I found this for BLE HID, but nothing for USBD) so some information about that would be appreciated.  Finally, if you are feeling particularly generous, maybe you could also clear up for me why I might use a separate endpoint for a new report descriptor vs just trying to append it to an existing descriptor?  Is it just if I plan on updating the data separately?

    Thanks for your help!

  • Hi

    Sorry for the slow reply. 

    The USB and HID interface in the SDK is not the easiest one to extend unfortunately ;)

    Essentially you have the choice of setting up a separate interface and endpoint(s) for your descriptor, or combine it with one of the existing ones.

    When combining it with an existing interface you need to combine the descriptors into one, and I recommend using different report ID's so that you can send either a standard keyboard/joystick packet, or send a battery system packet, depending on which one you want to update. 

    When using different report ID's you simply need to add an ID byte to the start of every packet, and the value of this will act as an index into the report descriptor. 

    I started some work on my own to try and include your descriptor into the usbd_hid_composite example, but I will have to continue this work over the weekend. 

    How are you planning to interface the battery system information from the host side? 

    Best regards
    Torbjørn

  • Hi,Overbekk:

        So do I meet the same problems above,..........Pls help!

  • Hi 

    I have set aside some time to try and add the Battery System report to one of the existing examples, but I am a bit unsure how to test this report and communicate with it from the host (PC) side. 

    Do you have some program or script that allows you to exchange information with the USB device over the Battery System report?

    Then it is much easier to test any code that I develop, if I have something to test it against. 

    Best regards
    Torbjørn

Related