/********************************************************************
 * @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 );
  }
}
Esempio n. 2
0
/********************************************************************
 * @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 );
  }
}
Esempio n. 3
0
/********************************************************************
 * @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;
}
Esempio n. 5
0
/********************************************************************
 * @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;
}
Esempio n. 6
0
/*********************************************************************
 * @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);
}
Esempio n. 7
0
/**
 *  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;
}
Esempio n. 8
0
/*********************************************************************
 * @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;
}
Esempio n. 9
0
/*********************************************************************
 * @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 );
    }
  }
}
Esempio n. 10
0
/*********************************************************************
 * @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;
  }
}
Esempio n. 11
0
/*********************************************************************
 * @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 );
}
Esempio n. 12
0
/*********************************************************************
 * @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;
}
Esempio n. 13
0
/*********************************************************************
 * @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;
}
Esempio n. 14
0
/*********************************************************************
 * @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(&paramUpdateClock);
  }
  // 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;
}
Esempio n. 16
0
/*********************************************************************
 * @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;
}