Hello,
Let me introduce you to the issue:
I am working on a custom firmware for a custom hardware, based on the nRF52832 and SD S132, as a central which need to connect to an already implemented peripheral device and write, read and receive indications/notifications from it.
I am developing on Keil 5.0 and I have the PCA10040 for development/testing purposes.
So the main issue here is that in the central part, after I connect successfully, discover services and characteristics with VS (vendor specific) UUIDs, I enable the notifications/indications for a characteristic, and when I write an encrypted value to that characteristic, I never receive the notifications/indication the peripheral sends as response.
Different points to consider:
- I mention both notifications and indications as the peripheral sends the same information on either of them when enabled.
- The peripheral works properly, as I developed an Android APP for testing purposes and the notifications/indications are received correctly.
- The encryption method on the central is working properly. Results are compared with the Android APP. Also, when writing the encrypted value to the peripheral, this processes the right "physical" task, but the notification (as response) from it it is never received.
Once I am connected to the peripheral and all the services and characteristics I need are discovered, I enable the notifications on CCCD handle using the code:
err_code = ble_peripheral_char_notif_enable(p_custom_srv_c); APP_ERROR_CHECK(err_code);
And the ''ble_peripheral_char_notif_enable()" function is:
uint32_t ble_peripheral_char_notif_enable(ble_custom_srv_c_t * evt) { VERIFY_PARAM_NOT_NULL(evt); if ( (evt->conn_handle == BLE_CONN_HANDLE_INVALID) ||(evt->handles[BLE_CUSTOM_SRV_C_CHAR_CCCD] == BLE_GATT_HANDLE_INVALID) ) { return NRF_ERROR_INVALID_STATE; } return cccd_configure(evt->conn_handle, evt->handles[BLE_CUSTOM_SRV_C_CHAR_CCCD], true); }
So above I check if my handles for CCCD and connection are OK. This works properly. (*the handles value is a structure which keeps all the handles for services and characteristics).
Then the cccd_configure function looks like:
static uint32_t cccd_configure(uint16_t conn_handle, uint16_t cccd_handle, bool enable) { uint8_t buf[BLE_CCCD_VALUE_LEN]; buf[0] = enable ? BLE_GATT_HVX_INDICATION : 0; 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 = cccd_handle, .offset = 0, .len = BLE_CCCD_VALUE_LEN, .p_value = (uint8_t *)buf }; return sd_ble_gattc_write(conn_handle, &write_params); }
After calling the above function, I successfully receive the event BLE_GATTC_EVT_WRITE_RSP for my char_type -> BLE_CUSTOM_SRV_C_CHAR_CCCD.
No error until here so I suppose my events handler works well.
Now, I write a characteristic with an encrypted value, and the Peripheral receives it properly (as it moves a servo motor as it should) but I never receive anything on the BLE_GATTC_EVT_HVX as I should as a response from it.
This is how my events handler looks like:
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) { uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; uint16_t role = ble_conn_state_role(conn_handle); if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt)) { on_ble_peripheral_evt(p_ble_evt); } else if ((role == BLE_GAP_ROLE_CENTRAL)) { ble_custom_srv_on_ble_evt(p_ble_evt, &m_custom_srv_c); ble_dis_c_on_ble_evt(p_ble_evt, &m_dis_c); on_ble_central_evt(p_ble_evt); } }
which forwards the events to my custom handler:
void ble_custom_srv_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) { ble_custom_srv_c_t * p_ble_custom_srv_c = (ble_custom_srv_c_t *) p_context; if ((p_ble_custom_srv_c == NULL) || (p_ble_evt == NULL)) { return; } if (p_ble_custom_srv_c->conn_handle == BLE_CONN_HANDLE_INVALID) { return; } switch (p_ble_evt->header.evt_id) { case BLE_GATTC_EVT_HVX: on_hvx(p_ble_custom_srv_c, p_ble_evt); break; case BLE_GATTC_EVT_READ_RSP: on_read_rsp(p_ble_custom_srv_c, p_ble_evt); break; case BLE_GAP_EVT_DISCONNECTED: on_disconnected(p_ble_custom_srv_c, p_ble_evt); break; case BLE_GATTC_EVT_WRITE_RSP: on_write_rsp(p_ble_custom_srv_c, p_ble_evt); break; default: // No implementation needed. break; } }
All the above cases are triggered properly when needed, except the HVX one.
I have also tried to read the CCCD value from the central side after enabling notifications/indications as seen on this post, but without success. The values are never, 0x0000, 0x0001, or 0x0002, but something like 0x20007723.
Furthermore, I have tried to compile and run different central examples from the SDK on my PCA10040 but without success, it never goes past "ble_stack_init()" from the main func.
Any idea on what am I doing wrong? Any advice on what I should test?
Thanks in advance for your help and sorry for the long question.
BR,