/********************************************************************* * @fn gapCentralRole_ProcessGAPMsg * * @brief Process an incoming task message from GAP. * * @param pMsg - message to process * * @return none */ static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg; if ( pPkt->hdr.status == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK ); // Save off the information VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN ); } } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { // Notify the Bond Manager of the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_CENTRAL ); } } break; case GAP_LINK_TERMINATED_EVENT: { uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle; GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); // Cancel RSSI reads GAPCentralRole_CancelRssi( connHandle ); } break; // temporary workaround case GAP_SLAVE_REQUESTED_SECURITY_EVENT: GAPBondMgr_ProcessGAPMsg( pMsg ); break; default: break; } // Pass event to app if ( pGapCentralRoleCB && pGapCentralRoleCB->eventCB ) { pGapCentralRoleCB->eventCB( (gapCentralRoleEvent_t *) pMsg ); } }
/********************************************************************* * @fn gapRole_ProcessGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 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 osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat = GAP_UpdateAdvertisingData( gapRole_TaskID, 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( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { // Start advertising VOID osal_set_event( gapRole_TaskID, 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 { gapRole_state = GAPROLE_ADVERTISING; } } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, 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 gapRole_AdvEnabled = FALSE; } // 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 osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_ConnectionHandle = pPkt->connectionHandle; gapRole_state = GAPROLE_CONNECTED; if ( gapRole_RSSIReadRate ) { // Start the RSSI Reads VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } // Check whether update parameter request is enabled, and check the connection parameters if ( ( gapRole_ParamUpdateEnable == TRUE ) && ( (pPkt->connInterval < gapRole_MinConnInterval) || (pPkt->connInterval > gapRole_MaxConnInterval) || (pPkt->connLatency != gapRole_SlaveLatency) || (pPkt->connTimeout != gapRole_TimeoutMultiplier) )) { gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency ); } // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL ); } else { gapRole_state = GAPROLE_ERROR; } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { VOID GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN ); if ( gapRole_state == GAPROLE_CONNECTED_ADV ) { // End the non-connectable advertising GAP_EndDiscoverable( gapRole_TaskID ); gapRole_state = GAPROLE_CONNECTED; } else { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM ) { gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT; } else { gapRole_state = GAPROLE_WAITING; } notify = TRUE; VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } gapRole_ConnectionHandle = INVALID_CONNHANDLE; } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; if ( (pPkt->hdr.status != SUCCESS) || (pPkt->connInterval < gapRole_MinConnInterval) || (pPkt->connInterval > gapRole_MaxConnInterval) ) { // Ask to change the interval gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency ); } else { // All is good stop Update Parameters timeout VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT ); } } break; default: break; } if ( notify == TRUE ) { // Notify the application 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 */ static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 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 osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat = GAP_UpdateAdvertisingData( gapRole_TaskID, 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( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { // Start advertising VOID osal_set_event( gapRole_TaskID, 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 ) { gapRole_state = GAPROLE_ADVERTISING; } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, 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 gapRole_AdvEnabled = FALSE; } // 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 osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_ConnectionHandle = pPkt->connectionHandle; gapRole_state = GAPROLE_CONNECTED; if ( gapRole_RSSIReadRate ) { // Start the RSSI Reads VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate ); } // Store connection information gapRole_ConnInterval = pPkt->connInterval; gapRole_ConnSlaveLatency = pPkt->connLatency; gapRole_ConnTimeout = pPkt->connTimeout; // 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 timeout = GAP_GetParamValue( TGAP_CONN_PAUSE_PERIPHERAL ); osal_start_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT, 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_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN ); // Erase connection information gapRole_ConnInterval = 0; gapRole_ConnSlaveLatency = 0; gapRole_ConnTimeout = 0; // Cancel all connection parameter update timers (if any active) VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT ); VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); // Go to WAITING state, and then start advertising if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM ) { gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT; } else { gapRole_state = GAPROLE_WAITING; } notify = TRUE; VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); gapRole_ConnectionHandle = INVALID_CONNHANDLE; } break; case GAP_LINK_PARAM_UPDATE_EVENT: { gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg; // Cancel connection param update timeout timer (if active) VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); 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 ( osal_get_timeoutEx( gapRole_TaskID, START_CONN_UPDATE_EVT ) == 0 ) { // Notify the application with the new connection parameters if ( pGapRoles_ParamUpdateCB != NULL ) { (*pGapRoles_ParamUpdateCB)( gapRole_ConnInterval, gapRole_ConnSlaveLatency, gapRole_ConnTimeout ); } } } } 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 */ 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); // Update the advertising data stat = GAP_UpdateAdvertisingData(selfEntity, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData); } if (stat != SUCCESS) { 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 (Util_isActive(&startAdvClock) == FALSE) { // Start advertising gapRole_setEvent(START_ADVERTISING_EVT); } } if (pPkt->hdr.status != SUCCESS) { // Set into Error state 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) { gapRole_AdvEnabled = TRUE; } 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; } } } notify = TRUE; } else if (pPkt->hdr.status == LL_STATUS_ERROR_COMMAND_DISALLOWED) //we're already advertising { notify = FALSE; } else { gapRole_abort(); } } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg; uint8_t advertEnable = TRUE; if (pPkt->hdr.status == SUCCESS) { // Notify the Bond Manager to the connection VOID GAPBondMgr_LinkEst(pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, pPkt->connRole); //advertising will stop after connection formed as slave if ((pPkt->connRole) == GAP_PROFILE_PERIPHERAL) { gapRole_AdvEnabled = FALSE; //reenable advertising GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advertEnable, NULL); } } 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; } else { gapRole_abort(); } notify = TRUE; } break; case GAP_LINK_TERMINATED_EVENT: { gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg; linkDBInfo_t pInfo; linkDB_GetInfo(pPkt->connectionHandle, &pInfo); // notify bond manager GAPBondMgr_LinkTerm(pPkt->connectionHandle); notify = TRUE; } 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_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) { notify = TRUE; } } break; default: notify = TRUE; 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; }
/********************************************************************* * @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; }
/********************************************************************* * @fn gapCentralRole_ProcessGAPMsg * * @brief Process an incoming task message from GAP. * * @param pMsg - message to process * * @return none */ static void gapCentralRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) { uint8 isBroadcastMsg = FALSE; switch ( pMsg->opcode ) { case GAP_DEVICE_INIT_DONE_EVENT: { gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *) pMsg; bStatus_t stat = pPkt->hdr.status; if ( pPkt->hdr.status == SUCCESS ) { // Save off the generated keys VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapCentralRoleIRK ); VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapCentralRoleSRK ); // Save off the information VOID osal_memcpy( gapCentralRoleBdAddr, pPkt->devAddr, B_ADDR_LEN ); /////////////////////////////////////////////////////////////////////// // Broadcast // Save off the information VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); gapRole_state = GAPROLE_STARTED; // Update the advertising data stat =GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData ); } if ( stat != SUCCESS ) { gapRole_state = GAPROLE_ERROR; } isBroadcastMsg = TRUE; } break; case GAP_LINK_ESTABLISHED_EVENT: { gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *) pMsg; if (pPkt->hdr.status == SUCCESS) { // Notify the Bond Manager of the connection VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_CENTRAL ); } } break; case GAP_LINK_TERMINATED_EVENT: { uint16 connHandle = ((gapTerminateLinkEvent_t *) pMsg)->connectionHandle; GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); // Cancel RSSI reads GAPCentralRole_CancelRssi( connHandle ); } break; // temporary workaround case GAP_SLAVE_REQUESTED_SECURITY_EVENT: GAPBondMgr_ProcessGAPMsg( pMsg ); 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( gapRole_TaskID, FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); } else { // Start advertising VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); } } if ( pPkt->hdr.status != SUCCESS ) { // Set into Error state gapRole_state = GAPROLE_ERROR; isBroadcastMsg = 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 ) { gapRole_state = GAPROLE_ADVERTISING; } else // GAP_END_DISCOVERABLE_DONE_EVENT { if ( gapRole_AdvertOffTime != 0 ) { if ( ( gapRole_AdvEnabled ) ) { VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, 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 gapRole_AdvEnabled = FALSE; } // In the Advertising Off period gapRole_state = GAPROLE_WAITING; } } else { gapRole_state = GAPROLE_ERROR; } isBroadcastMsg = TRUE; } break; default: break; } // If a broadcast event, pass to broadcast callback. if ( isBroadcastMsg == TRUE ) { // Notify the application if ( pGapCentralRoleCB && pGapCentralRoleCB->broadcastCB ) { pGapCentralRoleCB->broadcastCB( gapRole_state ); } } // Otherwise pass to central callback else if ( pGapCentralRoleCB && pGapCentralRoleCB->centralCB ) { pGapCentralRoleCB->centralCB( (gapCentralRoleEvent_t *) pMsg ); } }
/********************************************************************* * @fn gapRole_processGAPMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static uint8 gapRole_processGAPMsg(gapEventHdr_t *pMsg) { uint8_t stateChangeNotify = FALSE; // State changed stateChangeNotify the app? (default no) uint8_t gapEvtNotify = FALSE; 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; } stateChangeNotify = TRUE; gapEvtNotify = 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; stateChangeNotify = 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; } stateChangeNotify = TRUE; gapEvtNotify = FALSE; } 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; } stateChangeNotify = 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); stateChangeNotify = 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; case GAP_DEVICE_INFO_EVENT: //se ricevi questi due eventi girali semplicemente all'applicazione case GAP_DEVICE_DISCOVERY_EVENT: gapEvtNotify = TRUE; break; default: break; } if (stateChangeNotify == TRUE) { // Notify the application with the new state change if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange) { pGapRoles_AppCGs->pfnStateChange(gapRole_state); } } if(gapEvtNotify == TRUE){ // Pass event to app if (pGapRoles_AppCGs && pGapRoles_AppCGs->eventCB) { return (pGapRoles_AppCGs->eventCB( (gapObserverRoleEvent_t *)pMsg )); } } return TRUE; }