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

mouse + keyboard combo

Hello Guys,

I successfully used ble_hids_mouse and ble_hids_keyboard on my hardware but my final solution is a mouse + keyboard combo.

I merged the mouse and keyboard functions but when I pair with Windows it shows driver error. I suspect my problem has to do with the HID init because it is the only section of the merge I had to guess.

If anyone who has done this before is willing to help, you will have my eternal gratitude.

I'm not an expert on HID configuration so I tried the following approach:

#define MOVEMENT_SPEED                  5                                           // Number of pixels by which the cursor is moved each time a button is pushed
#define INPUT_REPORT_COUNT              4                                           // Number of input reports in this application. 
#define INPUT_REP_BUTTONS_LEN           3                                           // Length of Mouse Input Report containing button data. 
#define INPUT_REP_MOVEMENT_LEN          3                                           // Length of Mouse Input Report containing movement data. 
#define INPUT_REP_MEDIA_PLAYER_LEN      1                                           // Length of Mouse Input Report containing media player data. 
#define INPUT_REP_BUTTONS_INDEX         1                                           // Index of Mouse Input Report containing button data. 
#define INPUT_REP_MOVEMENT_INDEX        2                                           // Index of Mouse Input Report containing movement data. 
#define INPUT_REP_MPLAYER_INDEX         3                                           // Index of Mouse Input Report containing media player data. 
#define INPUT_REP_REF_BUTTONS_ID        1                                           // Id of reference to Mouse Input Report containing button data. 
#define INPUT_REP_REF_MOVEMENT_ID       2                                           // Id of reference to Mouse Input Report containing movement data. 
#define INPUT_REP_REF_MPLAYER_ID        3                                           // Id of reference to Mouse Input Report containing media player data. 
#define OUTPUT_REPORT_INDEX              0                                              // Index of Output Report. 
#define OUTPUT_REPORT_MAX_LEN            1                                              // Maximum length of Output Report. 
#define INPUT_REPORT_KEYS_INDEX          0                                              // Index of Input Report. 
#define OUTPUT_REPORT_BIT_MASK_CAPS_LOCK 0x02                                           // CAPS LOCK bit in Output Report (based on 'LED Page (0x08)' of the Universal Serial Bus HID Usage Tables). 
#define INPUT_REP_REF_ID                 0                                              // Id of reference to Keyboard Input Report. 
#define OUTPUT_REP_REF_ID                0                                              // Id of reference to Keyboard Output Report.


static void hids_init(void)
{
uint32_t                   err_code;
ble_hids_init_t            hids_init_obj;
ble_hids_inp_rep_init_t    input_report_array[INPUT_REPORT_COUNT];
ble_hids_inp_rep_init_t  * p_input_report;
ble_hids_outp_rep_init_t   output_report_array[1];
ble_hids_outp_rep_init_t * p_output_report;
uint8_t                    hid_info_flags;

static uint8_t report_map_data[] =
{
    0x05, 0x01,                 // Usage Page (Generic Desktop)
    0x09, 0x06,                 // Usage (Keyboard)
    0xA1, 0x01,                 // Collection (Application)
    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 Count (2)
    0x95, 0x02,                 //     Report Size (8 bit)
    0xB1, 0x02,                 //     Feature (Data, Variable, Absolute)

    0xC0,                        // End Collection (Application)
    
    0x09, 0x02,                     // Usage (Mouse)
    0xA1, 0x01,                     // Collection (Application)
    // Report ID 1: Mouse buttons + scroll/pan
    0x85, 0x01,                     //     Report Id 1
    0x09, 0x01,                     //     Usage (Pointer)
    0xA1, 0x00,                     //     Collection (Physical)
    0x95, 0x05,                     //         Report Count (3)
    0x75, 0x01,                     //         Report Size (1)
    0x05, 0x09,                     //         Usage Page (Buttons)
    0x19, 0x01,                     //             Usage Minimum (01)
    0x29, 0x05,                     //             Usage Maximum (05)
    0x15, 0x00,                     //             Logical Minimum (0)
    0x25, 0x01,                     //             Logical Maximum (1)
    0x81, 0x02,                     //             Input (Data, Variable, Absolute)
    0x95, 0x01,                     //             Report Count (1)
    0x75, 0x03,                     //             Report Size (3)
    0x81, 0x01,                     //             Input (Constant) for padding
    0x75, 0x08,                     //             Report Size (8)
    0x95, 0x01,                     //             Report Count (1)
    0x05, 0x01,                     //         Usage Page (Generic Desktop)
    0x09, 0x38,                     //             Usage (Wheel)
    0x15, 0x81,                     //             Logical Minimum (-127)
    0x25, 0x7F,                     //             Logical Maximum (127)
    0x81, 0x06,                     //             Input (Data, Variable, Relative)
    0x05, 0x0C,                     //         Usage Page (Consumer)
    0x0A, 0x38, 0x02,               //             Usage (AC Pan)
    0x95, 0x01,                     //             Report Count (1)
    0x81, 0x06,                     //             Input (Data,Value,Relative,Bit Field)
    0xC0,                           //     End Collection (Physical)

    // Report ID 2: Mouse motion
    0x85, 0x02,                     //     Report Id 2
    0x09, 0x01,                     //     Usage (Pointer)
    0xA1, 0x00,                     //     Collection (Physical)
    0x75, 0x0C,                     //         Report Size (12)
    0x95, 0x02,                     //         Report Count (2)
    0x05, 0x01,                     //         Usage Page (Generic Desktop)
    0x09, 0x30,                     //             Usage (X)
    0x09, 0x31,                     //             Usage (Y)
    0x16, 0x01, 0xF8,               //             Logical maximum (2047)
    0x26, 0xFF, 0x07,               //             Logical minimum (-2047)
    0x81, 0x06,                     //             Input (Data, Variable, Relative)
    0xC0,                           //     End Collection (Physical)
    0xC0,                           // End Collection (Application)

    // Report ID 3: Advanced buttons
    0x05, 0x0C,                     // Usage Page (Consumer)
    0x09, 0x01,                     // Usage (Consumer Control)
    0xA1, 0x01,                     // Collection (Application)
    0x85, 0x03,                     //     Report Id (3)
    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, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0x0A, 0x83, 0x01,               //     Usage (AL Consumer Control Configuration)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0x09, 0xB5,                     //     Usage (Scan Next Track)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0x09, 0xB6,                     //     Usage (Scan Previous Track)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)

    0x09, 0xEA,                     //     Usage (Volume Down)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0x09, 0xE9,                     //     Usage (Volume Up)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0x0A, 0x25, 0x02,               //     Usage (AC Forward)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0x0A, 0x24, 0x02,               //     Usage (AC Back)
    0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    0xC0                            // End Collection

    };

// Initialize HID Service
p_input_report                      = &input_report_array[INPUT_REPORT_KEYS_INDEX];
p_input_report->max_len             = INPUT_REPORT_KEYS_MAX_LEN;
p_input_report->rep_ref.report_id   = INPUT_REP_REF_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT; 

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

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;

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_output_report->security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_output_report->security_mode.write_perm);

// Mouse
// Initialize HID Service.
p_input_report                      = &input_report_array[INPUT_REP_BUTTONS_INDEX];
p_input_report->max_len             = INPUT_REP_BUTTONS_LEN;
p_input_report->rep_ref.report_id   = INPUT_REP_REF_BUTTONS_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

p_input_report                      = &input_report_array[INPUT_REP_MOVEMENT_INDEX];
p_input_report->max_len             = INPUT_REP_MOVEMENT_LEN;
p_input_report->rep_ref.report_id   = INPUT_REP_REF_MOVEMENT_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

p_input_report                      = &input_report_array[INPUT_REP_MPLAYER_INDEX];
p_input_report->max_len             = INPUT_REP_MEDIA_PLAYER_LEN;
p_input_report->rep_ref.report_id   = INPUT_REP_REF_MPLAYER_ID;
p_input_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_INPUT;

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

// === mouse
hid_info_flags = HID_INFO_FLAG_REMOTE_WAKE_MSK | HID_INFO_FLAG_NORMALLY_CONNECTABLE_MSK;

memset(&hids_init_obj, 0, sizeof(hids_init_obj));

hids_init_obj.evt_handler                    = on_hids_evt;
hids_init_obj.error_handler                  = service_error_handler;
hids_init_obj.is_kb                          = true;
hids_init_obj.is_mouse                       = true;
hids_init_obj.inp_rep_count                  = INPUT_REPORT_COUNT;
hids_init_obj.p_inp_rep_array                = input_report_array;
hids_init_obj.outp_rep_count                 = 1;
hids_init_obj.p_outp_rep_array               = output_report_array;
hids_init_obj.feature_rep_count              = 0;
hids_init_obj.p_feature_rep_array            = NULL;
hids_init_obj.rep_map.data_len               = sizeof(report_map_data);
hids_init_obj.rep_map.p_data                 = report_map_data;
hids_init_obj.hid_information.bcd_hid        = BASE_USB_HID_SPEC_VERSION;
hids_init_obj.hid_information.b_country_code = 0;
hids_init_obj.hid_information.flags          = hid_info_flags;
hids_init_obj.included_services_count        = 0;
hids_init_obj.p_included_services_array      = NULL;

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.rep_map.security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.rep_map.security_mode.write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.hid_information.security_mode.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.hid_information.security_mode.write_perm);

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
    &hids_init_obj.security_mode_boot_kb_inp_rep.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_inp_rep.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.security_mode_boot_kb_inp_rep.write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_outp_rep.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_outp_rep.write_perm);

// Mouse
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
    &hids_init_obj.security_mode_boot_mouse_inp_rep.cccd_write_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
    &hids_init_obj.security_mode_boot_mouse_inp_rep.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
    &hids_init_obj.security_mode_boot_mouse_inp_rep.write_perm);
// === mouse

BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_protocol.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_protocol.write_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.security_mode_ctrl_point.read_perm);
 BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_ctrl_point.write_perm);
err_code = ble_hids_init(&m_hids, &hids_init_obj);
APP_ERROR_CHECK(err_code);
}
Parents
  • Hi,

    The USB descriptor will most likely not be accepted by the OS on the central side. This is because how you've setup the report IDs in report_map_data[] array.

    The only scenario when you are allowed to not specify a report ID on a descriptor is when this is the only descriptor present on your device. Then this will be interpreted as report ID '0' (which is not legal to specify directly in the USB spec).

    You need to alter two things:

    • Start your keyboard descriptor with REPORT ID 1 and increment for each new usage
    • Do the same with all defines being set in "p_input_report->rep_ref.report_id". "INPUT_REP_REF_ID" should be '1', "INPUT_REP_REF_BUTTONS_ID" should be '2' etc.

    Note that when you are sending data over the BLE-link, you should use the INDEX define, which should start from '0' again. For instance, to send button data:

    ble_hids_inp_rep_send(&m_hids, INPUT_REP_BUTTONS_INDEX, INPUT_REP_BUTTONS_LEN, buttons_buffer);
    

    edit Here's the proposed fixes in the descriptor as well:

    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
        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 Count (2)
        0x95, 0x02,                 //     Report Size (8 bit)
        0xB1, 0x02,                 //     Feature (Data, Variable, Absolute)
    
        0xC0,                        // End Collection (Application)
    
        0x09, 0x02,                     // Usage (Mouse)
        0xA1, 0x01,                     // Collection (Application)
        // Report ID 2: Mouse buttons + scroll/pan
        0x85, 0x02,                     //     Report Id 2
        0x09, 0x01,                     //     Usage (Pointer)
        0xA1, 0x00,                     //     Collection (Physical)
        0x95, 0x05,                     //         Report Count (3)
        0x75, 0x01,                     //         Report Size (1)
        0x05, 0x09,                     //         Usage Page (Buttons)
        0x19, 0x01,                     //             Usage Minimum (01)
        0x29, 0x05,                     //             Usage Maximum (05)
        0x15, 0x00,                     //             Logical Minimum (0)
        0x25, 0x01,                     //             Logical Maximum (1)
        0x81, 0x02,                     //             Input (Data, Variable, Absolute)
        0x95, 0x01,                     //             Report Count (1)
        0x75, 0x03,                     //             Report Size (3)
        0x81, 0x01,                     //             Input (Constant) for padding
        0x75, 0x08,                     //             Report Size (8)
        0x95, 0x01,                     //             Report Count (1)
        0x05, 0x01,                     //         Usage Page (Generic Desktop)
        0x09, 0x38,                     //             Usage (Wheel)
        0x15, 0x81,                     //             Logical Minimum (-127)
        0x25, 0x7F,                     //             Logical Maximum (127)
        0x81, 0x06,                     //             Input (Data, Variable, Relative)
        0x05, 0x0C,                     //         Usage Page (Consumer)
        0x0A, 0x38, 0x02,               //             Usage (AC Pan)
        0x95, 0x01,                     //             Report Count (1)
        0x81, 0x06,                     //             Input (Data,Value,Relative,Bit Field)
        0xC0,                           //     End Collection (Physical)
    
        // Report ID 3: Mouse motion
        0x85, 0x03,                     //     Report Id 2
        0x09, 0x01,                     //     Usage (Pointer)
        0xA1, 0x00,                     //     Collection (Physical)
        0x75, 0x0C,                     //         Report Size (12)
        0x95, 0x02,                     //         Report Count (2)
        0x05, 0x01,                     //         Usage Page (Generic Desktop)
        0x09, 0x30,                     //             Usage (X)
        0x09, 0x31,                     //             Usage (Y)
        0x16, 0x01, 0xF8,               //             Logical maximum (2047)
        0x26, 0xFF, 0x07,               //             Logical minimum (-2047)
        0x81, 0x06,                     //             Input (Data, Variable, Relative)
        0xC0,                           //     End Collection (Physical)
        0xC0,                           // End Collection (Application)
    
        // Report ID 4: Advanced buttons
        0x05, 0x0C,                     // Usage Page (Consumer)
        0x09, 0x01,                     // Usage (Consumer Control)
        0xA1, 0x01,                     // Collection (Application)
        0x85, 0x04,                     //     Report Id (3)
        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, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x0A, 0x83, 0x01,               //     Usage (AL Consumer Control Configuration)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x09, 0xB5,                     //     Usage (Scan Next Track)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x09, 0xB6,                     //     Usage (Scan Previous Track)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    
        0x09, 0xEA,                     //     Usage (Volume Down)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x09, 0xE9,                     //     Usage (Volume Up)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x0A, 0x25, 0x02,               //     Usage (AC Forward)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x0A, 0x24, 0x02,               //     Usage (AC Back)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0xC0                            // End Collection
    
        };
    

    Cheers, Håkon

Reply
  • Hi,

    The USB descriptor will most likely not be accepted by the OS on the central side. This is because how you've setup the report IDs in report_map_data[] array.

    The only scenario when you are allowed to not specify a report ID on a descriptor is when this is the only descriptor present on your device. Then this will be interpreted as report ID '0' (which is not legal to specify directly in the USB spec).

    You need to alter two things:

    • Start your keyboard descriptor with REPORT ID 1 and increment for each new usage
    • Do the same with all defines being set in "p_input_report->rep_ref.report_id". "INPUT_REP_REF_ID" should be '1', "INPUT_REP_REF_BUTTONS_ID" should be '2' etc.

    Note that when you are sending data over the BLE-link, you should use the INDEX define, which should start from '0' again. For instance, to send button data:

    ble_hids_inp_rep_send(&m_hids, INPUT_REP_BUTTONS_INDEX, INPUT_REP_BUTTONS_LEN, buttons_buffer);
    

    edit Here's the proposed fixes in the descriptor as well:

    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
        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 Count (2)
        0x95, 0x02,                 //     Report Size (8 bit)
        0xB1, 0x02,                 //     Feature (Data, Variable, Absolute)
    
        0xC0,                        // End Collection (Application)
    
        0x09, 0x02,                     // Usage (Mouse)
        0xA1, 0x01,                     // Collection (Application)
        // Report ID 2: Mouse buttons + scroll/pan
        0x85, 0x02,                     //     Report Id 2
        0x09, 0x01,                     //     Usage (Pointer)
        0xA1, 0x00,                     //     Collection (Physical)
        0x95, 0x05,                     //         Report Count (3)
        0x75, 0x01,                     //         Report Size (1)
        0x05, 0x09,                     //         Usage Page (Buttons)
        0x19, 0x01,                     //             Usage Minimum (01)
        0x29, 0x05,                     //             Usage Maximum (05)
        0x15, 0x00,                     //             Logical Minimum (0)
        0x25, 0x01,                     //             Logical Maximum (1)
        0x81, 0x02,                     //             Input (Data, Variable, Absolute)
        0x95, 0x01,                     //             Report Count (1)
        0x75, 0x03,                     //             Report Size (3)
        0x81, 0x01,                     //             Input (Constant) for padding
        0x75, 0x08,                     //             Report Size (8)
        0x95, 0x01,                     //             Report Count (1)
        0x05, 0x01,                     //         Usage Page (Generic Desktop)
        0x09, 0x38,                     //             Usage (Wheel)
        0x15, 0x81,                     //             Logical Minimum (-127)
        0x25, 0x7F,                     //             Logical Maximum (127)
        0x81, 0x06,                     //             Input (Data, Variable, Relative)
        0x05, 0x0C,                     //         Usage Page (Consumer)
        0x0A, 0x38, 0x02,               //             Usage (AC Pan)
        0x95, 0x01,                     //             Report Count (1)
        0x81, 0x06,                     //             Input (Data,Value,Relative,Bit Field)
        0xC0,                           //     End Collection (Physical)
    
        // Report ID 3: Mouse motion
        0x85, 0x03,                     //     Report Id 2
        0x09, 0x01,                     //     Usage (Pointer)
        0xA1, 0x00,                     //     Collection (Physical)
        0x75, 0x0C,                     //         Report Size (12)
        0x95, 0x02,                     //         Report Count (2)
        0x05, 0x01,                     //         Usage Page (Generic Desktop)
        0x09, 0x30,                     //             Usage (X)
        0x09, 0x31,                     //             Usage (Y)
        0x16, 0x01, 0xF8,               //             Logical maximum (2047)
        0x26, 0xFF, 0x07,               //             Logical minimum (-2047)
        0x81, 0x06,                     //             Input (Data, Variable, Relative)
        0xC0,                           //     End Collection (Physical)
        0xC0,                           // End Collection (Application)
    
        // Report ID 4: Advanced buttons
        0x05, 0x0C,                     // Usage Page (Consumer)
        0x09, 0x01,                     // Usage (Consumer Control)
        0xA1, 0x01,                     // Collection (Application)
        0x85, 0x04,                     //     Report Id (3)
        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, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x0A, 0x83, 0x01,               //     Usage (AL Consumer Control Configuration)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x09, 0xB5,                     //     Usage (Scan Next Track)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x09, 0xB6,                     //     Usage (Scan Previous Track)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
    
        0x09, 0xEA,                     //     Usage (Volume Down)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x09, 0xE9,                     //     Usage (Volume Up)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x0A, 0x25, 0x02,               //     Usage (AC Forward)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0x0A, 0x24, 0x02,               //     Usage (AC Back)
        0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
        0xC0                            // End Collection
    
        };
    

    Cheers, Håkon

Children
No Data
Related