Hy,
still I can't get it to work: I try to implement pairing / bonding to my BLE Peripheral OAD Offchip based project. I use the same hardware and run the original project: Everything works and my own project: Bonding fails.
For the current tests I use nRF connect from Android as generic BLE Central device. In the well working variant I observe the following:
The device advertises. I connect. It discovers services and displays them. Then I hit "Bond", I need to enter the passcode, afterwards it says "Bonded".
The Log from nRF Connect looks like this:
nRF Connect, 2019-03-07 SBP OAD APP v0001 (A4:34:F1:81:CF:37) V 11:10:36.762 Connecting to A4:34:F1:81:CF:37... D 11:10:36.763 gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE) D 11:10:36.971 [Callback] Connection state changed with status: 0 and new state: CONNECTED (2) I 11:10:36.971 Connected to A4:34:F1:81:CF:37 D 11:10:36.976 [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED ... V 11:10:47.011 Starting pairing... D 11:10:47.011 device.createBond() D 11:10:47.057 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11) D 11:10:47.397 [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PIN (0) D 11:11:01.099 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12) I 11:11:01.099 Device bonded
Now when I use my device:
It advertises, I connect. Immediately, the Android device vibrates as if I need to enter a passcode, but no mask appears. It discovers services and displays them.When I hit "Bond" a mask to enter passcode appears, I enter the passcode but the device disconnects immediately. The nRF Connect log looks like this:
nRF Connect, 2019-03-07 MYDEVICE (A4:34:F1:81:CF:37) V 14:04:02.196 Connecting to A4:34:F1:81:CF:37... D 14:04:02.196 gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE) D 14:04:02.369 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11) D 14:04:02.397 [Callback] Connection state changed with status: 0 and new state: CONNECTED (2) I 14:04:02.397 Connected to A4:34:F1:81:CF:37 D 14:04:02.411 [Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED D 14:04:02.667 [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PIN (0) D 14:04:02.701 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10) I 14:04:02.701 Bonding failed ... V 14:04:24.311 Starting pairing... D 14:04:24.311 device.createBond() D 14:04:24.339 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11) D 14:04:24.693 [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PIN (0) D 14:04:24.693 [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10) I 14:04:24.693 Bonding failed D 14:04:27.703 [Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0) E 14:04:27.705 Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST I 14:04:27.705 Disconnected D 14:04:28.081 [Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
So apparently the device requests a bond right after connection?
I compared the code and it looks totally identical: From project_oad_offchip.c:
// Application events used with app queue (appEvtHdr_t) // These are not related to RTOS evts, but instead enqueued via state change CBs #define SBP_STATE_CHANGE_EVT 0x0001 #define SYSPROFILE_CHAR_CHANGE_EVT 0x0002 //#define SBP_PAIRING_STATE_EVT 0x0004 #define SBP_PASSCODE_NEEDED_EVT 0x0008 #define DATAPROFILE_CHAR_CHANGE_EVT 0x0010 // Application specific event ID for Connection Event End Events #define SBP_CONN_EVT 0x0020
// GAP Bond Manager Callbacks static gapBondCBs_t SimplePeripheral_BondMgrCBs = { (pfnPasscodeCB_t)SimplePeripheral_passcodeCB, // Passcode callback, NULL // Pairing / Bonding state Callback (not used by application) };
static void project_init(void) { ... // Setup the GAP Bond Manager { uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; uint8_t mitm = TRUE; uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; uint8_t bonding = TRUE; uint8_t scMode = GAPBOND_SECURE_CONNECTION_ALLOW; uint8_t replaceBonds = FALSE; GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode); GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm); GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap); GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding); GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &scMode); GAPBondMgr_SetParameter(GAPBOND_LRU_BOND_REPLACEMENT, sizeof(uint8_t), &replaceBonds); } ... // Start the Device VOID GAPRole_StartDevice(&Bauernstolz_gapRoleCBs); // Start Bond Manager VOID GAPBondMgr_Register(&SimplePeripheral_BondMgrCBs);
/********************************************************************* * @fn SimplePeripheral_passcodeCB * * @brief Passcode callback. * * @return none */ static void SimplePeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle, uint8_t uiInputs, uint8_t uiOutputs, uint32_t numComparison) { gapPasskeyNeededEvent_t *pData; // Allocate space for the passcode event. if ((pData = ICall_malloc(sizeof(gapPasskeyNeededEvent_t)))) { memcpy(pData->deviceAddr, deviceAddr, B_ADDR_LEN); pData->connectionHandle = connHandle; pData->uiInputs = uiInputs; pData->uiOutputs = uiOutputs; pData->numComparison = numComparison; // Enqueue the event. project_enqueueMsg(SBP_PASSCODE_NEEDED_EVT, NULL, (uint8_t *) pData); } }
/********************************************************************* * @fn project_processAppMsg * * @brief Process an incoming callback from a profile. * * @param pMsg - message to process * * @return None. */ static void project_processAppMsg(sbpEvt_t *pMsg) { switch (pMsg->hdr.event) { ... case SBP_PASSCODE_NEEDED_EVT: { SimplePeripheral_processPasscode((gapPasskeyNeededEvent_t*)pMsg->pData); break; } ... }
/********************************************************************* * @fn SimplePeripheral_processPasscode * * @brief Process the Passcode request. * * @return none */ static void SimplePeripheral_processPasscode(gapPasskeyNeededEvent_t *pData) { // Use static passcode uint32_t passcode = 331734; //Display_print1(dispHandle, SBP_ROW_SECURITY, 0, "Passcode: %d", passcode); // Send passcode to GAPBondMgr GAPBondMgr_PasscodeRsp(pData->connectionHandle, SUCCESS, passcode); }
Apparently, the passcode Callback never gets called: I added a counter variable, it never gets increased. Also, a breakpoint within SimplePeripheral_passcodeCB is never reached:
What other pieces of code might be interesting?
Any help appreciated
Harald