/** * @brief Respond to a passcode request. * * @param connectionHandle - connection handle of the connected device or 0xFFFF * if all devices in database. * @param status - SUCCESS if passcode is available, otherwise see @ref SMP_PAIRING_FAILED_DEFINES. * @param passcode - integer value containing the passcode. * * @return SUCCESS - bond record found and changed,<BR> * bleIncorrectMode - Link not found. */ bStatus_t GAPBondMgr_PasscodeRsp( uint16 connectionHandle, uint8 status, uint32 passcode ) { bStatus_t ret = SUCCESS; if ( status == SUCCESS ) { // Truncate the passcode passcode = passcode % (GAP_PASSCODE_MAX + 1); ret = GAP_PasscodeUpdate( passcode, connectionHandle ); if ( ret != SUCCESS ) { VOID GAP_TerminateAuth( connectionHandle, SMP_PAIRING_FAILED_PASSKEY_ENTRY_FAILED ); } } else { VOID GAP_TerminateAuth( connectionHandle, status ); } return ret; }
/********************************************************************* * @fn gapRole_processGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_processGAPMsg(gapEventHdr_t *pMsg) { uint8_t notify = FALSE; // State changed notify the app? (default no) switch (pMsg->opcode) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg; bStatus_t stat = pPkt->hdr.status; if (stat == SUCCESS) { // Save off the generated keys VOID osal_snv_write(BLE_NVID_IRK, KEYLEN, gapRole_IRK); VOID osal_snv_write(BLE_NVID_CSRK, KEYLEN, gapRole_SRK); // Save off the information VOID memcpy(gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat = GAP_UpdateAdvertisingData(selfEntity, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData); } if (stat != SUCCESS) { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg; if (pPkt->hdr.status == SUCCESS) { if (pPkt->adType) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData); } else if ((gapRole_state != GAPROLE_ADVERTISING) && (gapRole_state != GAPROLE_CONNECTED_ADV) && (gapRole_state != GAPROLE_CONNECTED || gapRole_AdvNonConnEnabled == TRUE) && (Util_isActive(&startAdvClock) == FALSE)) { // Start advertising gapRole_setEvent(START_ADVERTISING_EVT); } } if (pPkt->hdr.status != SUCCESS) { // Set into Error state gapRole_state = GAPROLE_ERROR; notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg; if (pPkt->hdr.status == SUCCESS) { if (pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT) { if (gapRole_state == GAPROLE_CONNECTED) { gapRole_state = GAPROLE_CONNECTED_ADV; } else if (gapRole_AdvEnabled) { gapRole_state = GAPROLE_ADVERTISING; } else { gapRole_state = GAPROLE_ADVERTISING_NONCONN; } } else // GAP_END_DISCOVERABLE_DONE_EVENT { if (gapRole_AdvertOffTime != 0) { if ((gapRole_AdvEnabled) || (gapRole_AdvNonConnEnabled)) { Util_restartClock(&startAdvClock, gapRole_AdvertOffTime); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE if (gapRole_AdvEnabled == TRUE) { gapRole_AdvEnabled = FALSE; } else { gapRole_AdvNonConnEnabled = FALSE; } } // Update state. if (gapRole_state == GAPROLE_CONNECTED_ADV) { // In the Advertising Off period gapRole_state = GAPROLE_CONNECTED; } else { // In the Advertising Off period gapRole_state = GAPROLE_WAITING; } } } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; if (pPkt->hdr.status == SUCCESS) { VOID memcpy(gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN); gapRole_ConnectionHandle = pPkt->connectionHandle; gapRole_state = GAPROLE_CONNECTED; // Store connection information gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; gapRole_ConnectedDevAddrType = pPkt->devAddrType; // Check whether update parameter request is enabled if (gapRole_ParamUpdateEnable == TRUE) { // Get the minimum time upon connection establishment before the // peripheral can start a connection update procedure. uint16_t timeout = GAP_GetParamValue(TGAP_CONN_PAUSE_PERIPHERAL); Util_restartClock(&startUpdateClock, timeout*1000); } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL); } else if (pPkt->hdr.status == bleGAPConnNotAcceptable) { // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; // Go to WAITING state, and then start advertising gapRole_state = GAPROLE_WAITING; } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; GAPBondMgr_LinkTerm(pPkt->connectionHandle); memset(gapRole_ConnectedDevAddr, 0, B_ADDR_LEN); // Erase connection information gapRole_ConnInterval = 0; gapRole_ConnSlaveLatency = 0; gapRole_ConnTimeout = 0; gapRole_ConnTermReason = pPkt->reason; // Cancel all connection parameter update timers (if any active) Util_stopClock(&startUpdateClock); Util_stopClock(&updateTimeoutClock); notify = TRUE; gapRole_ConnectionHandle = INVALID_CONNHANDLE; // If device was advertising when connection dropped if (gapRole_AdvNonConnEnabled) { // Continue advertising. gapRole_state = GAPROLE_ADVERTISING_NONCONN; } // Else go to WAITING state. else { if(pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM) { gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT; } else { gapRole_state = GAPROLE_WAITING; } // Start advertising, if enabled. gapRole_setEvent(START_ADVERTISING_EVT); } } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Cancel connection param update timeout timer (if active) Util_stopClock(&updateTimeoutClock); if (pPkt->hdr.status == SUCCESS) { // Store new connection parameters gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; // Make sure there's no pending connection update procedure if(Util_isActive(&startUpdateClock) == FALSE) { // Notify the application with the new connection parameters if (pGapRoles_ParamUpdateCB != NULL) { (*pGapRoles_ParamUpdateCB)(gapRole_ConnInterval, gapRole_ConnSlaveLatency, gapRole_ConnTimeout); } } } } break; case GAP_PAIRING_REQ_EVENT: { gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *)pMsg; // Send Pairing Failed Response VOID GAP_TerminateAuth(pPkt->connectionHandle, SMP_PAIRING_FAILED_NOT_SUPPORTED); } break; default: break; } if (notify == TRUE) { // Notify the application with the new state change if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange) { pGapRoles_AppCGs->pfnStateChange(gapRole_state); } } }
/********************************************************************* * @fn gapRole_ProcessGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ void gapBondMgr_ProcessGAPMsg( gapEventHdr_t *pMsg ) { switch ( pMsg->opcode ) { case GAP_PASSKEY_NEEDED_EVENT: { gapPasskeyNeededEvent_t *pPkt = (gapPasskeyNeededEvent_t *)pMsg; if ( pGapBondCB && pGapBondCB->passcodeCB ) { // Ask app for a passcode pGapBondCB->passcodeCB( pPkt->deviceAddr, pPkt->connectionHandle, pPkt->uiInputs, pPkt->uiOutputs ); } else { // No app support, use the default passcode if ( GAP_PasscodeUpdate( gapBond_Passcode, pPkt->connectionHandle ) != SUCCESS ) { VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_PASSKEY_ENTRY_FAILED ); } } } break; case GAP_AUTHENTICATION_COMPLETE_EVENT: { gapAuthCompleteEvent_t *pPkt = (gapAuthCompleteEvent_t *)pMsg; // Should we save bonding information if ( (pPkt->hdr.status == SUCCESS) && (pPkt->authState & SM_AUTH_STATE_BONDING) ) { gapBondRec_t bondRec; VOID osal_memset( &bondRec, 0, sizeof ( gapBondRec_t ) ) ; // Do we have a public address in the data? if ( pPkt->pIdentityInfo ) { VOID osal_memcpy( bondRec.publicAddr, pPkt->pIdentityInfo->bd_addr, B_ADDR_LEN ); } else { linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle ); if ( pLinkItem ) { VOID osal_memcpy( bondRec.publicAddr, pLinkItem->addr, B_ADDR_LEN ); } else { // We don't have an address, so ignore the message. break; } } // Save off of the authentication state bondRec.stateFlags |= (pPkt->authState & SM_AUTH_STATE_AUTHENTICATED) ? GAP_BONDED_STATE_AUTHENTICATED : 0; VOID gapBondMgrAddBond( &bondRec, (gapBondLTK_t *)pPkt->pSecurityInfo, (gapBondLTK_t *)pPkt->pDevSecInfo, ((uint8 *)((pPkt->pIdentityInfo) ? pPkt->pIdentityInfo->irk : NULL )), ((uint8 *)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->srk : NULL )), ((uint32)((pPkt->pSigningInfo) ? pPkt->pSigningInfo->signCounter : GAP_INIT_SIGN_COUNTER )) ); } // Call app state callback if ( pGapBondCB && pGapBondCB->pairStateCB ) { pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_COMPLETE, pPkt->hdr.status ); } } break; case GAP_BOND_COMPLETE_EVENT: // This message is received when the bonding is complete. If hdr.status is SUCCESS // then call app state callback. If hdr.status is NOT SUCCESS, the connection will be // dropped at the LL because of a MIC failure, so again nothing to do. if ( pGapBondCB && pGapBondCB->pairStateCB && pMsg->hdr.status == SUCCESS ) { pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_BONDED, pMsg->hdr.status ); } break; case GAP_SIGNATURE_UPDATED_EVENT: { uint8 idx; gapSignUpdateEvent_t *pPkt = (gapSignUpdateEvent_t *)pMsg; idx = GAPBondMgr_ResolveAddr( pPkt->addrType, pPkt->devAddr, NULL ); if ( idx < GAP_BONDINGS_MAX ) { // Save the sign counter VOID osal_snv_write( devSignCounterNvID(idx), sizeof ( uint32 ), &(pPkt->signCounter) ); } } break; case GAP_PAIRING_REQ_EVENT: { gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *)pMsg; if ( gapBond_AutoFail != FALSE ) { // Auto Fail TEST MODE (DON'T USE THIS) - Sends pre-setup reason VOID GAP_TerminateAuth( pPkt->connectionHandle, gapBond_AutoFailReason ); } else if ( gapBond_PairingMode == GAPBOND_PAIRING_MODE_NO_PAIRING ) { // No Pairing - Send error VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_NOT_SUPPORTED ); } else { gapAuthParams_t params; linkDBItem_t *pLinkItem = linkDB_Find( pPkt->connectionHandle ); // Requesting bonding? if ( pPkt->pairReq.authReq & SM_AUTH_STATE_BONDING ) { if ( pLinkItem ) { if ( (pLinkItem->addrType != ADDRTYPE_PUBLIC) && (pPkt->pairReq.keyDist.mIdKey == FALSE) ) { uint8 publicAddr[B_ADDR_LEN]; // Check if we already have the public address in NV if ( GAPBondMgr_ResolveAddr(pLinkItem->addrType, pLinkItem->addr, publicAddr ) == FALSE ) { // Can't bond to a non-public address if we don't know the public address VOID GAP_TerminateAuth( pPkt->connectionHandle, SMP_PAIRING_FAILED_AUTH_REQ ); break; } } } else { // Can't find the connection, ignore the message break; } } VOID osal_memset( ¶ms, 0, sizeof ( gapAuthParams_t ) ); // Setup the pairing parameters params.connectionHandle = pPkt->connectionHandle; params.secReqs.ioCaps = gapBond_IOCap; params.secReqs.oobAvailable = gapBond_OOBDataFlag; params.secReqs.maxEncKeySize = gapBond_KeySize; // TBD - Should we distribute keys if bonding is turned off??? params.secReqs.keyDist.sEncKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_SENCKEY) ? TRUE : FALSE; params.secReqs.keyDist.sIdKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_SIDKEY) ? TRUE : FALSE; params.secReqs.keyDist.mEncKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_MENCKEY) ? TRUE : FALSE; params.secReqs.keyDist.mIdKey = (gapBond_KeyDistList | GAPBOND_KEYDIST_MIDKEY) ? TRUE : FALSE; params.secReqs.keyDist.mSign = (gapBond_KeyDistList | GAPBOND_KEYDIST_MSIGN) ? TRUE : FALSE; params.secReqs.keyDist.sSign = (gapBond_KeyDistList | GAPBOND_KEYDIST_SSIGN) ? TRUE : FALSE; // Is bond manager setup for OOB data? if ( gapBond_OOBDataFlag ) { VOID osal_memcpy( params.secReqs.oob, gapBond_OOBData, KEYLEN ); } if ( (pPkt->pairReq.authReq & SM_AUTH_STATE_BONDING) && (gapBond_Bonding) ) { params.secReqs.authReq |= SM_AUTH_STATE_BONDING; if ( pLinkItem->addrType != ADDRTYPE_PUBLIC ) { // Force a master ID key params.secReqs.keyDist.mIdKey = TRUE; } } // Is Bond Manager setup for passkey protection? if ( gapBond_MITM ) { params.secReqs.authReq |= SM_AUTH_STATE_AUTHENTICATED; } VOID GAP_Authenticate( ¶ms, &(pPkt->pairReq) ); } // Call app state callback if ( pGapBondCB && pGapBondCB->pairStateCB ) { pGapBondCB->pairStateCB( GAPBOND_PAIRING_STATE_STARTED, pPkt->hdr.status ); } } break; default: break; } }
/********************************************************************* * @fn gapRole_processGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static uint8_t gapRole_processGAPMsg(gapEventHdr_t *pMsg) { uint8_t notify = FALSE; // State changed notify the app? (default no) switch (pMsg->opcode) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg; bStatus_t stat = pPkt->hdr.status; if (stat == SUCCESS) { // Save off the generated keys VOID osal_snv_write(BLE_NVID_IRK, KEYLEN, gapRole_IRK); VOID osal_snv_write(BLE_NVID_CSRK, KEYLEN, gapRole_SRK); // Save off the information VOID memcpy(gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN); gapRole_peripheralState = GAPROLE_STARTED; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); // Update the advertising data stat = GAP_UpdateAdvertisingData(selfEntity, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData); } if (stat != SUCCESS) { gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); //gapRole_abort(); } notify = TRUE; } break; case GAP_ADV_DATA_UPDATE_DONE_EVENT: { gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { if (pPkt->adType) { // Setup the Response Data pPkt->hdr.status = GAP_UpdateAdvertisingData(selfEntity, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData); } else if ((gapRole_peripheralState != GAPROLE_ADVERTISING) && (gapRole_peripheralState != GAPROLE_CONNECTED_ADV) && (gapRole_peripheralState != GAPROLE_CONNECTED || gapRole_AdvNonConnEnabled == TRUE) && (Util_isActive(&startAdvClock) == FALSE)) { // Start advertising gapRole_setEvent(START_ADVERTISING_EVT); } notify = FALSE; }else { // Set into Error state gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); //gapRole_abort(); notify = TRUE; } } break; case GAP_MAKE_DISCOVERABLE_DONE_EVENT: case GAP_END_DISCOVERABLE_DONE_EVENT: { gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { if (pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT) { if (gapRole_peripheralState == GAPROLE_CONNECTED) { gapRole_peripheralState = GAPROLE_CONNECTED_ADV; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else if (gapRole_AdvEnabled) { gapRole_peripheralState = GAPROLE_ADVERTISING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { gapRole_peripheralState = GAPROLE_ADVERTISING_NONCONN; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } } else // GAP_END_DISCOVERABLE_DONE_EVENT { if (gapRole_AdvertOffTime != 0) //restart advertising if param is set { if ((gapRole_AdvEnabled) || (gapRole_AdvNonConnEnabled)) { Util_restartClock(&startAdvClock, gapRole_AdvertOffTime); } } else { // Since gapRole_AdvertOffTime is set to 0, the device should not // automatically become discoverable again after a period of time. // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE if (gapRole_AdvEnabled == TRUE) { gapRole_AdvEnabled = FALSE; } else { gapRole_AdvNonConnEnabled = FALSE; } } // Update state. if (gapRole_peripheralState == GAPROLE_CONNECTED_ADV) { // In the Advertising Off period gapRole_peripheralState = GAPROLE_CONNECTED; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { // In the Advertising Off period gapRole_peripheralState = GAPROLE_WAITING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } } notify = TRUE; } else if (pPkt->hdr.status == LL_STATUS_ERROR_COMMAND_DISALLOWED) //we're already advertising { notify = FALSE; } else { gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); //gapRole_abort(); } } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { //add to database gapRoleInfo_Add(pPkt); // advertising will stop when a connection forms in the peripheral role if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) { gapRole_peripheralState = GAPROLE_CONNECTED; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); // Check whether update parameter request is enabled if (gapRole_ParamUpdateEnable == TRUE) { // Get the minimum time upon connection establishment before the // peripheral can start a connection update procedure. uint16_t timeout = GAP_GetParamValue( TGAP_CONN_PAUSE_PERIPHERAL); Util_restartClock(&startUpdateClock, timeout * 1000); } } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, pPkt->connRole); } else if (pPkt->hdr.status == bleGAPConnNotAcceptable) { // Set enabler to FALSE; device will become discoverable again when // this value gets set to TRUE gapRole_AdvEnabled = FALSE; // Go to WAITING state, and then start advertising if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) { gapRole_peripheralState = GAPROLE_WAITING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } } else { if (pPkt->connRole == GAP_PROFILE_PERIPHERAL) { gapRole_peripheralState = GAPROLE_ERROR; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { gapRole_abort(); } } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *) pMsg; // notify bond manager GAPBondMgr_LinkTerm(pPkt->connectionHandle); // Erase connection information (maybe make this a function) uint8 connHandleIndex = gapRoleInfo_Find(pPkt->connectionHandle); multiConnInfo[connHandleIndex].gapRole_ConnectionHandle = INVALID_CONNHANDLE; multiConnInfo[connHandleIndex].gapRole_ConnInterval = 0; multiConnInfo[connHandleIndex].gapRole_ConnSlaveLatency = 0; multiConnInfo[connHandleIndex].gapRole_ConnTimeout = 0; // Cancel all connection parameter update timers (if any active) Util_stopClock(&startUpdateClock); Util_stopClock(&updateTimeoutClock); notify = TRUE; if (multiConnInfo[connHandleIndex].gapRole_ConnRole == GAP_PROFILE_PERIPHERAL) { // If device was advertising when connection dropped if (gapRole_AdvNonConnEnabled) { // Continue advertising. gapRole_peripheralState = GAPROLE_ADVERTISING_NONCONN; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } // Else go to WAITING state. else { if (pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM) { gapRole_peripheralState = GAPROLE_WAITING_AFTER_TIMEOUT; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } else { gapRole_peripheralState = GAPROLE_WAITING; gapRole_peripheralStateChangeHandler(gapRole_peripheralState); } // Start advertising, if enabled. gapRole_setEvent(START_ADVERTISING_EVT); } } } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *) pMsg; // Cancel connection param update timeout timer (if active) Util_stopClock(&updateTimeoutClock); if (pPkt->hdr.status == SUCCESS) { // Store new connection parameters // gapRole_ConnInterval = pPkt->connInterval; // gapRole_ConnSlaveLatency = pPkt->connLatency; // gapRole_ConnTimeout = pPkt->connTimeout; // Make sure there's no pending connection update procedure if (Util_isActive(&startUpdateClock) == FALSE) { // // Notify the application with the new connection parameters // if (pGapRoles_ParamUpdateCB != NULL) // { // (*pGapRoles_ParamUpdateCB)(gapRole_ConnInterval, // gapRole_ConnSlaveLatency, // gapRole_ConnTimeout); // } } } notify = TRUE; } break; case GAP_PAIRING_REQ_EVENT: { gapPairingReqEvent_t *pPkt = (gapPairingReqEvent_t *) pMsg; // Send Pairing Failed Response VOID GAP_TerminateAuth(pPkt->connectionHandle, SMP_PAIRING_FAILED_NOT_SUPPORTED); } break; case GAP_SLAVE_REQUESTED_SECURITY_EVENT: { uint16_t connHandle = ((gapSlaveSecurityReqEvent_t *)pMsg)->connectionHandle; uint8_t authReq = ((gapSlaveSecurityReqEvent_t *)pMsg)->authReq; GAPBondMgr_SlaveReqSecurity(connHandle, authReq); } break; case GAP_DEVICE_INFO_EVENT: case GAP_DEVICE_DISCOVERY_EVENT: notify = TRUE; break; default: notify = FALSE; break; } if (notify == TRUE) //app needs to take further action { if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnPassThrough) { return (pGapRoles_AppCGs->pfnPassThrough((gapMultiRoleEvent_t *) pMsg)); } } return TRUE; }