/*********************************************************************
 * @brief   Set a GAP Role parameter.
 *
 * Public function defined in peripheral.h.
 */
bStatus_t GAPRole_SetParameter( uint16 param, uint8 len, void *pValue )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {
    case GAPROLE_IRK:
      if ( len == KEYLEN )
      {
        VOID osal_memcpy( gapRole_IRK, pValue, KEYLEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SRK:
      if ( len == KEYLEN )
      {
        VOID osal_memcpy( gapRole_SRK, pValue, KEYLEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SIGNCOUNTER:
      if ( len == sizeof ( uint32 ) )
      {
        gapRole_signCounter = *((uint32*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_ENABLED:
      if ( len == sizeof( uint8 ) )
      {
        if ( (gapRole_state == GAPROLE_CONNECTED) || (gapRole_state == GAPROLE_CONNECTED_ADV) )
        {
          uint8 advEnabled = *((uint8*)pValue);

          if ( (gapRole_state == GAPROLE_CONNECTED) && (advEnabled == TRUE) )
          {
            // Turn on advertising
            osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
          else if ( (gapRole_state == GAPROLE_CONNECTED_ADV) && (advEnabled == FALSE) )
          {
            // Turn off Advertising
            GAP_EndDiscoverable( gapRole_TaskID );
          }
        }
        else
        {
          uint8 oldAdvEnabled = gapRole_AdvEnabled;
          gapRole_AdvEnabled = *((uint8*)pValue);

          if ( (oldAdvEnabled) && (gapRole_AdvEnabled == FALSE) )
          {
            // Turn off Advertising
            VOID GAP_EndDiscoverable( gapRole_TaskID );
          }
          else if ( (oldAdvEnabled == FALSE) && (gapRole_AdvEnabled) )
          {
            // Turn on Advertising
            if ( (gapRole_state == GAPROLE_STARTED)
                || (gapRole_state == GAPROLE_WAITING )
                || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT) )
            {
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
            }
          }
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_OFF_TIME:
      if ( len == sizeof ( uint16 ) )
      {
        gapRole_AdvertOffTime = *((uint16*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_DATA:
      if ( len <= B_MAX_ADV_LEN )
      {
        VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_AdvertData, pValue, len );
        gapRole_AdvertDataLen = len;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SCAN_RSP_DATA:
      if ( len <= B_MAX_ADV_LEN )
      {
        VOID osal_memset( gapRole_ScanRspData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_ScanRspData, pValue, len );
        gapRole_ScanRspDataLen = len;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_EVENT_TYPE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND) )
      {
        gapRole_AdvEventType = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_TYPE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= ADDRTYPE_PRIVATE_RESOLVE) )
      {
        gapRole_AdvDirectType = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_ADDR:
      if ( len == B_ADDR_LEN )
      {
        VOID osal_memcpy( gapRole_AdvDirectAddr, pValue, B_ADDR_LEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_CHANNEL_MAP:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= 0x07) )
      {
        gapRole_AdvChanMap = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_FILTER_POLICY:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_FILTER_POLICY_WHITE) )
      {
        gapRole_AdvFilterPolicy = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_RSSI_READ_RATE:
      if ( len == sizeof ( uint16 ) )
      {
        gapRole_RSSIReadRate = *((uint16*)pValue);

        if ( (gapRole_RSSIReadRate) && (gapRole_state == GAPROLE_CONNECTED) )
        {
          // Start the RSSI Reads
          VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_PARAM_UPDATE_ENABLE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= TRUE) )
      {
        gapRole_ParamUpdateEnable = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;
       
    case GAPROLE_MIN_CONN_INTERVAL:
      {
        uint16 newInterval = *((uint16*)pValue);
        if (   len == sizeof ( uint16 )           &&
             ( newInterval >= MIN_CONN_INTERVAL ) && 
             ( newInterval <= MAX_CONN_INTERVAL ) )
        {
          gapRole_MinConnInterval = newInterval;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    case GAPROLE_MAX_CONN_INTERVAL:
      {
        uint16 newInterval = *((uint16*)pValue);
        if (   len == sizeof ( uint16 )          &&
             ( newInterval >= MIN_CONN_INTERVAL) &&
             ( newInterval <= MAX_CONN_INTERVAL) ) 
        {
          gapRole_MaxConnInterval = newInterval;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    case GAPROLE_SLAVE_LATENCY:
      {
        uint16 latency = *((uint16*)pValue);
        if ( len == sizeof ( uint16 ) && (latency < MAX_SLAVE_LATENCY) )
        {
          gapRole_SlaveLatency = latency;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    case GAPROLE_TIMEOUT_MULTIPLIER:
      {
        uint16 newTimeout = *((uint16*)pValue);
        if ( len == sizeof ( uint16 )
            && (newTimeout >= MIN_TIMEOUT_MULTIPLIER) && (newTimeout <= MAX_TIMEOUT_MULTIPLIER) )
        {
          gapRole_TimeoutMultiplier = newTimeout;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    default:
      // The param value isn't part of this profile, try the GAP.
      if ( (param < TGAP_PARAMID_MAX) && (len == sizeof ( uint16 )) )
      {
        ret = GAP_SetParamValue( param, *((uint16*)pValue) );
      }
      else
      {
        ret = INVALIDPARAMETER;
      }
      break;
  }

  return ( ret );
}
/*********************************************************************
 * @fn      gapRole_ProcessGAPMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg )
{
  uint8 notify = FALSE;   // State changed notify the app? (default no)

  switch ( pMsg->opcode )
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
      {
        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
        bStatus_t stat = pPkt->hdr.status;

        if ( stat == SUCCESS )
        {
          // Save off the generated keys
          VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK );
          VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );
          
          // Save off the information
          VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN );

          gapRole_state = GAPROLE_STARTED;

          // Update the advertising data
          stat = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
        }

        if ( stat != SUCCESS )
        {
          gapRole_state = GAPROLE_ERROR;
        }

        notify = TRUE;
      }
      break;

    case GAP_ADV_DATA_UPDATE_DONE_EVENT:
      {
        gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pPkt->adType )
          {
            // Setup the Response Data
            pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData );
          }
          else
          {
            // Start advertising
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }

        if ( pPkt->hdr.status != SUCCESS )
        {
          // Set into Error state
          gapRole_state = GAPROLE_ERROR;
          notify = TRUE;
        }
      }
      break;

    case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
    case GAP_END_DISCOVERABLE_DONE_EVENT:
      {
        gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
          {
            if ( gapRole_state == GAPROLE_CONNECTED )
            {
              gapRole_state = GAPROLE_CONNECTED_ADV;
            }
            else
            {
              gapRole_state = GAPROLE_ADVERTISING;
            }
          }
          else // GAP_END_DISCOVERABLE_DONE_EVENT
          {
            
            if ( gapRole_AdvertOffTime != 0 )
            {
              if ( ( gapRole_AdvEnabled ) )
              {
                VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime );
              }
            }
            else
            {            
              // Since gapRole_AdvertOffTime is set to 0, the device should not
              // automatically become discoverable again after a period of time.
              // Set enabler to FALSE; device will become discoverable again when
              // this value gets set to TRUE
              gapRole_AdvEnabled = FALSE;
            }

            // In the Advertising Off period
            gapRole_state = GAPROLE_WAITING;

          }
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN );
          gapRole_ConnectionHandle = pPkt->connectionHandle;
          gapRole_state = GAPROLE_CONNECTED;

          if ( gapRole_RSSIReadRate )
          {
            // Start the RSSI Reads
            VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
          }

          // Check whether update parameter request is enabled, and check the connection parameters
          if ( ( gapRole_ParamUpdateEnable == TRUE ) &&
               ( (pPkt->connInterval < gapRole_MinConnInterval) ||
                 (pPkt->connInterval > gapRole_MaxConnInterval) ||
                 (pPkt->connLatency != gapRole_SlaveLatency)    ||
                 (pPkt->connTimeout != gapRole_TimeoutMultiplier) ))
          {
            gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency );
          }
          
          // Notify the Bond Manager to the connection
          VOID GAPBondMgr_LinkEst( pPkt->devAddrType, pPkt->devAddr, pPkt->connectionHandle, GAP_PROFILE_PERIPHERAL );  
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_TERMINATED_EVENT:
      {
        VOID GAPBondMgr_ProcessGAPMsg( (gapEventHdr_t *)pMsg );
        osal_memset( gapRole_ConnectedDevAddr, 0, B_ADDR_LEN );
        
        if ( gapRole_state == GAPROLE_CONNECTED_ADV )
        {
          // End the non-connectable advertising
          GAP_EndDiscoverable( gapRole_TaskID );
          gapRole_state = GAPROLE_CONNECTED;
        }
        else
        {
          gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;
          if( pPkt->reason == LL_SUPERVISION_TIMEOUT_TERM )
          {
            gapRole_state = GAPROLE_WAITING_AFTER_TIMEOUT;
          }
          else
          {
            gapRole_state = GAPROLE_WAITING;
          }

          notify = TRUE;

          VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
        }

        gapRole_ConnectionHandle = INVALID_CONNHANDLE;
      }
      break;

    case GAP_LINK_PARAM_UPDATE_EVENT:
      {
        gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;

        if ( (pPkt->hdr.status != SUCCESS)
            || (pPkt->connInterval < gapRole_MinConnInterval)
              || (pPkt->connInterval > gapRole_MaxConnInterval) )
        {
          // Ask to change the interval
          gapRole_SendUpdateParam( pPkt->connInterval, pPkt->connLatency );
        }
        else
        {
          // All is good stop Update Parameters timeout
          VOID osal_stop_timerEx( gapRole_TaskID, UPDATE_PARAMS_TIMEOUT_EVT );
        }
      }
      break;
      
    default:
      break;
  }

  if ( notify == TRUE )
  {
    // Notify the application
    if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
    {
      pGapRoles_AppCGs->pfnStateChange( gapRole_state );
    }
  }
}
예제 #3
0
/*********************************************************************
 * @brief   Set a GAP Role parameter.
 *
 * Public function defined in broadcaster.h.
 */
bStatus_t GAPRole_SetParameter( uint16 param, uint8 len, void *pValue )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {
    case GAPROLE_ADVERT_ENABLED:
      if ( len == sizeof( uint8 ) )
      {
        uint8 oldAdvEnabled = gapRole_AdvEnabled;
        gapRole_AdvEnabled = *((uint8*)pValue);

        if ( (oldAdvEnabled) && (gapRole_AdvEnabled == FALSE) )
        {
          // Turn off Advertising
          if ( gapRole_state == GAPROLE_ADVERTISING )
          {
            VOID GAP_EndDiscoverable( gapRole_TaskID );
          }
        }
        else if ( (oldAdvEnabled == FALSE) && (gapRole_AdvEnabled) )
        {
          // Turn on Advertising
          if ( (gapRole_state == GAPROLE_STARTED)
              || (gapRole_state == GAPROLE_WAITING) )
          {
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_OFF_TIME:
      if ( len == sizeof ( uint16 ) )
      {
        gapRole_AdvertOffTime = *((uint16*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_DATA:
      if ( len <= B_MAX_ADV_LEN )
      {
        VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_AdvertData, pValue, len );
        gapRole_AdvertDataLen = len;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SCAN_RSP_DATA:
      if ( len <= B_MAX_ADV_LEN )
      {
        VOID osal_memset( gapRole_ScanRspData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_ScanRspData, pValue, len );
        gapRole_ScanRspDataLen = len;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_EVENT_TYPE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND) )
      {
        gapRole_AdvEventType = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_TYPE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= ADDRTYPE_PRIVATE_RESOLVE) )
      {
        gapRole_AdvDirectType = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_ADDR:
      if ( len == B_ADDR_LEN )
      {
        VOID osal_memcpy( gapRole_AdvDirectAddr, pValue, B_ADDR_LEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_CHANNEL_MAP:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= 0x07) )
      {
        gapRole_AdvChanMap = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_FILTER_POLICY:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_FILTER_POLICY_WHITE) )
      {
        gapRole_AdvFilterPolicy = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    default:
      // The param value isn't part of this profile, try the GAP.
      if ( (param < TGAP_PARAMID_MAX) && (len == sizeof ( uint16 )) )
      {
        ret = GAP_SetParamValue( param, *((uint16*)pValue) );
      }
      else
      {
        ret = INVALIDPARAMETER;
      }
      break;
  }

  return ( ret );
}
예제 #4
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 if ( ( gapRole_state != GAPROLE_ADVERTISING ) &&
                    ( osal_get_timeoutEx( gapRole_TaskID, START_ADVERTISING_EVT ) == 0 ) )
          {
            // Start advertising
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }

        if ( pPkt->hdr.status != SUCCESS )
        {
          // Set into Error state
          gapRole_state = GAPROLE_ERROR;
          notify = TRUE;
        }
      }
      break;

    case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
    case GAP_END_DISCOVERABLE_DONE_EVENT:
      {
        gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
          {
            if (gapRole_state == GAPROLE_CONNECTED)
            {
              gapRole_state = GAPROLE_CONNECTED_ADV;
            }
            else
            {
              gapRole_state = GAPROLE_ADVERTISING;
            }
          }
          else // GAP_END_DISCOVERABLE_DONE_EVENT
          {

            if ( gapRole_AdvertOffTime != 0 )
            {
              if ( ( gapRole_AdvEnabled ) )
              {
                VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime );
              }
            }
            else
            {
              // Since gapRole_AdvertOffTime is set to 0, the device should not
              // automatically become discoverable again after a period of time.
              // Set enabler to FALSE; device will become discoverable again when
              // this value gets set to TRUE
              gapRole_AdvEnabled = FALSE;
            }
            
            if (gapRole_state == GAPROLE_CONNECTED_ADV)
            {
              // In the Advertising Off period
              gapRole_state = GAPROLE_CONNECTED;
            }
            else if (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT)
            {
              // Advertising was just turned off after the link disconnected so begin
              // advertising again.
              gapRole_AdvEnabled = TRUE;
              
              // Turn advertising back on.
              VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
            }
            else
            {
              // In the Advertising Off period
              gapRole_state = GAPROLE_WAITING;
            }

          }
        }
        else
        {
          gapRole_state = GAPROLE_ERROR;
        }
        notify = TRUE;
      }
      break;

    case GAP_LINK_ESTABLISHED_EVENT:
      {
        gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;

        if ( pPkt->hdr.status == SUCCESS )
        {
          VOID 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 );
          
          // Set enabler to FALSE; device will become discoverable again when
          // this value gets set to TRUE
          gapRole_AdvEnabled = FALSE;          
        }
        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;

        VOID 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;
        
        // Check if still advertising from within last connection.
        if ( gapRole_AdvEnabled)
        {
          // End advertising so we can restart advertising in order 
          // to change to connectable advertising from nonconnectable.
          VOID GAP_EndDiscoverable( gapRole_TaskID );
        }
        else  // Turn advertising back on.
        {
          gapRole_AdvEnabled = 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 );
    }
  }
}
예제 #5
0
/*********************************************************************
 * @brief   Set a GAP Role parameter.
 *
 * Public function defined in peripheral.h.
 */
bStatus_t GAPRole_SetParameter( uint16 param, uint8 len, void *pValue )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {
    case GAPROLE_IRK:
      if ( len == KEYLEN )
      {
        VOID osal_memcpy( gapRole_IRK, pValue, KEYLEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SRK:
      if ( len == KEYLEN )
      {
        VOID osal_memcpy( gapRole_SRK, pValue, KEYLEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SIGNCOUNTER:
      if ( len == sizeof ( uint32 ) )
      {
        gapRole_signCounter = *((uint32*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_ENABLED:
      if ( len == sizeof( uint8 ) )
      {
        uint8 oldAdvEnabled = gapRole_AdvEnabled;
        gapRole_AdvEnabled = *((uint8*)pValue);

        if ( (oldAdvEnabled) && (gapRole_AdvEnabled == FALSE) )
        {
          // Turn off Advertising
          if ( ( gapRole_state == GAPROLE_ADVERTISING ) 
              || ( gapRole_state == GAPROLE_CONNECTED_ADV )
              || ( gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT ) )
          {
            VOID GAP_EndDiscoverable( gapRole_TaskID );
          }
        }
        else if ( (oldAdvEnabled == FALSE) && (gapRole_AdvEnabled) )
        {
          // Turn on Advertising
          if ( (gapRole_state == GAPROLE_STARTED)
              || (gapRole_state == GAPROLE_WAITING)
              || (gapRole_state == GAPROLE_CONNECTED)
              || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT) )
          {
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_OFF_TIME:
      if ( len == sizeof ( uint16 ) )
      {
        gapRole_AdvertOffTime = *((uint16*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_DATA:
      if ( len <= B_MAX_ADV_LEN )
      {
        VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_AdvertData, pValue, len );
        gapRole_AdvertDataLen = len;
        
        // Update the advertising data
        ret = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SCAN_RSP_DATA:
      if ( len <= B_MAX_ADV_LEN )
      {
        VOID osal_memset( gapRole_ScanRspData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_ScanRspData, pValue, len );
        gapRole_ScanRspDataLen = len;
        
        // Update the Response Data
        ret = GAP_UpdateAdvertisingData( gapRole_TaskID,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData );
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_EVENT_TYPE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND) )
      {
        gapRole_AdvEventType = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_TYPE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= ADDRTYPE_PRIVATE_RESOLVE) )
      {
        gapRole_AdvDirectType = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_ADDR:
      if ( len == B_ADDR_LEN )
      {
        VOID osal_memcpy( gapRole_AdvDirectAddr, pValue, B_ADDR_LEN ) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_CHANNEL_MAP:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= 0x07) )
      {
        gapRole_AdvChanMap = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_FILTER_POLICY:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= GAP_FILTER_POLICY_WHITE) )
      {
        gapRole_AdvFilterPolicy = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_RSSI_READ_RATE:
      if ( len == sizeof ( uint16 ) )
      {
        gapRole_RSSIReadRate = *((uint16*)pValue);

        if ( (gapRole_RSSIReadRate) && (gapRole_state == GAPROLE_CONNECTED) )
        {
          // Start the RSSI Reads
          VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_PARAM_UPDATE_ENABLE:
      if ( (len == sizeof ( uint8 )) && (*((uint8*)pValue) <= TRUE) )
      {
        gapRole_ParamUpdateEnable = *((uint8*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_MIN_CONN_INTERVAL:
      {
        uint16 newInterval = *((uint16*)pValue);
        if (   len == sizeof ( uint16 )           &&
             ( newInterval >= MIN_CONN_INTERVAL ) &&
             ( newInterval <= MAX_CONN_INTERVAL ) )
        {
          gapRole_MinConnInterval = newInterval;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    case GAPROLE_MAX_CONN_INTERVAL:
      {
        uint16 newInterval = *((uint16*)pValue);
        if (   len == sizeof ( uint16 )          &&
             ( newInterval >= MIN_CONN_INTERVAL) &&
             ( newInterval <= MAX_CONN_INTERVAL) )
        {
          gapRole_MaxConnInterval = newInterval;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    case GAPROLE_SLAVE_LATENCY:
      {
        uint16 latency = *((uint16*)pValue);
        if ( len == sizeof ( uint16 ) && (latency < MAX_SLAVE_LATENCY) )
        {
          gapRole_SlaveLatency = latency;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

    case GAPROLE_TIMEOUT_MULTIPLIER:
      {
        uint16 newTimeout = *((uint16*)pValue);
        if ( len == sizeof ( uint16 )
            && (newTimeout >= MIN_TIMEOUT_MULTIPLIER) && (newTimeout <= MAX_TIMEOUT_MULTIPLIER) )
        {
          gapRole_TimeoutMultiplier = newTimeout;
        }
        else
        {
          ret = bleInvalidRange;
        }
      }
      break;

      case GAPROLE_PARAM_UPDATE_REQ:
        {
          uint8 req = *((uint8*)pValue);
          if ( len == sizeof ( uint8 ) && (req == TRUE) )
          {
            // 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 ( osal_get_timeoutEx( gapRole_TaskID, CONN_PARAM_TIMEOUT_EVT ) == 0 )
            {             
              // Start connection update procedure
              gapRole_startConnUpdate( GAPROLE_NO_ACTION );
              
              // Connection update requested by app, cancel such pending procedure (if active)
              VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT );
            }
            else
            {
              ret = blePending;
            }
          }
          else
          {
            ret = bleInvalidRange;
          }
        }
        break;
  
    default:
      // The param value isn't part of this profile, try the GAP.
      if ( (param < TGAP_PARAMID_MAX) && (len == sizeof ( uint16 )) )
      {
        ret = GAP_SetParamValue( param, *((uint16*)pValue) );
      }
      else
      {
        ret = INVALIDPARAMETER;
      }
      break;
  }

  return ( ret );
}
예제 #6
0
/*********************************************************************
 * @brief   Set a GAP Role parameter.
 *
 * Public function defined in peripheral.h.
 */
bStatus_t GAPRole_SetParameter(uint16_t param, uint8_t len, void *pValue, uint8 connHandle)
{
  bStatus_t ret = SUCCESS;
  switch (param)
  {
    case GAPROLE_IRK:
      if (len == KEYLEN)
      {
        VOID memcpy(gapRole_IRK, pValue, KEYLEN) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SRK:
      if (len == KEYLEN)
      {
        VOID memcpy(gapRole_SRK, pValue, KEYLEN) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SIGNCOUNTER:
      if (len == sizeof (uint32_t))
      {
        gapRole_signCounter = *((uint32_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_ENABLED:  //connectable advertising
      if (len == sizeof(uint8_t))
      {
        // Non-connectable advertising must be disabled.
        if (gapRole_AdvNonConnEnabled != TRUE)
        {
          uint8_t oldAdvEnabled = gapRole_AdvEnabled;
          gapRole_AdvEnabled = *((uint8_t*)pValue);

          if ((oldAdvEnabled) && (gapRole_AdvEnabled == FALSE))
          {
            return GAP_EndDiscoverable(selfEntity);
          }
          else if ((oldAdvEnabled == FALSE) && (gapRole_AdvEnabled))
          {
            // Turn on advertising.
            if (linkDB_NumActive() >= MAX_NUM_BLE_CONNS) //don't do conn adv if we don't have any avilable links
            {
              return bleNoResources; // no more available links
            }
            else
            {
              gapRole_setEvent(START_ADVERTISING_EVT);
            }
          }
        }
        else
        {
          ret = bleIncorrectMode;
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;
      
    case GAPROLE_ADV_NONCONN_ENABLED:
      if (len == sizeof(uint8_t))
      {
        // Connectable advertising must be disabled.
        if (gapRole_AdvEnabled != TRUE)
        {
          uint8_t oldAdvEnabled = gapRole_AdvNonConnEnabled;
          gapRole_AdvNonConnEnabled = *((uint8_t*)pValue);
          
          if ((oldAdvEnabled) && (gapRole_AdvNonConnEnabled == FALSE))
          {
            VOID GAP_EndDiscoverable(selfEntity);
          }
          else if ((oldAdvEnabled == FALSE) && (gapRole_AdvNonConnEnabled))
          {  //turnon advertising
            gapRole_setEvent(START_ADVERTISING_EVT);
          }
        }
        else
        {
          ret = bleIncorrectMode;
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_OFF_TIME:
      if (len == sizeof (uint16_t))
      {
        gapRole_AdvertOffTime = *((uint16_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADVERT_DATA:
      if (len <= B_MAX_ADV_LEN)
      {
        VOID memset(gapRole_AdvertData, 0, B_MAX_ADV_LEN);
        VOID memcpy(gapRole_AdvertData, pValue, len);
        gapRole_AdvertDataLen = len;
        
        // Update the advertising data
        ret = GAP_UpdateAdvertisingData(selfEntity,
                              TRUE, gapRole_AdvertDataLen, gapRole_AdvertData);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_SCAN_RSP_DATA:
      if (len <= B_MAX_ADV_LEN)
      {
        VOID memset(gapRole_ScanRspData, 0, B_MAX_ADV_LEN);
        VOID memcpy(gapRole_ScanRspData, pValue, len);
        gapRole_ScanRspDataLen = len;
        
        // Update the Response Data
        ret = GAP_UpdateAdvertisingData(selfEntity,
                              FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_EVENT_TYPE:
      if ((len == sizeof (uint8_t)) && (*((uint8_t*)pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND))
      {
        gapRole_AdvEventType = *((uint8_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_TYPE:
      if ((len == sizeof (uint8_t)) && (*((uint8_t*)pValue) <= ADDRMODE_PRIVATE_RESOLVE)) 
      {
        gapRole_AdvDirectType = *((uint8_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_DIRECT_ADDR:
      if (len == B_ADDR_LEN)
      {
        VOID memcpy(gapRole_AdvDirectAddr, pValue, B_ADDR_LEN) ;
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_CHANNEL_MAP:
      if ((len == sizeof (uint8_t)) && (*((uint8_t*)pValue) <= 0x07))
      {
        gapRole_AdvChanMap = *((uint8_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case GAPROLE_ADV_FILTER_POLICY:
      if ((len == sizeof (uint8_t)) && (*((uint8_t*)pValue) <= GAP_FILTER_POLICY_WHITE))
      {
        gapRole_AdvFilterPolicy = *((uint8_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;
    
  case GAPROLE_MAX_SCAN_RES:
      if (len == sizeof (uint8_t))
      {
        gapRoleMaxScanRes = *((uint8_t*)pValue);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;        
  
    default:
      // The param value isn't part of this profile, try the GAP.
      if ((param < TGAP_PARAMID_MAX) && (len == sizeof (uint16_t)))
      {
        ret = GAP_SetParamValue(param, *((uint16_t*)pValue));
      }
      else
      {
        ret = INVALIDPARAMETER;
      }
      break;
  }

  return (ret);
}
/*********************************************************************
 * @brief   Set a GAP Role parameter.
 *
 * Public function defined in peripheral.h.
 */
bStatus_t GAPRole_SetParameter(uint16_t param, uint8_t len, void *pValue, uint8 connHandle) {
	bStatus_t ret = SUCCESS;
	switch (param) {
	case GAPROLE_IRK:
		if (len == KEYLEN) {
			VOID memcpy(gapRole_IRK, pValue, KEYLEN);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_SRK:
		if (len == KEYLEN) {
			VOID memcpy(gapRole_SRK, pValue, KEYLEN);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_SIGNCOUNTER:
		if (len == sizeof(uint32_t)) {
			gapRole_signCounter = *((uint32_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADVERT_ENABLED:  //connectable advertising
		if (len == sizeof(uint8_t)) {
			// Non-connectable advertising must be disabled.
			if (gapRole_AdvNonConnEnabled != TRUE) {
				uint8_t oldAdvEnabled = gapRole_AdvEnabled;
				gapRole_AdvEnabled = *((uint8_t*) pValue);

				if ((oldAdvEnabled) && (gapRole_AdvEnabled == FALSE)) {
					// Turn off advertising.
					//if ((gapRole_peripheralState == GAPROLE_ADVERTISING) || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) {
						VOID GAP_EndDiscoverable(selfEntity);
					//}
				} else if ((oldAdvEnabled == FALSE) && (gapRole_AdvEnabled)) {
					// Turn on advertising.
					if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS)) //don't do conn adv if we don't have any avilable links
							{
						// Turn on advertising.
						//if ((gapRole_peripheralState == GAPROLE_STARTED) || (gapRole_peripheralState == GAPROLE_WAITING) || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) {
							gapRole_setEvent(START_ADVERTISING_EVT);
						//}
						//gapRole_setEvent(START_ADVERTISING_EVT);
					} else {
						return bleNoResources; // no more available links
					}
				}
			} else {
				ret = bleIncorrectMode;
			}
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADV_NONCONN_ENABLED:
		if (len == sizeof(uint8_t)) {
			// Connectable advertising must be disabled.
			if (gapRole_AdvEnabled != TRUE) {
				uint8_t oldAdvEnabled = gapRole_AdvNonConnEnabled;
				gapRole_AdvNonConnEnabled = *((uint8_t*) pValue);

				if ((oldAdvEnabled) && (gapRole_AdvNonConnEnabled == FALSE)) {
					//if ((gapRole_peripheralState == GAPROLE_ADVERTISING_NONCONN) || (gapRole_peripheralState == GAPROLE_CONNECTED_ADV) || (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) {
						VOID GAP_EndDiscoverable(selfEntity);
					//}
				} else if ((oldAdvEnabled == FALSE) && (gapRole_AdvNonConnEnabled)) {
					// Turn on advertising.
					//if ((gapRole_peripheralState == GAPROLE_STARTED) || (gapRole_peripheralState == GAPROLE_WAITING) || (gapRole_peripheralState == GAPROLE_CONNECTED)
					//		|| (gapRole_peripheralState == GAPROLE_WAITING_AFTER_TIMEOUT)) {
						gapRole_setEvent(START_ADVERTISING_EVT);
					//}
				}
			} else {
				ret = bleIncorrectMode;
			}
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADVERT_OFF_TIME:
		if (len == sizeof(uint16_t)) {
			gapRole_AdvertOffTime = *((uint16_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADVERT_DATA:
		if (len <= B_MAX_ADV_LEN) {
			VOID memset(gapRole_AdvertData, 0, B_MAX_ADV_LEN);
			VOID memcpy(gapRole_AdvertData, pValue, len);
			gapRole_AdvertDataLen = len;

			// Update the advertising data
			ret = GAP_UpdateAdvertisingData(selfEntity,
			TRUE, gapRole_AdvertDataLen, gapRole_AdvertData);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_SCAN_RSP_DATA:
		if (len <= B_MAX_ADV_LEN) {
			VOID memset(gapRole_ScanRspData, 0, B_MAX_ADV_LEN);
			VOID memcpy(gapRole_ScanRspData, pValue, len);
			gapRole_ScanRspDataLen = len;

			// Update the Response Data
			ret = GAP_UpdateAdvertisingData(selfEntity,
			FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADV_EVENT_TYPE:
		if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= GAP_ADTYPE_ADV_LDC_DIRECT_IND)) {
			gapRole_AdvEventType = *((uint8_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADV_DIRECT_TYPE:

		if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= ADDRMODE_PRIVATE_RESOLVE)) {
			gapRole_AdvDirectType = *((uint8_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADV_DIRECT_ADDR:
		if (len == B_ADDR_LEN) {
			VOID memcpy(gapRole_AdvDirectAddr, pValue, B_ADDR_LEN);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADV_CHANNEL_MAP:
		if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= 0x07)) {
			gapRole_AdvChanMap = *((uint8_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_ADV_FILTER_POLICY:
		if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= GAP_FILTER_POLICY_WHITE)) {
			gapRole_AdvFilterPolicy = *((uint8_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_PARAM_UPDATE_ENABLE:
		if ((len == sizeof(uint8_t)) && (*((uint8_t*) pValue) <= TRUE)) {
			gapRole_ParamUpdateEnable = *((uint8_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	case GAPROLE_MIN_CONN_INTERVAL: {
		uint16_t newInterval = *((uint16_t*) pValue);
		if (len == sizeof(uint16_t) && (newInterval >= MIN_CONN_INTERVAL) && (newInterval <= MAX_CONN_INTERVAL)) {
			gapRole_MinConnInterval = newInterval;
		} else {
			ret = bleInvalidRange;
		}
	}
		break;

	case GAPROLE_MAX_CONN_INTERVAL: {
		uint16_t newInterval = *((uint16_t*) pValue);
		if (len == sizeof(uint16_t) && (newInterval >= MIN_CONN_INTERVAL) && (newInterval <= MAX_CONN_INTERVAL)) {
			gapRole_MaxConnInterval = newInterval;
		} else {
			ret = bleInvalidRange;
		}
	}
		break;

	case GAPROLE_SLAVE_LATENCY: {
		uint16_t latency = *((uint16_t*) pValue);
		if (len == sizeof(uint16_t) && (latency < MAX_SLAVE_LATENCY)) {
			gapRole_SlaveLatency = latency;
		} else {
			ret = bleInvalidRange;
		}
	}
		break;

	case GAPROLE_TIMEOUT_MULTIPLIER: {
		uint16_t newTimeout = *((uint16_t*) pValue);
		if (len == sizeof(uint16_t) && (newTimeout >= MIN_TIMEOUT_MULTIPLIER) && (newTimeout <= MAX_TIMEOUT_MULTIPLIER)) {
			gapRole_TimeoutMultiplier = newTimeout;
		} else {
			ret = bleInvalidRange;
		}
	}
		break;

	case GAPROLE_PARAM_UPDATE_REQ: {
		uint8_t req = *((uint8_t*) pValue);
		if (len == sizeof(uint8_t) && (req == TRUE)) {
			// 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) {
				// Start connection update procedure
				uint8 index = 0;

				while (index < MAX_NUM_BLE_CONNS && multiConnInfo[index].gapRole_ConnRole != GAP_PROFILE_PERIPHERAL
						&& multiConnInfo[index].gapRole_ConnectionHandle != GAPROLE_CONN_JUST_TERMINATED) {
					index++;
				}
				if (index >= MAX_NUM_BLE_CONNS) { //no connection as peripheral found
					ret = INVALIDPARAMETER;
					//Util_stopClock(&startUpdateClock);
				} else {
					ret = gapRole_startConnUpdate(GAPROLE_NO_ACTION, multiConnInfo[index].gapRole_ConnectionHandle);
				}
				if (ret == SUCCESS) {
					// Connection update requested by app, cancel such pending procedure (if active)
					Util_stopClock(&startUpdateClock);
				}
			} else {
				ret = blePending;
			}
		} else {
			ret = bleInvalidRange;
		}
	}
		break;

	case GAPROLE_MAX_SCAN_RES:
		if (len == sizeof(uint8_t)) {
			gapRoleMaxScanRes = *((uint8_t*) pValue);
		} else {
			ret = bleInvalidRange;
		}
		break;

	default:
		// The param value isn't part of this profile, try the GAP.
		if ((param < TGAP_PARAMID_MAX) && (len == sizeof(uint16_t))) {
			ret = GAP_SetParamValue(param, *((uint16_t*) pValue));
		} else {
			ret = INVALIDPARAMETER;
		}
		break;
	}

	return (ret);
}