NRF52832初学笔记1.5之hids_keyboard

最近在搞一个锁的项目,使用NRF51822芯片。基本功能,就是手机端与锁第一次配对绑定以后,在手机端不取消配对的情况,每次手机靠近锁,BLE自动回连,然后开锁,锁与手机远离以后,断开连接,锁自动锁上。功能很简单,第一眼就想到使用hids服务,因为之前也没有用过,这里也是初学,把自己的心得体会分享一下,以便大家相互学习。
本次是在NRF52832的Demo板上测试的 ,使用的是SDK12.3的hids_keyboard 例程,这次主要讲流程。我们从主函数一步一步分析讲起。

1.0 配对管理初始化。
配对信息初始化,主要是对开关机以后,软件对之前是否存在绑定设备的信息校验和初始化。因为,如果之前存在绑定信息,在绑定回调里面,会将绑定信息和手机MAC 地址保存在芯片内部flash里面(再次之前,会加入白名单里面) 。如下图:
NRF52832初学笔记1.5之hids_keyboard_第1张图片
1.2 GAP 外观设置
在GAP 初始化里面,增加一个外观设置,这个就是我们使用手机蓝牙搜索时候,出现的键盘图标,没什么特别的东西,大家在使用其他东西时候,也可以通过这个函数进行更改自己的图标,
NRF52832初学笔记1.5之hids_keyboard_第2张图片
1.3 广播初始化
在广播初始化里面,增加了定向广播,这个目的就是为了断开连接(不是取消配对造成的断开)之后,回连手机的操作。
NRF52832初学笔记1.5之hids_keyboard_第3张图片
1.4服务初始化
服务初始化里面,增加了 HIDS的keyboard 初始化,这个里面,最重要的就是键盘配置表,也是最难得的,对于我这种菜鸡,目前还没整明白,不过,大家如果有时间,可以自己看看,这里介绍一款软件,可以帮助学习,软件名字叫做DT
链接:https://www.usb.org/sites/default/files/documents/dt2_4.zip
还有一个文档,就是这些USB HID 所遵循的协议,也是够难的,大家自己看 。有明白和知道的评论区分享出来。
链接:https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf

static void hids_init(void)
{
    uint32_t                   err_code;
    ble_hids_init_t            hids_init_obj;
    ble_hids_inp_rep_init_t    input_report_array[1];
    ble_hids_inp_rep_init_t  * p_input_report;
    ble_hids_outp_rep_init_t   output_report_array[1];
    ble_hids_outp_rep_init_t * p_output_report;
    uint8_t                    hid_info_flags;

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


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

        0xC0              // End Collection (Application)
    };

    // 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;

    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_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;

    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_output_report->security_mode.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&p_output_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                  = 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              = 0;
    hids_init_obj.p_feature_rep_array            = NULL;
    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;

    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_kb_inp_rep.cccd_write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_inp_rep.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&hids_init_obj.security_mode_boot_kb_inp_rep.write_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_outp_rep.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&hids_init_obj.security_mode_boot_kb_outp_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);
}

1.5 广播开始
广播开始时,会进行白名单获取和设置绑定参数信息
NRF52832初学笔记1.5之hids_keyboard_第4张图片
在 ble_advertising_start 里面 ,最主要的就是下面两处,这两个地方直接决定了广播的模式是快速还是定向
NRF52832初学笔记1.5之hids_keyboard_第5张图片
我们来看一下定向广播里面的设置,是把手机的Mac地址赋值过去 ,就可以了 !不知道我的操作有问题,还是其他的原因,我把广播初始化直接设置成定向广播,然后强制修改成我自己的手机Mac地址,它是无法回连到我的手机上,必须经过一次配对绑定才行。
NRF52832初学笔记1.5之hids_keyboard_第6张图片
2.0绑定信息存储
在绑定管理会呆里面,最重要的两个事件 :
PM_EVT_BONDED_PEER_CONNECTED :连接上已经绑定的设备。(这个事件是在回连成功以后,触发的)
PM_EVT_CONN_SEC_SUCCEEDED : 连接到绑定设备。(这个是在第一次绑定触发的)
NRF52832初学笔记1.5之hids_keyboard_第7张图片
看一下PM_EVT_CONN_SEC_SUCCEEDED 里面的操作,就是判断绑定链接属性,然后满足判断,就把绑定的信息保存下来,当然,这里还有一些链接秘钥等信息。
2.2 广播回调事件
在on_adv_evt 里面,关注两个事件 :BLE_ADV_EVT_WHITELIST_REQUEST 和 BLE_ADV_EVT_PEER_ADDR_REQUEST
这两个回调事件基本功能就是把绑定信息读取出来,把手机mac地址赋值给m_peer_address,这两个事件的触发也是在ble_start里面触发的,在上面已经介绍过了。这里就是为了定向广播的数据赋值做准备的。
NRF52832初学笔记1.5之hids_keyboard_第8张图片
3.0 结束
到这里整个过程已近介绍完了 ,如果还想看keyboard 发送数据到手机端的 ,可以自己看一下bsp_event_handler 连的发送,其他不介绍,配对绑定的过程很复杂,先要有配对才行,绑定在一些情况下会出现。这个过程大家自己网络搜索资料 或者去nrf 官网看看 。
NRF52832初学笔记1.5之hids_keyboard_第9张图片我这边发现有两个问题!
1、Hids_keyboard 和 mousce 例程,使用过程中会使手机端出现自动打字和鼠标图案,想了很久也没解决掉,不知道其他的hid 服务 比如 :电子笔,扫描枪,游戏柄等是否可以。需要验证一下。这些例程官网上资料少,个人还没有去实践操作。
2、不管是Hids_keyboard 还是 mousce 例程,如果手机端和 ble进行了配对绑定成功,此时,把ble关闭,手机蓝牙取消配对。然后,在打开ble和手机蓝牙,虽然ble的log显示是进行的定向广播,但是,却无法回连。我手动去连接ble(不使用nrf connect 工具),也无法连接成功。这个地方不知道是不是一个 bug。

你可能感兴趣的:(技术,初学)