We have a product that uses nRF52832 and works as a peripheral, connecting to mobile phones.
Lately we have noticed that in some clients with Android phones, they cannot connect to the device. The logging info that we get is that function delete_bonds is called and indeed the issue is solved after the client erases bond info from their phone and implement pair and bond again.
In our code, we call delete_bonds function only in pm_evt_handler, in case of event PM_EVT_CONN_SEC_FAILED.
The security is SEC_MITM, with static passkey, no LESC, and all is handled by the peer manager.
So my questions are:
1. What could cause the device to delete bonding information? One reason I am thinking is probably when storage gets full, but could this be a case? If not, what could be the reason?
2. Is there any better way to handle this event?
3. I have also noticed sometimes reason for disconnection 0x22 (BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT). What does this mean and how should I handle it?
Here are some parts of my code:
/**@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); 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); 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); }
/**@brief Function for handling Peer Manager events. * * @param[in] p_evt Peer Manager event. */ 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) 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. delete_bonds(); break; default: break; } }
/**@brief Clear bond information from persistent storage. */ static void delete_bonds(void) { ret_code_t err_code; NRF_LOG_INFO("Erase bonds!"); err_code = pm_peers_delete(); hardfault = app_error_check_logger(err_code, true, log_str[DELETE_BONDS], 0); }
We have now added some more logs at the PM_EVT_CONN_SEC_FAILED about the procedure and the error (provided by pm_conn_secure_failed_evt_t struct) that will probably help in the future, but unfortunately we haven't had this info before to provide you also.
The problem is also, that we cannot reproduce the error in order to solve it, so hopefully you could have some ideas.
Thank you very much in advance.
Best regards
Dimitra