Hello,
We have a custom board with nRF52832 in production, nRF5 SDK, s132, using BLE. We recently have faced some issues regarding connection from some of our clients.
The problem they have described to us is: They connect to the device with a mobile phone or a tablet (Android) and perform bonding with a static key. At first it looks like it is completed successfully but after trying to have access to the characteristics with our app, the pop-up window of pairing appears again and they see at Bluetooth settings that the device was removed from bonded devices. This happens again and again and they cannot eventually connect to the device.
About our application:
/**@brief Function for the Peer Manager initialization. */ static void peer_manager_init(void) { ble_gap_sec_params_t sec_param; ret_code_t err_code; err_code = pm_init(); hardfault = app_error_check_logger(err_code, true, log_str[PEER_MANAGER_INIT], 0, NULL); memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); // Security parameters to be used for all security procedures. These are common parameters for bonding. sec_param.bond = 1; sec_param.mitm = 0; sec_param.lesc = 0; sec_param.keypress = 0; sec_param.io_caps = BLE_GAP_IO_CAPS_DISPLAY_ONLY; sec_param.oob = 0; sec_param.min_key_size = 7; sec_param.max_key_size = 16; sec_param.kdist_own.enc = 1; sec_param.kdist_own.id = 1; sec_param.kdist_peer.enc = 1; sec_param.kdist_peer.id = 1; err_code = pm_sec_params_set(&sec_param); // sets security parameters for pairing and bonding hardfault = app_error_check_logger(err_code, true, log_str[PEER_MANAGER_INIT], 1, NULL); err_code = pm_register(pm_evt_handler); // register an event handler for the module hardfault = app_error_check_logger(err_code, true, log_str[PEER_MANAGER_INIT], 2, NULL); }
peer manager initialization
static void pm_evt_handler(pm_evt_t const * p_evt) { pm_handler_on_pm_evt(p_evt); // Logging peer events. Starts encryption if connected to a bonded device. pm_handler_disconnect_on_sec_failure(p_evt); // Disconnects if the connection was not secured. pm_handler_flash_clean(p_evt); switch (p_evt->evt_id) { case PM_EVT_CONN_SEC_SUCCEEDED: //a link has been encrypted, result of a call of pm_conn_secure or of an action by the peer. m_peer_id = p_evt->peer_id; pm_local_database_has_changed(); break; case PM_EVT_PEERS_DELETE_SUCCEEDED: // a peer was cleared from flash storage (result of pm_peer_delete) NRF_LOG_INFO("PM_EVT_PEERS_DELETE_SUCCEEDED"); hardfault = app_error_check_logger(1, false, "peersdel", 1, NULL); advertising_start(false); break; case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: // a piece of peer data was tored, updated or cleared in flash storage. if ( p_evt->params.peer_data_update_succeeded.flash_changed && (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_BONDING)) { NRF_LOG_INFO("New Bond. Peer data update succeeded."); } break; case PM_EVT_CONN_SEC_FAILED: // a pairing or encryption procedure has failed. in some cases, this means that security is not possible on this link. { NRF_LOG_INFO("Pairing or Encryption procedure failed. Peer id=%d, Error=%x, Procedure=%d, Source=%d", p_evt->peer_id, p_evt->params.conn_sec_failed.error, p_evt->params.conn_sec_failed.procedure,p_evt->params.conn_sec_failed.error_src); uint8_t proc=0; if(p_evt->params.conn_sec_failed.error_src == 1) { proc = p_evt->params.conn_sec_failed.procedure + 10; } else { proc = p_evt->params.conn_sec_failed.procedure; } hardfault = app_error_check_logger(p_evt->params.conn_sec_failed.error, false, "secfail", proc, NULL); m_scoliosense.err_code = p_evt->params.conn_sec_failed.error; ble_error_sec_update(m_conn_handle, &m_scoliosense); } break; case PM_EVT_CONN_SEC_CONFIG_REQ: { // Allow or reject pairing request from an already bonded peer. NRF_LOG_INFO("Repairing Process was initiated."); pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); } break; default: break; } }
peer manager handler
static void conn_params_init(void) { ret_code_t err_code; ble_conn_params_init_t cp_init; memset(&cp_init, 0, sizeof(cp_init)); cp_init.p_conn_params = NULL; cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; cp_init.disconnect_on_fail = false; cp_init.evt_handler = on_conn_params_evt; cp_init.error_handler = conn_params_error_handler; err_code = ble_conn_params_init(&cp_init); hardfault = app_error_check_logger(err_code, true, log_str[CONN_PARAMS_INIT], 0, 1); }
conn params init, where
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000)
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000)
#define MAX_CONN_PARAMS_UPDATE_COUNT 3
Connection parameters:
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
#define SLAVE_LATENCY 0
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(10000, UNIT_10_MS)
Also, we see in our analytics that these errors are caused:
BLE_GAP_SEC_STATUS_UNSPECIFIED
BLE_GAP_SEC_STATUS_TIMEOUT
at PM_EVT_CONN_SEC_FAILED event.
and sometimes at connection parameter handler error 0x8 Invalid state is triggered which is " Disconnection in progress or link has not been established"
Finally, at sdk_config, we have
PM_HANDLER_SEC_DELAY_MS 400
PM_RA_PROTECTION_ENABLED 0
1. What could cause this issue ?
2. Could it be the allowed repairing ? Could it be the delay of 400 ms before starting security?
3. Could it be that we haven't enabled PM_RA_PROTECTION_ENABLED ?
4. Could it be something about connection parameters update? because at this part of code, we haven't included any logs to track any errors there apart from conn_params_handler.
5. Could it be something caused by the specific phones? because in developing and testing we have never encountered such issues.
Maybe we have set something wrong about pairing bonding and peer manager, something is not set as it supposed to, or something is missing?
Any help is very much appreciated.
Kind regards,
Dimitra