HID connect, key and modifier sending and keyboard state

Hi,

I am using ble_sdk_app_hids_keyboard example:

https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Fble_sdk_app_hids_keyboard.html

I try to HID connect an iOS MPA, toggle the keyboard and send HID keys.

I encounter the following issues:

1) On HID connect, the state of the keyboard is unknown (User/System - meaning the keyboard is toggled up or down). On that case the toggle might create the opposite conditions required in the application. Is there a way to configure that on HID connection, the keyboard will be toggled down allways?

2) With regards to (1), is there a way to know the keyboard state on connection (i.e. through descriptors or other info).

3) I have been able to write characters to the screen (a, b, c..) using key - 0x04, 0x05 .. and modifiers 0x00. However, when trying to send other sequences (such as spotlight - modifier 0x08, key 0x2C), the HID send has no effect. I am using the upper example, so no sure what could go wrong.

I'll really appreciate any help,

Kobi

Parents
  • I used the following HID init function flow:

    static void hids_init(void)
    {
    ret_code_t err_code;
    ble_hids_init_t hids_init_obj;
    ble_hids_inp_rep_init_t * p_input_report;
    ble_hids_outp_rep_init_t * p_output_report;
    ble_hids_feature_rep_init_t * p_feature_report;
    uint8_t hid_info_flags;

    static ble_hids_inp_rep_init_t input_report_array[2];
    static ble_hids_outp_rep_init_t output_report_array[1];
    static ble_hids_feature_rep_init_t feature_report_array[1];
    static uint8_t report_map_data[] =
    {
    0x05, 0x01, // Usage Page (Generic Desktop)
    ...

    0xC0,

    // End Collection (Application)

    // Report ID 2: Advanced buttons
    0x05, 0x0C, // Usage Page (Consumer)
    0x09, 0x01, // Usage (Consumer Control)
    0xA1, 0x01, // Collection (Application)
    0x85, 0x01, // Report Id (1)
    0x15, 0x00, // Logical minimum (0)
    0x25, 0x01, // Logical maximum (1)
    0x75, 0x01, // Report Size (1)
    0x95, 0x01, // Report Count (1)

    0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
    0x81, 0x06, // Input (Data,Value,Relative,Bit Field)
    0xC0 // End Collection
    };

    memset((void *)input_report_array, 0, 2 * sizeof(ble_hids_inp_rep_init_t));
    memset((void *)output_report_array, 0, sizeof(ble_hids_outp_rep_init_t));
    memset((void *)feature_report_array, 0, sizeof(ble_hids_feature_rep_init_t));

    // 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;

    p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
    p_input_report->sec.wr = SEC_JUST_WORKS;
    p_input_report->sec.rd = SEC_JUST_WORKS;

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

    p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
    p_input_report->sec.wr = SEC_JUST_WORKS;
    p_input_report->sec.rd = SEC_JUST_WORKS;
    p_input_report = &input_report_array[INPUT_REPORT_KEYS_INDEX];

    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;

    p_feature_report = &feature_report_array[FEATURE_REPORT_INDEX];
    p_feature_report->max_len = FEATURE_REPORT_MAX_LEN;
    p_feature_report->rep_ref.report_id = FEATURE_REP_REF_ID;
    p_feature_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_FEATURE;

    p_feature_report->sec.rd = SEC_JUST_WORKS;
    p_feature_report->sec.wr = SEC_JUST_WORKS;

    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 = false;
    hids_init_obj.inp_rep_count = 2;
    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 = 1;
    hids_init_obj.p_feature_rep_array = feature_report_array;
    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;

    hids_init_obj.rep_map.rd_sec = SEC_JUST_WORKS;
    hids_init_obj.hid_information.rd_sec = SEC_JUST_WORKS;

    hids_init_obj.boot_kb_inp_rep_sec.cccd_wr = SEC_JUST_WORKS;
    hids_init_obj.boot_kb_inp_rep_sec.rd = SEC_JUST_WORKS;

    hids_init_obj.boot_kb_outp_rep_sec.rd = SEC_JUST_WORKS;
    hids_init_obj.boot_kb_outp_rep_sec.wr = SEC_JUST_WORKS;

    hids_init_obj.protocol_mode_rd_sec = SEC_JUST_WORKS;
    hids_init_obj.protocol_mode_wr_sec = SEC_JUST_WORKS;
    hids_init_obj.ctrl_point_wr_sec = SEC_JUST_WORKS;

    err_code = ble_hids_init(&m_hids, &hids_init_obj);
    APP_ERROR_CHECK(err_code);
    }

    When I remove the colored lines, the shift seems to work.

    However, I can not use the toggle functionality.

    How can I use both the toggle and the Shift features?

    K.E.

Reply
  • I used the following HID init function flow:

    static void hids_init(void)
    {
    ret_code_t err_code;
    ble_hids_init_t hids_init_obj;
    ble_hids_inp_rep_init_t * p_input_report;
    ble_hids_outp_rep_init_t * p_output_report;
    ble_hids_feature_rep_init_t * p_feature_report;
    uint8_t hid_info_flags;

    static ble_hids_inp_rep_init_t input_report_array[2];
    static ble_hids_outp_rep_init_t output_report_array[1];
    static ble_hids_feature_rep_init_t feature_report_array[1];
    static uint8_t report_map_data[] =
    {
    0x05, 0x01, // Usage Page (Generic Desktop)
    ...

    0xC0,

    // End Collection (Application)

    // Report ID 2: Advanced buttons
    0x05, 0x0C, // Usage Page (Consumer)
    0x09, 0x01, // Usage (Consumer Control)
    0xA1, 0x01, // Collection (Application)
    0x85, 0x01, // Report Id (1)
    0x15, 0x00, // Logical minimum (0)
    0x25, 0x01, // Logical maximum (1)
    0x75, 0x01, // Report Size (1)
    0x95, 0x01, // Report Count (1)

    0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
    0x81, 0x06, // Input (Data,Value,Relative,Bit Field)
    0xC0 // End Collection
    };

    memset((void *)input_report_array, 0, 2 * sizeof(ble_hids_inp_rep_init_t));
    memset((void *)output_report_array, 0, sizeof(ble_hids_outp_rep_init_t));
    memset((void *)feature_report_array, 0, sizeof(ble_hids_feature_rep_init_t));

    // 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;

    p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
    p_input_report->sec.wr = SEC_JUST_WORKS;
    p_input_report->sec.rd = SEC_JUST_WORKS;

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

    p_input_report->sec.cccd_wr = SEC_JUST_WORKS;
    p_input_report->sec.wr = SEC_JUST_WORKS;
    p_input_report->sec.rd = SEC_JUST_WORKS;
    p_input_report = &input_report_array[INPUT_REPORT_KEYS_INDEX];

    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;

    p_feature_report = &feature_report_array[FEATURE_REPORT_INDEX];
    p_feature_report->max_len = FEATURE_REPORT_MAX_LEN;
    p_feature_report->rep_ref.report_id = FEATURE_REP_REF_ID;
    p_feature_report->rep_ref.report_type = BLE_HIDS_REP_TYPE_FEATURE;

    p_feature_report->sec.rd = SEC_JUST_WORKS;
    p_feature_report->sec.wr = SEC_JUST_WORKS;

    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 = false;
    hids_init_obj.inp_rep_count = 2;
    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 = 1;
    hids_init_obj.p_feature_rep_array = feature_report_array;
    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;

    hids_init_obj.rep_map.rd_sec = SEC_JUST_WORKS;
    hids_init_obj.hid_information.rd_sec = SEC_JUST_WORKS;

    hids_init_obj.boot_kb_inp_rep_sec.cccd_wr = SEC_JUST_WORKS;
    hids_init_obj.boot_kb_inp_rep_sec.rd = SEC_JUST_WORKS;

    hids_init_obj.boot_kb_outp_rep_sec.rd = SEC_JUST_WORKS;
    hids_init_obj.boot_kb_outp_rep_sec.wr = SEC_JUST_WORKS;

    hids_init_obj.protocol_mode_rd_sec = SEC_JUST_WORKS;
    hids_init_obj.protocol_mode_wr_sec = SEC_JUST_WORKS;
    hids_init_obj.ctrl_point_wr_sec = SEC_JUST_WORKS;

    err_code = ble_hids_init(&m_hids, &hids_init_obj);
    APP_ERROR_CHECK(err_code);
    }

    When I remove the colored lines, the shift seems to work.

    However, I can not use the toggle functionality.

    How can I use both the toggle and the Shift features?

    K.E.

Children
No Data
Related