/******************************************************************** * @fn gapRole_startConnUpdate * * @brief Start the connection update procedure * * @param handleFailure - what to do if the update does not occur. * Method may choose to terminate connection, try again, or take no action * * @return none */ static void gapRole_startConnUpdate( uint8 handleFailure ) { // First check the current connection parameters versus the configured parameters if ( (gapRole_ConnInterval < gapRole_MinConnInterval) || (gapRole_ConnInterval > gapRole_MaxConnInterval) || (gapRole_ConnSlaveLatency != gapRole_SlaveLatency) || (gapRole_ConnTimeout != gapRole_TimeoutMultiplier) ) { l2capParamUpdateReq_t updateReq; uint16 timeout = GAP_GetParamValue( TGAP_CONN_PARAM_TIMEOUT ); updateReq.intervalMin = gapRole_MinConnInterval; updateReq.intervalMax = gapRole_MaxConnInterval; updateReq.slaveLatency = gapRole_SlaveLatency; updateReq.timeoutMultiplier = gapRole_TimeoutMultiplier; VOID L2CAP_ConnParamUpdateReq( gapRole_ConnectionHandle, &updateReq, gapRole_TaskID ); paramUpdateNoSuccessOption = handleFailure; // Let's wait for L2CAP Connection Parameters Update Response VOID osal_start_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT, timeout ); } }
/******************************************************************** * @fn gapRole_startConnUpdate * * @brief Start the connection update procedure * * @param handleFailure - what to do if the update does not occur. * Method may choose to terminate connection, try again, or take no action * * @return none */ static void gapRole_startConnUpdate( uint8 handleFailure ) { // First check the current connection parameters versus the configured parameters if ( (gapRole_ConnInterval < gapRole_MinConnInterval) || (gapRole_ConnInterval > gapRole_MaxConnInterval) || (gapRole_ConnSlaveLatency != gapRole_SlaveLatency) || (gapRole_ConnTimeout != gapRole_TimeoutMultiplier) ) { gapUpdateLinkParamReq_t linkParams; uint16 timeout = GAP_GetParamValue( TGAP_CONN_PARAM_TIMEOUT ); linkParams.connectionHandle = gapRole_ConnectionHandle; linkParams.intervalMin = gapRole_MinConnInterval; linkParams.intervalMax = gapRole_MaxConnInterval; linkParams.connLatency = gapRole_SlaveLatency; linkParams.connTimeout = gapRole_TimeoutMultiplier; VOID GAP_UpdateLinkParamReq( &linkParams ); paramUpdateNoSuccessOption = handleFailure; // Let's wait either for L2CAP Connection Parameters Update Response or // for Controller to update connection parameters VOID osal_start_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT, timeout ); } }
/******************************************************************** * @fn gapRole_connUpdate * * @brief Start the connection update procedure * * @param handleFailure - what to do if the update does not occur. * Method may choose to terminate connection, try again, * or take no action * @param pConnParams - connection parameters to use * * @return SUCCESS: operation was successful. * INVALIDPARAMETER: Data can not fit into one packet. * MSG_BUFFER_NOT_AVAIL: No HCI buffer is available. * bleInvalidRange: * bleIncorrectMode: invalid profile role. * bleAlreadyInRequestedMode: already updating link parameters. * bleNotConnected: Connection is down * bleMemAllocError: Memory allocation error occurred. * bleNoResources: No available resource */ bStatus_t gapRole_connUpdate(uint8_t handleFailure, gapRole_updateConnParams_t *pConnParams) { bStatus_t status; linkDBInfo_t pInfo; //ensure connection exists linkDB_GetInfo(pConnParams->connHandle, &pInfo); if (!(pInfo.stateFlags & LINK_CONNECTED)) { return (bleNotConnected); } // Make sure we don't send an L2CAP Connection Parameter Update Request // command within TGAP(conn_param_timeout) of an L2CAP Connection Parameter // Update Response being received. if (Util_isActive(&updateTimeoutClock) == FALSE) { uint16_t timeout = GAP_GetParamValue(TGAP_CONN_PARAM_TIMEOUT); #if defined(L2CAP_CONN_UPDATE) l2capParamUpdateReq_t updateReq; updateReq.intervalMin = pConnParams->minConnInterval; updateReq.intervalMax = pConnParams->maxConnInterval; updateReq.slaveLatency = pConnParams->slaveLatency; updateReq.timeoutMultiplier = pConnParams->timeoutMultiplier; status = L2CAP_ConnParamUpdateReq(pConnParams->connHandle, &updateReq, selfEntity); #else gapUpdateLinkParamReq_t linkParams; linkParams.connectionHandle = pConnParams->connHandle; linkParams.intervalMin = pConnParams->minConnInterval; linkParams.intervalMax = pConnParams->maxConnInterval; linkParams.connLatency = pConnParams->slaveLatency; linkParams.connTimeout = pConnParams->timeoutMultiplier; status = GAP_UpdateLinkParamReq( &linkParams ); #endif // L2CAP_CONN_UPDATE if(status == SUCCESS) { //store update params for possible resending paramUpdateNoSuccessOption = handleFailure; VOID memcpy(&gapRole_updateConnParams, pConnParams, sizeof(gapRole_updateConnParams_t)); // start timeout clock Util_restartClock(&updateTimeoutClock, timeout); } } else { return(blePending); } return status; }
/******************************************************************** * @fn gapRole_startConnUpdate * * @brief Start the connection update procedure * * @param handleFailure - what to do if the update does not occur. * Method may choose to terminate connection, try again, * or take no action * * @return none */ static bStatus_t gapRole_startConnUpdate(uint8_t handleFailure, uint8 connHandle) { bStatus_t status; uint8 connHandleIndex = gapRoleInfo_Find(connHandle); //update only connection to master, not those to slave if (multiConnInfo[connHandleIndex].gapRole_ConnRole != GAP_PROFILE_PERIPHERAL) { return (bleNotConnected); } // If there is no existing connection no update need be sent if (multiConnInfo[connHandleIndex].gapRole_ConnectionHandle == GAPROLE_CONN_JUST_TERMINATED || multiConnInfo[connHandleIndex].gapRole_ConnectionHandle == INVALID_CONNHANDLE) { return (bleNotConnected); } // First check the current connection parameters versus the configured parameters // if ((multiConnInfo[connHandleIndex].gapRole_ConnInterval < gapRole_MinConnInterval) || (multiConnInfo[connHandleIndex].gapRole_ConnInterval > gapRole_MaxConnInterval) // || (multiConnInfo[connHandleIndex].gapRole_ConnSlaveLatency != gapRole_SlaveLatency) // || (multiConnInfo[connHandleIndex].gapRole_ConnTimeout != gapRole_TimeoutMultiplier)) { if (gapRole_MinConnInterval > 6 && gapRole_MinConnInterval < 3200){ //TODO: do some test to check if parameters are within specification of ble uint16_t timeout = GAP_GetParamValue(TGAP_CONN_PARAM_TIMEOUT); #if defined(L2CAP_CONN_UPDATE) l2capParamUpdateReq_t updateReq; updateReq.intervalMin = gapRole_MinConnInterval; updateReq.intervalMax = gapRole_MaxConnInterval; updateReq.slaveLatency = gapRole_SlaveLatency; updateReq.timeoutMultiplier = gapRole_TimeoutMultiplier; status = L2CAP_ConnParamUpdateReq(connHandle, &updateReq, selfEntity); #else gapUpdateLinkParamReq_t linkParams; linkParams.connectionHandle = connHandle; linkParams.intervalMin = gapRole_MinConnInterval; linkParams.intervalMax = gapRole_MaxConnInterval; linkParams.connLatency = gapRole_SlaveLatency; linkParams.connTimeout = gapRole_TimeoutMultiplier; status = GAP_UpdateLinkParamReq(&linkParams); #endif // L2CAP_CONN_UPDATE if (status == SUCCESS) { paramUpdateNoSuccessOption = handleFailure; // Let's wait either for L2CAP Connection Parameters Update Response or // for Controller to update connection parameters Util_restartClock(&updateTimeoutClock, timeout); } } else { status = bleInvalidRange; } return status; }
/******************************************************************** * @fn gapRole_startConnUpdate * * @brief Start the connection update procedure * * @param handleFailure - what to do if the update does not occur. * Method may choose to terminate connection, try again, * or take no action * * @return none */ static bStatus_t gapRole_startConnUpdate(uint8_t handleFailure) { bStatus_t status; // First check the current connection parameters versus the configured parameters if ((gapRole_ConnInterval < gapRole_MinConnInterval) || (gapRole_ConnInterval > gapRole_MaxConnInterval) || (gapRole_ConnSlaveLatency != gapRole_SlaveLatency) || (gapRole_ConnTimeout != gapRole_TimeoutMultiplier)) { uint16_t timeout = GAP_GetParamValue(TGAP_CONN_PARAM_TIMEOUT); #if defined(L2CAP_CONN_UPDATE) l2capParamUpdateReq_t updateReq; updateReq.intervalMin = gapRole_MinConnInterval; updateReq.intervalMax = gapRole_MaxConnInterval; updateReq.slaveLatency = gapRole_SlaveLatency; updateReq.timeoutMultiplier = gapRole_TimeoutMultiplier; status = L2CAP_ConnParamUpdateReq(gapRole_ConnectionHandle, &updateReq, selfEntity); #else gapUpdateLinkParamReq_t linkParams; linkParams.connectionHandle = gapRole_ConnectionHandle; linkParams.intervalMin = gapRole_MinConnInterval; linkParams.intervalMax = gapRole_MaxConnInterval; linkParams.connLatency = gapRole_SlaveLatency; linkParams.connTimeout = gapRole_TimeoutMultiplier; status = GAP_UpdateLinkParamReq( &linkParams ); #endif // L2CAP_CONN_UPDATE if(status == SUCCESS) { paramUpdateNoSuccessOption = handleFailure; // Let's wait either for L2CAP Connection Parameters Update Response or // for Controller to update connection parameters Util_restartClock(&updateTimeoutClock, timeout); } } else { status = bleInvalidRange; } return status; }
/********************************************************************* * @fn gapRole_processStackMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static uint8_t gapRole_processStackMsg(ICall_Hdr *pMsg) { uint8_t safeToDealloc = TRUE; switch (pMsg->event) { case GAP_MSG_EVENT: safeToDealloc = gapRole_processGAPMsg((gapEventHdr_t *)pMsg); break; case L2CAP_SIGNAL_EVENT: { l2capSignalEvent_t *pPkt = (l2capSignalEvent_t *)pMsg; // Process the Parameter Update Response if (pPkt->opcode == L2CAP_PARAM_UPDATE_RSP) { l2capParamUpdateRsp_t *pRsp = (l2capParamUpdateRsp_t *)&(pPkt->cmd.updateRsp); if ((pRsp->result == L2CAP_CONN_PARAMS_REJECTED) && (paramUpdateNoSuccessOption == GAPROLE_TERMINATE_LINK)) { // Cancel connection param update timeout timer Util_stopClock(&updateTimeoutClock); // Terminate connection immediately GAPRole_TerminateConnection(pPkt->connHandle); } else { uint16_t timeout = GAP_GetParamValue(TGAP_CONN_PARAM_TIMEOUT); // Let's wait for Controller to update connection parameters if they're // accepted. Otherwise, decide what to do based on no success option. Util_restartClock(&updateTimeoutClock, timeout); } } } break; default: break; } return (safeToDealloc); }
/** * SNP_getGapParam * */ uint8_t SNP_getGapParam(snpGetGapParamReq_t* pReq) { uint8_t status; //Move part of the simple peripheral init back here if((pReq->paramId != TGAP_AUTH_TASK_ID) && (pReq->value < TGAP_PARAMID_MAX)) { uint16_t value; value = GAP_GetParamValue(pReq->paramId); pReq->value = BUILD_UINT16( LO_UINT16(value), HI_UINT16(value)); } if(pReq->value != 0xFFFF) { status = SNP_SUCCESS; } else { status = SNP_INVALID_PARAMS; } return status; }
/********************************************************************* * @fn SensorGapStateCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void SensorGapStateCB( gaprole_States_t newState ) { // if connected if (newState == GAPROLE_CONNECTED) { // get connection handle GAPRole_GetParameter(GAPROLE_CONNHANDLE, &gapConnHandle); // Set timer to update connection parameters // 5 seconds should allow enough time for Service Discovery by the collector to finish osal_start_timerEx( sensor_TaskID, RSC_CONN_PARAM_UPDATE_EVT, SVC_DISC_DELAY); } // if disconnected else if (gapProfileState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED) { uint8 advState = TRUE; uint8 bondCount = 0; // stop periodic measurement osal_stop_timerEx( sensor_TaskID, RSC_PERIODIC_EVT ); // reset client characteristic configuration descriptors Running_HandleConnStatusCB( gapConnHandle, LINKDB_STATUS_UPDATE_REMOVED ); //Batt_HandleConnStatusCB( gapConnHandle, LINKDB_STATUS_UPDATE_REMOVED ); // If not already using white list, begin to do so. GAPBondMgr_GetParameter( GAPBOND_BOND_COUNT, &bondCount ); if(USING_WHITE_LIST && sensorUsingWhiteList == FALSE && bondCount > 0 ) { uint8 value = GAP_FILTER_POLICY_WHITE; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8 ), &value); sensorUsingWhiteList = TRUE; } if ( newState == GAPROLE_WAITING_AFTER_TIMEOUT ) { // link loss timeout-- use fast advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION ); } else { // Else use slow advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION ); } // Enable advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } // if advertising stopped else if ( gapProfileState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING ) { uint8 whiteListUsed = FALSE; // if white list is in use, disable to allow general access if ( sensorUsingWhiteList == TRUE ) { uint8 value = GAP_FILTER_POLICY_ALL; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof( uint8), &value); whiteListUsed = TRUE; sensorUsingWhiteList = FALSE; } // if advertising stopped by user if ( sensorAdvCancelled ) { sensorAdvCancelled = FALSE; } // if fast advertising interrupted to cancel white list else if ( ( (!USING_WHITE_LIST) || whiteListUsed) && (GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL ) ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } // if fast advertising switch to slow or if was already slow but using white list. else if ( ((!USING_WHITE_LIST) || whiteListUsed) || (GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL) ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } } // if started else if (newState == GAPROLE_STARTED) { // Set the system ID from the bd addr uint8 systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, systemId); // shift three bytes up systemId[7] = systemId[5]; systemId[6] = systemId[4]; systemId[5] = systemId[3]; // set middle bytes to zero systemId[4] = 0; systemId[3] = 0; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); } gapProfileState = newState; }
/********************************************************************* * @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_ProcessOSALMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void gapRole_ProcessOSALMsg( osal_event_hdr_t *pMsg ) { switch ( pMsg->event ) { case HCI_GAP_EVENT_EVENT: if ( pMsg->status == HCI_COMMAND_COMPLETE_EVENT_CODE ) { hciEvt_CmdComplete_t *pPkt = (hciEvt_CmdComplete_t *)pMsg; if ( pPkt->cmdOpcode == HCI_READ_RSSI ) { int8 rssi = (int8)pPkt->pReturnParam[3]; if ( (gapRole_state == GAPROLE_CONNECTED) && (rssi != RSSI_NOT_AVAILABLE) ) { // Report RSSI to app if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnRssiRead ) { pGapRoles_AppCGs->pfnRssiRead( rssi ); } } } } break; case GAP_MSG_EVENT: gapRole_ProcessGAPMsg( (gapEventHdr_t *)pMsg ); break; case L2CAP_SIGNAL_EVENT: { l2capSignalEvent_t *pPkt = (l2capSignalEvent_t *)pMsg; // Process the Parameter Update Response if ( pPkt->opcode == L2CAP_PARAM_UPDATE_RSP ) { l2capParamUpdateRsp_t *pRsp = (l2capParamUpdateRsp_t *)&(pPkt->cmd.updateRsp); if ( ( pRsp->result == L2CAP_CONN_PARAMS_REJECTED ) && ( paramUpdateNoSuccessOption == GAPROLE_TERMINATE_LINK ) ) { // Cancel connection param update timeout timer VOID osal_stop_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ); // Terminate connection immediately GAPRole_TerminateConnection(); } else { uint16 timeout = GAP_GetParamValue( TGAP_CONN_PARAM_TIMEOUT ); // Let's wait for Controller to update connection parameters if they're // accepted. Otherwise, decide what to do based on no success option. VOID osal_start_timerEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT, timeout ); } } } break; default: break; } }
/********************************************************************* * @brief Get a GAP Role parameter. * * Public function defined in broadcaster.h. */ bStatus_t GAPRole_GetParameter( uint16 param, void *pValue ) { bStatus_t ret = SUCCESS; switch ( param ) { case GAPROLE_PROFILEROLE: *((uint8*)pValue) = gapRole_profileRole; break; case GAPROLE_BD_ADDR: VOID osal_memcpy( pValue, gapRole_bdAddr, B_ADDR_LEN ) ; break; case GAPROLE_ADVERT_ENABLED: *((uint8*)pValue) = gapRole_AdvEnabled; break; case GAPROLE_ADVERT_OFF_TIME: *((uint16*)pValue) = gapRole_AdvertOffTime; break; case GAPROLE_ADVERT_DATA: VOID osal_memcpy( pValue , gapRole_AdvertData, gapRole_AdvertDataLen ); break; case GAPROLE_SCAN_RSP_DATA: VOID osal_memcpy( pValue, gapRole_ScanRspData, gapRole_ScanRspDataLen ) ; break; case GAPROLE_ADV_EVENT_TYPE: *((uint8*)pValue) = gapRole_AdvEventType; break; case GAPROLE_ADV_DIRECT_TYPE: *((uint8*)pValue) = gapRole_AdvDirectType; break; case GAPROLE_ADV_DIRECT_ADDR: VOID osal_memcpy( pValue, gapRole_AdvDirectAddr, B_ADDR_LEN ) ; break; case GAPROLE_ADV_CHANNEL_MAP: *((uint8*)pValue) = gapRole_AdvChanMap; break; case GAPROLE_ADV_FILTER_POLICY: *((uint8*)pValue) = gapRole_AdvFilterPolicy; break; default: // The param value isn't part of this profile, try the GAP. if ( param < TGAP_PARAMID_MAX ) { *((uint16*)pValue) = GAP_GetParamValue( param ); } else { ret = INVALIDPARAMETER; } break; } return ( ret ); }
/********************************************************************* * @fn timeAppGapStateCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void timeAppGapStateCB( gaprole_States_t newState ) { // if connected if ( newState == GAPROLE_CONNECTED ) { linkDBItem_t *pItem; // Get connection handle GAPRole_GetParameter( GAPROLE_CONNHANDLE, &timeAppConnHandle ); // Get peer bd address if ( (pItem = linkDB_Find( timeAppConnHandle )) != NULL) { // If connected to device without bond do service discovery if ( !osal_memcmp( pItem->addr, timeAppBondedAddr, B_ADDR_LEN ) ) { timeAppDiscoveryCmpl = FALSE; } // Initiate service discovery if necessary if ( timeAppDiscoveryCmpl == FALSE ) { osal_start_timerEx( timeAppTaskId, START_DISCOVERY_EVT, DEFAULT_DISCOVERY_DELAY ); } // Perform configuration of characteristics on connection setup else { timeAppConfigState = timeAppConfigNext( TIMEAPP_CONFIG_CONN_START ); } } LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); } // if disconnected else if ( timeAppGapState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED ) { uint8 advState = TRUE; timeAppDisconnected(); if ( newState == GAPROLE_WAITING_AFTER_TIMEOUT ) { // link loss timeout-- use fast advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION ); } else { // Else use slow advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); } // Enable advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( "", HAL_LCD_LINE_2 ); } // if advertising stopped else if ( timeAppGapState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING ) { // if advertising stopped by user if ( timeAppAdvCancelled ) { timeAppAdvCancelled = FALSE; } // if fast advertising switch to slow else if ( GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } } // if started else if ( newState == GAPROLE_STARTED ) { #ifndef CC2540_MINIDK uint8 bdAddr[B_ADDR_LEN]; GAPRole_GetParameter( GAPROLE_BD_ADDR, &bdAddr ); LCD_WRITE_STRING( "Time App", HAL_LCD_LINE_1 ); LCD_WRITE_STRING( bdAddr2Str( bdAddr ), HAL_LCD_LINE_2 ); #endif // Initialize time clock after writing first two lines of LCD timeAppClockInit(); } timeAppGapState = newState; }
/********************************************************************* * @fn HeartRateGapStateCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void HeartRateGapStateCB( gaprole_States_t newState ) { // if connected if (newState == GAPROLE_CONNECTED) { // get connection handle GAPRole_GetParameter(GAPROLE_CONNHANDLE, &gapConnHandle); } // if disconnected else if (gapProfileState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED) { uint8 advState = TRUE; // stop periodic measurement osal_stop_timerEx( heartRate_TaskID, HEART_PERIODIC_EVT ); if ( newState == GAPROLE_WAITING_AFTER_TIMEOUT ) { // link loss timeout-- use fast advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION ); } else { // Else use slow advertising GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); } // Enable advertising GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } // if advertising stopped else if ( gapProfileState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING ) { // if advertising stopped by user if ( heartRateAdvCancelled ) { heartRateAdvCancelled = FALSE; } // if fast advertising switch to slow else if ( GAP_GetParamValue( TGAP_GEN_DISC_ADV_INT_MIN ) == DEFAULT_FAST_ADV_INTERVAL ) { uint8 advState = TRUE; GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL ); GAP_SetParamValue( TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION ); GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advState ); } } // if started else if (newState == GAPROLE_STARTED) { // Set the system ID from the bd addr uint8 systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, systemId); // shift three bytes up systemId[7] = systemId[5]; systemId[6] = systemId[4]; systemId[5] = systemId[3]; // set middle bytes to zero systemId[4] = 0; systemId[3] = 0; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); } gapProfileState = newState; }
/********************************************************************* * @brief Get a GAP Role parameter. * * Public function defined in peripheral.h. */ bStatus_t GAPRole_GetParameter(uint16_t param, void *pValue, uint8_t connHandle) { bStatus_t ret = SUCCESS; linkDBInfo_t pInfo; switch (param) { case GAPROLE_PROFILEROLE: *((uint8_t*)pValue) = gapRole_profileRole; break; case GAPROLE_IRK: VOID memcpy(pValue, gapRole_IRK, KEYLEN) ; break; case GAPROLE_SRK: VOID memcpy(pValue, gapRole_SRK, KEYLEN) ; break; case GAPROLE_SIGNCOUNTER: *((uint32_t*)pValue) = gapRole_signCounter; break; case GAPROLE_BD_ADDR: VOID memcpy(pValue, gapRole_bdAddr, B_ADDR_LEN) ; break; case GAPROLE_ADVERT_ENABLED: *((uint8_t*)pValue) = gapRole_AdvEnabled; break; case GAPROLE_ADV_NONCONN_ENABLED: *((uint8_t*)pValue) = gapRole_AdvNonConnEnabled; break; case GAPROLE_ADVERT_OFF_TIME: *((uint16_t*)pValue) = gapRole_AdvertOffTime; break; case GAPROLE_ADVERT_DATA: VOID memcpy(pValue , gapRole_AdvertData, gapRole_AdvertDataLen); break; case GAPROLE_SCAN_RSP_DATA: VOID memcpy(pValue, gapRole_ScanRspData, gapRole_ScanRspDataLen) ; break; case GAPROLE_ADV_EVENT_TYPE: *((uint8_t*)pValue) = gapRole_AdvEventType; break; case GAPROLE_ADV_DIRECT_TYPE: *((uint8_t*)pValue) = gapRole_AdvDirectType; break; case GAPROLE_ADV_DIRECT_ADDR: VOID memcpy(pValue, gapRole_AdvDirectAddr, B_ADDR_LEN) ; break; case GAPROLE_ADV_CHANNEL_MAP: *((uint8_t*)pValue) = gapRole_AdvChanMap; break; case GAPROLE_ADV_FILTER_POLICY: *((uint8_t*)pValue) = gapRole_AdvFilterPolicy; break; case GAPROLE_CONN_BD_ADDR: linkDB_GetInfo(connHandle, &pInfo); VOID memcpy(pValue, pInfo.addr, B_ADDR_LEN) ; break; case GAPROLE_CONN_INTERVAL: linkDB_GetInfo(connHandle, &pInfo); *((uint16_t*)pValue) = pInfo.connInterval; case GAPROLE_CONN_LATENCY: //wait for linkdb update // linkDB_GetInfo(connHandle, &pInfo); // *((uint16_t*)pValue) = pInfo.connLatency; break; case GAPROLE_CONN_TIMEOUT: //wait for linkdb update // linkDB_GetInfo(connHandle, &pInfo); // *((uint16_t*)pValue) = pInfo.connTimeout; break; case GAPROLE_MAX_SCAN_RES: *((uint8_t*)pValue) = gapRoleMaxScanRes; break; default: // The param value isn't part of this profile, try the GAP. if (param < TGAP_PARAMID_MAX) { *((uint16_t*)pValue) = GAP_GetParamValue(param); } else { ret = INVALIDPARAMETER; } break; } return (ret); }
/********************************************************************* * @fn RunningSensor_processStateChangeEvt * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void RunningSensor_processStateChangeEvt(gaprole_States_t newState) { // If connected if (newState == GAPROLE_CONNECTED) { // Get the connection handle. GAPRole_GetParameter(GAPROLE_CONNHANDLE, &gapConnHandle); // Begin delay for service discovery. Util_startClock(¶mUpdateClock); } // If disconnected else if (gapProfileState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED) { uint8_t advState = TRUE; uint8_t bondCount = 0; // Stop periodic measurement. Util_stopClock(&periodicClock); // Get the bond count. GAPBondMgr_GetParameter(GAPBOND_BOND_COUNT, &bondCount); // If enabled and previously bonded, turn on white list if not already done. if(USING_WHITE_LIST && sensorUsingWhiteList == FALSE && bondCount > 0) { uint8_t value = GAP_FILTER_POLICY_WHITE; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof(uint8_t), &value); sensorUsingWhiteList = TRUE; } // If waiting after a connection timeout if (newState == GAPROLE_WAITING_AFTER_TIMEOUT) { // Link loss timeout-- use fast advertising. GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION); } else { // Use slow advertising. GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_WHITE_LIST_ADV_DURATION); } // Enable advertising. GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advState); } // If advertising stopped else if (gapProfileState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING) { uint8_t whiteListUsed = FALSE; // If white list is in use, turn off white list filtering to allow general // access. if (sensorUsingWhiteList == TRUE) { uint8_t value = GAP_FILTER_POLICY_ALL; GAPRole_SetParameter(GAPROLE_ADV_FILTER_POLICY, sizeof(uint8_t), &value); whiteListUsed = TRUE; sensorUsingWhiteList = FALSE; } // If advertising stopped by user if (sensorAdvCancelled) { sensorAdvCancelled = FALSE; } // If fast advertising was interrupted to cancel white list else if (((!USING_WHITE_LIST) || whiteListUsed) && (GAP_GetParamValue(TGAP_GEN_DISC_ADV_INT_MIN) == DEFAULT_FAST_ADV_INTERVAL)) { uint8_t advState = TRUE; GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION); GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advState); } // If fast advertising or was using white list switch to slow advertising. else if (((!USING_WHITE_LIST) || whiteListUsed) || (GAP_GetParamValue(TGAP_GEN_DISC_ADV_INT_MIN) == DEFAULT_FAST_ADV_INTERVAL)) { uint8_t advState = TRUE; GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION); GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &advState); } } // If started else if (newState == GAPROLE_STARTED) { // Set the system ID from the bd addr. uint8_t systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, systemId); // Shift three bytes up. systemId[7] = systemId[5]; systemId[6] = systemId[4]; systemId[5] = systemId[3]; // Set middle bytes to zero. systemId[4] = 0; systemId[3] = 0; DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); } // Update state. gapProfileState = newState; }
/********************************************************************* * @fn HeartRate_stateChangeEvt * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void HeartRate_stateChangeEvt(gaprole_States_t newState) { // If no change to the GAP Role state has occurred if (gapProfileState == newState) { return; } // If connected if (newState == GAPROLE_CONNECTED) { // Get connection handle. GAPRole_GetParameter(GAPROLE_CONNHANDLE, &gapConnHandle); } // If disconnected else if (gapProfileState == GAPROLE_CONNECTED && newState != GAPROLE_CONNECTED) { // Stop periodic measurement of heart rate. Util_stopClock(&measPerClock); if (newState == GAPROLE_WAITING_AFTER_TIMEOUT) { // Link loss timeout-- use fast advertising GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_FAST_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_FAST_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_FAST_ADV_DURATION); } else { // Else use slow advertising GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION); } // Enable advertising. HeartRate_toggleAdvertising(); } // If advertising stopped else if (gapProfileState == GAPROLE_ADVERTISING && newState == GAPROLE_WAITING) { // If advertising stopped by user if (advCancelled) { // Disable advertising. advCancelled = FALSE; } // Else if fast advertising switch to slow else if (GAP_GetParamValue(TGAP_GEN_DISC_ADV_INT_MIN) == DEFAULT_FAST_ADV_INTERVAL) { GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, DEFAULT_SLOW_ADV_INTERVAL); GAP_SetParamValue(TGAP_GEN_DISC_ADV_MIN, DEFAULT_SLOW_ADV_DURATION); // Enable advertising. HeartRate_toggleAdvertising(); } #if ADVERTISE_WHEN_NOT_CONNECTED else { // Test mode: continue advertising. HeartRate_toggleAdvertising(); } #endif //ADVERTISE_WHEN_NOT_CONNECTED } #if ADVERTISE_WHEN_NOT_CONNECTED else if (newState == GAPROLE_WAITING_AFTER_TIMEOUT) { // Test mode: continue advertising. HeartRate_toggleAdvertising(); } #endif //ADVERTISE_WHEN_NOT_CONNECTED // If started else if (newState == GAPROLE_STARTED) { // Set the system ID from the bd addr. uint8_t systemId[DEVINFO_SYSTEM_ID_LEN]; GAPRole_GetParameter(GAPROLE_BD_ADDR, systemId); // Shift three bytes up. systemId[7] = systemId[5]; systemId[6] = systemId[4]; systemId[5] = systemId[3]; // Set middle bytes to zero. systemId[4] = 0; systemId[3] = 0; // Pass systemId to the Device Info service. DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); } // Update GAP profile state. gapProfileState = newState; }
/********************************************************************* * @brief Get a GAP Role parameter. * * Public function defined in peripheral.h. */ bStatus_t GAPRole_GetParameter(uint16_t param, void *pValue, uint8_t connHandle) { bStatus_t ret = SUCCESS; uint8_t index; switch (param) { case GAPROLE_PROFILEROLE: *((uint8_t*) pValue) = gapRole_profileRole; break; case GAPROLE_IRK: VOID memcpy(pValue, gapRole_IRK, KEYLEN); break; case GAPROLE_SRK: VOID memcpy(pValue, gapRole_SRK, KEYLEN); break; case GAPROLE_SIGNCOUNTER: *((uint32_t*) pValue) = gapRole_signCounter; break; case GAPROLE_BD_ADDR: VOID memcpy(pValue, gapRole_bdAddr, B_ADDR_LEN); break; case GAPROLE_ADVERT_ENABLED: *((uint8_t*) pValue) = gapRole_AdvEnabled; break; case GAPROLE_ADV_NONCONN_ENABLED: *((uint8_t*) pValue) = gapRole_AdvNonConnEnabled; break; case GAPROLE_ADVERT_OFF_TIME: *((uint16_t*) pValue) = gapRole_AdvertOffTime; break; case GAPROLE_ADVERT_DATA: VOID memcpy(pValue, gapRole_AdvertData, gapRole_AdvertDataLen); break; case GAPROLE_SCAN_RSP_DATA: VOID memcpy(pValue, gapRole_ScanRspData, gapRole_ScanRspDataLen); break; case GAPROLE_ADV_EVENT_TYPE: *((uint8_t*) pValue) = gapRole_AdvEventType; break; case GAPROLE_ADV_DIRECT_TYPE: *((uint8_t*) pValue) = gapRole_AdvDirectType; break; case GAPROLE_ADV_DIRECT_ADDR: VOID memcpy(pValue, gapRole_AdvDirectAddr, B_ADDR_LEN); break; case GAPROLE_ADV_CHANNEL_MAP: *((uint8_t*) pValue) = gapRole_AdvChanMap; break; case GAPROLE_ADV_FILTER_POLICY: *((uint8_t*) pValue) = gapRole_AdvFilterPolicy; break; case GAPROLE_PARAM_UPDATE_ENABLE: *((uint16_t*) pValue) = gapRole_ParamUpdateEnable; break; case GAPROLE_MIN_CONN_INTERVAL: *((uint16_t*) pValue) = gapRole_MinConnInterval; break; case GAPROLE_MAX_CONN_INTERVAL: *((uint16_t*) pValue) = gapRole_MaxConnInterval; break; case GAPROLE_SLAVE_LATENCY: *((uint16_t*) pValue) = gapRole_SlaveLatency; break; case GAPROLE_TIMEOUT_MULTIPLIER: *((uint16_t*) pValue) = gapRole_TimeoutMultiplier; break; case GAPROLE_CONN_BD_ADDR: index = gapRoleInfo_Find(connHandle); if (index != 0xFF) { VOID memcpy(pValue, multiConnInfo[index].gapRole_devAddr, B_ADDR_LEN); } else { return bleNotConnected; } break; case GAPROLE_CONN_INTERVAL: index = gapRoleInfo_Find(connHandle); if (index != 0xFF) { *((uint16_t*) pValue) = multiConnInfo[index].gapRole_ConnInterval; } else { return bleNotConnected; } break; case GAPROLE_CONN_LATENCY: index = gapRoleInfo_Find(connHandle); if (index != 0xFF) { *((uint16_t*) pValue) = multiConnInfo[index].gapRole_ConnSlaveLatency; } else { return bleNotConnected; } break; case GAPROLE_CONN_TIMEOUT: index = gapRoleInfo_Find(connHandle); if (index != 0xFF) { *((uint16_t*) pValue) = multiConnInfo[index].gapRole_ConnTimeout; } else { return bleNotConnected; } break; case GAPROLE_MAX_SCAN_RES: *((uint8_t*) pValue) = gapRoleMaxScanRes; break; default: // The param value isn't part of this profile, try the GAP. if (param < TGAP_PARAMID_MAX) { *((uint16_t*) pValue) = GAP_GetParamValue(param); } else { ret = INVALIDPARAMETER; } break; } return (ret); }
/********************************************************************* * @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; }
/********************************************************************* * @brief Get a GAP Role parameter. * * Public function defined in peripheral.h. */ bStatus_t GAPRole_GetParameter( uint16 param, void *pValue ) { bStatus_t ret = SUCCESS; switch ( param ) { case GAPROLE_PROFILEROLE: *((uint8*)pValue) = gapRole_profileRole; break; case GAPROLE_IRK: VOID osal_memcpy( pValue, gapRole_IRK, KEYLEN ) ; break; case GAPROLE_SRK: VOID osal_memcpy( pValue, gapRole_SRK, KEYLEN ) ; break; case GAPROLE_SIGNCOUNTER: *((uint32*)pValue) = gapRole_signCounter; break; case GAPROLE_BD_ADDR: VOID osal_memcpy( pValue, gapRole_bdAddr, B_ADDR_LEN ) ; break; case GAPROLE_ADVERT_ENABLED: *((uint8*)pValue) = gapRole_AdvEnabled; break; case GAPROLE_ADVERT_OFF_TIME: *((uint16*)pValue) = gapRole_AdvertOffTime; break; case GAPROLE_ADVERT_DATA: VOID osal_memcpy( pValue , gapRole_AdvertData, gapRole_AdvertDataLen ); break; case GAPROLE_SCAN_RSP_DATA: VOID osal_memcpy( pValue, gapRole_ScanRspData, gapRole_ScanRspDataLen ) ; break; case GAPROLE_ADV_EVENT_TYPE: *((uint8*)pValue) = gapRole_AdvEventType; break; case GAPROLE_ADV_DIRECT_TYPE: *((uint8*)pValue) = gapRole_AdvDirectType; break; case GAPROLE_ADV_DIRECT_ADDR: VOID osal_memcpy( pValue, gapRole_AdvDirectAddr, B_ADDR_LEN ) ; break; case GAPROLE_ADV_CHANNEL_MAP: *((uint8*)pValue) = gapRole_AdvChanMap; break; case GAPROLE_ADV_FILTER_POLICY: *((uint8*)pValue) = gapRole_AdvFilterPolicy; break; case GAPROLE_CONNHANDLE: *((uint16*)pValue) = gapRole_ConnectionHandle; break; case GAPROLE_RSSI_READ_RATE: *((uint16*)pValue) = gapRole_RSSIReadRate; break; case GAPROLE_PARAM_UPDATE_ENABLE: *((uint16*)pValue) = gapRole_ParamUpdateEnable; break; case GAPROLE_MIN_CONN_INTERVAL: *((uint16*)pValue) = gapRole_MinConnInterval; break; case GAPROLE_MAX_CONN_INTERVAL: *((uint16*)pValue) = gapRole_MaxConnInterval; break; case GAPROLE_SLAVE_LATENCY: *((uint16*)pValue) = gapRole_SlaveLatency; break; case GAPROLE_TIMEOUT_MULTIPLIER: *((uint16*)pValue) = gapRole_TimeoutMultiplier; break; case GAPROLE_CONN_BD_ADDR: VOID osal_memcpy( pValue, gapRole_ConnectedDevAddr, B_ADDR_LEN ) ; break; default: // The param value isn't part of this profile, try the GAP. if ( param < TGAP_PARAMID_MAX ) { *((uint16*)pValue) = GAP_GetParamValue( param ); } else { ret = INVALIDPARAMETER; } break; } return ( ret ); }
/********************************************************************* * @brief Get a GAP Bond Manager parameter. * * Public function defined in gapperiphbondmgr.h. */ bStatus_t GAPBondMgr_GetParameter( uint16 param, void *pValue ) { bStatus_t ret = SUCCESS; // return value switch ( param ) { case GAPBOND_PAIRING_MODE: *((uint8*)pValue) = gapBond_PairingMode; break; case GAPBOND_INITIATE_WAIT: *((uint16*)pValue) = gapBond_InitiateWait; break; case GAPBOND_MITM_PROTECTION: *((uint8*)pValue) = gapBond_MITM; break; case GAPBOND_IO_CAPABILITIES: *((uint8*)pValue) = gapBond_IOCap; break; case GAPBOND_OOB_ENABLED: *((uint8*)pValue) = gapBond_OOBDataFlag; break; case GAPBOND_OOB_DATA: VOID osal_memcpy( pValue, gapBond_OOBData, KEYLEN ) ; break; case GAPBOND_BONDING_ENABLED: *((uint8*)pValue) = gapBond_Bonding; break; case GAPBOND_KEY_DIST_LIST: *((uint8*)pValue) = gapBond_KeyDistList; break; case GAPBOND_DEFAULT_PASSCODE: *((uint32*)pValue) = gapBond_Passcode; break; case GAPBOND_AUTO_FAIL_PAIRING: *((uint8*)pValue) = gapBond_AutoFail; break; case GAPBOND_AUTO_FAIL_REASON: *((uint8*)pValue) = gapBond_AutoFailReason; break; case GAPBOND_KEYSIZE: *((uint8*)pValue) = gapBond_KeySize; break; default: // The param value isn't part of this profile, try the GAP. if ( param < TGAP_PARAMID_MAX ) { *((uint16*)pValue) = GAP_GetParamValue( param ); } else { ret = INVALIDPARAMETER; } break; } return ( ret ); }
/********************************************************************* * @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; }