I am trying to read (the report map) and receive notifications (the report) from an HID device as a BLE central. The bonding process has been completedsuccessfully to my knowledge.
When using sd_ble_gattc_read(), only the first two bytes of the response in the BLE_GATTC_EVT_READ_RSP event is correct. I can call sd_ble_gattc_read() multiple times with the offset increasing and only the first two bytes for each call is correct. Since 22 bytes are read with each call, only bytes 1 and 2, 23 and 24, 45 and 46, and so on are correct.
Similarly, only the first two bytes received in BLE_GATTC_EVT_HVX is correct.
To begin with, I registered the HID UUID with the discovery module.ble_uuid_t hids_uuid = {
.uuid = BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE,
.type = BLE_UUID_TYPE_BLE,
};
APP_ERROR_CHECK(ble_db_discovery_init(db_disc_handler));
APP_ERROR_CHECK(ble_db_discovery_evt_register(&hids_uuid));
I start service discovery inside ble_evt_handler.
case BLE_GAP_EVT_CONNECTED: {
// Initiate bonding.
err_code = pm_conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false);
if (err_code != NRF_ERROR_BUSY) {
APP_ERROR_CHECK(err_code);
}
err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
APP_ERROR_CHECK(err_code);
} break;
Inside the service discover handler, I begin reading the report map value.
uint16_t report_map_handle, report_handle;
static void db_disc_handler(ble_db_discovery_evt_t * p_evt) {
if (p_evt->evt_type != BLE_DB_DISCOVERY_COMPLETE) {
return;
}
if (p_evt->params.discovered_db.srv_uuid.uuid != hids_uuid.uuid) {
return;
}
if (p_evt->params.discovered_db.srv_uuid.type != hids_uuid.type) {
return;
}
for (int i = 0; i < p_evt->params.discovered_db.char_count; i++) {
ble_gatt_db_char_t chr = p_evt->params.discovered_db.charateristics[i];
uint16_t uuid = chr.characteristic.uuid.uuid;
switch (uuid) {
case BLE_UUID_REPORT_MAP_CHAR:
report_map_handle = chr.characteristic.handle_value;
break;
case BLE_UUID_REPORT_CHAR:
report_handle = chr.cccd_handle;
break;
default:
break;
}
}
APP_ERROR_CHECK(sd_ble_gattc_read(p_evt->conn_handle, report_map_handle, 0));
}
Also inside ble_evt_handler, I handle the read values. Once all of the report map has been read, I enable notifications on the report characteristic using the CCCD.
case BLE_GATTC_EVT_READ_RSP: {
ble_gattc_evt_read_rsp_t resp = p_ble_evt->evt.gattc_evt.params.read_rsp;
memcpy(&hid_data[hid_len], resp.data, resp.len);
hid_len += resp.len;
NRF_LOG_HEXDUMP_INFO(resp.data, resp.len);
NRF_LOG_INFO("total read %d", hid_len);
uint16_t ch = p_ble_evt->evt.gattc_evt.conn_handle;
if (resp.len > 0) {
APP_ERROR_CHECK(sd_ble_gattc_read(ch, report_map_handle, hid_len));
} else {
start_notify(ch);
}
} break;
For start_notify(), I used code from cccd_configure() in components/ble/ble_services/ble_nus_c/ble_nus_c.cstatic void start_notify(uint16_t ch) {
uint8_t buf[BLE_CCCD_VALUE_LEN];
buf[0] = BLE_GATT_HVX_NOTIFICATION;
buf[1] = 0;
ble_gattc_write_params_t const write_params = {
.write_op = BLE_GATT_OP_WRITE_REQ,
.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
.handle = report_handle,
.offset = 0,
.len = sizeof(buf),
.p_value = buf
};
APP_ERROR_CHECK(sd_ble_gattc_write(ch, &write_params));
}
Inside ble_evt_handler I simply dump all of the notification data.
case BLE_GATTC_EVT_HVX: {
ble_gattc_evt_hvx_t hvx = p_ble_evt->evt.gattc_evt.params.hvx;
NRF_LOG_HEXDUMP_INFO(hvx.data, hvx.len);
} break;
For the report map, I get the following log output. Note that bytes 3 through 22 of each read is identical.<info> app: 05 01 00 00 00 00 08 D9|........
<info> app: 03 00 1C FD 03 20 08 D9|..... ..
<info> app: 03 00 F4 01 00 00 |......
<info> app: total read 22
<info> app: 81 02 00 00 00 00 08 D9|........
<info> app: 03 00 1C FD 03 20 08 D9|..... ..
<info> app: 03 00 F4 01 00 00 |......
<info> app: total read 44
<info> app: 01 A1 00 00 00 00 08 D9|........
<info> app: 03 00 1C FD 03 20 08 D9|..... ..
<info> app: 03 00 F4 01 00 00 |......
<info> app: total read 66
<info> app: 05 01 00 00 00 00 08 D9|........
<info> app: 03 00 1C FD 03 20 08 D9|..... ..
<info> app: 03 00 F4 01 00 00 |......
<info> app: total read 88
<info> app: 15 00 00 00 00 00 08 D9|........
<info> app: 03 00 1C FD 03 20 08 D9|..... ..
<info> app: 03 00 F4 01 00 00 |......
<info> app: total read 110
<info> app: 09 38 00 00 00 00 08 D9|.8......
<info> app: 03 00 |..
<info> app: total read 120
I'm inclined to think there is something wrong on the central side since the HID device works correctly. Suggestions on how to debug this would be appreciated.