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?

  • Hi,

     

    Your input_report_array[] size is not matching the amount of report_ids you're using.

    See the ble_app_hids_mouse/main.c::hids_init() on how to setup more input_reports.

     

    I tried to send 0x65 data as hid report but it did not work.

    How does the "report" array look?

    Is it this command you're trying to send? (taken from page 56 in this doc: https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf)

     

    Kind regards,

    Håkon

  • Thanks for your reply. I fixed my input buffer size. Report array is [0, 0, 0x65, 0 ,0 ,0 ,0 ,0]. I tried to send only 0x65 as hid data. How should I send command for show up IOS keyboard?

  • 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);
    }

Related