Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

AFTER CONNECT BLE HID DEVICES TO IOS VIRTUAL KEYPAD DOES NOT SHOWN

Hi, I try to connect ble devices to my iphone. I can send hid data over bluetooth but virtual keypad is hiding. I cant open it. I tried to send 0x65 data as hid report but it did not work.

Heere is my hids_init function.

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[1];
    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 Count (2)
        0x95, 0x02,                 //     Report Size (8 bit)
        0xB1, 0x02,                 //     Feature (Data, Variable, Absolute)

        0xC0,                        // End Collection (Application)
        // Report ID 2: Advanced buttons
        0x05, 0x0C,                     // Usage Page (Consumer)
        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)

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

    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_OPEN;
    p_input_report->sec.wr      = SEC_OPEN;
    p_input_report->sec.rd      = SEC_OPEN;

    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_OPEN;
    p_output_report->sec.rd = SEC_OPEN;

    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_OPEN;
    p_feature_report->sec.wr              = SEC_OPEN;

    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                  = 1;
    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_OPEN;
    hids_init_obj.hid_information.rd_sec = SEC_OPEN;

    hids_init_obj.boot_kb_inp_rep_sec.cccd_wr = SEC_OPEN;
    hids_init_obj.boot_kb_inp_rep_sec.rd      = SEC_OPEN;

    hids_init_obj.boot_kb_outp_rep_sec.rd = SEC_OPEN;
    hids_init_obj.boot_kb_outp_rep_sec.wr = SEC_OPEN;

    hids_init_obj.protocol_mode_rd_sec = SEC_OPEN;
    hids_init_obj.protocol_mode_wr_sec = SEC_OPEN;
    hids_init_obj.ctrl_point_wr_sec    = SEC_OPEN;

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

And this is the part that I send hid report for make virtual keypad shown.

    // Assuming report_index for Boot Keyboard Input Report is 0
    if(BLE_CONN_HANDLE_INVALID != g_conn_handle)
    {
        ret_code_t err_code = ble_hids_inp_rep_send(&m_hids, 0, sizeof(report), report, g_conn_handle);
        NRF_LOG_INFO("HID REPORT SENT");
        APP_ERROR_CHECK(err_code);
    }

I am using nrf5 SDK and nRF52832.

What should I do for use virtual keypad in IOS while ble hid device connected?

Parents Reply Children
  • Hi,

     

    According to this thread on stack overflow, you need to send a different command on ios:

    https://stackoverflow.com/questions/61183450/toggle-virtual-keyboard-with-bluetooth-hid

     

    You should send on the consumer control report, meaning that you will need to adjust your input_report_array[] to also include that report. Please see the ble_app_hids_mouse sample on how to do this.

     

    Kind regards,

    Håkon

  • I got same report map when I implemented the link you send. Still iphone virtual keyboard does not show up. I checked out ble_app_hids_mouse. I fixed my input array bug according to this project but it didnt fix my keyboard problem. How must I configure my report map or Do Imust send extra report?

    How can I toggle keyboard or make keyboard shown?

  • Here is my hid init function.

    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)
            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)
            0x05, 0x0C,                     // Usage Page (Consumer)
            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)
            0x0A, 0xAE, 0x01,               //     Usage (AL Keyboard Layout)
            0x81, 0x06,                     //     Input (Data,Value,Relative,Bit Field)
            0xC0 
        };
    
        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;
    
        p_input_report                      = &input_report_array[1];
        p_input_report->max_len             = 8;
        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_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                  = 1;
        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);
    }

  • Hi,

     

    1. Adjust .inp_rep_count to match the amount of input reports

    2. The size of the max_len for input_report_array[1] is wrong. It is 1 byte.

    3. When triggering the "report_id 2", you should reference the index '1' when calling ble_hids_inp_rep_send(&m_hids, 1, ....)

     

    Kind regards,

    Håkon

  • As I said, I applied all of your 3 suggestions. They are fixed the sending report problem. But I am struggling with sending useful command. Which hid command I have to send iphone and which report index I have to send with?

Related