Example #1
0
/********************************************************************
 * @fn          GAPRole_SendUpdateParam
 *
 * @brief       Update the parameters of an existing connection
 *
 * @param       minConnInterval - the new min connection interval
 * @param       maxConnInterval - the new max connection interval
 * @param       latency - the new slave latency
 * @param       connTimeout - the new timeout value
 * @param       handleFailure - what to do if the update does not occur.
 *              Method may choose to terminate connection, try again, or take no action
 *
 * @return      SUCCESS, bleNotConnected, or bleInvalidRange
 */
bStatus_t GAPRole_SendUpdateParam( uint16 minConnInterval, uint16 maxConnInterval,
                                   uint16 latency, uint16 connTimeout, uint8 handleFailure )
{    
  // If there is no existing connection no update need be sent
  if ( gapRole_state != GAPROLE_CONNECTED )
  {
    return ( bleNotConnected );
  }
  
  // Check that all parameters are in range before sending request
  if ( ( minConnInterval >= DEFAULT_MIN_CONN_INTERVAL ) &&
       ( minConnInterval < DEFAULT_MAX_CONN_INTERVAL  ) &&
       ( maxConnInterval >= DEFAULT_MIN_CONN_INTERVAL ) &&
       ( maxConnInterval < DEFAULT_MAX_CONN_INTERVAL  ) &&
       ( latency         < MAX_SLAVE_LATENCY          ) &&
       ( connTimeout     >= MIN_TIMEOUT_MULTIPLIER    ) &&
       ( connTimeout     < MAX_TIMEOUT_MULTIPLIER     ) )
  {
    gapRole_MinConnInterval = minConnInterval;
    gapRole_MaxConnInterval = maxConnInterval;
    gapRole_SlaveLatency = latency;
    gapRole_TimeoutMultiplier = connTimeout;

    // Start connection update procedure
    gapRole_startConnUpdate( handleFailure );

    // Connection update requested by app, cancel such pending procedure (if active)
    VOID osal_stop_timerEx( gapRole_TaskID, START_CONN_UPDATE_EVT );
              
    return ( SUCCESS );
  }

  return ( bleInvalidRange );
}
/********************************************************************
 * @fn          GAPRole_SendUpdateParam
 *
 * @brief       Update the parameters of an existing connection
 *
 * @param       minConnInterval - the new min connection interval
 * @param       maxConnInterval - the new max connection interval
 * @param       latency - the new slave latency
 * @param       connTimeout - the new timeout value
 * @param       handleFailure - what to do if the update does not occur.
 *              Method may choose to terminate connection, try again,
 *              or take no action
 *
 * @return      SUCCESS, bleNotConnected, or bleInvalidRange
 */
bStatus_t GAPRole_SendUpdateParam(uint16_t minConnInterval, uint16_t maxConnInterval, uint16_t latency, uint16_t connTimeout, uint8_t handleFailure, uint16_t connHandle) {

	uint8 connHandleIndex = gapRoleInfo_Find(connHandle);

	// 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);
	}

	if (multiConnInfo[connHandleIndex].gapRole_ConnRole != GAP_PROFILE_PERIPHERAL) {
		return (bleNotConnected);
	}

	  // If there is no existing connection no update need be sent
	if (gapRole_peripheralState != GAPROLE_CONNECTED) {
		return (bleNotConnected);
	}

	// Check that all parameters are in range before sending request
	if ((minConnInterval >= DEFAULT_MIN_CONN_INTERVAL) && (minConnInterval < DEFAULT_MAX_CONN_INTERVAL) && (maxConnInterval >= DEFAULT_MIN_CONN_INTERVAL)
			&& (maxConnInterval < DEFAULT_MAX_CONN_INTERVAL) && (latency < MAX_SLAVE_LATENCY) && (connTimeout >= MIN_TIMEOUT_MULTIPLIER)
			&& (connTimeout < MAX_TIMEOUT_MULTIPLIER)) {
		gapRole_MinConnInterval = minConnInterval;
		gapRole_MaxConnInterval = maxConnInterval;
		gapRole_SlaveLatency = latency;
		gapRole_TimeoutMultiplier = connTimeout;

		// Start connection update procedure
		VOID gapRole_startConnUpdate(handleFailure, multiConnInfo[connHandleIndex].gapRole_ConnectionHandle);

		// Connection update requested by app, cancel such pending procedure (if active)
		Util_stopClock(&startUpdateClock);

		return (SUCCESS);
	}

	return (bleInvalidRange);
}
Example #3
0
/*********************************************************************
 * @brief   Task Event Processor function.
 *
 * Internal function defined in peripheral.h.
 */
uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events )
{
  VOID task_id; // OSAL required parameter that isn't used in this function

  if ( events & SYS_EVENT_MSG )
  {
    uint8 *pMsg;

    if ( (pMsg = osal_msg_receive( gapRole_TaskID )) != NULL )
    {
      gapRole_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );

      // Release the OSAL message
      VOID osal_msg_deallocate( pMsg );
    }

    // return unprocessed events
    return (events ^ SYS_EVENT_MSG);
  }

  if ( events & GAP_EVENT_SIGN_COUNTER_CHANGED )
  {
    // Sign counter changed, save it to NV
    VOID osal_snv_write( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter );

    return ( events ^ GAP_EVENT_SIGN_COUNTER_CHANGED );
  }

  if ( events & START_ADVERTISING_EVT )
  {
    if ( gapRole_AdvEnabled )
    {
      gapAdvertisingParams_t params;

      // Setup advertisement parameters
      params.eventType = gapRole_AdvEventType;
      params.initiatorAddrType = gapRole_AdvDirectType;
      VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN );
      params.channelMap = gapRole_AdvChanMap;
      params.filterPolicy = gapRole_AdvFilterPolicy;

      if ( GAP_MakeDiscoverable( gapRole_TaskID, &params ) != SUCCESS )
      {
        gapRole_state = GAPROLE_ERROR;
        
        // Notify the application with the new state change
        if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
        {
          pGapRoles_AppCGs->pfnStateChange( gapRole_state );
        }
      }
    }
    return ( events ^ START_ADVERTISING_EVT );
  }

  if ( events & RSSI_READ_EVT )
  {
    // Only get RSSI when in a connection
    if ( gapRole_state == GAPROLE_CONNECTED )
    {
      // Ask for RSSI
      VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle );

      // Setup next event
      if ( gapRole_RSSIReadRate )
      {
        VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
      }
    }
    return ( events ^ RSSI_READ_EVT );
  }

  if ( events & START_CONN_UPDATE_EVT )
  {
    // Start connection update procedure
    gapRole_startConnUpdate( GAPROLE_NO_ACTION );

    return ( events ^ START_CONN_UPDATE_EVT );
  }
  
  if ( events & CONN_PARAM_TIMEOUT_EVT )
  {
    // Unsuccessful in updating connection parameters
    gapRole_HandleParamUpdateNoSuccess();

    return ( events ^ CONN_PARAM_TIMEOUT_EVT );
  }
  
  // Discard unknown events
  return 0;
}
Example #4
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 )
          {
            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_NONCONN_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 );
}
Example #5
0
/*********************************************************************
 * @fn      gapRole_taskFxn
 *
 * @brief   Task entry point for the GAP Peripheral Role.
 *
 * @param   a0 - first argument
 * @param   a1 - second argument
 *
 * @return  none
 */
static void gapRole_taskFxn(UArg a0, UArg a1)
{
    // Initialize profile
    gapRole_init();

    // Profile main loop
    for (;;)
    {
        // Waits for a signal to the semaphore associated with the calling thread.
        // Note that the semaphore associated with a thread is signaled when a
        // message is queued to the message receive queue of the thread or when
        // ICall_signal() function is called onto the semaphore.
        ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);

        if (errno == ICALL_ERRNO_SUCCESS)
        {
            ICall_EntityID dest;
            ICall_ServiceEnum src;
            ICall_HciExtEvt *pMsg = NULL;

            if (ICall_fetchServiceMsg(&src, &dest,
                                      (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
            {
                if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
                {
                    ICall_Event *pEvt = (ICall_Event *)pMsg;

                    // Check for BLE stack events first
                    if (pEvt->signature == 0xffff)
                    {
                        if (pEvt->event_flag & GAP_EVENT_SIGN_COUNTER_CHANGED)
                        {
                            // Sign counter changed, save it to NV
                            VOID osal_snv_write(BLE_NVID_SIGNCOUNTER, sizeof(uint32_t),
                                                &gapRole_signCounter);
                        }
                    }
                    else
                    {
                        // Process inter-task message
                        gapRole_processStackMsg((ICall_Hdr *)pMsg);
                    }
                }

                if (pMsg)
                {
                    ICall_freeMsg(pMsg);
                }
            }
        }

        if (events & START_ADVERTISING_EVT)
        {
            events &= ~START_ADVERTISING_EVT;

            if (gapRole_AdvEnabled || gapRole_AdvNonConnEnabled)
            {
                gapAdvertisingParams_t params;

                // Setup advertisement parameters
                if (gapRole_AdvNonConnEnabled)
                {
                    // Only advertise non-connectable undirected.
                    params.eventType = GAP_ADTYPE_ADV_NONCONN_IND;
                }
                else
                {
                    params.eventType = gapRole_AdvEventType;
                    params.initiatorAddrType = gapRole_AdvDirectType;
                    VOID memcpy(params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN);
                }

                params.channelMap = gapRole_AdvChanMap;
                params.filterPolicy = gapRole_AdvFilterPolicy;

                if (GAP_MakeDiscoverable(selfEntity, &params) != SUCCESS)
                {
                    gapRole_state = GAPROLE_ERROR;

                    // Notify the application with the new state change
                    if (pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange)
                    {
                        pGapRoles_AppCGs->pfnStateChange(gapRole_state);
                    }
                }
            }
        }

        if (events & START_CONN_UPDATE_EVT)
        {
            events &= ~START_CONN_UPDATE_EVT;

            // Start connection update procedure
            gapRole_startConnUpdate(GAPROLE_NO_ACTION);
        }

        if (events & CONN_PARAM_TIMEOUT_EVT)
        {
            events &= ~CONN_PARAM_TIMEOUT_EVT;

            // Unsuccessful in updating connection parameters
            gapRole_HandleParamUpdateNoSuccess();
        }
    } // for
}
Example #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)
{
    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:
        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_state == GAPROLE_ADVERTISING)
                            || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT))
                    {
                        VOID GAP_EndDiscoverable(selfEntity);
                    }
                }
                else if ((oldAdvEnabled == FALSE) && (gapRole_AdvEnabled))
                {
                    // Turn on advertising.
                    if ((gapRole_state == GAPROLE_STARTED)
                            || (gapRole_state == GAPROLE_WAITING)
                            || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT))
                    {
                        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))
                {
                    if ((gapRole_state == GAPROLE_ADVERTISING_NONCONN)
                            || (gapRole_state == GAPROLE_CONNECTED_ADV)
                            || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT))
                    {
                        VOID GAP_EndDiscoverable(selfEntity);
                    }
                }
                else if ((oldAdvEnabled == FALSE) && (gapRole_AdvNonConnEnabled))
                {
                    // Turn on advertising.
                    if ((gapRole_state == GAPROLE_STARTED)
                            || (gapRole_state == GAPROLE_WAITING)
                            || (gapRole_state == GAPROLE_CONNECTED)
                            || (gapRole_state == 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) <= ADDRTYPE_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
                ret = gapRole_startConnUpdate(GAPROLE_NO_ACTION);
                if (ret == SUCCESS)
                {
                    // Connection update requested by app, cancel such pending procedure (if active)
                    Util_stopClock(&startUpdateClock);
                }
            }
            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_t)))
        {
            ret = GAP_SetParamValue(param, *((uint16_t*)pValue));
        }
        else
        {
            ret = INVALIDPARAMETER;
        }
        break;
    }

    return (ret);
}
/*********************************************************************
 * @fn      gapRole_taskFxn
 *
 * @brief   Task entry point for the GAP Peripheral Role.
 *
 * @param   a0 - first argument
 * @param   a1 - second argument
 *
 * @return  none
 */
static void gapRole_taskFxn(UArg a0, UArg a1) {
	// Initialize profile
	gapRole_init();

	// Profile main loop
	for (;;) {
		// Waits for a signal to the semaphore associated with the calling thread.
		// Note that the semaphore associated with a thread is signaled when a
		// message is queued to the message receive queue of the thread or when
		// ICall_signal() function is called onto the semaphore.
		ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);

		if (errno == ICALL_ERRNO_SUCCESS) {
			ICall_EntityID dest;
			ICall_ServiceEnum src;
			ICall_HciExtEvt *pMsg = NULL;

			if (ICall_fetchServiceMsg(&src, &dest, (void **) &pMsg) == ICALL_ERRNO_SUCCESS) {
				uint8_t safeToDealloc = TRUE;

				if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity)) {
					ICall_Stack_Event *pEvt = (ICall_Stack_Event *) pMsg;

					// Check for BLE stack events first
					if (pEvt->signature == 0xffff) {
						if (pEvt->event_flag & GAP_EVENT_SIGN_COUNTER_CHANGED) {
							// Sign counter changed, save it to NV
							VOID osal_snv_write(BLE_NVID_SIGNCOUNTER, sizeof(uint32_t), &gapRole_signCounter);
						}
					} else {
						// Process inter-task message
						safeToDealloc = gapRole_processStackMsg((ICall_Hdr *) pMsg);
					}
				}

				if (pMsg && safeToDealloc) {
					ICall_freeMsg(pMsg);
				}
			}
		}

		if (events & START_ADVERTISING_EVT) {
			events &= ~START_ADVERTISING_EVT;

			if (gapRole_AdvEnabled || gapRole_AdvNonConnEnabled) {
				gapAdvertisingParams_t params;

				// Setup advertisement parameters
				if (gapRole_AdvNonConnEnabled) {
					// Only advertise non-connectable undirected.
					params.eventType = GAP_ADTYPE_ADV_NONCONN_IND;
				} else {
					params.eventType = gapRole_AdvEventType;
					params.initiatorAddrType = gapRole_AdvDirectType;
					VOID memcpy(params.initiatorAddr, gapRole_AdvDirectAddr,
					B_ADDR_LEN);
				}

				params.channelMap = gapRole_AdvChanMap;
				params.filterPolicy = gapRole_AdvFilterPolicy;

				if (GAP_MakeDiscoverable(selfEntity, &params) != SUCCESS) {
					gapRole_peripheralState = GAPROLE_ERROR;
					gapRole_peripheralStateChangeHandler(gapRole_peripheralState);
					//gapRole_abort();
				}
			}
		}
		if (events & START_CONN_UPDATE_EVT) {
			events &= ~START_CONN_UPDATE_EVT;

			// 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
				//INVALIDPARAMETER;
				//Util_stopClock(&startUpdateClock);
			} else {
				gapRole_startConnUpdate(GAPROLE_NO_ACTION, multiConnInfo[index].gapRole_ConnectionHandle);
			}
		}

		if (events & CONN_PARAM_TIMEOUT_EVT) {
			events &= ~CONN_PARAM_TIMEOUT_EVT;

			// Unsuccessful in updating connection parameters
			gapRole_HandleParamUpdateNoSuccess();
		}
	} // for
}