nordic 52832添加HID服务实现手机蓝牙自拍杆功能 附遇到的问题和解决方法

此教程基于SD 2.0

原理:添加HID服务模拟外设滑鼠给手机发送音量加或减实现控制相机拍照,参照SDK工程->ble_app_hids_mouse

需要添加的功能

1.HID服务

2.设备管理机制DM

3.储存设备信息pstorage

流程

1.蓝牙初始化内添加device_manager_init(0);参数0代表保存以往连接设备,方便自动连接

void device_manager_init(bool erase_bonds)
{
    uint32_t               err_code;
    dm_init_param_t        init_param = {.clear_persistent_data = erase_bonds};
    dm_application_param_t register_param;

    // Initialize peer device handle.
    err_code = dm_handle_initialize(&m_bonded_peer_handle);
    APP_ERROR_CHECK(err_code);

    // Initialize persistent storage module.
    err_code = pstorage_init();
    APP_ERROR_CHECK(err_code);

    err_code = dm_init(&init_param);
    APP_ERROR_CHECK(err_code);

    memset(&register_param.sec_param, 0, sizeof(ble_gap_sec_params_t));

    register_param.sec_param.bond         = SEC_PARAM_BOND;
    register_param.sec_param.mitm         = SEC_PARAM_MITM;
    register_param.sec_param.lesc         = SEC_PARAM_LESC;
    register_param.sec_param.keypress     = SEC_PARAM_KEYPRESS;
    register_param.sec_param.io_caps      = SEC_PARAM_IO_CAPABILITIES;
    register_param.sec_param.oob          = SEC_PARAM_OOB;
    register_param.sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
    register_param.sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
    register_param.evt_handler            = device_manager_evt_handler;
    register_param.service_type           = DM_PROTOCOL_CNTXT_GATT_SRVR_ID;

    err_code = dm_register(&m_app_handle, &register_param);
    APP_ERROR_CHECK(err_code);
}

2.services_init()内增加HID服务hids_init();

void hids_init(void)
{
    uint32_t                  err_code;
    ble_hids_init_t           hids_init_obj;
    ble_hids_inp_rep_init_t   inp_rep_array[INPUT_REPORT_COUNT];
    ble_hids_inp_rep_init_t * p_input_report;
    uint8_t                   hid_info_flags;

    static uint8_t rep_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
    };

    memset(inp_rep_array, 0, sizeof(inp_rep_array));
    // Initialize HID Service.
    p_input_report                      = &inp_rep_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;

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

    p_input_report                      = &inp_rep_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;

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

    p_input_report                      = &inp_rep_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;

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_input_report->security_mode.write_perm);

    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                  = NULL;
    hids_init_obj.is_kb                          = false;
    hids_init_obj.is_mouse                       = true;
    hids_init_obj.inp_rep_count                  = INPUT_REPORT_COUNT;
    hids_init_obj.p_inp_rep_array                = inp_rep_array;
    hids_init_obj.outp_rep_count                 = 0;
    hids_init_obj.p_outp_rep_array               = NULL;
    hids_init_obj.feature_rep_count              = 0;
    hids_init_obj.p_feature_rep_array            = NULL;
    hids_init_obj.rep_map.data_len               = sizeof(rep_map_data);
    hids_init_obj.rep_map.p_data                 = rep_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;

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.rep_map.security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.rep_map.security_mode.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.hid_information.security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.hid_information.security_mode.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
        &hids_init_obj.security_mode_boot_mouse_inp_rep.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
        &hids_init_obj.security_mode_boot_mouse_inp_rep.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(
        &hids_init_obj.security_mode_boot_mouse_inp_rep.write_perm);

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_protocol.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_protocol.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.security_mode_ctrl_point.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_ctrl_point.write_perm);

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

3.ble_evt_dispatch内添加

 dm_ble_evt_handler(p_ble_evt);
ble_hids_on_ble_evt(&m_hids, p_ble_evt);

4.sys_evt_dispatch内添加

pstorage_sys_event_handler(sys_evt);

5.添加UUID

static ble_uuid_t                       m_adv_uuids[] = {{BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE, BLE_UUID_TYPE_BLE}																											}; 

6.增加发送音量函数

void media_player_control(uint8_t control)
{

  uint32_t err_code;

  uint8_t buffer[1];

  buffer[0] = control;

  err_code = ble_hids_inp_rep_send( &m_hids,

                                    INPUT_REP_MPLAYER_INDEX,

                                    1,

																		buffer );

  if(( err_code != NRF_SUCCESS ) &&

      ( err_code != NRF_ERROR_INVALID_STATE ) &&

      ( err_code != BLE_ERROR_NO_TX_PACKETS ) &&

      ( err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING ))

    {
			NRF_LOG_PRINTF("-step1error-");

      APP_ERROR_HANDLER( err_code );

    }

  buffer[0] = 0;

  err_code = ble_hids_inp_rep_send( &m_hids,

                                    INPUT_REP_MPLAYER_INDEX,

                                    1,

                                    buffer );

  if(( err_code != NRF_SUCCESS ) &&

      ( err_code != NRF_ERROR_INVALID_STATE ) &&

      ( err_code != BLE_ERROR_NO_TX_PACKETS ) &&

      ( err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING ))

    
    {
			NRF_LOG_PRINTF("-step-2-error-\r\n");
      APP_ERROR_HANDLER( err_code );

  
    }

}

这里兼容IOS和Android,触发了2次发送

7.device_manager_cnfg.h修改CCCD连接数

#define DM_GATT_CCCD_COUNT               6

8.可能的问题和解决方法

 

1.连接了一台设备,断开他后其他设备搜不到设备的广播。

办法:device_manager_init(0);DEVICE_MANAGER_MAX_CONNECTIONS改大;DEVICE_MANAGER_MAX_BONDS改大。

2.手机系统拒绝配对。

办法:on_ble_evt函数内将BLE_GAP_EVT_SEC_PARAMS_REQUEST下的内容全部注释掉

3.每次正常使用都需要重新配对。

办法:CCCD设置太少,DM_GATT_CCCD_COUNT改大

4.程序下到板子后一直重启。办法:

1.注意SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);是否多次使用

2.步骤5.添加UUID时注意内容,有时候添加多个UUID会死机

3.注意gap_params_init();设置

4.services_init();和advertising_init();的先后顺序

感谢这些哥们:

https://blog.csdn.net/sinat_20059415/article/details/80777813 

https://blog.csdn.net/pig10086/article/details/72402066

https://blog.csdn.net/everestzhang/article/details/47165417

https://blog.csdn.net/gyb510/article/details/70188616

https://blog.csdn.net/weixin_40204595/article/details/81179361

 

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值