hid suspend request

Hey,

I am using an HID keyboard + keyboard toggle in my project,

When the nrf connects an iOS phone, it takes control over the phone's keyboard.

To release the kb we use toggle hid report send.

The problem is, if we send the hid, when the phone is not in a text field application, the toggle has no effect.

I read about an HID suspend/resume feature that should practice an HID connection/disconnection like behavior.

I could not find a lot of info about the suspend in the spec sheet of nrf.

1) Please, could u point me to the right direction?  

2) Is there another way to take/release control over the keyboard in the iOS phone, from the nrf board.

Will appreciate any help,

Kobi

Parents
  • Hi Kobi

    I assume this HID keyboard you're making is going to use HID over GATT since it's connecting to a phone, instead of HID over USB. The HID over GATT don't have anything like the suspend feature you're mentioning here as far as I know. Can you show me the "toggle HID report" you use to release the keyboard now? I don't see why this shouldn't work when the phone isn't in a text field, as it should still be connected to the keyboard.

    An alternative would be to manually disconnect/connect when you want to release the phone from the board, and then connect when you want to use it again. This shouldn't require anything from the iOS phone as long as the devices are bonded.

    What SDK and SDK version are you using?

    Best regards,

    Simon

Reply
  • Hi Kobi

    I assume this HID keyboard you're making is going to use HID over GATT since it's connecting to a phone, instead of HID over USB. The HID over GATT don't have anything like the suspend feature you're mentioning here as far as I know. Can you show me the "toggle HID report" you use to release the keyboard now? I don't see why this shouldn't work when the phone isn't in a text field, as it should still be connected to the keyboard.

    An alternative would be to manually disconnect/connect when you want to release the phone from the board, and then connect when you want to use it again. This shouldn't require anything from the iOS phone as long as the devices are bonded.

    What SDK and SDK version are you using?

    Best regards,

    Simon

Children
  • Hey Simon,

    1) This is how I initialize the HID:


    /**@brief Function for initializing HID Service.
    */
    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)
    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 Size (8 bit)
    0x95, 0x02, // Report Count (2)
    0xB1, 0x02, // Feature (Data, Variable, Absolute)

    0xC0, // End Collection (Application)
    // Report ID 2: Advanced buttons
    0x05, 0x0C, // Usage Page (Consumer)
    0xA1, 0x01, // Collection (Application)
    0x85, 0x02, // Report Id (2)
    0x15, 0x00, // Logical minimum (0)
    0x25, 0x01, // Logical maximum (1)
    0x0A, 0xAE, 0x01, // Usage (AL Keyboard Layout)
    0x75, 0x01, // Report Size (1)
    0x95, 0x01, // Report Count (1)
    0x81, 0x06, // Input (Data,Value,Relative,Bit Field)
    0xC0 // End Collection
    };

    memset((void *)input_report_array, 0, 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[INPUT_REPORT_TOGGLE_INDEX];
    p_input_report->max_len = INPUT_REPORT_KEYS_MAX_LEN;
    p_input_report->rep_ref.report_id = INPUT_REP_TOGGLE_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;
    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);
    }

    2) This is how we send the Toggle report:

    uint8_t release[] = {0};
    uint8_t keyboard_toggle[] = {1};
    uint32_t err_code = ble_hids_inp_rep_send(&m_hids, HID_TOGGLE_REPORT_INDEX, sizeof(keyboard_toggle), keyboard_toggle, innerConHandle);
    APP_ERROR_CHECK(err_code);
    ble_hids_inp_rep_send(&m_hids, HID_TOGGLE_REPORT_INDEX, sizeof(release), release, innerConHandle);
    APP_ERROR_CHECK(err_code);

    3) I searched some in the nrf and saw this:

    int bt_hogp_suspend(struct bt_hogp *hogp)

    int bt_hogp_exit_suspend(struct bt_hogp *hogp)

    Would this help with my requierment? 

    Tnx a lot

    Kobi

Related