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

Integrating HID mouse and HID keyboard.

Hi,

   I want to integrate HID mouse and HID keyboard in a single device. Can you tell me the complete configuration procedure to integrate HID mouse and HID keyboard in a single HID device?

Thanks 

Parents
  • Hello,

    You will need to combine the hid keyboard and hid mouse example in this case, in specific look at the implementation of hids_init() in terms of updating the report_map and adjusting the number of input reports and report indexes.

    This old answer should still be valid for most part, since the report map show how it looks for a combined keyboard+mouse:
    https://devzone.nordicsemi.com/f/nordic-q-a/4408/mouse-keyboard-combo/15659#15659

    Best regards,
    Kenneth

  • Hi Kenneth

       Thanks for the reply. I have tested that report map and descriptor, HID connects successfully but does not send any data or show any error.

    Here are my report ID, report map, and hids_init(). 

    Report ID's

    #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         0                                           /**< Index of Mouse Input Report containing button data. */
    #define INPUT_REP_MOVEMENT_INDEX        1                                           /**< Index of Mouse Input Report containing movement data. */
    #define INPUT_REP_MPLAYER_INDEX         2                                           /**< 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 INPUT_REPORT_KEYS_MAX_LEN           8   
    
    //---------------------------
    #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             3                                          /**< 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. */
    #define FEATURE_REP_REF_ID                  0                                          /**< ID of reference to Keyboard Feature Report. */
    #define FEATURE_REPORT_MAX_LEN              2                                          /**< Maximum length of Feature Report. */
    #define FEATURE_REPORT_INDEX                0  

    hids_init()

    static void hids_init(void)
    {
        ret_code_t                    err_code;
        ble_hids_init_t               hids_init_obj;
    
        ble_hids_init_t               hids_init_obj_keyboard;
        ble_hids_init_t               hids_init_obj_mouse;
    
        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[INPUT_REPORT_COUNT];
        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, 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
    		
    //------------------------------------------------------		
            0x05, 0x01,       // Usage Page (Generic Desktop)
            0x09, 0x06,       // Usage (Keyboard)
            0xA1, 0x01,       // Collection (Application)
    	0x85, 0x04,       // Report Id 4
            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)
        };
    
        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_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;
    
    //--------------------------------------
        // 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;
    
        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_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;
    
        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_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;
    
        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;
    
    
        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                  = 4;
        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.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.boot_mouse_inp_rep_sec.cccd_wr = SEC_JUST_WORKS;
        hids_init_obj.boot_mouse_inp_rep_sec.wr      = SEC_JUST_WORKS;
        hids_init_obj.boot_mouse_inp_rep_sec.rd      = 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);
    }
    

    I

  • I recommend to parse the report map from the case I linked and yours here:
    http://eleccelerator.com/usbdescreqparser/

    Hopefully this should help you find differences between the two, e.g. have you tried using the report map as-is from the case I linked?

Reply Children
No Data
Related