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.