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

HID get report from a mac not as expected

Hello again, This time I am trying to read HID reports using bluetooth to get the state of the caps lock. I know this should be super simple and its explained in the hid keyboard peripheral example using ble_hids_outp_rep_get. I am using a mac as a test machine and the report never becomes 0x02 (caps enabled).

Sadly I am unable to test it either using nRF connect due to the following: ˇgithub.com/.../4

Can anyone confirm that this is the case and if so, assuming it works on windows, explain why mac behaves this way?

Thank you, Yiangos

Parents
  • I know this thread is 3 years old but I think I've found a solution to this issue if anyone else is coming across it.

    When using the ble_hids_keyboard example from the SDK I was experiencing the same problem, I would receive a report from macOS but the value of the caps lock bit wouldn't change. As I developed my firmware further I added a consumer control report to the hid device descriptor which meant that I needed to explicitly add a report ID to both the keyboard report and consumer control report. After adding the report ID to the keyboard report the capslock functionality started working on macOS. I haven't had time to fully test that this was the change that did it but I pretty sure it was.

    My report descriptor looks like this:

    static uint8_t report_map_data[] = 
        {
            0x05, 0x01,       // Usage Page (Generic Desktop)
            0x09, 0x06,       // Usage (Keyboard)
            0xA1, 0x01,       // Collection (Application)
            0x85, 0x01,       // Report ID (1) <---- !!!!This is the bit I added
            0x05, 0x07,       // Usage Page (Key Codes)
            0x19, 0xe0,       // Usage Minimum (224)
            0x29, 0xe7,       // Usage Maximum (231)
            0x15, 0x00,       // Logical Minimum (0)
            0x25, 0x01,       // Logical Maximum (1)
            0x75, 0x01,       // Report Size (1)
            0x95, 0x08,       // Report Count (8)
            0x81, 0x02,       // Input (Data, Variable, Absolute)
    
            0x95, 0x01,       // Report Count (1)
            0x75, 0x08,       // Report Size (8)
            0x81, 0x01,       // Input (Constant) reserved byte(1)
    
            0x95, 0x05,       // Report Count (5)
            0x75, 0x01,       // Report Size (1)
            0x05, 0x08,       // Usage Page (Page# for LEDs)
            0x19, 0x01,       // Usage Minimum (1)
            0x29, 0x05,       // Usage Maximum (5)
            0x91, 0x02,       // Output (Data, Variable, Absolute), Led report
            0x95, 0x01,       // Report Count (1)
            0x75, 0x03,       // Report Size (3)
            0x91, 0x01,       // Output (Data, Variable, Absolute), Led report padding
    
            0x95, 0x06,       // Report Count (6)
            0x75, 0x08,       // Report Size (8)
            0x15, 0x00,       // Logical Minimum (0)
            0x25, 0x65,       // Logical Maximum (101)
            0x05, 0x07,       // Usage Page (Key codes)
            0x19, 0x00,       // Usage Minimum (0)
            0x29, 0x65,       // Usage Maximum (101)
            0x81, 0x00,       // Input (Data, Array) Key array(6 bytes)
    
            0x09, 0x05,       // Usage (Vendor Defined)
            0x15, 0x00,       // Logical Minimum (0)
            0x26, 0xFF, 0x00, // Logical Maximum (255)
            0x75, 0x08,       // Report Size (8 bit)
            0x95, 0x02,       // Report Count (2)
            0xB1, 0x02,       // Feature (Data, Variable, Absolute)
    
            0xC0,             // End Collection (Application)
    
            //Consumer Control report
            0x05, 0x0C,       // Usage Page (Consumer Devices)
            0x09, 0x01,       // Usage (Consumer Control)
            0xA1, 0x01,       // Collection (Application)
            0x85, 0x02,       // Report ID (2)
            0x15, 0x00,       // Logical Minimum (0)
            0x25, 0x01,       // Logical Maximum (1)
            0x75, 0x01,       // Report Size (1)
            0x95, 0x01,       // Report Count (1)
    
            0x09, 0xCD,       // Usage (Play/Pause)
            0x81, 0x02,       // Input (Data, Value, Relative, Bit Field)
            0x09, 0xB5,       // Usage (Scan Next Track)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xB6,       // Usage (Scan Previous Track)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xE2,       // Usage (Mute)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xE9,       // Usage (Vol Up)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xEA,       // Usage (Vol Down)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0x6F,       // Usage (Brightness Up)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0x70,       // Usage (Brightness Down)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
    
            0xC0
        };

     And my output report now looks like this:

        #define OUTPUT_REPORT_INDEX   0
        #define OUTPUT_REP_REF_ID     1//<----!!! This must match the report id specified in the descriptor
        #define OUTPUT_REPORT_MAX_LEN 1
    
        p_output_report                       = &output_report_array[OUTPUT_REPORT_INDEX];
        p_output_report->max_len              = OUTPUT_REPORT_MAX_LEN;
        p_output_report->rep_ref.report_id    = OUTPUT_REP_REF_ID;
        p_output_report->rep_ref.report_type  = BLE_HIDS_REP_TYPE_OUTPUT;
    
        p_output_report->sec.wr               = SEC_JUST_WORKS;
        p_output_report->sec.rd               = SEC_JUST_WORKS;

    I have no idea why specifying a report id would cause macOS to act differently but it seems it does.

    I hope this can help anyone who's having this problem!

Reply
  • I know this thread is 3 years old but I think I've found a solution to this issue if anyone else is coming across it.

    When using the ble_hids_keyboard example from the SDK I was experiencing the same problem, I would receive a report from macOS but the value of the caps lock bit wouldn't change. As I developed my firmware further I added a consumer control report to the hid device descriptor which meant that I needed to explicitly add a report ID to both the keyboard report and consumer control report. After adding the report ID to the keyboard report the capslock functionality started working on macOS. I haven't had time to fully test that this was the change that did it but I pretty sure it was.

    My report descriptor looks like this:

    static uint8_t report_map_data[] = 
        {
            0x05, 0x01,       // Usage Page (Generic Desktop)
            0x09, 0x06,       // Usage (Keyboard)
            0xA1, 0x01,       // Collection (Application)
            0x85, 0x01,       // Report ID (1) <---- !!!!This is the bit I added
            0x05, 0x07,       // Usage Page (Key Codes)
            0x19, 0xe0,       // Usage Minimum (224)
            0x29, 0xe7,       // Usage Maximum (231)
            0x15, 0x00,       // Logical Minimum (0)
            0x25, 0x01,       // Logical Maximum (1)
            0x75, 0x01,       // Report Size (1)
            0x95, 0x08,       // Report Count (8)
            0x81, 0x02,       // Input (Data, Variable, Absolute)
    
            0x95, 0x01,       // Report Count (1)
            0x75, 0x08,       // Report Size (8)
            0x81, 0x01,       // Input (Constant) reserved byte(1)
    
            0x95, 0x05,       // Report Count (5)
            0x75, 0x01,       // Report Size (1)
            0x05, 0x08,       // Usage Page (Page# for LEDs)
            0x19, 0x01,       // Usage Minimum (1)
            0x29, 0x05,       // Usage Maximum (5)
            0x91, 0x02,       // Output (Data, Variable, Absolute), Led report
            0x95, 0x01,       // Report Count (1)
            0x75, 0x03,       // Report Size (3)
            0x91, 0x01,       // Output (Data, Variable, Absolute), Led report padding
    
            0x95, 0x06,       // Report Count (6)
            0x75, 0x08,       // Report Size (8)
            0x15, 0x00,       // Logical Minimum (0)
            0x25, 0x65,       // Logical Maximum (101)
            0x05, 0x07,       // Usage Page (Key codes)
            0x19, 0x00,       // Usage Minimum (0)
            0x29, 0x65,       // Usage Maximum (101)
            0x81, 0x00,       // Input (Data, Array) Key array(6 bytes)
    
            0x09, 0x05,       // Usage (Vendor Defined)
            0x15, 0x00,       // Logical Minimum (0)
            0x26, 0xFF, 0x00, // Logical Maximum (255)
            0x75, 0x08,       // Report Size (8 bit)
            0x95, 0x02,       // Report Count (2)
            0xB1, 0x02,       // Feature (Data, Variable, Absolute)
    
            0xC0,             // End Collection (Application)
    
            //Consumer Control report
            0x05, 0x0C,       // Usage Page (Consumer Devices)
            0x09, 0x01,       // Usage (Consumer Control)
            0xA1, 0x01,       // Collection (Application)
            0x85, 0x02,       // Report ID (2)
            0x15, 0x00,       // Logical Minimum (0)
            0x25, 0x01,       // Logical Maximum (1)
            0x75, 0x01,       // Report Size (1)
            0x95, 0x01,       // Report Count (1)
    
            0x09, 0xCD,       // Usage (Play/Pause)
            0x81, 0x02,       // Input (Data, Value, Relative, Bit Field)
            0x09, 0xB5,       // Usage (Scan Next Track)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xB6,       // Usage (Scan Previous Track)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xE2,       // Usage (Mute)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xE9,       // Usage (Vol Up)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0xEA,       // Usage (Vol Down)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0x6F,       // Usage (Brightness Up)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
            0x09, 0x70,       // Usage (Brightness Down)
            0x81, 0x02,       // Input (Data,Value,Relative,Bit Field)
    
            0xC0
        };

     And my output report now looks like this:

        #define OUTPUT_REPORT_INDEX   0
        #define OUTPUT_REP_REF_ID     1//<----!!! This must match the report id specified in the descriptor
        #define OUTPUT_REPORT_MAX_LEN 1
    
        p_output_report                       = &output_report_array[OUTPUT_REPORT_INDEX];
        p_output_report->max_len              = OUTPUT_REPORT_MAX_LEN;
        p_output_report->rep_ref.report_id    = OUTPUT_REP_REF_ID;
        p_output_report->rep_ref.report_type  = BLE_HIDS_REP_TYPE_OUTPUT;
    
        p_output_report->sec.wr               = SEC_JUST_WORKS;
        p_output_report->sec.rd               = SEC_JUST_WORKS;

    I have no idea why specifying a report id would cause macOS to act differently but it seems it does.

    I hope this can help anyone who's having this problem!

Children
Related