This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2640R2F: CC2640R2F

Part Number: CC2640R2F

i am using simple central and project zero as base , i have two launchpad . i am using custom 128bits UUID , after successful connection i am unable to gatt Read / write data . 

i have done appropriate changes in the both project for custom 128bits . i have attched simple gatt profile .c file , where i have made few changes . 

/******************************************************************************

 @file  simple_gatt_profile.c

 @brief This file contains the Simple GATT profile sample GATT service profile
        for use with the BLE sample application.

 Group: WCS, BTS
 Target Device: cc2640r2

 ******************************************************************************
 
 Copyright (c) 2010-2021, Texas Instruments Incorporated
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:

 *  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

 *  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

 *  Neither the name of Texas Instruments Incorporated nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 ******************************************************************************
 
 
 *****************************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include <string.h>
#include <icall.h>
#include "util.h"
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"

#include "simple_gatt_profile.h"

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

#define SERVAPP_NUM_ATTR_SUPPORTED        17

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */

//TODO : Change Macro
#define FMCU_CUSTOM

#ifdef FMCU_CUSTOM
*************************************************************/
// Simple GATT Profile Service UUID: 0xFFF0
CONST uint8 simpleProfileServUUID[ATT_UUID_SIZE] =
{
 SIMPLEPROFILE_SERV_UUID_BASE128(SIMPLEPROFILE_SERV_UUID)
};

#else /********** NORMAL **************/

// Simple GATT Profile Service UUID: 0xFFF0
CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};

#endif

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */

static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;

/*********************************************************************
 * Profile Attributes - variables
 */


// Simple Profile Service attribute
#ifdef FMCU_CUSTOM
   static CONST gattAttrType_t simpleProfileService = { ATT_UUID_SIZE, simpleProfileServUUID };
#else
   static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };
#endif

// Simple Profile Characteristic 1 Properties
static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE;

// Characteristic 1 Value
static uint8 simpleProfileChar1 = 0;

// Simple Profile Characteristic 1 User Description
static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1";



/*********************************************************************
 * Profile Attributes - Table
 */
#ifdef FMCU_CUSTOM
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
  // Simple Profile Service
  {
    { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
    GATT_PERMIT_READ,                         /* permissions */
    0,                                        /* handle */
    (uint8 *)&simpleProfileService            /* pValue */
  },

    // Characteristic 1 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar1Props
    },

      // Characteristic Value 1
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        &simpleProfileChar1
      },

      // Characteristic 1 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar1UserDesp
      },

};

#else /************Working *************/

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
  // Simple Profile Service
  {
    { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
    GATT_PERMIT_READ,                         /* permissions */
    0,                                        /* handle */
    (uint8 *)&simpleProfileService            /* pValue */
  },

    // Characteristic 1 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar1Props
    },

      // Characteristic Value 1
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        &simpleProfileChar1
      },

      // Characteristic 1 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar1UserDesp
      },


};
#endif



/*********************************************************************
 * LOCAL FUNCTIONS
 */
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                          gattAttribute_t *pAttr,
                                          uint8_t *pValue, uint16_t *pLen,
                                          uint16_t offset, uint16_t maxLen,
                                          uint8_t method);
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                           gattAttribute_t *pAttr,
                                           uint8_t *pValue, uint16_t len,
                                           uint16_t offset, uint8_t method);

/*********************************************************************
 * PROFILE CALLBACKS
 */

// Simple Profile Service Callbacks
// Note: When an operation on a characteristic requires authorization and
// pfnAuthorizeAttrCB is not defined for that characteristic's service, the
// Stack will report a status of ATT_ERR_UNLIKELY to the client.  When an
// operation on a characteristic requires authorization the Stack will call
// pfnAuthorizeAttrCB to check a client's authorization prior to calling
// pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be
// made within these functions.
CONST gattServiceCBs_t simpleProfileCBs =
{
  simpleProfile_ReadAttrCB,  // Read callback function pointer
  simpleProfile_WriteAttrCB, // Write callback function pointer
  NULL                       // Authorization callback function pointer
};

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      SimpleProfile_AddService
 *
 * @brief   Initializes the Simple Profile service by registering
 *          GATT attributes with the GATT server.
 *
 * @param   services - services to add. This is a bit map and can
 *                     contain more than one service.
 *
 * @return  Success or Failure
 */
bStatus_t SimpleProfile_AddService( uint32 services )
{
  uint8 status;

  // Allocate Client Characteristic Configuration table
  simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
                                                            linkDBNumConns );
  if ( simpleProfileChar4Config == NULL )
  {
    return ( bleMemAllocError );
  }

  // Initialize Client Characteristic Configuration attributes
  GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar4Config );

  if ( services & SIMPLEPROFILE_SERVICE )
  {
    // Register GATT attribute list and CBs with GATT Server App
    status = GATTServApp_RegisterService( simpleProfileAttrTbl,
                                          GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                          GATT_MAX_ENCRYPT_KEY_SIZE,
                                          &simpleProfileCBs );
  }
  else
  {
    status = SUCCESS;
  }

  return ( status );
}

/*********************************************************************
 * @fn      SimpleProfile_RegisterAppCBs
 *
 * @brief   Registers the application callback function. Only call
 *          this function once.
 *
 * @param   callbacks - pointer to application callbacks.
 *
 * @return  SUCCESS or bleAlreadyInRequestedMode
 */
bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks )
{
  if ( appCallbacks )
  {
    simpleProfile_AppCBs = appCallbacks;

    return ( SUCCESS );
  }
  else
  {
    return ( bleAlreadyInRequestedMode );
  }
}

/*********************************************************************
 * @fn      SimpleProfile_SetParameter
 *
 * @brief   Set a Simple Profile parameter.
 *
 * @param   param - Profile parameter ID
 * @param   len - length of data to write
 * @param   value - pointer to data to write.  This is dependent on
 *          the parameter ID and WILL be cast to the appropriate
 *          data type (example: data type of uint16 will be cast to
 *          uint16 pointer).
 *
 * @return  bStatus_t
 */
bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
{
  bStatus_t ret = SUCCESS;

      if ( len == sizeof ( uint8 ) )
      {
        simpleProfileChar1 = *((uint8*)value);
      }
      else
      {
        ret = bleInvalidRange;
      }


  return ( ret );
}

/*********************************************************************
 * @fn      SimpleProfile_GetParameter
 *
 * @brief   Get a Simple Profile parameter.
 *
 * @param   param - Profile parameter ID
 * @param   value - pointer to data to put.  This is dependent on
 *          the parameter ID and WILL be cast to the appropriate
 *          data type (example: data type of uint16 will be cast to
 *          uint16 pointer).
 *
 * @return  bStatus_t
 */
bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
{
  bStatus_t ret = SUCCESS;

      *((uint8*)value) = simpleProfileChar1;

      return ( ret );
}

/*********************************************************************
 * @fn          simpleProfile_ReadAttrCB
 *
 * @brief       Read an attribute.
 *
 * @param       connHandle - connection message was received on
 * @param       pAttr - pointer to attribute
 * @param       pValue - pointer to data to be read
 * @param       pLen - length of data to be read
 * @param       offset - offset of the first octet to be read
 * @param       maxLen - maximum length of data to be read
 * @param       method - type of read message
 *
 * @return      SUCCESS, blePending or Failure
 */
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                          gattAttribute_t *pAttr,
                                          uint8_t *pValue, uint16_t *pLen,
                                          uint16_t offset, uint16_t maxLen,
                                          uint8_t method)
{
  bStatus_t status = SUCCESS;

  // Make sure it's not a blob operation (no attributes in the profile are long)
  if ( offset > 0 )
  {
    return ( ATT_ERR_ATTR_NOT_LONG );
  }

  if (pAttr->type.len == ATT_BT_UUID_SIZE) //ATT_BT_UUID_SIZE
  {
    *pLen = 1;
     pValue[0] = *pAttr->pValue;
  }

  if (pAttr->type.len == ATT_UUID_SIZE) //ATT_BT_UUID_SIZE
  {
    *pLen = 1;
     pValue[0] = *pAttr->pValue;
  }
  else
  {
    // 128-bit UUID
    *pLen = 0;
    status = ATT_ERR_INVALID_HANDLE;
  }

  return ( status );
}

/*********************************************************************
 * @fn      simpleProfile_WriteAttrCB
 *
 * @brief   Validate attribute data prior to a write operation
 *
 * @param   connHandle - connection message was received on
 * @param   pAttr - pointer to attribute
 * @param   pValue - pointer to data to be written
 * @param   len - length of data
 * @param   offset - offset of the first octet to be written
 * @param   method - type of write message
 *
 * @return  SUCCESS, blePending or Failure
 */
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                           gattAttribute_t *pAttr,
                                           uint8_t *pValue, uint16_t len,
                                           uint16_t offset, uint8_t method)
{
  bStatus_t status = SUCCESS;
  uint8 notifyApp = 0xFF;

  if (pAttr->type.len == ATT_UUID_SIZE)//ATT_BT_UUID_SIZE
  {
    // 16-bit UUID
    //uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);

    // 128-bit UUID
      uint16 uuid = BUILD_UINT16( pAttr->type.uuid[12], pAttr->type.uuid[13]);
    if ( offset == 0 )
        {
          if ( len != 1 )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
            Display_print1(dispHandle, 4, 0, "ATT_ERR_INVALID_VALUE_SIZE % d ", status);
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
          Display_print1(dispHandle, 4, 0, "ATT_ERR_ATTR_NOT_LONG % d ", status);
        }

        //Write the value
        if ( status == SUCCESS )
        {
          uint8 *pCurValue = (uint8 *)pAttr->pValue;
          *pCurValue = pValue[0];

          if( pAttr->pValue == &simpleProfileChar1 )
          {
            notifyApp = SIMPLEPROFILE_CHAR1;
          }
          else
          {
            notifyApp = SIMPLEPROFILE_CHAR3;
          }
        }

  }
  else
  {
    // 16-bit UUID
    status = ATT_ERR_INVALID_HANDLE;
  }

  // If a characteristic value changed then callback function to notify application of change
  if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  {
    simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
  }

  return ( status );
}

/*********************************************************************
*********************************************************************/
 

In SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg) function pmsg-> method value is always coming 1 (ATT_ERROR_RSP).

/******************************************************************************

 @file  simple_central.c

 @brief This file contains the Simple Central sample application for use
        with the CC2650 Bluetooth Low Energy Protocol Stack.

 Group: WCS, BTS
 Target Device: cc2640r2

 ******************************************************************************
 
 Copyright (c) 2013-2021, Texas Instruments Incorporated
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:

 *  Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

 *  Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.

 *  Neither the name of Texas Instruments Incorporated nor the names of
    its contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 ******************************************************************************
 
 
 *****************************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include <string.h>

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>

#include <ti/display/Display.h>

#include "bcomdef.h"

#include <icall.h>
#include "util.h"
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"

#include "board_key.h"
#include "board.h"

#include "ble_user_config.h"

#include "simple_gatt_profile.h"


#include <menu/two_btn_menu.h>
#include "simple_central.h"
#include "simple_central_menu.h"


//Mauf data
static const uint8_t ManufData[6] = {0x0D,0x00,0xC0,0xFF,0xEE};

/*********************************************************************
 * MACROS
 */

CONST uint8 simpleProfileServUUID[ATT_UUID_SIZE] =
{
 SIMPLEPROFILE_SERV_UUID_BASE128(SIMPLEPROFILE_SERV_UUID)
 //LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
/*********************************************************************
 * CONSTANTS
 */

// Application events
#define SC_EVT_KEY_CHANGE          0x01
#define SC_EVT_SCAN_ENABLED        0x02
#define SC_EVT_SCAN_DISABLED       0x03
#define SC_EVT_ADV_REPORT          0x04
#define SC_EVT_SVC_DISC            0x05
#define SC_EVT_READ_RSSI           0x06
#define SC_EVT_PAIR_STATE          0x07
#define SC_EVT_PASSCODE_NEEDED     0x08
#define SC_EVT_READ_RPA            0x09
#define SC_EVT_INSUFFICIENT_MEM    0x0A

// Simple Central Task Events
#define SC_ICALL_EVT                         ICALL_MSG_EVENT_ID  // Event_Id_31
#define SC_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30

#define SC_ALL_EVENTS                        (SC_ICALL_EVT           | \
                                              SC_QUEUE_EVT)

// Address mode of the local device
// Note: When using the DEFAULT_ADDRESS_MODE as ADDRMODE_RANDOM or 
// ADDRMODE_RP_WITH_RANDOM_ID, GAP_DeviceInit() should be called with 
// it's last parameter set to a static random address
#define DEFAULT_ADDRESS_MODE                 ADDRMODE_RP_WITH_PUBLIC_ID

// Default PHY for scanning and initiating
#define DEFAULT_SCAN_PHY                     SCAN_PRIM_PHY_1M
#define DEFAULT_INIT_PHY                     INIT_PHY_1M

// Default scan duration in 10 ms
#define DEFAULT_SCAN_DURATION                100 // 1 sec

// Default RSSI polling period in ms
#define DEFAULT_RSSI_PERIOD                  3000

// TRUE to filter discovery results on desired service UUID
#define DEFAULT_DEV_DISC_BY_SVC_UUID         TRUE

// Minimum connection interval (units of 1.25ms) if automatic parameter update
// request is enabled
#define DEFAULT_UPDATE_MIN_CONN_INTERVAL      400

// Maximum connection interval (units of 1.25ms) if automatic parameter update
// request is enabled
#define DEFAULT_UPDATE_MAX_CONN_INTERVAL      800

// Slave latency to use if automatic parameter update request is enabled
#define DEFAULT_UPDATE_SLAVE_LATENCY          0

// Supervision timeout value (units of 10ms) if automatic parameter update
// request is enabled
#define DEFAULT_UPDATE_CONN_TIMEOUT           600

// Supervision timeout conversion rate to miliseconds
#define CONN_TIMEOUT_MS_CONVERSION            10

// How often to read current current RPA (in ms)
#define SC_READ_RPA_PERIOD                    3000

// Task configuration
#define SC_TASK_PRIORITY                     1

#ifndef SC_TASK_STACK_SIZE
#define SC_TASK_STACK_SIZE                   1024
#endif

// Advertising report fields to keep in the list
// Interested in only peer address type and peer address
#define SC_ADV_RPT_FIELDS   (SCAN_ADVRPT_FLD_ADDRTYPE | SCAN_ADVRPT_FLD_ADDRESS)

// Size of string-converted device address ("0xXXXXXXXXXXXX")
#define SC_ADDR_STR_SIZE     15

// Row numbers for two-button menu
#define SC_ROW_SEPARATOR     (TBM_ROW_APP + 0)
#define SC_ROW_CUR_CONN      (TBM_ROW_APP + 1)
#define SC_ROW_ANY_CONN      (TBM_ROW_APP + 2)
#define SC_ROW_NON_CONN      (TBM_ROW_APP + 3)
#define SC_ROW_NUM_CONN      (TBM_ROW_APP + 4)
#define SC_ROW_IDA           (TBM_ROW_APP + 5)
#define SC_ROW_RPA           (TBM_ROW_APP + 6)

// Spin if the expression is not true
#define SIMPLECENTRAL_ASSERT(expr) if (!(expr)) SimpleCentral_spin();

/*********************************************************************
 * TYPEDEFS
 */

// Discovery states
enum
{
  BLE_DISC_STATE_IDLE,                // Idle
  BLE_DISC_STATE_MTU,                 // Exchange ATT MTU size
  BLE_DISC_STATE_SVC,                 // Service discovery
  BLE_DISC_STATE_CHAR                 // Characteristic discovery
};

// App event passed from profiles.
typedef struct
{
  appEvtHdr_t hdr; // event header
  uint8_t *pData;  // event data
} scEvt_t;

// Scanned device information record
typedef struct
{
  uint8_t addrType;         // Peer Device's Address Type
  uint8_t addr[B_ADDR_LEN]; // Peer Device Address
} scanRec_t;

// Connected device information
typedef struct
{
  uint16_t connHandle;        // Connection Handle
  uint8_t  addr[B_ADDR_LEN];  // Peer Device Address
  uint8_t  charHandle;        // Characteristic Handle
  Clock_Struct *pRssiClock;   // pointer to clock struct
} connRec_t;

// Container to store paring state info when passing from gapbondmgr callback
// to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
  uint16_t connHandle;
  uint8_t  status;
} scPairStateData_t;

// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
  uint8_t deviceAddr[B_ADDR_LEN];
  uint16_t connHandle;
  uint8_t uiInputs;
  uint8_t uiOutputs;
  uint32_t numComparison;
} scPasscodeData_t;
/*********************************************************************
 * GLOBAL VARIABLES
 */

// Display Interface
Display_Handle dispHandle = NULL;

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * LOCAL VARIABLES
 */

// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;

// Event globally used to post local events and pend on system and
// local events.
static ICall_SyncHandle syncEvent;

// Queue object used for app messages
static Queue_Struct appMsg;
static Queue_Handle appMsgQueue;

// Task configuration
Task_Struct scTask;
#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(scTaskStack, 8)
#else
#pragma data_alignment=8
#endif
uint8_t scTaskStack[SC_TASK_STACK_SIZE];

// GAP GATT Attributes
static const uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Central";

#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
// Number of scan results filtered by Service UUID
static uint8_t numScanRes = 0;

// Scan results filtered by Service UUID
static scanRec_t scanList[DEFAULT_MAX_SCAN_RES];
#endif // DEFAULT_DEV_DISC_BY_SVC_UUID

// Number of connected devices
static uint8_t numConn = 0;

// List of connections
static connRec_t connList[MAX_NUM_BLE_CONNS];

// Connection handle of current connection
static uint16_t scConnHandle = CONNHANDLE_INVALID;

// Accept or reject L2CAP connection parameter update request
static bool acceptParamUpdateReq = true;

// Discovery state
static uint8_t discState = BLE_DISC_STATE_IDLE;

// Discovered service start and end handle
static uint16_t svcStartHdl = 0;
static uint16_t svcEndHdl = 0;

// Value to write
static uint8_t charVal = 0;

// Maximum PDU size (default = 27 octets)
static uint16_t scMaxPduSize;

// Clock instance for RPA read events.
static Clock_Struct clkRpaRead;

// Address mode
static GAP_Addr_Modes_t addrMode = DEFAULT_ADDRESS_MODE;

#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & PRIVACY_1_2_CFG)
// Current Random Private Address
static uint8 rpa[B_ADDR_LEN] = {0};
#endif // PRIVACY_1_2_CFG

/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void SimpleCentral_init(void);
static void SimpleCentral_taskFxn(uintptr_t a0, uintptr_t a1);

static void SimpleCentral_handleKeys(uint8_t keys);
static uint8_t SimpleCentral_processStackMsg(ICall_Hdr *pMsg);
static void SimpleCentral_processGapMsg(gapEventHdr_t *pMsg);
static void SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg);
static void SimpleCentral_processAppMsg(scEvt_t *pMsg);
static void SimpleCentral_processGATTDiscEvent(gattMsgEvent_t *pMsg);
static void SimpleCentral_startSvcDiscovery(void);
#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)

static bool SimpleCentral_findUuid(const uint8_t *uuid, const uint8_t *pManufData ,uint8_t manDataLen ,uint8_t *pData,
                                           uint8_t dataLen);

/*
static bool SimpleCentral_findSvcUuid(uint16_t uuid, uint8_t *pData,
                                      uint16_t dataLen);
*/
static void SimpleCentral_addScanInfo(uint8_t *pAddr, uint8_t addrType);


#endif // DEFAULT_DEV_DISC_BY_SVC_UUID
static uint8_t SimpleCentral_addConnInfo(uint16_t connHandle, uint8_t *pAddr);
static uint8_t SimpleCentral_removeConnInfo(uint16_t connHandle);
static uint8_t SimpleCentral_getConnIndex(uint16_t connHandle);
#ifndef Display_DISABLE_ALL
static char* SimpleCentral_getConnAddrStr(uint16_t connHandle);
#endif
static void SimpleCentral_processPairState(uint8_t state,
                                           scPairStateData_t* pPairStateData);
static void SimpleCentral_processPasscode(scPasscodeData_t *pData);

static void SimpleCentral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
static status_t SimpleCentral_StartRssi();
static status_t SimpleCentral_CancelRssi(uint16_t connHandle);

static void SimpleCentral_passcodeCb(uint8_t *deviceAddr, uint16_t connHandle,
                                     uint8_t uiInputs, uint8_t uiOutputs,
                                     uint32_t numComparison);
static void SimpleCentral_pairStateCb(uint16_t connHandle, uint8_t state,
                                      uint8_t status);

static void SimpleCentral_keyChangeHandler(uint8 keys);
static void SimpleCentral_clockHandler(UArg arg);

static status_t SimpleCentral_enqueueMsg(uint8_t event, uint8_t status,
                                         uint8_t *pData);

static void SimpleCentral_scanCb(uint32_t evt, void* msg, uintptr_t arg);
static void SimpleCentral_menuSwitchCb(tbmMenuObj_t* pMenuObjCurr,
                                       tbmMenuObj_t* pMenuObjNext);

/*********************************************************************
 * EXTERN FUNCTIONS
 */
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);

/*********************************************************************
 * PROFILE CALLBACKS
 */

// Bond Manager Callbacks
static gapBondCBs_t bondMgrCBs =
{
  SimpleCentral_passcodeCb, // Passcode callback
  SimpleCentral_pairStateCb // Pairing/Bonding state Callback
};

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      SimpleCentral_spin
 *
 * @brief   Spin forever
 *
 * @param   none
 */
static void SimpleCentral_spin(void)
{
  volatile uint8_t x;

  while(1)
  {
    x++;
  }
}

/*********************************************************************
 * @fn      SimpleCentral_createTask
 *
 * @brief   Task creation function for the Simple Central.
 *
 * @param   none
 *
 * @return  none
 */
void SimpleCentral_createTask(void)
{
  Task_Params taskParams;

  // Configure task
  Task_Params_init(&taskParams);
  taskParams.stack = scTaskStack;
  taskParams.stackSize = SC_TASK_STACK_SIZE;
  taskParams.priority = SC_TASK_PRIORITY;

  Task_construct(&scTask, SimpleCentral_taskFxn, &taskParams, NULL);
}

/*********************************************************************
 * @fn      SimpleCentral_Init
 *
 * @brief   Initialization function for the Simple Central App Task.
 *          This is called during initialization and should contain
 *          any application specific initialization (ie. hardware
 *          initialization/setup, table initialization, power up
 *          notification).
 *
 * @param   none
 *
 * @return  none
 */
static void SimpleCentral_init(void)
{
  uint8_t i;

  // ******************************************************************
  // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
  // ******************************************************************
  // Register the current thread as an ICall dispatcher application
  // so that the application can send and receive messages.
  ICall_registerApp(&selfEntity, &syncEvent);

  // Create an RTOS queue for message from profile to be sent to app.
  appMsgQueue = Util_constructQueue(&appMsg);

  // Initialize internal data
  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    connList[i].connHandle = CONNHANDLE_INVALID;
    connList[i].pRssiClock = NULL;
  }

  Board_initKeys(SimpleCentral_keyChangeHandler);

  GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN,
                   (void *)attDeviceName);

  //Set default values for Data Length Extension
  //Extended Data Length Feature is already enabled by default
  //in build_config.opt in stack project.
  {
    //Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
    #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
    #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)

    //This API is documented in hci.h
    //See the LE Data Length Extension section in the BLE5-Stack User's Guide for information on using this command:
    //http://software-dl.ti.com/lprf/ble5stack-latest/
    //HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
  }

  // Initialize GATT Client
  VOID GATT_InitClient();

  // Register to receive incoming ATT Indications/Notifications
  GATT_RegisterForInd(selfEntity);

  // Initialize GATT attributes
  GGS_AddService(GATT_ALL_SERVICES);         // GAP
  GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes

  // Register for GATT local events and ATT Responses pending for transmission
  GATT_RegisterForMsgs(selfEntity);

  // Set Bond Manager parameters
  {
    // Don't send a pairing request after connecting; the device waits for the
    // application to start pairing
    uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;
    // Do not use authenticated pairing
    uint8_t mitm = FALSE;
    // This is a display only device
    uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
    // Create a bond during the pairing process
    uint8_t bonding = TRUE;

    GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
    GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
    GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
    GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
  }

  // Start Bond Manager and register callback
  // This must be done before initialing the GAP layer
  VOID GAPBondMgr_Register(&bondMgrCBs);

  // Accept all parameter update requests
  GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, GAP_UPDATE_REQ_ACCEPT_ALL);

  // Register with GAP for HCI/Host messages (for RSSI)
  GAP_RegisterForMsgs(selfEntity);

  // Initialize GAP layer for Central role and register to receive GAP events
  GAP_DeviceInit(GAP_PROFILE_CENTRAL, selfEntity, addrMode, NULL);

  dispHandle = Display_open(Display_Type_UART , NULL);

  // Disable all items in the main menu
  tbm_setItemStatus(&scMenuMain, SC_ITEM_NONE, SC_ITEM_ALL);
  // Initialize Two-button Menu
  tbm_initTwoBtnMenu(dispHandle, &scMenuMain, 4, SimpleCentral_menuSwitchCb);
  Display_printf(dispHandle, SC_ROW_SEPARATOR, 0, "====================");
}

/*********************************************************************
 * @fn      SimpleCentral_taskFxn
 *
 * @brief   Application task entry point for the Simple Central.
 *
 * @param   none
 *
 * @return  events not processed
 */
static void SimpleCentral_taskFxn(uintptr_t a0, uintptr_t a1)
{
  // Initialize application
  SimpleCentral_init();

  // Application main loop
  for (;;)
  {
    uint32_t events;

    events = Event_pend(syncEvent, Event_Id_NONE, SC_ALL_EVENTS,
                        ICALL_TIMEOUT_FOREVER);

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

      if (ICall_fetchServiceMsg(&src, &dest,
                                (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
      {
        uint8 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)
          {
            // Process inter-task message
            safeToDealloc = SimpleCentral_processStackMsg((ICall_Hdr *)pMsg);
          }
        }

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

      // If RTOS queue is not empty, process app message
      if (events & SC_QUEUE_EVT)
      {
        scEvt_t *pMsg;
        while (pMsg = (scEvt_t *)Util_dequeueMsg(appMsgQueue))
        {
          // Process message
          SimpleCentral_processAppMsg(pMsg);

          // Free the space from the message
          ICall_free(pMsg);
        }
      }
    }
  }
}

/*********************************************************************
 * @fn      SimpleCentral_processStackMsg
 *
 * @brief   Process an incoming task message.
 *
 * @param   pMsg - message to process
 *
 * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
 */
static uint8_t SimpleCentral_processStackMsg(ICall_Hdr *pMsg)
{
  uint8_t safeToDealloc = TRUE;

  switch (pMsg->event)
  {
    case GAP_MSG_EVENT:
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "GAP_MSG_EVENT");
      SimpleCentral_processGapMsg((gapEventHdr_t*) pMsg);
      break;

    case GATT_MSG_EVENT:
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "GATT_MSG_EVENT");
      SimpleCentral_processGATTMsg((gattMsgEvent_t *)pMsg);
      break;

    case HCI_GAP_EVENT_EVENT:
    {
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "HCI_GAP_EVENT_EVENT");
      // Process HCI message
      switch (pMsg->status)
      {
        case HCI_COMMAND_COMPLETE_EVENT_CODE:
          SimpleCentral_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
          break;

        case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
          AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
          break;

        // HCI Commands Events
        case HCI_COMMAND_STATUS_EVENT_CODE:
          {
            hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
            switch ( pMyMsg->cmdOpcode )
            {
              case HCI_LE_SET_PHY:
                {
                  if (pMyMsg->cmdStatus ==
                      HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
                  {
                    Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                            "PHY Change failure, peer does not support this");
                  }
                  else
                  {
                    Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                                   "PHY Update Status: 0x%02x",
                                   pMyMsg->cmdStatus);
                  }
                }
                break;
              case HCI_DISCONNECT:
                break;

              default:
                {
                  Display_printf(dispHandle, SC_ROW_NON_CONN, 0,
                                 "Unknown Cmd Status: 0x%04x::0x%02x",
                                 pMyMsg->cmdOpcode, pMyMsg->cmdStatus);
                }
              break;
            }
          }
          break;

        // LE Events
        case HCI_LE_EVENT_CODE:
        {
          hciEvt_BLEPhyUpdateComplete_t *pPUC
            = (hciEvt_BLEPhyUpdateComplete_t*) pMsg;

          if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
          {
            if (pPUC->status != SUCCESS)
            {
              Display_printf(dispHandle, SC_ROW_ANY_CONN, 0,
                             "%s: PHY change failure",
                             SimpleCentral_getConnAddrStr(pPUC->connHandle));
            }
            else
            {
              Display_printf(dispHandle, SC_ROW_ANY_CONN, 0,
                             "%s: PHY updated to %s",
                             SimpleCentral_getConnAddrStr(pPUC->connHandle),
              // Only symmetrical PHY is supported.
              // rxPhy should be equal to txPhy.
                                (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1 Mbps" :
                                (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2 Mbps" :
                                (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value");
            }
          }

          break;
        }

        default:
          break;
      }

      break;
    }

    case L2CAP_SIGNAL_EVENT:
      // place holder for L2CAP Connection Parameter Reply
      break;

    default:
      break;
  }

  return (safeToDealloc);
}

/*********************************************************************
 * @fn      SimpleCentral_processAppMsg
 *
 * @brief   Scanner application event processing function.
 *
 * @param   pMsg - pointer to event structure
 *
 * @return  none
 */
static void SimpleCentral_processAppMsg(scEvt_t *pMsg)
{
  bool safeToDealloc = TRUE;

  switch (pMsg->hdr.event)
  {
    case SC_EVT_KEY_CHANGE:
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_KEY_CHANGE");
      SimpleCentral_handleKeys(pMsg->hdr.state);
      break;

    case SC_EVT_ADV_REPORT:
    {
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_ADV_REPORT");
      GapScan_Evt_AdvRpt_t* pAdvRpt = (GapScan_Evt_AdvRpt_t*) (pMsg->pData);

#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
//      if (SimpleCentral_findSvcUuid(SIMPLEPROFILE_SERV_UUID,
//                                    pAdvRpt->pData, pAdvRpt->dataLen))
      if (SimpleCentral_findUuid(simpleProfileServUUID,//128bit
                                 ManufData,
                                 sizeof(ManufData),
                                 pAdvRpt->pData,
                                 pAdvRpt->dataLen))
      {
        SimpleCentral_addScanInfo(pAdvRpt->addr, pAdvRpt->addrType);
        Display_printf(dispHandle, 4, 0, "Discovered: %s",
                       Util_convertBdAddr2Str(pAdvRpt->addr));
      }
#else // !DEFAULT_DEV_DISC_BY_SVC_UUID
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Discovered: %s",
                     Util_convertBdAddr2Str(pAdvRpt->addr));
#endif // DEFAULT_DEV_DISC_BY_SVC_UUID

      // Free report payload data
      if (pAdvRpt->pData != NULL)
      {
        ICall_free(pAdvRpt->pData);
      }
      break;
    }

    case SC_EVT_SCAN_ENABLED:
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_SCAN_ENABLED");
      // Disable everything but "Stop Discovering" on the menu
      tbm_setItemStatus(&scMenuMain, SC_ITEM_STOPDISC,(SC_ITEM_ALL & ~SC_ITEM_STOPDISC));
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Discovering...");
      break;

    case SC_EVT_SCAN_DISABLED:
    {
      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_SCAN_DISABLED");
      uint8_t numReport;
      uint8_t i;
      static uint8_t* pAddrs = NULL;
      uint8_t* pAddrTemp;
      uint16_t itemsToEnable = SC_ITEM_STARTDISC | SC_ITEM_SCANPHY;
#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
      numReport = numScanRes;
#else // !DEFAULT_DEV_DISC_BY_SVC_UUID
      GapScan_Evt_AdvRpt_t advRpt;

      numReport = ((GapScan_Evt_End_t*) (pMsg->pData))->numReport;
#endif // DEFAULT_DEV_DISC_BY_SVC_UUID

      Display_printf(dispHandle, SC_ROW_NON_CONN, 0,
                     "%d devices discovered", numReport);

      if (numReport > 0)
      {
        // Also enable "Connect to"
        itemsToEnable |= SC_ITEM_CONNECT;
      }

      if (numConn > 0)
      {
        // Also enable "Work with"
        itemsToEnable |= SC_ITEM_SELECTCONN;

        //todo
        itemsToEnable |= SC_ITEM_GATTWRITE;


      }

      // Enable "Discover Devices", "Set Scanning PHY", and possibly
      // "Connect to" and/or "Work with".
      // Disable "Stop Discovering".
      tbm_setItemStatus(&scMenuMain, itemsToEnable, SC_ITEM_STOPDISC);

      // Allocate buffer to display addresses
      if (pAddrs != NULL)
      {
        // A scan has been done previously, release the previously allocated buffer
        ICall_free(pAddrs);
      }
      pAddrs = ICall_malloc(numReport * SC_ADDR_STR_SIZE);
      if (pAddrs == NULL)
      {
        numReport = 0;
      }

      TBM_SET_NUM_ITEM(&scMenuConnect, numReport);

      if (pAddrs != NULL)
      {
        pAddrTemp = pAddrs;
        for (i = 0; i < numReport; i++, pAddrTemp += SC_ADDR_STR_SIZE)
        {
  #if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
          // Get the address from the list, convert it to string, and
          // copy the string to the address buffer
          memcpy(pAddrTemp, Util_convertBdAddr2Str(scanList[i].addr),
                 SC_ADDR_STR_SIZE);
  #else // !DEFAULT_DEV_DISC_BY_SVC_UUID
          // Get the address from the report, convert it to string, and
          // copy the string to the address buffer
          GapScan_getAdvReport(i, &advRpt);
          memcpy(pAddrTemp, Util_convertBdAddr2Str(advRpt.addr),
                 SC_ADDR_STR_SIZE);
  #endif // DEFAULT_DEV_DISC_BY_SVC_UUID

          // Assign the string to the corresponding action description of the menu
          TBM_SET_ACTION_DESC(&scMenuConnect, i, pAddrTemp);
        }

        // Disable any non-active scan results
        for (; i < DEFAULT_MAX_SCAN_RES; i++)
        {
          tbm_setItemStatus(&scMenuConnect, TBM_ITEM_NONE, (1 << i));
        }

        // Note: pAddrs is not freed since it will be used by the two button menu
        // to display the discovered address.
        // This implies that at least the last discovered addresses
        // will be maintained until a new scan is done.
      }
      break;
    }

    case SC_EVT_SVC_DISC:
        Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_SVC_DISC");
      SimpleCentral_startSvcDiscovery();
      break;

//    case SC_EVT_READ_RSSI:
//    {
//        Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_READ_RSSI");
//      uint8_t connIndex = pMsg->hdr.state;
//      uint16_t connHandle = connList[connIndex].connHandle;
//
//      // If link is still valid
//      if (connHandle != CONNHANDLE_INVALID)
//      {
//        // Restart timer
//        Util_startClock(connList[connIndex].pRssiClock);
//
//        // Read RSSI
//        VOID HCI_ReadRssiCmd(connHandle);
//      }

//      break;
    //}

//    // Pairing event
//    case SC_EVT_PAIR_STATE:
//    {
//        Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_PAIR_STATE");
//      SimpleCentral_processPairState(pMsg->hdr.state,
//                                     (scPairStateData_t*) (pMsg->pData));
//      break;
//    }
//
//    // Passcode event
//    case SC_EVT_PASSCODE_NEEDED:
//    {
//      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "SC_EVT_PASSCODE_NEEDED");
//      SimpleCentral_processPasscode((scPasscodeData_t *)(pMsg->pData));
//      break;
//    }

#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & PRIVACY_1_2_CFG)


//    case SC_EVT_READ_RPA:
//    {
//      uint8_t* pRpaNew;
//      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Inside SC_EVT_READ_RP");
//
//      // Read the current RPA.
//      pRpaNew = GAP_GetDevAddress(FALSE);
//
//      if (memcmp(pRpaNew, rpa, B_ADDR_LEN))
//      {
//        // If the RPA has changed, update the display
//        Display_printf(dispHandle, SC_ROW_RPA, 0, "RP Addr: %s",Util_convertBdAddr2Str(pRpaNew));
//        memcpy(rpa, pRpaNew, B_ADDR_LEN);
//      }
//      break;
//    }
#endif // PRIVACY_1_2_CFG

    // Insufficient memory
    case SC_EVT_INSUFFICIENT_MEM:
    {

      // We are running out of memory.
      Display_printf(dispHandle, SC_ROW_ANY_CONN, 0, "Insufficient Memory");

      // We might be in the middle of scanning, try stopping it.
      GapScan_disable();
      break;
    }

    default:
      // Do nothing.
      break;
  }

  if ((safeToDealloc == TRUE) && (pMsg->pData != NULL))
  {
    ICall_free(pMsg->pData);
  }
}

/*********************************************************************
 * @fn      SimpleCentral_processGapMsg
 *
 * @brief   GAP message processing function.
 *
 * @param   pMsg - pointer to event message structure
 *
 * @return  none
 */
static void SimpleCentral_processGapMsg(gapEventHdr_t *pMsg)
{
  switch (pMsg->opcode)
  {
    case GAP_DEVICE_INIT_DONE_EVENT:
    {
      uint8_t temp8;
      uint16_t temp16;
      gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;

      // Setup scanning
      // For more information, see the GAP section in the User's Guide:
      // http://software-dl.ti.com/lprf/ble5stack-latest/

      // Register callback to process Scanner events
      GapScan_registerCb(SimpleCentral_scanCb, NULL);

      // Set Scanner Event Mask
      GapScan_setEventMask(GAP_EVT_SCAN_ENABLED | GAP_EVT_SCAN_DISABLED | GAP_EVT_ADV_REPORT);

      // Set Scan PHY parameters
     // GapScan_setPhyParams(DEFAULT_SCAN_PHY, SCAN_TYPE_PASSIVE,SCAN_PARAM_DFLT_INTERVAL, SCAN_PARAM_DFLT_INTERVAL);
      GapScan_setPhyParams(DEFAULT_SCAN_PHY, SCAN_TYPE_ACTIVE,SCAN_PARAM_DFLT_INTERVAL, SCAN_PARAM_DFLT_INTERVAL); //changed by me

      // Set Advertising report fields to keep
      temp16 = SC_ADV_RPT_FIELDS;
      GapScan_setParam(SCAN_PARAM_RPT_FIELDS, &temp16);

      // Set Scanning Primary PHY
      temp8 = DEFAULT_SCAN_PHY;
      GapScan_setParam(SCAN_PARAM_PRIM_PHYS, &temp8);

      // Set LL Duplicate Filter
      temp8 = SCAN_FLT_DUP_ENABLE;
      GapScan_setParam(SCAN_PARAM_FLT_DUP, &temp8);

      // Set PDU type filter -
      // Only 'Connectable' and 'Complete' packets are desired.
      // It doesn't matter if received packets are
      // whether Scannable or Non-Scannable, whether Directed or Undirected,
      // whether Scan_Rsp's or Advertisements, and whether Legacy or Extended.
      temp16 = SCAN_FLT_PDU_CONNECTABLE_ONLY | SCAN_FLT_PDU_COMPLETE_ONLY;
      //GapScan_setParam(SCAN_PARAM_FLT_PDU_TYPE, &temp16);
      GapScan_setParam(SCAN_PARAM_FLT_PDU_TYPE, &temp16);

//      SCAN_PARAM_FLT_PDU_TYPE -  Filter by PDU Type
//      SCAN_PARAM_FLT_MIN_RSSI -  Filter by Minimum RSSI
//      SCAN_PARAM_FLT_DISC_MODE - Filter by Discoverable Mode
//      SCAN_PARAM_RPT_FIELDS -    Advertising Report Fields


      scMaxPduSize = pPkt->dataPktLen;

      // Enable "Discover Devices", "Set Scanning PHY", and "Set Address Type"
      // in the main menu
      tbm_setItemStatus(&scMenuMain,
                        SC_ITEM_STARTDISC | SC_ITEM_SCANPHY, SC_ITEM_NONE);

      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Initialized");
      Display_printf(dispHandle, SC_ROW_NUM_CONN, 0, "Num Conns: %d", numConn);

      // Display device address
      Display_printf(dispHandle, SC_ROW_IDA, 0, "%s Addr: %s",
                     (addrMode <= ADDRMODE_RANDOM) ? "Dev" : "ID",
                     Util_convertBdAddr2Str(pPkt->devAddr));

#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & PRIVACY_1_2_CFG)
      if (addrMode > ADDRMODE_RANDOM)
      {
        // Update the current RPA.
        memcpy(rpa, GAP_GetDevAddress(FALSE), B_ADDR_LEN);

        Display_printf(dispHandle, SC_ROW_RPA, 0, "RP Addr: %s",
                       Util_convertBdAddr2Str(rpa));

        // Create one-shot clock for RPA check event.
        Util_constructClock(&clkRpaRead, SimpleCentral_clockHandler,
                            SC_READ_RPA_PERIOD, 0, true, SC_EVT_READ_RPA);
      }
#endif // PRIVACY_1_2_CFG
      break;
    }

    case GAP_CONNECTING_CANCELLED_EVENT:
    {
      uint16_t itemsToEnable = SC_ITEM_SCANPHY | SC_ITEM_STARTDISC |
                               SC_ITEM_CONNECT;

      if (numConn > 0)
      {
        itemsToEnable |= SC_ITEM_SELECTCONN;
      }

      Display_printf(dispHandle, SC_ROW_NON_CONN, 0,"Connecting attempt cancelled");

      // Enable "Discover Devices", "Connect To", and "Set Scanning PHY"
      // and disable everything else.
      tbm_setItemStatus(&scMenuMain,
                        itemsToEnable, SC_ITEM_ALL & ~itemsToEnable);

      break;
    }

    case GAP_LINK_ESTABLISHED_EVENT:
    {
      uint16_t connHandle = ((gapEstLinkReqEvent_t*) pMsg)->connectionHandle;
      uint8_t* pAddr = ((gapEstLinkReqEvent_t*) pMsg)->devAddr;
      uint8_t  connIndex;
      uint32_t itemsToDisable = SC_ITEM_STOPDISC | SC_ITEM_CANCELCONN;
      uint8_t* pStrAddr;
      uint8_t i;
      uint8_t numConnectable = 0;

      // Add this connection info to the list
      connIndex = SimpleCentral_addConnInfo(connHandle, pAddr);

      // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
      SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

      connList[connIndex].charHandle = 0;

      pStrAddr = (uint8_t*) Util_convertBdAddr2Str(connList[connIndex].addr);

      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Connected to %s", pStrAddr);
      Display_printf(dispHandle, SC_ROW_NUM_CONN, 0, "Num Conns: %d", numConn);

      // Disable "Connect To" until another discovery is performed
      itemsToDisable |= SC_ITEM_CONNECT;

      // If we already have maximum allowed number of connections,
      // disable device discovery and additional connection making.
      if (numConn >= MAX_NUM_BLE_CONNS)
      {
        itemsToDisable |= SC_ITEM_SCANPHY | SC_ITEM_STARTDISC;
      }

      for (i = 0; i < TBM_GET_NUM_ITEM(&scMenuConnect); i++)
      {
        if (!memcmp(TBM_GET_ACTION_DESC(&scMenuConnect, i), pStrAddr,
            SC_ADDR_STR_SIZE))
        {
          // Disable this device from the connection choices
          tbm_setItemStatus(&scMenuConnect, SC_ITEM_NONE, 1 << i);
        }
        else if (TBM_IS_ITEM_ACTIVE(&scMenuConnect, i))
        {
          numConnectable++;
        }
      }

      // Enable/disable Main menu items properly
      tbm_setItemStatus(&scMenuMain,SC_ITEM_ALL & ~(itemsToDisable), itemsToDisable);

      break;
    }

    case GAP_LINK_TERMINATED_EVENT:
    {
      uint16_t connHandle = ((gapTerminateLinkEvent_t*) pMsg)->connectionHandle;
      uint8_t connIndex;
      uint32_t itemsToEnable = SC_ITEM_STARTDISC | SC_ITEM_SCANPHY;
      uint8_t* pStrAddr;
      uint8_t i;
      uint8_t numConnectable = 0;

      // Cancel timers
      SimpleCentral_CancelRssi(connHandle);

      // Mark this connection deleted in the connected device list.
      connIndex = SimpleCentral_removeConnInfo(connHandle);

      // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
      SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

      pStrAddr = (uint8_t*) Util_convertBdAddr2Str(connList[connIndex].addr);

      Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "%s is disconnected",
                     pStrAddr);
      Display_printf(dispHandle, SC_ROW_NUM_CONN, 0, "Num Conns: %d", numConn);

      for (i = 0; i < TBM_GET_NUM_ITEM(&scMenuConnect); i++)
      {
        if (!memcmp(TBM_GET_ACTION_DESC(&scMenuConnect, i), pStrAddr,
                     SC_ADDR_STR_SIZE))
        {
          // Enable this device in the connection choices
          tbm_setItemStatus(&scMenuConnect, 1 << i, SC_ITEM_NONE);
        }

        if (TBM_IS_ITEM_ACTIVE(&scMenuConnect, i))
        {
          numConnectable++;
        }
      }

      if (numConn > 0)
      {
        // There still is an active connection to select
        itemsToEnable |= SC_ITEM_SELECTCONN;
      }

      // Enable/disable items properly.
      tbm_setItemStatus(&scMenuMain,
                        itemsToEnable, SC_ITEM_ALL & ~itemsToEnable);

      // If we are in the context which the teminated connection was associated
      // with, go to main menu.
      if (connHandle == scConnHandle)
      {
        tbm_goTo(&scMenuMain);
      }

      break;
    }

    case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
    {
      gapUpdateLinkParamReqReply_t rsp;
      gapUpdateLinkParamReq_t *pReq;

      pReq = &((gapUpdateLinkParamReqEvent_t *)pMsg)->req;

      rsp.connectionHandle = pReq->connectionHandle;
      rsp.signalIdentifier = pReq->signalIdentifier;

      if (acceptParamUpdateReq)
      {
        rsp.intervalMin = pReq->intervalMin;
        rsp.intervalMax = pReq->intervalMax;
        rsp.connLatency = pReq->connLatency;
        rsp.connTimeout = pReq->connTimeout;
        rsp.accepted = TRUE;
      }
      else
      {
        // Reject the request.
        rsp.accepted = FALSE;
      }

      // Send Reply
      VOID GAP_UpdateLinkParamReqReply(&rsp);

      break;
    }

    case GAP_LINK_PARAM_UPDATE_EVENT:
    {
      gapLinkUpdateEvent_t *pPkt = (gapLinkUpdateEvent_t *)pMsg;
      // Get the address from the connection handle
      linkDBInfo_t linkInfo;

      if (linkDB_GetInfo(pPkt->connectionHandle, &linkInfo) ==  SUCCESS)
      {
        if(pPkt->status == SUCCESS)
        {
          Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                         "Updated: %s, connTimeout:%d",
                         Util_convertBdAddr2Str(linkInfo.addr),
                         linkInfo.connTimeout*CONN_TIMEOUT_MS_CONVERSION);
        }
        else
        {
          // Display the address of the connection update failure
          Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                         "Update Failed 0x%h: %s", pPkt->opcode,
                         Util_convertBdAddr2Str(linkInfo.addr));
        }
      }

      break;
    }

    default:
      break;
  }
}

/*********************************************************************
 * @fn      SimpleCentral_handleKeys
 *
 * @brief   Handles all key events for this device.
 *
 * @param   keys - bit field for key events. Valid entries:
 *                 KEY_LEFT
 *                 KEY_RIGHT
 *
 * @return  none
 */
static void SimpleCentral_handleKeys(uint8_t keys)
{
  if (keys & KEY_LEFT)
  {
    // Check if the key is still pressed. Workaround for possible bouncing.
    if (PIN_getInputValue(Board_PIN_BUTTON0) == 0)
    {
      tbm_buttonLeft();
    }
  }
  else if (keys & KEY_RIGHT)
  {
    // Check if the key is still pressed. Workaround for possible bouncing.
    if (PIN_getInputValue(Board_PIN_BUTTON1) == 0)
    {
      tbm_buttonRight();
    }
  }
}
/*********************************************************************
 * @fn      SimpleCentral_processGATTMsg
 *
 * @brief   Process GATT messages and events.
 *
 * @return  none
 */
static void SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg)
{
  if (linkDB_Up(pMsg->connHandle))
  {
    // See if GATT server was unable to transmit an ATT response
    if (pMsg->hdr.status == blePending)
    {
      // No HCI buffer was available. App can try to retransmit the response
      // on the next connection event. Drop it for now.
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                     "ATT Rsp dropped %d", pMsg->method);
    }
    else if ((pMsg->method == ATT_READ_RSP)   ||
             ((pMsg->method == ATT_ERROR_RSP) &&
              (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
    {
      if (pMsg->method == ATT_ERROR_RSP)
      {
        Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                       "Read Error %d", pMsg->msg.errorRsp.errCode);
      }
      else
      {
        // After a successful read, display the read value
        Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                       "Read rsp: 0x%02x", pMsg->msg.readRsp.pValue[0]);
      }
    }
    else if ((pMsg->method == ATT_WRITE_RSP)  ||
             ((pMsg->method == ATT_ERROR_RSP) &&
              (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
    {
      if (pMsg->method == ATT_ERROR_RSP)
      {
        Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                       "Write Error %d", pMsg->msg.errorRsp.errCode);
      }
      else
      {
        // After a successful write, display the value that was written and
        // increment value
        Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                       "Write sent: 0x%02x", charVal);
      }

      tbm_goTo(&scMenuPerConn);
    }
    else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
    {
      // ATT request-response or indication-confirmation flow control is
      // violated. All subsequent ATT requests or indications will be dropped.
      // The app is informed in case it wants to drop the connection.

      // Display the opcode of the message that caused the violation.
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                     "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
    }
    else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
    {
      // MTU size updated
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                     "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
    }
    else if (discState != BLE_DISC_STATE_IDLE)
    {
      SimpleCentral_processGATTDiscEvent(pMsg);
    }
  } // else - in case a GATT message came after a connection has dropped, ignore it.

  // Needed only for ATT Protocol messages
  GATT_bm_free(&pMsg->msg, pMsg->method);
}

/*********************************************************************
 * @fn      SimpleCentral_processCmdCompleteEvt
 *
 * @brief   Process an incoming OSAL HCI Command Complete Event.
 *
 * @param   pMsg - message to process
 *
 * @return  none
 */
static void SimpleCentral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
{
  switch (pMsg->cmdOpcode)
  {
    case HCI_READ_RSSI:
    {
#ifndef Display_DISABLE_ALL
      uint16_t connHandle = BUILD_UINT16(pMsg->pReturnParam[1],
                                         pMsg->pReturnParam[2]);
      int8 rssi = (int8)pMsg->pReturnParam[3];
      
      Display_printf(dispHandle, SC_ROW_ANY_CONN, 0, "%s: RSSI %d dBm",
                   SimpleCentral_getConnAddrStr(connHandle), rssi);

#endif
      break;
    }

    default:
      break;
  }
}

/*********************************************************************
 * @fn      SimpleCentral_StartRssi
 *
 * @brief   Start periodic RSSI reads on the current link.
 *
 * @return  SUCCESS: RSSI Read timer started
 *          bleIncorrectMode: Aready started
 *          bleNoResources: No resources
 */
static status_t SimpleCentral_StartRssi(void)
{
  uint8_t connIndex = SimpleCentral_getConnIndex(scConnHandle);

  // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
  SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

  // If already running
  if (connList[connIndex].pRssiClock != NULL)
  {
    return bleIncorrectMode;
  }

  // Create a clock object and start
  connList[connIndex].pRssiClock
    = (Clock_Struct*) ICall_malloc(sizeof(Clock_Struct));

  if (connList[connIndex].pRssiClock)
  {
    Util_constructClock(connList[connIndex].pRssiClock,
                        SimpleCentral_clockHandler,
                        DEFAULT_RSSI_PERIOD, 0, true,
                        (connIndex << 8) | SC_EVT_READ_RSSI);
  }
  else
  {
    return bleNoResources;
  }

  return SUCCESS;
}

/*********************************************************************
 * @fn      SimpleCentral_CancelRssi
 *
 * @brief   Cancel periodic RSSI reads on a link.
 *
 * @param   connection handle
 *
 * @return  SUCCESS: Operation successful
 *          bleIncorrectMode: Has not started
 */
static status_t SimpleCentral_CancelRssi(uint16_t connHandle)
{
  uint8_t connIndex = SimpleCentral_getConnIndex(connHandle);

  // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
  SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

  // If already running
  if (connList[connIndex].pRssiClock == NULL)
  {
    return bleIncorrectMode;
  }

  // Stop timer
  Util_stopClock(connList[connIndex].pRssiClock);

  // Destroy the clock object
  Clock_destruct(connList[connIndex].pRssiClock);

  // Free clock struct
  ICall_free(connList[connIndex].pRssiClock);
  connList[connIndex].pRssiClock = NULL;

  Display_clearLine(dispHandle, SC_ROW_ANY_CONN);

  return SUCCESS;
}

/*********************************************************************
 * @fn      SimpleCentral_processPairState
 *
 * @brief   Process the new paring state.
 *
 * @return  none
 */
static void SimpleCentral_processPairState(uint8_t state,
                                           scPairStateData_t* pPairData)
{
  uint8_t status = pPairData->status;

  if (state == GAPBOND_PAIRING_STATE_STARTED)
  {
    Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Pairing started");
  }
  else if (state == GAPBOND_PAIRING_STATE_COMPLETE)
  {
    if (status == SUCCESS)
    {
      linkDBInfo_t linkInfo;

      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Pairing success");

#if defined(BLE_V42_FEATURES) && (BLE_V42_FEATURES & PRIVACY_1_2_CFG)
      if (linkDB_GetInfo(pPairData->connHandle, &linkInfo) == SUCCESS)
      {
        // If the peer was using private address, update with ID address
        if ((linkInfo.addrType == ADDRTYPE_PUBLIC_ID ||
             linkInfo.addrType == ADDRTYPE_RANDOM_ID) &&
             !Util_isBufSet(linkInfo.addrPriv, 0, B_ADDR_LEN))
        {
          // Update the address of the peer to the ID address
          Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Addr updated: %s",
                         Util_convertBdAddr2Str(linkInfo.addr));

          // Update the connection list with the ID address
          uint8_t i = SimpleCentral_getConnIndex(pPairData->connHandle);

          SIMPLECENTRAL_ASSERT(i < MAX_NUM_BLE_CONNS);
          memcpy(connList[i].addr, linkInfo.addr, B_ADDR_LEN);
        }
      }
#endif // PRIVACY_1_2_CFG
    }
    else
    {
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Pairing fail: %d", status);
    }
  }
  else if (state == GAPBOND_PAIRING_STATE_ENCRYPTED)
  {
    if (status == SUCCESS)
    {
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Encryption success");
    }
    else
    {
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Encryption failed: %d", status);
    }
  }
  else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED)
  {
    if (status == SUCCESS)
    {
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Bond save success");
    }
    else
    {
      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Bond save failed: %d", status);
    }
  }
}

/*********************************************************************
 * @fn      SimpleCentral_processPasscode
 *
 * @brief   Process the Passcode request.
 *
 * @return  none
 */
static void SimpleCentral_processPasscode(scPasscodeData_t *pData)
{
  // Display passcode to user
  if (pData->uiOutputs != 0)
  {
    Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Passcode: %d",
                   B_APP_DEFAULT_PASSCODE);
  }

  // Send passcode response
  GAPBondMgr_PasscodeRsp(pData->connHandle, SUCCESS, B_APP_DEFAULT_PASSCODE);
}

/*********************************************************************
 * @fn      SimpleCentral_startSvcDiscovery
 *
 * @brief   Start service discovery.
 *
 * @return  none
 */
static void SimpleCentral_startSvcDiscovery(void)
{
  attExchangeMTUReq_t req;

  // Initialize cached handles
  svcStartHdl = svcEndHdl = 0;

  discState = BLE_DISC_STATE_MTU;

  // Discover GATT Server's Rx MTU size
  req.clientRxMTU = scMaxPduSize - L2CAP_HDR_SIZE;

  // ATT MTU size should be set to the minimum of the Client Rx MTU
  // and Server Rx MTU values
  VOID GATT_ExchangeMTU(scConnHandle, &req, selfEntity);
}

/*********************************************************************
 * @fn      SimpleCentral_processGATTDiscEvent
 *
 * @brief   Process GATT discovery event
 *
 * @return  none
 */
static void SimpleCentral_processGATTDiscEvent(gattMsgEvent_t *pMsg)
{
    //TESTTTTT
    // Now we can use GATT Read/Write
    tbm_setItemStatus(&scMenuPerConn,SC_ITEM_GATTREAD | SC_ITEM_GATTWRITE, SC_ITEM_NONE);


  if (discState == BLE_DISC_STATE_MTU)
  {
    // MTU size response received, discover simple service
    if (pMsg->method == ATT_EXCHANGE_MTU_RSP)
    {
     /* uint8_t uuid[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_SERV_UUID),
                                         HI_UINT16(SIMPLEPROFILE_SERV_UUID) };*/

       uint8_t uuid[ATT_UUID_SIZE] = {simpleProfileServUUID};

      discState = BLE_DISC_STATE_SVC;

      // Discovery simple service
      VOID GATT_DiscPrimaryServiceByUUID(pMsg->connHandle, uuid,ATT_UUID_SIZE, selfEntity);

     }
  }
  else if (discState == BLE_DISC_STATE_SVC)
  {
    // Service found, store handles
    if (pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
        pMsg->msg.findByTypeValueRsp.numInfo > 0)
    {
      svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
      svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
    }

    // If procedure complete
    if (((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP) &&
         (pMsg->hdr.status == bleProcedureComplete))  ||
        (pMsg->method == ATT_ERROR_RSP))
    {
      if (svcStartHdl != 0)
      {
        attReadByTypeReq_t req;

        // Discover characteristic
        discState = BLE_DISC_STATE_CHAR;

        req.startHandle = svcStartHdl;
        req.endHandle = svcEndHdl;
        req.type.len = ATT_UUID_SIZE;
        req.type.uuid[12] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
        req.type.uuid[13] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);

        VOID GATT_DiscCharsByUUID(pMsg->connHandle, &req, selfEntity);
      }
    }
  }
  else if (discState == BLE_DISC_STATE_CHAR)
  {
    // Characteristic found, store handle
    if ((pMsg->method == ATT_READ_BY_TYPE_RSP) &&
        (pMsg->msg.readByTypeRsp.numPairs > 0))
    {
      uint8_t connIndex = SimpleCentral_getConnIndex(scConnHandle);

      // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
      SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

      // Store the handle of the simpleprofile characteristic 1 value
      connList[connIndex].charHandle
        = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[3],
                       pMsg->msg.readByTypeRsp.pDataList[4]);

      Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Simple Svc Found");

      // Now we can use GATT Read/Write
      tbm_setItemStatus(&scMenuPerConn,SC_ITEM_GATTREAD | SC_ITEM_GATTWRITE, SC_ITEM_NONE);
    }

    discState = BLE_DISC_STATE_IDLE;
  }
}

#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)

/**********************************************************************
 * @fn      SimpleCentral_findUuid
 *
 * @brief   Find a given UUID in an advertiser's service UUID list.
 *
 * @return  TRUE if service UUID found
 */
static bool SimpleCentral_findUuid(const uint8_t *uuid, const uint8_t *pManufData ,uint8_t manDataLen ,uint8_t *pData,
                                         uint8_t dataLen)
{
   uint8_t matchingIdUuid =0;
   uint8_t adLen;
   uint8_t adType;
   uint8_t *pEnd;

   pEnd = pData + dataLen - 1;

   // while end of data not reached
 while ((dataLen > 0) && (pData <pEnd))
  {
      // Get length of next AD item
      adLen = *pData++;
      if (adLen > 0)
      {
        adType = *pData;

        // If AD type is for 128-bit service UUID
        if ((adType == GAP_ADTYPE_128BIT_MORE) ||
            (adType == GAP_ADTYPE_128BIT_COMPLETE))
        {
          pData++;
          adLen--;

          // For each UUID in list
          while (adLen >= 2 && pData < pEnd)
          {
            // Check for match
           if(!memcmp(pData,uuid,ATT_UUID_SIZE))
            {
               matchingIdUuid++;
            }

            // Go to next
            pData += 2;
            adLen -= 2;
          }

          // Handle possible erroneous extra byte in UUID list
          if (adLen == 1)
          {
            pData++;
          }
        }

        if(adType== GAP_ADTYPE_MANUFACTURER_SPECIFIC)
        {
           uint8_t len = adLen;
           if(manDataLen < len)
           {
               len = manDataLen;
           }
           // Check for match
         if(memcmp(pManufData,pData,len))
          {
           matchingIdUuid++;
          }
        }


    if(matchingIdUuid<2) // 2 when we are cheking manuf data
          {
            // Go to next item
            pData += adLen;
          }
    else
        {
          return TRUE;
        }
      }
    }

  // Match not found
  return FALSE;
}

///*********************************************************************
// * @fn      SimpleCentral_findSvcUuid
// *
// * @brief   Find a given UUID in an advertiser's service UUID list.
// *
// * @return  TRUE if service UUID found
// */
//static bool SimpleCentral_findSvcUuid(uint16_t uuid, uint8_t *pData,
//                                      uint16_t dataLen)
//{
//  uint8_t adLen;
//  uint8_t adType;
//  uint8_t *pEnd;
//
//  if (dataLen > 0)
//  {
//    pEnd = pData + dataLen - 1;
//
//    // While end of data not reached
//    while (pData < pEnd)
//    {
//      // Get length of next AD item
//      adLen = *pData++;
//      if (adLen > 0)
//      {
//        adType = *pData;
//
//        // If AD type is for 16-bit service UUID
//        if ((adType == GAP_ADTYPE_16BIT_MORE) ||
//            (adType == GAP_ADTYPE_16BIT_COMPLETE))
//        {
//          pData++;
//          adLen--;
//
//          // For each UUID in list
//          while (adLen >= 2 && pData < pEnd)
//          {
//            // Check for match
//            if ((pData[0] == LO_UINT16(uuid)) && (pData[1] == HI_UINT16(uuid)))
//            {
//              // Match found
//              return TRUE;
//            }
//
//            // Go to next
//            pData += 2;
//            adLen -= 2;
//          }
//
//          // Handle possible erroneous extra byte in UUID list
//          if (adLen == 1)
//          {
//            pData++;
//          }
//        }
//        else
//        {
//          // Go to next item
//          pData += adLen;
//        }
//      }
//    }
//  }
//
//  // Match not found
//  return FALSE;
//}

/*********************************************************************
 * @fn      SimpleCentral_addScanInfo
 *
 * @brief   Add a device to the scanned device list
 *
 * @return  none
 */
static void SimpleCentral_addScanInfo(uint8_t *pAddr, uint8_t addrType)
{
  uint8_t i;

  // If result count not at max
  if (numScanRes < DEFAULT_MAX_SCAN_RES)
  {
    // Check if device is already in scan results
    for (i = 0; i < numScanRes; i++)
    {
      if (memcmp(pAddr, scanList[i].addr , B_ADDR_LEN) == 0)
      {
        return;
      }
    }

    // Add addr to scan result list
    memcpy(scanList[numScanRes].addr, pAddr, B_ADDR_LEN);
    scanList[numScanRes].addrType = addrType;

    // Increment scan result count
    numScanRes++;
  }
}
#endif // DEFAULT_DEV_DISC_BY_SVC_UUID

/*********************************************************************
 * @fn      SimpleCentral_addConnInfo
 *
 * @brief   Add a device to the connected device list
 *
 * @return  index of the connected device list entry where the new connection
 *          info is put in.
 *          if there is no room, MAX_NUM_BLE_CONNS will be returned.
 */
static uint8_t SimpleCentral_addConnInfo(uint16_t connHandle, uint8_t *pAddr)
{
  uint8_t i;

  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    if (connList[i].connHandle == CONNHANDLE_INVALID)
    {
      // Found available entry to put a new connection info in
      connList[i].connHandle = connHandle;
      memcpy(connList[i].addr, pAddr, B_ADDR_LEN);
      numConn++;

      break;
    }
  }

  return i;
}

/*********************************************************************
 * @fn      SimpleCentral_removeConnInfo
 *
 * @brief   Remove a device from the connected device list
 *
 * @return  index of the connected device list entry where the new connection
 *          info is removed from.
 *          if connHandle is not found, MAX_NUM_BLE_CONNS will be returned.
 */
static uint8_t SimpleCentral_removeConnInfo(uint16_t connHandle)
{
  uint8_t i;

  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    if (connList[i].connHandle == connHandle)
    {
      // Found the entry to mark as deleted
      connList[i].connHandle = CONNHANDLE_INVALID;
      numConn--;

      break;
    }
  }

  return i;
}

/*********************************************************************
 * @fn      SimpleCentral_getConnIndex
 *
 * @brief   Find index in the connected device list by connHandle
 *
 * @return  the index of the entry that has the given connection handle.
 *          if there is no match, MAX_NUM_BLE_CONNS will be returned.
 */
static uint8_t SimpleCentral_getConnIndex(uint16_t connHandle)
{
  uint8_t i;

  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    if (connList[i].connHandle == connHandle)
    {
      break;
    }
  }

  return i;
}

#ifndef Display_DISABLE_ALL
/*********************************************************************
 * @fn      SimpleCentral_getConnAddrStr
 *
 * @brief   Return, in string form, the address of the peer associated with
 *          the connHandle.
 *
 * @return  A null-terminated string of the address.
 *          if there is no match, NULL will be returned.
 */
static char* SimpleCentral_getConnAddrStr(uint16_t connHandle)
{
  uint8_t i;

  for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
  {
    if (connList[i].connHandle == connHandle)
    {
      return Util_convertBdAddr2Str(connList[i].addr);
    }
  }

  return NULL;
}
#endif

/*********************************************************************
 * @fn      SimpleCentral_pairStateCb
 *
 * @brief   Pairing state callback.
 *
 * @return  none
 */
static void SimpleCentral_pairStateCb(uint16_t connHandle, uint8_t state,
                                      uint8_t status)
{
  scPairStateData_t *pData;

  // Allocate space for the event data.
  if ((pData = ICall_malloc(sizeof(scPairStateData_t))))
  {
    pData->connHandle = connHandle;
    pData->status = status;

    // Queue the event.
    if(SimpleCentral_enqueueMsg(SC_EVT_PAIR_STATE, state, (uint8_t*) pData) != SUCCESS)
    {
      ICall_free(pData);
    }
  }
}

/*********************************************************************
* @fn      SimpleCentral_passcodeCb
*
* @brief   Passcode callback.
*
* @param   deviceAddr - pointer to device address
*
* @param   connHandle - the connection handle
*
* @param   uiInputs - pairing User Interface Inputs
*
* @param   uiOutputs - pairing User Interface Outputs
*
* @param   numComparison - numeric Comparison 20 bits
*
* @return  none
*/
static void SimpleCentral_passcodeCb(uint8_t *deviceAddr, uint16_t connHandle,
                                  uint8_t uiInputs, uint8_t uiOutputs,
                                  uint32_t numComparison)
{
  scPasscodeData_t *pData = ICall_malloc(sizeof(scPasscodeData_t));

  // Allocate space for the passcode event.
  if (pData)
  {
    pData->connHandle = connHandle;
    memcpy(pData->deviceAddr, deviceAddr, B_ADDR_LEN);
    pData->uiInputs = uiInputs;
    pData->uiOutputs = uiOutputs;
    pData->numComparison = numComparison;

    // Enqueue the event.
    if (SimpleCentral_enqueueMsg(SC_EVT_PASSCODE_NEEDED, 0,(uint8_t *) pData) != SUCCESS)
    {
      ICall_free(pData);
    }
  }
}

/*********************************************************************
 * @fn      SimpleCentral_keyChangeHandler
 *
 * @brief   Key event handler function
 *
 * @param   a0 - ignored
 *
 * @return  none
 */
static void SimpleCentral_keyChangeHandler(uint8 keys)
{
  SimpleCentral_enqueueMsg(SC_EVT_KEY_CHANGE, keys, NULL);
}

/*********************************************************************
 * @fn      SimpleCentral_clockHandler
 *
 * @brief   clock handler function
 *
 * @param   arg - argument from the clock initiator
 *
 * @return  none
 */
void SimpleCentral_clockHandler(UArg arg)
{
  uint8_t evtId = (uint8_t) (arg & 0xFF);

  switch (evtId)
  {
    case SC_EVT_READ_RSSI:
      SimpleCentral_enqueueMsg(SC_EVT_READ_RSSI, (uint8_t) (arg >> 8) , NULL);
      break;

    case SC_EVT_READ_RPA:
      // Restart timer
      Util_startClock(&clkRpaRead);
      // Let the application handle the event
      SimpleCentral_enqueueMsg(SC_EVT_READ_RPA, 0, NULL);
      break;

    default:
      break;
  }
}

/*********************************************************************
 * @fn      SimpleCentral_enqueueMsg
 *
 * @brief   Creates a message and puts the message in RTOS queue.
 *
 * @param   event - message event.
 * @param   state - message state.
 * @param   pData - message data pointer.
 *
 * @return  TRUE or FALSE
 */
static status_t SimpleCentral_enqueueMsg(uint8_t event, uint8_t state,
                                           uint8_t *pData)
{
  uint8_t success;
  scEvt_t *pMsg = ICall_malloc(sizeof(scEvt_t));

  // Create dynamic pointer to message.
  if (pMsg)
  {
    pMsg->hdr.event = event;
    pMsg->hdr.state = state;
    pMsg->pData = pData;

    // Enqueue the message.
    success = Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);
    return (success) ? SUCCESS : FAILURE;
  }

  return(bleMemAllocError);
}

/*********************************************************************
 * @fn      SimpleCentral_scanCb
 *
 * @brief   Callback called by GapScan module
 *
 * @param   evt - event
 * @param   msg - message coming with the event
 * @param   arg - user argument
 *
 * @return  none
 */
void SimpleCentral_scanCb(uint32_t evt, void* pMsg, uintptr_t arg)
{
  uint8_t event;

  if (evt & GAP_EVT_ADV_REPORT)
  {
    event = SC_EVT_ADV_REPORT;
  }
  else if (evt & GAP_EVT_SCAN_ENABLED)
  {
    event = SC_EVT_SCAN_ENABLED;
  }
  else if (evt & GAP_EVT_SCAN_DISABLED)
  {
    event = SC_EVT_SCAN_DISABLED;
  }
  else if (evt & GAP_EVT_INSUFFICIENT_MEMORY)
  {
    event = SC_EVT_INSUFFICIENT_MEM;
  }
  else
  {
    return;
  }

  if(SimpleCentral_enqueueMsg(event, SUCCESS, pMsg) != SUCCESS)
  {
    ICall_free(pMsg);
  }
}

/*********************************************************************
 * @fn      SimpleCentral_doSetScanPhy
 *
 * @brief   Set PHYs for scanning.
 *
 * @param   index - 0: 1M PHY
 *                  1: CODED PHY (Long range)
 *
 * @return  always true
 */
bool SimpleCentral_doSetScanPhy(uint8_t index)
{
  uint8_t temp8;

  if (index == 0)
  {
    temp8 = SCAN_PRIM_PHY_1M;
  }
  else
  {
    temp8 = SCAN_PRIM_PHY_CODED;
  }

  // Set scanning primary PHY
  GapScan_setParam(SCAN_PARAM_PRIM_PHYS, &temp8);

  Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Primary Scan PHY: %s",
                 TBM_GET_ACTION_DESC(&scMenuScanPhy, index));

  tbm_goTo(&scMenuMain);

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doDiscoverDevices
 *
 * @brief   Enables scanning
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doDiscoverDevices(uint8_t index)
{
  (void) index;

#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
  // Scanning for DEFAULT_SCAN_DURATION x 10 ms.
  // The stack does not need to record advertising reports
  // since the application will filter them by Service UUID and save.

  // Reset number of scan results to 0 before starting scan
  numScanRes = 0;
  GapScan_enable(0, DEFAULT_SCAN_DURATION, 0);
#else // !DEFAULT_DEV_DISC_BY_SVC_UUID
  // Scanning for DEFAULT_SCAN_DURATION x 10 ms.
  // Let the stack record the advertising reports as many as up to DEFAULT_MAX_SCAN_RES.
  GapScan_enable(0, DEFAULT_SCAN_DURATION, DEFAULT_MAX_SCAN_RES);

#endif // DEFAULT_DEV_DISC_BY_SVC_UUID

  // Enable only "Stop Discovering" and disable all others in the main menu
  tbm_setItemStatus(&scMenuMain, SC_ITEM_STOPDISC,
                    (SC_ITEM_ALL & ~SC_ITEM_STOPDISC));

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doStopDiscovering
 *
 * @brief   Stop on-going scanning
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doStopDiscovering(uint8_t index)
{
  (void) index;

  GapScan_disable();

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doEstablishLink
 *
 * @brief   Establish a link to a peer device
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doConnect(uint8_t index)
{
#if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
  GapInit_connect(scanList[index].addrType & MASK_ADDRTYPE_ID,
                  scanList[index].addr, DEFAULT_INIT_PHY, 0);
#else // !DEFAULT_DEV_DISC_BY_SVC_UUID
  GapScan_Evt_AdvRpt_t advRpt;

  GapScan_getAdvReport(index, &advRpt);

  GapInit_connect(advRpt.addrType & MASK_ADDRTYPE_ID,
                  advRpt.addr, DEFAULT_INIT_PHY, 0);
#endif // DEFAULT_DEV_DISC_BY_SVC_UUID

  // Enable only "Cancel Connecting" and disable all others in the main menu
  tbm_setItemStatus(&scMenuMain, SC_ITEM_CANCELCONN,
                    (SC_ITEM_ALL & ~SC_ITEM_CANCELCONN));

  Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Connecting...");

  tbm_goTo(&scMenuMain);

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doCancelConnecting
 *
 * @brief   Cancel on-going connection attempt
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doCancelConnecting(uint8_t index)
{
  (void) index;

  GapInit_cancelConnect();

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doSelectConn
 *
 * @brief   Select a connection to communicate with
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doSelectConn(uint8_t index)
{
  uint32_t itemsToDisable = SC_ITEM_NONE;

  // index cannot be equal to or greater than MAX_NUM_BLE_CONNS
  SIMPLECENTRAL_ASSERT(index < MAX_NUM_BLE_CONNS);

  scConnHandle = connList[index].connHandle;

  if (connList[index].charHandle == 0)
  {
    // Initiate service discovery
    SimpleCentral_enqueueMsg(SC_EVT_SVC_DISC, 0, NULL);

    // Diable GATT Read/Write until simple service is found
    itemsToDisable = SC_ITEM_GATTREAD | SC_ITEM_GATTWRITE;
  }

  // Set the menu title and go to this connection's context
  TBM_SET_TITLE(&scMenuPerConn, TBM_GET_ACTION_DESC(&scMenuSelectConn, index));

  // Set RSSI items properly depending on current state
  if (connList[index].pRssiClock == NULL)
  {
    tbm_setItemStatus(&scMenuPerConn,
                      SC_ITEM_STRTRSSI, SC_ITEM_STOPRSSI | itemsToDisable);
  }
  else
  {
    tbm_setItemStatus(&scMenuPerConn,
                      SC_ITEM_STOPRSSI, SC_ITEM_STRTRSSI | itemsToDisable);
  }

  // Clear non-connection-related message
  Display_clearLine(dispHandle, SC_ROW_NON_CONN);

  tbm_goTo(&scMenuPerConn);

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doGattRead
 *
 * @brief   GATT Read
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doGattRead(uint8_t index)
{
  attReadReq_t req;
  uint8_t connIndex = SimpleCentral_getConnIndex(scConnHandle);

  // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
  SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

  req.handle = connList[connIndex].charHandle;
  GATT_ReadCharValue(scConnHandle, &req, selfEntity);

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doGattWrite
 *
 * @brief   GATT Write
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doGattWrite(uint8_t index)
{
  status_t status;
  uint8_t charVals[4] = { 0x00, 0x55, 0xAA, 0xFF }; // Should be consistent with
                                                    // those in scMenuGattWrite

  attWriteReq_t req;

  req.pValue = GATT_bm_alloc(scConnHandle, ATT_WRITE_REQ, 1, NULL);

  if ( req.pValue != NULL )
  {
    uint8_t connIndex = SimpleCentral_getConnIndex(scConnHandle);

    // connIndex cannot be equal to or greater than MAX_NUM_BLE_CONNS
    SIMPLECENTRAL_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

    req.handle = connList[connIndex].charHandle;
    req.len = 1;
    charVal = charVals[index];
    req.pValue[0] = charVal;
    req.sig = 0;
    req.cmd = 0;

    status = GATT_WriteCharValue(scConnHandle, &req, selfEntity);
    if ( status != SUCCESS )
    {
      GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
    }
  }

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doRssiRead
 *
 * @brief   Toggle RSSI Read
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doRssiRead(uint8_t index)
{
  status_t status;

  if ((1 << index) == SC_ITEM_STRTRSSI)
  {
    if ((status = SimpleCentral_StartRssi()) == SUCCESS)
    {
      tbm_setItemStatus(&scMenuPerConn, SC_ITEM_STOPRSSI, SC_ITEM_STRTRSSI);
    }
  }
  else // SC_ITEM_STOP_RSSI
  {
    if ((status = SimpleCentral_CancelRssi(scConnHandle)) == SUCCESS)
    {
      tbm_setItemStatus(&scMenuPerConn, SC_ITEM_STRTRSSI, SC_ITEM_STOPRSSI);
    }
  }

  return ((status == SUCCESS) ? true : false);
}

/*********************************************************************
 * @fn      SimpleCentral_doConnUpdate
 *
 * @brief   Initiate Connection Update procedure
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doConnUpdate(uint8_t index)
{
  gapUpdateLinkParamReq_t params;

  (void) index;

  params.connectionHandle = scConnHandle;
  params.intervalMin = DEFAULT_UPDATE_MIN_CONN_INTERVAL;
  params.intervalMax = DEFAULT_UPDATE_MAX_CONN_INTERVAL;
  params.connLatency = DEFAULT_UPDATE_SLAVE_LATENCY;

  linkDBInfo_t linkInfo;
  if (linkDB_GetInfo(scConnHandle, &linkInfo) == SUCCESS)
  {
    if (linkInfo.connTimeout == DEFAULT_UPDATE_CONN_TIMEOUT)
    {
      params.connTimeout = DEFAULT_UPDATE_CONN_TIMEOUT + 200;
    }
    else
    {
      params.connTimeout = DEFAULT_UPDATE_CONN_TIMEOUT;
    }
  }
  else
  {
    Display_printf(dispHandle, SC_ROW_CUR_CONN, 0,
                   "update :%s, Unable to find link information",
                    Util_convertBdAddr2Str(linkInfo.addr));
  }
  GAP_UpdateLinkParamReq(&params);

  Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Param update Request:connTimeout =%d",
                 params.connTimeout*CONN_TIMEOUT_MS_CONVERSION);

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doSetConnPhy
 *
 * @brief   Set Connection PHY preference.
 *
 * @param   index - 0: 1M PHY
 *                  1: 2M PHY
 *                  2: 1M + 2M PHY
 *                  3: CODED PHY (Long range)
 *                  4: 1M + 2M + CODED PHY
 *
 * @return  always true
 */
bool SimpleCentral_doSetConnPhy(uint8_t index)
{
  static uint8_t phy[] = {
    HCI_PHY_1_MBPS, HCI_PHY_2_MBPS, HCI_PHY_1_MBPS | HCI_PHY_2_MBPS,
    HCI_PHY_CODED, HCI_PHY_1_MBPS | HCI_PHY_2_MBPS | HCI_PHY_CODED,
  };

  // Set Phy Preference on the current connection. Apply the same value
  // for RX and TX. For more information, see the LE 2M PHY section in the User's Guide:
  // http://software-dl.ti.com/lprf/ble5stack-latest/
  // Note PHYs are already enabled by default in build_config.opt in stack project.
  HCI_LE_SetPhyCmd(scConnHandle, 0, phy[index], phy[index], 0);

  Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "PHY preference: %s",
                 TBM_GET_ACTION_DESC(&scMenuConnPhy, index));

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_doDisconnect
 *
 * @brief   Disconnect the specified link
 *
 * @param   index - item index from the menu
 *
 * @return  always true
 */
bool SimpleCentral_doDisconnect(uint8_t index)
{
  (void) index;

  GAP_TerminateLinkReq(scConnHandle, HCI_DISCONNECT_REMOTE_USER_TERM);

  return (true);
}

/*********************************************************************
 * @fn      SimpleCentral_menuSwitchCb
 *
 * @brief   Detect menu context switching
 *
 * @param   pMenuObjCurr - the current menu object
 * @param   pMenuObjNext - the menu object the context is about to switch to
 *
 * @return  none
 */
static void SimpleCentral_menuSwitchCb(tbmMenuObj_t* pMenuObjCurr,
                                       tbmMenuObj_t* pMenuObjNext)
{
  // interested in only the events of
  // entering scMenuConnect, scMenuSelectConn, and scMenuMain for now
  if (pMenuObjNext == &scMenuConnect)
  {
    uint8_t i, j;
    uint32_t itemsToDisable = SC_ITEM_NONE;

    for (i = 0; i < TBM_GET_NUM_ITEM(&scMenuConnect); i++)
    {
      for (j = 0; j < MAX_NUM_BLE_CONNS; j++)
      {
        if ((connList[j].connHandle != CONNHANDLE_INVALID) &&
            !memcmp(TBM_GET_ACTION_DESC(&scMenuConnect, i),
                    Util_convertBdAddr2Str(connList[j].addr),
                    SC_ADDR_STR_SIZE))
        {
          // Already connected. Add to the set to be disabled.
          itemsToDisable |= (1 << i);
        }
      }
    }

    // Eventually only non-connected device addresses will be displayed.
    tbm_setItemStatus(&scMenuConnect,
                      SC_ITEM_ALL & ~itemsToDisable, itemsToDisable);
  }
  else if (pMenuObjNext == &scMenuSelectConn)
  {
    static uint8_t* pAddrs;
    uint8_t* pAddrTemp;

    if (pAddrs != NULL)
    {
      ICall_free(pAddrs);
    }

    // Allocate buffer to display addresses
    pAddrs = ICall_malloc(numConn * SC_ADDR_STR_SIZE);

    if (pAddrs == NULL)
    {
      TBM_SET_NUM_ITEM(&scMenuSelectConn, 0);
    }
    else
    {
      uint8_t i;

      TBM_SET_NUM_ITEM(&scMenuSelectConn, MAX_NUM_BLE_CONNS);

      pAddrTemp = pAddrs;

      // Add active connection info to the menu object
      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      {
        if (connList[i].connHandle != CONNHANDLE_INVALID)
        {
          // This connection is active. Set the corresponding menu item with
          // the address of this connection and enable the item.
          memcpy(pAddrTemp, Util_convertBdAddr2Str(connList[i].addr),
                 SC_ADDR_STR_SIZE);
          TBM_SET_ACTION_DESC(&scMenuSelectConn, i, pAddrTemp);
          tbm_setItemStatus(&scMenuSelectConn, (1 << i), SC_ITEM_NONE);
          pAddrTemp += SC_ADDR_STR_SIZE;
        }
        else
        {
          // This connection is not active. Disable the corresponding menu item.
          tbm_setItemStatus(&scMenuSelectConn, SC_ITEM_NONE, (1 << i));
        }
      }
    }
  }
  else if (pMenuObjNext == &scMenuMain)
  {
    // Now we are not in a specific connection's context
    scConnHandle = CONNHANDLE_INVALID;

    // Clear connection-related message
    Display_clearLine(dispHandle, SC_ROW_CUR_CONN);
  }
}


/*********************************************************************
*********************************************************************/

Please let me know what more changes require so , i can read /write GATT msgs .

Modified Project zero .

/*
 ******************************************************************************
 *****************************************************************************/

/*******************************************************************************
 * INCLUDES
 */
#define FMCU_APP
#define DEVINFO_SYSTEM_ID_LEN 8

#include <string.h>

#if !(defined __TI_COMPILER_VERSION__)
#include <intrinsics.h>
#endif


#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/BIOS.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/uart/UARTCC26X2.h>


#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/drivers/utils/List.h>

//#include <xdc/runtime/Log.h> // Comment this in to use xdc.runtime.Log
#include <uartlog/UartLog.h>  // Comment out if using xdc Log

#include <ti/display/AnsiColor.h>

#include <ti/devices/DeviceFamily.h>
#include DeviceFamily_constructPath(driverlib/sys_ctrl.h)

#include <icall.h>
#include <bcomdef.h>
/* This Header file contains all BLE API and icall structure definition */
#include <icall_ble_api.h>

/* Bluetooth Profiles */
//#include <devinfoservice.h>

#ifndef FMCU_APP
  #include <services/button_service.h>
  #include <services/led_service.h>
#endif

#define USE_RCOSC


/* Stack size in bytes */
#define THREADSTACKSIZE    1024


UART_Handle temp_handle;
uint8_t Start_timer_100msec=0;


#include <services/data_service.h>


/* Application specific includes */
#include <Board.h>

#include <project_zero.h>
#include <util.h>

#ifdef USE_RCOSC
 #include "rcosc_calibration.h"
#endif //USE_RCOSC



/*********************************************************************
 * MACROS
 */

// Spin if the expression is not true
#define APP_ASSERT(expr) if(!(expr)) {project_zero_spin();}

#define UTIL_ARRTOHEX_REVERSE     1
#define UTIL_ARRTOHEX_NO_REVERSE  0

/*********************************************************************
 * CONSTANTS
 */

uint8_t Wake_Event_Sts=0;
uint8_t TX_Count=0;

// Task configuration
#define PZ_TASK_PRIORITY                     1

#ifndef PZ_TASK_STACK_SIZE
#define PZ_TASK_STACK_SIZE                   2048
#endif

// Internal Events for RTOS application
#define PZ_ICALL_EVT                         ICALL_MSG_EVENT_ID  // Event_Id_31
#define PZ_APP_MSG_EVT                       Event_Id_30

// Bitwise OR of all RTOS events to pend on
#define PZ_ALL_EVENTS                        ( PZ_ICALL_EVT | PZ_APP_MSG_EVT )

// Types of messages that can be sent to the user application task from other
// tasks or interrupts. Note: Messages from BLE Stack are sent differently.
#define PZ_SERVICE_WRITE_EVT     0  /* A characteristic value has been written     */
#define PZ_SERVICE_CFG_EVT       1  /* A characteristic configuration has changed  */
#define PZ_UPDATE_CHARVAL_EVT    2  /* Request from ourselves to update a value    */
#define PZ_BUTTON_DEBOUNCED_EVT  3  /* A button has been debounced with new value  */
#define PZ_PAIRSTATE_EVT         4  /* The pairing state is updated                */
#define PZ_PASSCODE_EVT          5  /* A pass-code/PIN is requested during pairing */
#define PZ_ADV_EVT               6  /* A subscribed advertisement activity         */
#define PZ_START_ADV_EVT         7  /* Request advertisement start from task ctx   */
#define PZ_SEND_PARAM_UPD_EVT    8  /* Request parameter update req be sent        */
#define PZ_CONN_EVT              9  /* Connection Event End notice                 */

// General discoverable mode: advertise indefinitely
#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL

// Minimum connection interval (units of 1.25ms, 80=100ms) for parameter update request
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL     12

// Maximum connection interval (units of 1.25ms, 800=1000ms) for  parameter update request
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL     36

// Slave latency to use for parameter update request
#define DEFAULT_DESIRED_SLAVE_LATENCY         0

// Supervision timeout value (units of 10ms, 1000=10s) for parameter update request
#define DEFAULT_DESIRED_CONN_TIMEOUT          200

// Supervision timeout conversion rate to miliseconds
#define CONN_TIMEOUT_MS_CONVERSION            10

// Connection interval conversion rate to miliseconds
#define CONN_INTERVAL_MS_CONVERSION           1.25

// Pass parameter updates to the app for it to decide.
#define DEFAULT_PARAM_UPDATE_REQ_DECISION     GAP_UPDATE_REQ_PASS_TO_APP

// Delay (in ms) after connection establishment before sending a parameter update requst
#define PZ_SEND_PARAM_UPDATE_DELAY            6000

/*********************************************************************
 * TYPEDEFS
 */
// Struct for messages sent to the application task
typedef struct
{
    uint8_t event;
    void    *pData;
} pzMsg_t;

// Struct for messages about characteristic data
typedef struct
{
    uint16_t svcUUID; // UUID of the service
    uint16_t dataLen; //
    uint8_t paramID; // Index of the characteristic
    uint8_t data[]; // Flexible array member, extended to malloc - sizeof(.)
} pzCharacteristicData_t;

// Struct for message about sending/requesting passcode from peer.
typedef struct
{
    uint16_t connHandle;
    uint8_t uiInputs;
    uint8_t uiOutputs;
    uint32_t numComparison;
} pzPasscodeReq_t;

// Struct for message about a pending parameter update request.
typedef struct
{
    uint16_t connHandle;
} pzSendParamReq_t;

#ifndef FMCU_APP
// Struct for message about button state
typedef struct
{
    PIN_Id pinId;
    uint8_t state;
} pzButtonState_t;
#endif

// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
    uint8_t state;
    uint16_t connHandle;
    uint8_t status;
} pzPairStateData_t;

// Container to store passcode data when passing from gapbondmgr callback
// to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h
// header file for more information on each parameter.
typedef struct
{
    uint8_t deviceAddr[B_ADDR_LEN];
    uint16_t connHandle;
    uint8_t uiInputs;
    uint8_t uiOutputs;
    uint32_t numComparison;
} pzPasscodeData_t;

// Container to store advertising event data when passing from advertising
// callback to app event. See the respective event in GapAdvScan_Event_IDs
// in gap_advertiser.h for the type that pBuf should be cast to.
typedef struct
{
    uint32_t event;
    void *pBuf;
} pzGapAdvEventData_t;

// List element for parameter update and PHY command status lists
typedef struct
{
    List_Elem elem;
    uint16_t *connHandle;
} pzConnHandleEntry_t;

// Connected device information
typedef struct
{
    uint16_t connHandle;                    // Connection Handle
    Clock_Struct* pUpdateClock;             // pointer to clock struct
    bool phyCngRq;                          // Set to true if PHY change request is in progress
    uint8_t currPhy;                        // The active PHY for a connection
    uint8_t rqPhy;                          // The requested PHY for a connection
    uint8_t phyRqFailCnt;                   // PHY change request fail count
} pzConnRec_t;

/*********************************************************************
 * GLOBAL VARIABLES
 */
// Task configuration
Task_Struct pzTask;
#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(appTaskStack, 8)
#else
#pragma data_alignment=8
#endif
uint8_t appTaskStack[PZ_TASK_STACK_SIZE];

static uint8_t ResponseStatus=0;

/*********************************************************************
 * LOCAL VARIABLES
 */

// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;

// Event globally used to post local events and pend on system and
// local events.
static ICall_SyncHandle syncEvent;

// Queue object used for app messages
static Queue_Struct appMsgQueue;
static Queue_Handle appMsgQueueHandle;

// GAP GATT Attributes
static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "FMCU MML";

/*
// Advertisement data
static uint8_t advertData[] =
{
    0x02, // length of this data
    GAP_ADTYPE_FLAGS,
    DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

    // complete name
   14, // length of this data
    GAP_ADTYPE_LOCAL_NAME_COMPLETE,
    'T',
    'T',
    'T',
    'T',
    '-',
    'B',
    'L',
    'E',
    '-',
    'T',
    'T',
    'T',
    'T',
};

// Scan Response Data
static uint8_t scanRspData[] =
{
//     service UUID, to notify central devices what services are included
//     in this peripheral
  //(ATT_UUID_SIZE + 0x01),   // length of this data, LED service UUID + header
  //GAP_ADTYPE_128BIT_MORE,   // some of the UUID's, but not all

 // (ATT_UUID_SIZE),
 // GAP_ADTYPE_128BIT_COMPLETE,
 // DATA_SERVICE_SERV_UUID_BASE128(DATA_SERVICE_SERV_UUID),
};
*/


// Advertisement data
static uint8_t advertData[] =
{
  0x02,   // length of this data
  GAP_ADTYPE_FLAGS,
  DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

  // service UUID, to notify central devices what services are included
  // in this peripheral
  0x03,   // length of this data //0x03
  GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all //GAP_ADTYPE_16BIT_MORE
  //GAP_ADTYPE_16BIT_COMPLETE,
  //DATA_SERVICE_SERV_UUID_BASE128(DATA_SERVICE_SERV_UUID),
  LO_UINT16(DATA_SERVICE_SERV_UUID),
  HI_UINT16(DATA_SERVICE_SERV_UUID)
};

// Scan Response Data
static uint8_t scanRspData[] =
{
  // complete name
  14,   // length of this data
  GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  'T',
  'T',
  'T',
  'T',
  '-',
  'B',
  'L',
  'E',
  '-',
  'T',
  'T',
  'T',
  'T',

  // connection interval range
  5,   // length of this data
  GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
  LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),   // 100ms
  HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
  LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),   // 1s
  HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),

  // Tx power level
  2,   // length of this data
  GAP_ADTYPE_POWER_LEVEL,
  0       // 0dBm
};



// Advertising handles
static uint8_t advHandleLegacy;

// Per-handle connection info
static pzConnRec_t connList[MAX_NUM_BLE_CONNS];

// List to store connection handles for set phy command status's
static List_List setPhyCommStatList;

// List to store connection handles for queued param updates
static List_List paramUpdateList;

#ifndef FMCU_APP

/* Pin driver handles */
static PIN_Handle buttonPinHandle;
static PIN_Handle ledPinHandle;

/* Global memory storage for a PIN_Config table */
static PIN_State buttonPinState;
static PIN_State ledPinState;

#endif

//#ifdef FMCU_APP_WAKEUP
 static PIN_Handle ledPinHandle;
 static PIN_State ledPinState;
//#endif

/*
 * Initial LED pin configuration table
 *   - LEDs Board_PIN_LED0 & Board_PIN_LED1 are off.
 */
PIN_Config ledPinTable[] =
{
    Board_PIN_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |   PIN_DRVSTR_MAX,
    Board_PIN_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |   PIN_DRVSTR_MAX,
    WakeUp_Event | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |   PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

#ifdef FMCU_APP
/*
 * Application button pin configuration table:
 *   - Buttons interrupts are configured to trigger on falling edge.
 */
PIN_Config buttonPinTable[] = {
    Board_PIN_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    Board_PIN_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    PIN_TERMINATE
};

// Clock objects for debouncing the buttons
static Clock_Struct button0DebounceClock;
static Clock_Struct button1DebounceClock;
static Clock_Handle button0DebounceClockHandle;
static Clock_Handle button1DebounceClockHandle;

// State of the buttons
static uint8_t button0State = 0;
static uint8_t button1State = 0;
#endif

static Clock_Struct Wait_Timer_100ms_Clock;
static Clock_Handle Wait_Timer_100ms;

// Create the FMCU WakeUp Event clock objects
static void WakeupEventFunction();


static void WakeupEventFunction()
{
 Start_timer_100msec=0;
}

//Util_startClock((Clock_Struct *)LeadMe_WakeUpClockHandle);
//Util_startClock((Clock_Struct *)EngineStart_WakeUpClockHandle);



/*********************************************************************
 * LOCAL FUNCTIONS
 */

void Send_Packet(UART_Handle handle);
char* itoa(int num, char* str, int base);

/* Task functions */
static void ProjectZero_init(void);
static void ProjectZero_taskFxn(UArg a0,UArg a1);

/* Event message processing functions */
static void ProjectZero_processStackEvent(uint32_t stack_event);
//static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg,UART_Handle handle);
static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg);
static uint8_t ProjectZero_processGATTMsg(gattMsgEvent_t *pMsg);
static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg);

static void ProjectZero_processHCIMsg(ICall_HciExtEvt *pMsg);
//static void ProjectZero_processHCIMsg(ICall_HciExtEvt *pMsg,UART_Handle Uart_handle);
static void ProjectZero_processPairState(pzPairStateData_t *pPairState);
static void ProjectZero_processPasscode(pzPasscodeReq_t *pReq);
static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
//static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg,UART_Handle Uart_handle);
static void ProjectZero_processAdvEvent(pzGapAdvEventData_t *pEventData);

/* Profile value change handlers */
static void ProjectZero_updateCharVal(pzCharacteristicData_t *pCharData);

#ifdef FMCU_APP
static void ProjectZero_LedService_ValueChangeHandler(pzCharacteristicData_t *pCharData);
static void ProjectZero_ButtonService_CfgChangeHandler(pzCharacteristicData_t *pCharData);
#endif

static void ProjectZero_DataService_ValueChangeHandler(pzCharacteristicData_t *pCharData);

//static void ProjectZero_DataService_ValueChangeHandler(pzCharacteristicData_t *pCharData,UART_Handle handle);
static void ProjectZero_DataService_CfgChangeHandler(pzCharacteristicData_t *pCharData);

/* Stack or profile callback function */
static void ProjectZero_advCallback(uint32_t event,
                                    void *pBuf,
                                    uintptr_t arg);
static void ProjectZero_passcodeCb(uint8_t *pDeviceAddr,
                                   uint16_t connHandle,
                                   uint8_t uiInputs,
                                   uint8_t uiOutputs,
                                   uint32_t numComparison);
static void ProjectZero_pairStateCb(uint16_t connHandle,
                                    uint8_t state,
                                    uint8_t status);
#ifndef FMCU_APP
static void ProjectZero_LedService_ValueChangeCB(uint16_t connHandle,
                                                 uint8_t paramID,
                                                 uint16_t len,
                                                 uint8_t *pValue);
#endif

static void ProjectZero_DataService_ValueChangeCB(uint16_t connHandle,
                                                  uint8_t paramID,
                                                  uint16_t len,
                                                  uint8_t *pValue);
#ifndef FMCU_APP
static void ProjectZero_ButtonService_CfgChangeCB(uint16_t connHandle,
                                                  uint8_t paramID,
                                                  uint16_t len,
                                                  uint8_t *pValue);
#endif
static void ProjectZero_DataService_CfgChangeCB(uint16_t connHandle,
                                                uint8_t paramID,
                                                uint16_t len,
                                                uint8_t *pValue);

/* Connection handling functions */
static uint8_t ProjectZero_getConnIndex(uint16_t connHandle);
static uint8_t ProjectZero_clearConnListEntry(uint16_t connHandle);
static uint8_t ProjectZero_addConn(uint16_t connHandle);
static uint8_t ProjectZero_removeConn(uint16_t connHandle);

static void ProjectZero_updatePHYStat(uint16_t eventCode,uint8_t *pMsg);
static void ProjectZero_handleUpdateLinkParamReq(gapUpdateLinkParamReqEvent_t *pReq);
static void ProjectZero_sendParamUpdate(uint16_t connHandle);
static void ProjectZero_handleUpdateLinkEvent(gapLinkUpdateEvent_t *pEvt);
static void ProjectZero_paramUpdClockHandler(UArg arg);
static void ProjectZero_processConnEvt(Gap_ConnEventRpt_t *pReport);

#ifndef FMCU_APP

/* Button handling functions */
static void buttonDebounceSwiFxn(UArg buttonId);
static void buttonCallbackFxn(PIN_Handle handle,PIN_Id pinId);
static void ProjectZero_handleButtonPress(pzButtonState_t *pState);

#endif

/* Utility functions */
static status_t ProjectZero_enqueueMsg(uint8_t event,void *pData);


static char * util_arrtohex(uint8_t const *src,
                            uint8_t src_len,
                            uint8_t       *dst,
                            uint8_t dst_len,
                            uint8_t reverse);
static char * util_getLocalNameStr(const uint8_t *advData, uint8_t len);
static void ProjectZero_processL2CAPMsg(l2capSignalEvent_t *pMsg);

/*********************************************************************
 * EXTERN FUNCTIONS
 */
extern void AssertHandler(uint8_t assertCause,
                          uint8_t assertSubcause);

/*********************************************************************
 * PROFILE CALLBACKS
 */
// GAP Bond Manager Callbacks
static gapBondCBs_t ProjectZero_BondMgrCBs =
{
    ProjectZero_passcodeCb,     // Passcode callback
    ProjectZero_pairStateCb     // Pairing/Bonding state Callback
};

/*
 * Callbacks in the user application for events originating from BLE services.
 */
#ifndef FMCU_APP

// LED Service callback handler.
// The type LED_ServiceCBs_t is defined in led_service.h
static LedServiceCBs_t ProjectZero_LED_ServiceCBs =
{
    .pfnChangeCb = ProjectZero_LedService_ValueChangeCB,  // Characteristic value change callback handler
    .pfnCfgChangeCb = NULL, // No notification-/indication enabled chars in LED Service
};

// Button Service callback handler.
// The type Button_ServiceCBs_t is defined in button_service.h
static ButtonServiceCBs_t ProjectZero_Button_ServiceCBs =
{
    .pfnChangeCb = NULL,  // No writable chars in Button Service, so no change handler.
    .pfnCfgChangeCb = ProjectZero_ButtonService_CfgChangeCB, // Noti/ind configuration callback handler
};
#endif

// Data Service callback handler.
// The type Data_ServiceCBs_t is defined in data_service.h
static DataServiceCBs_t ProjectZero_Data_ServiceCBs =
{
    .pfnChangeCb = ProjectZero_DataService_ValueChangeCB,  // Characteristic value change callback handler
    .pfnCfgChangeCb = ProjectZero_DataService_CfgChangeCB, // Noti/ind configuration callback handler
};


/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn     project_zero_spin
 *
 * @brief   Spin forever
 */
static void project_zero_spin(void)
{
  volatile uint8_t x = 0;;

  while(1)
  {
    x++;
  }
}

/*********************************************************************
 * @fn      ProjectZero_createTask
 *
 * @brief   Task creation function for the Project Zero.
 */
void ProjectZero_createTask()
  {

    Task_Params taskParams;

   //  Configure task
    Task_Params_init(&taskParams);
    taskParams.stack = appTaskStack;
    taskParams.stackSize = PZ_TASK_STACK_SIZE;
    taskParams.priority = PZ_TASK_PRIORITY;

    Task_construct(&pzTask, ProjectZero_taskFxn, &taskParams, NULL);
}


/*********************************************************************
 * @fn      ProjectZero_init
 *
 * @brief   Called during initialization and contains application
 *          specific initialization (ie. hardware initialization/setup,
 *          table initialization, power up notification, etc), and
 *          profile initialization/setup.
 */
static void ProjectZero_init(void)
{


    //Log_info0( "Entering in ProjectZero_init");
    // ******************************************************************
    // NO STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
    // ******************************************************************
    // Register the current thread as an ICall dispatcher application
    // so that the application can send and receive messages.
    ICall_registerApp(&selfEntity, &syncEvent);

    // Initialize queue for application messages.
    // Note: Used to transfer control to application thread from e.g. interrupts.
    Queue_construct(&appMsgQueue, NULL);
    appMsgQueueHandle = Queue_handle(&appMsgQueue);

    // ******************************************************************
    // Hardware initialization
    // ******************************************************************

#ifdef USE_RCOSC
     RCOSC_enableCalibration();
#endif // USE_RCOSC

#ifndef FMCU_APP_WAKEUP

     Wait_Timer_100ms = Util_constructClock(&Wait_Timer_100ms_Clock,
                                                WakeupEventFunction,100,
                                                0,
                                                0,
                                                0);
#endif


    // Set the Device Name characteristic in the GAP GATT Service
    // For more information, see the section in the User's Guide:
    // http://software-dl.ti.com/lprf/ble5stack-latest/

//    Log_info1("Line 636","Entering in GGS_SetParameter");
    GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);

    // Configure GAP for param update
    {
        uint16_t paramUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION;

        // Pass all parameter update requests to the app for it to decide
        GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision);
    }

    // Setup the GAP Bond Manager. For more information see the GAP Bond Manager
    // section in the User's Guide:
    // http://software-dl.ti.com/lprf/ble5stack-latest/
    {
        // Don't send a pairing request after connecting (the peer device must
        // initiate pairing)
        uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
        // Use authenticated pairing: require passcode.
        uint8_t mitm = TRUE;
        // This device only has display capabilities. Therefore, it will display the
        // passcode during pairing. However, since the default passcode is being
        // used, there is no need to display anything.
        uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
        // Request bonding (storing long-term keys for re-encryption upon subsequent
        // connections without repairing)
        uint8_t bonding = TRUE;

        // For Authentication
        uint8_t gapbondSecure = GAPBOND_SECURE_CONNECTION_ONLY;//Only Secure connection only
        GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &gapbondSecure);

        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t),     &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t),  &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t),  &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t),  &bonding);
    }

    // ******************************************************************
    // BLE Service initialization
    // ******************************************************************
  //  Log_info0("BLE Service initialization");

    GGS_AddService(GATT_ALL_SERVICES);         // GAP GATT Service
    GATTServApp_AddService(GATT_ALL_SERVICES); // GATT Service
#ifndef FMCU_APP
    //DevInfo_AddService();                      // Device Information Service


    // Add services to GATT server and give ID of this task for Indication acks.
    LedService_AddService(selfEntity);
    ButtonService_AddService(selfEntity);
#endif
     //DevInfo_AddService();                      // Device Information Service
    //Log_info0(" Entering in DataService_AddService");
    DataService_AddService(selfEntity);

#ifndef FMCU_APP

    // Register callbacks with the generated services that
    // can generate events (writes received) to the application
   LedService_RegisterAppCBs(&ProjectZero_LED_ServiceCBs);
   ButtonService_RegisterAppCBs(&ProjectZero_Button_ServiceCBs);
#endif
    //Log_info0("Entering in DataService_RegisterAppCBs");
    DataService_RegisterAppCBs(&ProjectZero_Data_ServiceCBs);

    // Placeholder variable for characteristic intialization
    uint8_t initVal[40] = {0};
    uint8_t initString[] = "This is a pretty long string, isn't it!";

#ifndef FMCU_APP

    // Initalization of characteristics in LED_Service that can provide data.
  LedService_SetParameter(LS_LED0_ID, LS_LED0_LEN, initVal);
  LedService_SetParameter(LS_LED1_ID, LS_LED1_LEN, initVal);

    // Initalization of characteristics in Button_Service that can provide data.
  ButtonService_SetParameter(BS_BUTTON0_ID, BS_BUTTON0_LEN, initVal);
  ButtonService_SetParameter(BS_BUTTON1_ID, BS_BUTTON1_LEN, initVal);

#endif
    // Initalization of characteristics in Data_Service that can provide data.
  //DataService_SetParameter(DS_STRING_ID, sizeof(initString), initString);
    //Log_info0("Entering in DataService_SetParameter");
    DataService_SetParameter(DS_STREAM_ID, DS_STREAM_LEN, initVal);

    // Start Bond Manager and register callback
    VOID GAPBondMgr_Register(&ProjectZero_BondMgrCBs);

    // Register with GAP for HCI/Host messages. This is needed to receive HCI
    // events. For more information, see the HCI section in the User's Guide:
    // http://software-dl.ti.com/lprf/ble5stack-latest/
    GAP_RegisterForMsgs(selfEntity);

    // Register for GATT local events and ATT Responses pending for transmission
    GATT_RegisterForMsgs(selfEntity);

    // Set default values for Data Length Extension
    // Extended Data Length Feature is already enabled by default
    {
      // Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
      // Some brand smartphone is essentially needing 251/2120, so we set them here.
      #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
      #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)

      // This API is documented in hci.h
      // See the LE Data Length Extension section in the BLE5-Stack User's Guide for information on using this command:
      // http://software-dl.ti.com/lprf/ble5stack-latest/
      HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
    }

    // Initialize GATT Client, used by GAPBondMgr to look for RPAO characteristic for network privacy
    GATT_InitClient();

    // Initialize Connection List
    ProjectZero_clearConnListEntry(CONNHANDLE_ALL);

    //Initialize GAP layer for Peripheral role and register to receive GAP events
    GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, selfEntity, ADDRMODE_PUBLIC, NULL);
}

/*********************************************************************
 * @fn      ProjectZero_taskFxn
 *
 * @brief   Application task entry point for the Project Zero.
 *
 * @param   a0, a1 - not used.
 */





Semaphore_Struct sem;
Semaphore_Handle hSem;


static void uartRxCb(UART_Handle handle, void *buf, size_t count);

static void ProjectZero_taskFxn(UArg a0, UArg a1)
{
   // Initialize application
    ProjectZero_init();


    Semaphore_Params sParams;
    Semaphore_Params_init(&sParams);
    sParams.mode = Semaphore_Mode_BINARY;

    Semaphore_construct(&sem, 0, &sParams);
    hSem = Semaphore_handle(&sem);

    // Application main loop
    for(;; )
    {
        uint32_t events;

        // Waits for an event to be posted associated with the calling thread.
        // Note that an event associated with a thread is posted when a
        // message is queued to the message receive queue of the thread
        events = Event_pend(syncEvent, Event_Id_NONE, PZ_ALL_EVENTS,ICALL_TIMEOUT_FOREVER);


        if(events)
        {
            // Log_info1("Events %d %s",events);
            ICall_EntityID dest;
            ICall_ServiceEnum src;
            ICall_HciExtEvt *pMsg = NULL;

            // Fetch any available messages that might have been sent from the stack
            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)
                    {
                        // Process stack events
                        ProjectZero_processStackEvent(pEvt->event_flag);
                    }
                    else
                    {
                        switch(pMsg->hdr.event)
                        {
                        case GAP_MSG_EVENT:
                            // Process GAP message
                            // Log_info0(" Entering ProjectZero_processGapMessage "); //only fmcu debug
                            ProjectZero_processGapMessage((gapEventHdr_t*) pMsg);
                            // Log_info0(" Exit from ProjectZero_processGapMessage "); //only fmcu debug
                            break;

                        case GATT_MSG_EVENT:
                            // Process GATT message
                            // Log_info0(" Entering ProjectZero_processGATTMsg "); //only fmcu debug
                            safeToDealloc = ProjectZero_processGATTMsg((gattMsgEvent_t *)pMsg);
                            // Log_info0(" Exit from ProjectZero_processGATTMsg "); //only fmcu debug
                            break;

                        case HCI_GAP_EVENT_EVENT:
                            ProjectZero_processHCIMsg(pMsg);//,hUART);
                            break;

                        case L2CAP_SIGNAL_EVENT:
                            // Process L2CAP free buffer notification
                            ProjectZero_processL2CAPMsg((l2capSignalEvent_t *)pMsg);
                            break;

                        default:
                            // do nothing
                            break;
                        }
                    }
                }

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

            // Process messages sent from another task or another context.
            while(!Queue_empty(appMsgQueueHandle))
            {
                pzMsg_t *pMsg = (pzMsg_t *)Util_dequeueMsg(appMsgQueueHandle);
                if(pMsg)
                {
                    // Log_info0(" Entering ProjectZero_processApplicationMessage "); //only fmcu debug
                    // Process application-layer message probably sent from ourselves.
                    //ProjectZero_processApplicationMessage(pMsg,hUART);
                    ProjectZero_processApplicationMessage(pMsg);
                    // Free the received message.
                    ICall_free(pMsg);
                }
            }
        }
    }
}

/*********************************************************************
 * @fn      ProjectZero_processL2CAPMsg
 *
 * @brief   Process L2CAP messages and events.
 *
 * @param   pMsg - L2CAP signal buffer from stack
 *
 * @return  None
 */
static void ProjectZero_processL2CAPMsg(l2capSignalEvent_t *pMsg)
{
    switch(pMsg->opcode)
    {
      case L2CAP_NUM_CTRL_DATA_PKT_EVT:
          break;
      default:
          break;
    }
}


/*********************************************************************
 * @fn      ProjectZero_processStackEvent
 *
 * @brief   Process stack event. The event flags received are user-selected
 *          via previous calls to stack APIs.
 *
 * @param   stack_event - mask of events received
 *
 * @return  none
 */
static void ProjectZero_processStackEvent(uint32_t stack_event)
{
    // Intentionally blank
}

/*********************************************************************
 * @fn      ProjectZero_processGATTMsg
 *
 * @brief   Process GATT messages and events.
 *
 * @param   pMsg - message to process
 *
 * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
 */
static uint8_t ProjectZero_processGATTMsg(gattMsgEvent_t *pMsg)
{
    if(pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
    {
        // ATT request-response or indication-confirmation flow control is
        // violated. All subsequent ATT requests or indications will be dropped.
        // The app is informed in case it wants to drop the connection.

        // Display the opcode of the message that caused the violation.
        Log_error1("FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
    }
    else if(pMsg->method == ATT_MTU_UPDATED_EVENT)
    {
        // MTU size updated
        Log_info1("MTU Size: %d", pMsg->msg.mtuEvt.MTU);
    }

    // Free message payload. Needed only for ATT Protocol messages
    GATT_bm_free(&pMsg->msg, pMsg->method);

    // It's safe to free the incoming message
    return(TRUE);
}

/*********************************************************************
 * @fn      ProjectZero_processApplicationMessage
 *
 * @brief   Handle application messages
 *
 *          These are messages not from the BLE stack, but from the
 *          application itself.
 *
 *          For example, in a Software Interrupt (Swi) it is not possible to
 *          call any BLE APIs, so instead the Swi function must send a message
 *          to the application Task for processing in Task context.
 *
 * @param   pMsg  Pointer to the message of type pzMsg_t.
 */
//static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg,UART_Handle handle)
static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg)
{
    // Cast to pzCharacteristicData_t* here since it's a common message pdu type.
    pzCharacteristicData_t *pCharData = (pzCharacteristicData_t *)pMsg->pData;

    Log_info2("Inside Process application message %s %d ",pMsg->event,pMsg->event);

    switch(pMsg->event)
    {
      case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
          AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
          break;

      case PZ_SERVICE_WRITE_EVT: /* Message about received value write */
          /* Call different handler per service */

          Log_info0("PZ_SERVICE_WRITE_EVT");

          switch(pCharData->svcUUID)
          {
#ifndef FMCU_APP

          case LED_SERVICE_SERV_UUID:
                ProjectZero_LedService_ValueChangeHandler(pCharData);
                break;
#endif
          case DATA_SERVICE_SERV_UUID:
              //Log_info1("Line 956","Entering in ProjectZero_DataService_ValueChangeHandler");
                Log_info0("Entering in ProjectZero_DataService_ValueChangeHandler ");
                ProjectZero_DataService_ValueChangeHandler(pCharData);
                break;
          }
          /****Added RSSI Read Value ***/
          // HCI_ReadRssiCmd(advHandleLegacy);
          break;

      case PZ_SERVICE_CFG_EVT: /* Message about received CCCD write */
          /* Call different handler per service */
          switch(pCharData->svcUUID)
          {
#ifndef FMCU_APP
          case BUTTON_SERVICE_SERV_UUID:
                ProjectZero_ButtonService_CfgChangeHandler(pCharData);
                break;
#endif
          case DATA_SERVICE_SERV_UUID:
              Log_info1("Line 972","Entering in ProjectZero_DataService_CfgChangeHandler");
                ProjectZero_DataService_CfgChangeHandler(pCharData);
                break;
          }
          break;

      case PZ_UPDATE_CHARVAL_EVT: /* Message from ourselves to send  */
          ProjectZero_updateCharVal(pCharData);
          break;

#ifndef FMCU_APP
      case PZ_BUTTON_DEBOUNCED_EVT: /* Message from swi about pin change */
      {
          pzButtonState_t *pButtonState = (pzButtonState_t *)pMsg->pData;
          ProjectZero_handleButtonPress(pButtonState);
      }
      break;
#endif

      case PZ_ADV_EVT:
          ProjectZero_processAdvEvent((pzGapAdvEventData_t*)(pMsg->pData));
          break;

      case PZ_SEND_PARAM_UPD_EVT:
      {
          // Send connection parameter update
          pzSendParamReq_t* req = (pzSendParamReq_t *)pMsg->pData;
          ProjectZero_sendParamUpdate(req->connHandle);
      }
      break;

      case PZ_START_ADV_EVT:
          if(linkDB_NumActive() < MAX_NUM_BLE_CONNS)
          {
              // Enable advertising if there is room for more connections
              GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
          }
          break;

      case PZ_PAIRSTATE_EVT: /* Message about the pairing state */
          ProjectZero_processPairState((pzPairStateData_t*)(pMsg->pData));
          break;

      case PZ_PASSCODE_EVT: /* Message about pairing PIN request */
      {
          pzPasscodeReq_t *pReq = (pzPasscodeReq_t *)pMsg->pData;
          ProjectZero_processPasscode(pReq);
      }
      break;

      case PZ_CONN_EVT:
        ProjectZero_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData));
        break;

      default:
        break;
    }

    if(pMsg->pData != NULL)
    {
        ICall_free(pMsg->pData);
    }
}

/*********************************************************************
 * @fn      ProjectZero_processGapMessage
 *
 * @brief   Process an incoming GAP event.
 *
 * @param   pMsg - message to process
 */
static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg)
{
    switch(pMsg->opcode)
    {
    case GAP_DEVICE_INIT_DONE_EVENT:
    {
        bStatus_t status = FAILURE;

        gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;

        if(pPkt->hdr.status == SUCCESS)
        {

            //Store the system ID
            uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];

            // use 6 bytes of device address for 8 bytes of system ID value
            systemId[0] = pPkt->devAddr[0];
            systemId[1] = pPkt->devAddr[1];
            systemId[2] = pPkt->devAddr[2];

            // set middle bytes to zero
            systemId[4] = 0x00;
            systemId[3] = 0x00;

            // shift three bytes up
            systemId[7] = pPkt->devAddr[5];
            systemId[6] = pPkt->devAddr[4];
            systemId[5] = pPkt->devAddr[3];

            // Set Device Info Service Parameter
      //DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN,systemId);

            // Display device address
            // Need static so string persists until printed in idle thread.
            static uint8_t addrStr[3 * B_ADDR_LEN + 1];
            util_arrtohex(pPkt->devAddr, B_ADDR_LEN, addrStr, sizeof addrStr,
                          UTIL_ARRTOHEX_REVERSE);
          Log_info1("GAP is started. Our address: " \
                      ANSI_COLOR(FG_GREEN) "%s" ANSI_COLOR(ATTR_RESET),
                      (uintptr_t)addrStr);

            // Setup and start Advertising
            // For more information, see the GAP section in the User's Guide:
            // http://software-dl.ti.com/lprf/ble5stack-latest/

            // Temporary memory for advertising parameters for set #1. These will be copied
            // by the GapAdv module
            GapAdv_params_t advParamLegacy = GAPADV_PARAMS_LEGACY_SCANN_CONN;

            // Create Advertisement set #1 and assign handle
            status = GapAdv_create(&ProjectZero_advCallback, &advParamLegacy,
                                   &advHandleLegacy);
            APP_ASSERT(status == SUCCESS);

            Log_info1("Name in advertData array: " \
                      ANSI_COLOR(FG_YELLOW) "%s" ANSI_COLOR(ATTR_RESET),
                      (uintptr_t)util_getLocalNameStr(advertData,
                                                      sizeof(advertData)));

            // Load advertising data for set #1 that is statically allocated by the app
            status = GapAdv_loadByHandle(advHandleLegacy, GAP_ADV_DATA_TYPE_ADV,
                                         sizeof(advertData), advertData);
            APP_ASSERT(status == SUCCESS);

            // Load scan response data for set #1 that is statically allocated by the app
            status =
                GapAdv_loadByHandle(advHandleLegacy, GAP_ADV_DATA_TYPE_SCAN_RSP,
                                    sizeof(scanRspData),
                                    scanRspData);
            APP_ASSERT(status == SUCCESS);

            // Set event mask for set #1
            status = GapAdv_setEventMask(advHandleLegacy,
                                         GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
                                         GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
                                         GAP_ADV_EVT_MASK_SET_TERMINATED);

            // Enable legacy advertising for set #1
            status =
                GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX,
                              0);
            APP_ASSERT(status == SUCCESS);
        }

        break;
    }

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

        // Display the amount of current connections
        Log_info2("Link establish event, status 0x%02x. Num Conns: %d",
                  pPkt->hdr.status,
                  linkDB_NumActive());

        if(pPkt->hdr.status == SUCCESS)
        {
            // Add connection to list
            ProjectZero_addConn(pPkt->connectionHandle);

            // Display the address of this connection
            static uint8_t addrStr[3 * B_ADDR_LEN + 1];
            util_arrtohex(pPkt->devAddr, B_ADDR_LEN, addrStr, sizeof addrStr,
                          UTIL_ARRTOHEX_REVERSE);
//            Log_info1("Connected. Peer address: " \
//                        ANSI_COLOR(FG_GREEN)"%s"ANSI_COLOR(ATTR_RESET),
//                      (uintptr_t)addrStr);

            //Set Dio_7 High to Know FMCU that mobile is connected
            PIN_setOutputValue(ledPinHandle, WakeUp_Event,1);
        }

        if(linkDB_NumActive() < MAX_NUM_BLE_CONNS)
        {
//            Log_info1("Continue to Advertise, %d possible connection remain", MAX_NUM_BLE_CONNS - linkDB_NumActive());
            // Start advertising since there is room for more connections
            GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
        }
        else
        {
//            Log_info1("Max Number of Connection reach: %d, Adv. will not be enable again", linkDB_NumActive());
        }
    }
    break;

    case GAP_LINK_TERMINATED_EVENT:
    {
        gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;

        // Set DIO_7 Low For FMCU to know device is disconnected or out of range
        PIN_setOutputValue(ledPinHandle, WakeUp_Event,0);

        // Display the amount of current connections
        Log_info0("Device Disconnected!");
        Log_info1("Num Conns: %d", linkDB_NumActive());

        // Remove the connection from the list and disable RSSI if needed
        ProjectZero_removeConn(pPkt->connectionHandle);

        // GapAdv_enable will return success only if the maximum number of connections 
        // has been reached, and adv was not re-enable in GAP_LINK_ESTABLISHED_EVENT
        // switch case.
        // If less connection were in used, Advertisement will have been restart in 
        // the GAP_LINK_ESTABLISHED_EVENT switch case and calling GapAdv_enable will
        // just return an error.
        if ( GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0) == SUCCESS)
        {
//          Log_info1("Restart Advertising, %d possible connection remain", MAX_NUM_BLE_CONNS - linkDB_NumActive());
        }
    }
    break;

    case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
//        Log_info0("GAP_UPDATE_LINK_PARAM_REQ_EVENT");
        ProjectZero_handleUpdateLinkParamReq((gapUpdateLinkParamReqEvent_t *)pMsg);
        break;

    case GAP_LINK_PARAM_UPDATE_EVENT:
       // Log_info0("GAP_LINK_PARAM_UPDATE_EVENT");//Only Debug FMCU Mux
        ProjectZero_handleUpdateLinkEvent((gapLinkUpdateEvent_t *)pMsg);
        //Log_info0(" coming out of GAP_LINK_PARAM_UPDATE_EVENT");//Only Debug FMCU Mux
        break;

    case GAP_PAIRING_REQ_EVENT:
        // Disable advertising so that the peer device can be added to
        // the resolving list
        GapAdv_disable(advHandleLegacy);
        break;

    default:
        break;
    }
}
void ProjectZero_processHCIMsg(ICall_HciExtEvt *pEvt)
//void ProjectZero_processHCIMsg(ICall_HciExtEvt *pEvt,UART_Handle hUART)
{
    ICall_Hdr *pMsg = (ICall_Hdr *)pEvt;

    // Process HCI message
    switch(pMsg->status)
    {
    case HCI_COMMAND_COMPLETE_EVENT_CODE:
        // Process HCI Command Complete Events here
        ProjectZero_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
        //UART_write(hUART,"Going",5);
        //ProjectZero_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg, hUART);

        break;

    case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
        AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
        break;

    // HCI Commands Events
    case HCI_COMMAND_STATUS_EVENT_CODE:
    {
        hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
        switch(pMyMsg->cmdOpcode)
        {
        case HCI_LE_SET_PHY:
        {
            if(pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
            {
//                Log_info0("PHY Change failure, peer does not support this");
            }
            else
            {
//                Log_info1("PHY Update Status Event: 0x%x",
//                          pMyMsg->cmdStatus);
            }

            ProjectZero_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg);
        }
        break;

        default:
            break;
        }
    }
    break;

    // LE Events
    case HCI_LE_EVENT_CODE:
    {
        hciEvt_BLEPhyUpdateComplete_t *pPUC =
            (hciEvt_BLEPhyUpdateComplete_t*) pMsg;

        // A Phy Update Has Completed or Failed
        if(pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
        {
            if(pPUC->status != SUCCESS)
            {
//                Log_info0("PHY Change failure");
            }
            else
            {
                // Only symmetrical PHY is supported.
                // rxPhy should be equal to txPhy.
                Log_info1("PHY Updated to %s",
                          (uintptr_t)((pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1M" :
                                      (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2M" :
                                      (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value"));
            }

            ProjectZero_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT,
                                      (uint8_t *)pMsg);
        }
    }
    break;

    default:
        break;
    }
}

/*********************************************************************
 * @fn      ProjectZero_processAdvEvent
 *
 * @brief   Process advertising event in app context
 *
 * @param   pEventData
 *
 * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
 */
static void ProjectZero_processAdvEvent(pzGapAdvEventData_t *pEventData)
{
    switch(pEventData->event)
    {
    /* Sent on the first advertisement after a GapAdv_enable */
    case GAP_EVT_ADV_START_AFTER_ENABLE:
   //     Log_info1("Adv Set %d Enabled", *(uint8_t *)(pEventData->pBuf));
        break;

    /* Sent after advertising stops due to a GapAdv_disable */
    case GAP_EVT_ADV_END_AFTER_DISABLE:
    //    Log_info1("Adv Set %d Disabled", *(uint8_t *)(pEventData->pBuf));
        break;

    /* Sent at the beginning of each advertisement. (Note that this event
     * is not enabled by default, see GapAdv_setEventMask). */
    case GAP_EVT_ADV_START:
        break;

    /* Sent after each advertisement. (Note that this event is not enabled
     * by default, see GapAdv_setEventMask). */
    case GAP_EVT_ADV_END:
        break;

    /* Sent when an advertisement set is terminated due to a
     * connection establishment */
    case GAP_EVT_ADV_SET_TERMINATED:
    {
        GapAdv_setTerm_t *advSetTerm = (GapAdv_setTerm_t *)(pEventData->pBuf);

//        Log_info2("Adv Set %d disabled after conn %d",
//                  advSetTerm->handle, advSetTerm->connHandle);
    }
    break;

    /* Sent when a scan request is received. (Note that this event
     * is not enabled by default, see GapAdv_setEventMask). */
    case GAP_EVT_SCAN_REQ_RECEIVED:
        break;

    /* Sent when an operation could not complete because of a lack of memory.
       This message is not allocated on the heap and must not be freed */
    case GAP_EVT_INSUFFICIENT_MEMORY:
        break;

    default:
        break;
    }

  // All events have associated memory to free except the insufficient memory
  // event
  if (pEventData->event != GAP_EVT_INSUFFICIENT_MEMORY)
  {
    ICall_free(pEventData->pBuf);
  }
}

/*********************************************************************
 * @fn      ProjectZero_processPairState
 *
 * @brief   Process the new paring state.
 *
 * @param   pPairData - pointer to pair state data container
 */
static void ProjectZero_processPairState(pzPairStateData_t *pPairData)
{
    uint8_t state = pPairData->state;
    uint8_t status = pPairData->status;

    switch(state)
    {
    case GAPBOND_PAIRING_STATE_STARTED:
        Log_info0("Pairing started");
        break;

    case GAPBOND_PAIRING_STATE_COMPLETE:
        if(status == SUCCESS)
        {
//            Log_info0("Pairing success");
        }
        else
        {
//            Log_info1("Pairing fail: %d", status);
        }
        break;

    case GAPBOND_PAIRING_STATE_ENCRYPTED:
        if(status == SUCCESS)
        {
//            Log_info0("Encryption success");
        }
        else
        {
//            Log_info1("Encryption failed: %d", status);
        }
        break;

    case GAPBOND_PAIRING_STATE_BOND_SAVED:
        if(status == SUCCESS)
        {
//            Log_info0("Bond save success");
        }
        else
        {
//            Log_info1("Bond save failed: %d", status);
        }
        break;

    default:
        break;
    }
}

/*********************************************************************
 * @fn      ProjectZero_processPasscode
 *
 * @brief   Process the Passcode request.
 *
 * @param   pReq - pointer to passcode req
 */
static void ProjectZero_processPasscode(pzPasscodeReq_t *pReq)
{
//    Log_info2("BondMgr Requested passcode. We are %s passcode %06d",
//              (uintptr_t)(pReq->uiInputs ? "Sending" : "Displaying"),
//              B_APP_DEFAULT_PASSCODE);

    // Send passcode response.
    GAPBondMgr_PasscodeRsp(pReq->connHandle, SUCCESS, B_APP_DEFAULT_PASSCODE);
}
/*********************************************************************
 * @fn      ProjectZero_processConnEvt
 *
 * @brief   Process connection event.
 *
 * @param pReport pointer to connection event report
 */
static void ProjectZero_processConnEvt(Gap_ConnEventRpt_t *pReport)
{
//  Log_info1("Connection event done for connHandle: %d", pReport->handle);
}



char rev[5];

// Implementation of itoa()
char* itoa(int num, char* str, int base)
{
    int i = 0;
    bool isNegative = false;

    /* Handle 0 explicitely, otherwise empty string is printed for 0 */
    if (num == 0)
    {
        str[i++] = '0';
        str[i] = '\0';
        return str;
    }

    // In standard itoa(), negative numbers are handled only with
    // base 10. Otherwise numbers are considered unsigned.
    if (num < 0 && base == 10)
    {
        isNegative = true;
        num = -num;
    }

    // Process individual digits
    while (num != 0)
    {
        int rem = num % base;
        str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
        num = num/base;
    }

    // If number is negative, append '-'
    if (isNegative)
        str[i++] = '-';

    str[i] = '\0'; // Append string terminator

    // Reverse the string
    //reverse(str, i);

    return str;
}




/*********************************************************************
 * @fn      ProjectZero_processCmdCompleteEvt
 *
 * @brief   Process an incoming OSAL HCI Command Complete Event.
 *
 * @param   pMsg - message to process
 */
//static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg,UART_Handle hUART)

static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
{
    uint8_t status = pMsg->pReturnParam[0];

    //Find which command this command complete is for
    switch(pMsg->cmdOpcode)
    {
    case HCI_READ_RSSI:
    {
        char buf [5];
            int8 rssi = (int8)pMsg->pReturnParam[3];
    
        // Display RSSI value, if RSSI is higher than threshold, change to faster PHY
        if(status == SUCCESS)
        {
            uint16_t handle = BUILD_UINT16(pMsg->pReturnParam[1],
                                           pMsg->pReturnParam[2]);

            Log_info2("RSSI:%d, connHandle %d",
                      (uint32_t)(rssi),
                      (uint32_t)handle);

            //UART_write(hUART,"Inside :",8);

            itoa(rssi,buf,10);

                       int length=4,k=0;
                       int j= length-1;

                         //reversing the string by swapping
                         for (k = 0; k < length; k++)
                             {
                               rev[k] = buf[j];
                               j--;
                             }

                         rev[k] = '\0';

                       //UART_write(hUART,rev,5);

            //UART_write(hUART,"ok",2);

        } // end of if (status == SUCCESS)
        break;
    }

    case HCI_LE_READ_PHY:
    {
        if(status == SUCCESS)
        {
//            Log_info2("RXPh: %d, TXPh: %d",
//                      pMsg->pReturnParam[3], pMsg->pReturnParam[4]);
        }
        break;
    }

    default:
        break;
    } // end of switch (pMsg->cmdOpcode)
}

/*********************************************************************
 * @fn      ProjectZero_handleUpdateLinkParamReq
 *
 * @brief   Receive and respond to a parameter update request sent by
 *          a peer device
 *
 * @param   pReq - pointer to stack request message
 */
static void ProjectZero_handleUpdateLinkParamReq(gapUpdateLinkParamReqEvent_t *pReq)
{
 //   Log_info0("Inside the ProjectZero_handleUpdateLinkParamReq");
    gapUpdateLinkParamReqReply_t rsp;

    rsp.connectionHandle = pReq->req.connectionHandle;
    rsp.signalIdentifier = pReq->req.signalIdentifier;

    // Only accept connection intervals with slave latency of 0
    // This is just an example of how the application can send a response
    if(pReq->req.connLatency == 0)
    {
        rsp.intervalMin = pReq->req.intervalMin;
        rsp.intervalMax = pReq->req.intervalMax;
        rsp.connLatency = pReq->req.connLatency;
        rsp.connTimeout = pReq->req.connTimeout;
        rsp.accepted = TRUE;
    }
    else
    {
        Log_info0("rsp_accepted = FALSE");//Only Debug FMCU Mux
        rsp.accepted = FALSE;
    }

    // Send Reply
   // Log_info0("Entering GAP_UpdateLinkParamReqReply ");//Only Debug FMCU Mux
    VOID GAP_UpdateLinkParamReqReply(&rsp);
   // Log_info0("Exiting GAP_UpdateLinkParamReqReply ");//Only Debug FMCU Mux

}

/*********************************************************************
 * @fn      ProjectZero_handleUpdateLinkEvent
 *
 * @brief   Receive and parse a parameter update that has occurred.
 *
 * @param   pEvt - pointer to stack event message
 */
static void ProjectZero_handleUpdateLinkEvent(gapLinkUpdateEvent_t *pEvt)
{
   // Log_info0("Entering ProjectZero_handleUpdateLinkEvent ");//Only Debug FMCU Mux
    // Get the address from the connection handle
    linkDBInfo_t linkInfo;
    linkDB_GetInfo(pEvt->connectionHandle, &linkInfo);
  //  Log_info1("Link DB_info0 %d ",(uintptr_t)pEvt->connectionHandle);//Only Debug FMCU Mux

    static uint8_t addrStr[3 * B_ADDR_LEN + 1];
    util_arrtohex(linkInfo.addr, B_ADDR_LEN, addrStr, sizeof addrStr,
                  UTIL_ARRTOHEX_REVERSE);

    if(pEvt->status == SUCCESS)
    {
        //Log_info0("Entered ProjectZero_handleUpdateLinkEvent"  );//Only Debug FMCU Mux

        uint8_t ConnIntervalFracture = 25*(pEvt->connInterval % 4);
        // Display the address of the connection update
       /* Log_info5(
            "Updated params for %s, interval: %d.%d ms, latency: %d, timeout: %d ms",
            (uintptr_t)addrStr,
            (uintptr_t)(pEvt->connInterval*CONN_INTERVAL_MS_CONVERSION),
            ConnIntervalFracture,
            pEvt->connLatency,
            pEvt->connTimeout*CONN_TIMEOUT_MS_CONVERSION);*/
    }
    else
    {
        // Display the address of the connection update failure
      //  Log_info2("Update Failed 0x%02x: %s", pEvt->opcode, (uintptr_t)addrStr);
    }

    // Check if there are any queued parameter updates
    pzConnHandleEntry_t *connHandleEntry = (pzConnHandleEntry_t *)List_get(&paramUpdateList);

    if(connHandleEntry != NULL)
    {
        // Attempt to send queued update now
        ProjectZero_sendParamUpdate(*(connHandleEntry->connHandle));

        // Free list element
        ICall_free(connHandleEntry->connHandle);
        ICall_free(connHandleEntry);
        //Log_info0("Exit ProjectZero_handleUpdateLinkEvent ");//Only Debug FMCU Mux

    }
}

/*********************************************************************
 * @fn      ProjectZero_addConn
 *
 * @brief   Add a device to the connected device list
 *
 * @param   connHandle - connection handle
 *
 * @return  bleMemAllocError if a param update event could not be sent. Else SUCCESS.
 */
static uint8_t ProjectZero_addConn(uint16_t connHandle)
{
    uint8_t i;
    uint8_t status = bleNoResources;

    // Try to find an available entry
    for(i = 0; i < MAX_NUM_BLE_CONNS; i++)
    {
        if(connList[i].connHandle == CONNHANDLE_INVALID)
        {
            // Found available entry to put a new connection info in
            connList[i].connHandle = connHandle;

            // Create a clock object and start
            connList[i].pUpdateClock
              = (Clock_Struct*) ICall_malloc(sizeof(Clock_Struct));

            if (connList[i].pUpdateClock)
            {
              Util_constructClock(connList[i].pUpdateClock,
                                  ProjectZero_paramUpdClockHandler,
                                  PZ_SEND_PARAM_UPDATE_DELAY, 0, true,
                                  (uintptr_t)connHandle);
            }

            // Set default PHY to 1M
            connList[i].currPhy = HCI_PHY_1_MBPS; // TODO: Is this true, neccessarily?

            break;
        }
    }

    return(status);
}

/*********************************************************************
 * @fn      ProjectZero_getConnIndex
 *
 * @brief   Find index in the connected device list by connHandle
 *
 * @param   connHandle - connection handle
 *
 * @return  the index of the entry that has the given connection handle.
 *          if there is no match, MAX_NUM_BLE_CONNS will be returned.
 */
static uint8_t ProjectZero_getConnIndex(uint16_t connHandle)
{
    uint8_t i;

    for(i = 0; i < MAX_NUM_BLE_CONNS; i++)
    {
        if(connList[i].connHandle == connHandle)
        {
          //  Log_info1("Inside ProjectZero_getConnIndex ",connList[i].connHandle); //Only for FMCU_Debug
            return(i);
        }

    }

    return(MAX_NUM_BLE_CONNS);
}

/*********************************************************************
 * @fn      ProjectZero_clearConnListEntry
 *
 * @brief   Clear the connection information structure held locally.
 *
 * @param   connHandle - connection handle
 *
 * @return  SUCCESS if connHandle found valid index or bleInvalidRange
 *          if index wasn't found. LINKDB_CONNHANDLE_ALL will always succeed.
 */
static uint8_t ProjectZero_clearConnListEntry(uint16_t connHandle)
{
   // Log_info0("Inside ProjectZero_clearConnListEntry ");// only for FMCU_Debug

    uint8_t i;
    // Set to invalid connection index initially
    uint8_t connIndex = MAX_NUM_BLE_CONNS;

    if(connHandle != CONNHANDLE_ALL)
    {
        // Get connection index from handle
        connIndex = ProjectZero_getConnIndex(connHandle);
        if(connIndex >= MAX_NUM_BLE_CONNS)
        {
            return(bleInvalidRange);
        }
    }

    // Clear specific handle or all handles
    for(i = 0; i < MAX_NUM_BLE_CONNS; i++)
    {
        if((connIndex == i) || (connHandle == CONNHANDLE_ALL))
        {
            connList[i].connHandle = CONNHANDLE_INVALID;
            connList[i].currPhy = 0;
            connList[i].phyCngRq = 0;
            connList[i].phyRqFailCnt = 0;
            connList[i].rqPhy = 0;
        }
    }

    return(SUCCESS);
}

/*********************************************************************
 * @fn      ProjectZero_removeConn
 *
 * @brief   Remove a device from the connected device list
 *
 * @param   connHandle - connection handle
 *
 * @return  index of the connected device list entry where the new connection
 *          info is removed from.
 *          if connHandle is not found, MAX_NUM_BLE_CONNS will be returned.
 */
static uint8_t ProjectZero_removeConn(uint16_t connHandle)
{
  //  Log_info0("Inside ProjectZero_removeConn ");// only for FMCU_Debug

    uint8_t connIndex = ProjectZero_getConnIndex(connHandle);

    if(connIndex < MAX_NUM_BLE_CONNS)
    {
      Clock_Struct* pUpdateClock = connList[connIndex].pUpdateClock;

      if (pUpdateClock != NULL)
      {
        // Stop and destruct the RTOS clock if it's still alive
        if (Util_isActive(pUpdateClock))
        {
          Util_stopClock(pUpdateClock);
        }

        // Destruct the clock object
        Clock_destruct(pUpdateClock);
        // Free clock struct
        ICall_free(pUpdateClock);
      }
      // Clear Connection List Entry
      ProjectZero_clearConnListEntry(connHandle);
    }

    return connIndex;
}

/*********************************************************************
 * @fn      ProjectZero_sendParamUpdate
 *
 * @brief   Remove a device from the connected device list
 *
 * @param   connHandle - connection handle
 */
static void ProjectZero_sendParamUpdate(uint16_t connHandle)
{
    gapUpdateLinkParamReq_t req;
    uint8_t connIndex;

    req.connectionHandle = connHandle;
    req.connLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
    req.connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
    req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
    req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;

    connIndex = ProjectZero_getConnIndex(connHandle);
    APP_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

    // Deconstruct the clock object
    Clock_destruct(connList[connIndex].pUpdateClock);
    // Free clock struct
    ICall_free(connList[connIndex].pUpdateClock);
    connList[connIndex].pUpdateClock = NULL;

    // Send parameter update
    bStatus_t status = GAP_UpdateLinkParamReq(&req);

    // If there is an ongoing update, queue this for when the update completes
    if(status == bleAlreadyInRequestedMode)
    {
        pzConnHandleEntry_t *connHandleEntry =
            ICall_malloc(sizeof(pzConnHandleEntry_t));
        if(connHandleEntry)
        {
            connHandleEntry->connHandle = ICall_malloc(sizeof(uint16_t));

            if(connHandleEntry->connHandle)
            {
                *(connHandleEntry->connHandle) = connHandle;

                List_put(&paramUpdateList, (List_Elem *)&connHandleEntry);
            }
        }
    }
}

/*********************************************************************
 * @fn      ProjectZero_updatePHYStat
 *
 * @brief   Update the auto phy update state machine
 *
 * @param   eventCode - HCI LE Event code
 *          pMsg - message to process
 */
static void ProjectZero_updatePHYStat(uint16_t eventCode, uint8_t *pMsg)
{
    uint8_t connIndex;
    pzConnHandleEntry_t *connHandleEntry;

    switch(eventCode)
    {
    case HCI_LE_SET_PHY:
    {
        // Get connection handle from list
        connHandleEntry = (pzConnHandleEntry_t *)List_get(&setPhyCommStatList);

        if(connHandleEntry)
        {
            // Get index from connection handle
            connIndex = ProjectZero_getConnIndex(*(connHandleEntry->connHandle));
            APP_ASSERT(connIndex < MAX_NUM_BLE_CONNS);

            ICall_free(connHandleEntry->connHandle);
            ICall_free(connHandleEntry);

            hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;

            if(pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
            {
                // Update the phy change request status for active RSSI tracking connection
                connList[connIndex].phyCngRq = FALSE;
                connList[connIndex].phyRqFailCnt++;
            }
        }
        break;
    }

    // LE Event - a Phy update has completed or failed
    case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT:
    {
        hciEvt_BLEPhyUpdateComplete_t *pPUC =
            (hciEvt_BLEPhyUpdateComplete_t*) pMsg;

        if(pPUC)
        {
            // Get index from connection handle
            uint8_t index = ProjectZero_getConnIndex(pPUC->connHandle);
            APP_ASSERT(index < MAX_NUM_BLE_CONNS);

            // Update the phychange request status for active RSSI tracking connection
            connList[index].phyCngRq = FALSE;

            if(pPUC->status == SUCCESS)
            {
                connList[index].currPhy = pPUC->rxPhy;
            }
            if(pPUC->rxPhy != connList[index].rqPhy)
            {
                connList[index].phyRqFailCnt++;
            }
            else
            {
                // Reset the request phy counter and requested phy
                connList[index].phyRqFailCnt = 0;
                connList[index].rqPhy = 0;
            }
        }

        break;
    }

    default:
        break;
    } // end of switch (eventCode)
}


//static void uartRxCb(UART_Handle handle, void *buf, size_t count)
//{
//  //Copy rxBuf to txBuf
//  memset(txBuf, 0, BUFSIZE);
//
//  memcpy(txBuf, rxBuf, count);
//  //Wake task to echo
//  Semaphore_post(hSem);
//}



//MobileApp Button data
char EngineStart[8]={36, 172, 4, 36, 173, 7, 32,  0};  //EngineStart String    36 172 4 36 173 7 32 0
char EngineStop[8]= {36, 172, 4, 36, 173, 7, 32,  1};  //EngineSTOP            36 172 4 36 173 7 32 1
char LeadMe_ON[8]=  {36, 172, 4, 36, 173, 1,  0, 138};  //LEAD ME ON            36 172 4 36 173 1 0 138
char LeadMe_OFF[8]= {36, 172, 4, 36, 173, 1,  0, 139};  //LEAD ME OFF           36 172 4 36 173 1 0 139

#define Rx_Size               4
#define LeadMeButton_ON       10
#define LeadMeButton_OFF      20
#define EngineStart_Button    30
#define EngineStop_Button     40

char rxBuf[Rx_Size];
char txBuf[Rx_Size];

static uint8_t Button=0;
uint8_t RXcount=0;

uint8_t ACK_Flag = 0;
uint8_t Counter_retry=0;

#define Maximum_Number_of_Try 3

char RxResponse[Rx_Size];

char PACK[Rx_Size] =   {"PACK"};
char NACK[Rx_Size] =   {"NACK"};

//char  PACK[Rx_Size]  =   {0x41,0x41};
//char NACK[Rx_Size]  =   {0x4B,0x4B};
//


static void uartRxCb(UART_Handle handle, void *buf, size_t count)
 {
  if(count>=Rx_Size)
     {
      //Clear RxResponse
      memset(RxResponse, 0, count);

      //Store rx data in other memory
      memcpy(RxResponse, buf, count);

      //UART_write(handle,RxString,sizeof(RxString));

      //UART_write(handle,RxString, count);

     }
  else
       memcpy(RxResponse, "NO-DATA", count);

  Semaphore_post(hSem);
 }

//**************************************************************************************
/*
 * PACKET STRUTURE FROM BLE TO FMCU
 * Start_Byte    : 0x23 (1 Byte)
 * Packet_Length : 0x31 0x36 (1 Byte) (16 bytes of data by default)
 * DATA_START_ID : 0x3C (1 Byte)
 * PayLoad       : xxxx (16 Bytes)
 * DATA_STOP_ID  : 0x3E (1 Byte)
 **************************************************************************************/


void Send_Packet(UART_Handle handle)
 {
    //0x23      ----> #
    //0x31 0x36 ----> data of 16 bytes
    //0x3C    ------> <
    //0x3E     -----> >

    static uint8_t Packet_array[3]={0X23,16,0X3C};

    UART_write(handle,&Packet_array[0],3);

 }

void ProjectZero_DataService_ValueChangeHandler( pzCharacteristicData_t *pCharData)
{
  //  Log_info0(" Inside ProjectZero_DataService_ValueChangeHandler ");

  //  Value to hold the received string for printing via Log, as Log printouts
  //  happen in the Idle task, and so need to refer to a global/static variable.
  //  static uint8_t received_string[DS_STRING_LEN] = {0};
  //  static uint8_t received_string[DS_STREAM_LEN] = {0};

    // Rx buffer size
    uint8_t RxDataLength = pCharData->dataLen;

    // Buffer to hold RX data from Mobile App
    uint8_t Buffer[(RxDataLength + 1)];

    uint8_t RxCount = 0;

 switch(pCharData->paramID)
    {
    case DS_STREAM_ID:
               // Log_info0("Value Change msg:");
               memset(Buffer,0,RxDataLength);

             for(int i=0;i<RxDataLength;i++)
                 {
                 Buffer[i]=pCharData->data[i];
                 //Log_info1("%02x",pCharData->data[i]);
                 }



//             UART_write(handle,&Buffer[0],8);


//          // Display rx data in array
//              for(int i=0;i<RxDataLength;i++)     //  36 172 4 36 173 1 0 138
//                 {
//                //  Log_info1("Received data : %d ",Buffer[i]);
//                 }

             //UART initialization
           /* Call driver init functions */
               UART_init();
               UART_Params params;
               UART_Params_init(&params);
               UART_Handle handle;
               uint32_t timeoutUs = 100000; //1second // 5000;  // 5ms timeout, default timeout is no timeout (BIOS_WAIT_FOREVER)


           params.readMode     = UART_MODE_CALLBACK;
           params.writeMode    = UART_MODE_BLOCKING;
           params.readCallback = uartRxCb;
           params.readTimeout   = timeoutUs / ClockP_getSystemTickPeriod(); // Default tick period is 10us
           params.baudRate     = 115200;

           handle = UART_open(Board_UART0, &params);

           // Enable RETURN_PARTIAL
           // UART_control(hUART, UARTCC26X2_CMD_RETURN_PARTIAL_ENABLE, NULL);

          if(handle==NULL)
            {

            }

          /****Added RSSI Read Value ***/
          HCI_ReadRssiCmd(advHandleLegacy);

//          int Pcount=0;
//          char Lead[16]={"24AC"};
//          for(int i=0;i<4;i++)
//              {
//               if(Buffer[i]==Lead[i])
//                    Pcount++;
//               else
//                    Pcount=0;
//              }
//          if (Pcount>=3)
//              UART_write(handle,"Hello",5);
//
//            Pcount=0;
//    }//remove me
//}//remove me
            //Check for Button Press ?

if((memcmp(LeadMe_ON,Buffer,RxDataLength))==0)
        {
         Button=LeadMeButton_ON;
        }

else if((memcmp(LeadMe_OFF,Buffer,RxDataLength))==0)
        {
         Button=LeadMeButton_OFF;
        }
else if((memcmp(EngineStart,Buffer,RxDataLength))==0)
        {
         Button=EngineStart_Button;
        }

else if((memcmp(EngineStop,Buffer,RxDataLength))==0)
        {
         Button=EngineStop_Button;
        }

//Start Process

switch(Button)
{
 case LeadMeButton_ON :
   {
     Start_timer_100msec=0;
     Counter_retry=0;
     ACK_Flag=0;

     // Max 500msec wait time
    while(ACK_Flag == 0)
     {

        if((Start_timer_100msec == 0) && (Counter_retry < 5))
        {
            Counter_retry++;
            Start_timer_100msec = 1;

            UART_write(handle,"#<24AC0424AD01008A>",19);

            //Start a timer of 100 msec
            Util_startClock((Clock_Struct *)Wait_Timer_100ms);
        }
        else if(Counter_retry >= 5)
        {
            ACK_Flag = 1;
            Start_timer_100msec=0;
            Counter_retry=0;
        }



        //Start Reading Response
         UART_read(handle, rxBuf, sizeof(rxBuf));

         //Wait for Acknowledgment from FMCU side
         //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);

         //Check the Received Data is ACK ?
         if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
         {
             PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
             ACK_Flag=1;
             Start_timer_100msec=0;
             Counter_retry=0;
         }

         //Check the Received Data is NACK ?
         else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
         {
            //Send the 1st default packet Received String to FMCU
            PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
            ACK_Flag=0;
         }
         memset(Buffer,0,RxDataLength);
         memset(RxResponse,0,sizeof(NACK));
     }
     UART_close(handle);
     break;
   }
case LeadMeButton_OFF :
{
  Start_timer_100msec=0;
  Counter_retry=0;
  ACK_Flag=0;

  // Max 500msec wait time
 while(ACK_Flag == 0)
  {

     if((Start_timer_100msec == 0) && (Counter_retry < 5))
     {
         Counter_retry++;
         Start_timer_100msec = 1;

         UART_write(handle,"#<24AC0424AD01008B>",19);

         //Start a timer of 100 msec
         Util_startClock((Clock_Struct *)Wait_Timer_100ms);
     }
     else if(Counter_retry >=5)
     {
         ACK_Flag = 1;
         Start_timer_100msec=0;
         Counter_retry=0;
     }



     //Start Reading Response
      UART_read(handle, rxBuf, sizeof(rxBuf));

      //Wait for Acknowledgment from FMCU side
      //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);

      //Check the Received Data is ACK ?
      if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
      {
          PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
          ACK_Flag=1;
          Start_timer_100msec=0;
          Counter_retry=0;
      }

      //Check the Received Data is NACK ?
      else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
      {
         //Send the 1st default packet Received String to FMCU
         PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
         ACK_Flag=0;
      }
      memset(Buffer,0,RxDataLength);
      memset(RxResponse,0,sizeof(NACK));
  }
 UART_close(handle);
  break;
}

case EngineStart_Button :
{
    Start_timer_100msec=0;
    Counter_retry=0;
    ACK_Flag=0;

    // Max 500msec wait time
   while(ACK_Flag == 0)
    {

       if((Start_timer_100msec == 0) && (Counter_retry < 5))
       {
           Counter_retry++;
           Start_timer_100msec = 1;

           UART_write(handle,"#<24AC0424AD072000>",19);

           //Start a timer of 100 msec
           Util_startClock((Clock_Struct *)Wait_Timer_100ms);
       }
       else if(Counter_retry >=5)
       {
           ACK_Flag = 1;
           Start_timer_100msec=0;
           Counter_retry=0;
       }



       //Start Reading Response
        UART_read(handle, rxBuf, sizeof(rxBuf));

        //Wait for Acknowledgment from FMCU side
        //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);

        //Check the Received Data is ACK ?
        if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
        {
            PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
            ACK_Flag=1;
            Start_timer_100msec=0;
            Counter_retry=0;
        }

        //Check the Received Data is NACK ?
        else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
        {
           //Send the 1st default packet Received String to FMCU
           PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
           ACK_Flag=0;
        }
        memset(Buffer,0,RxDataLength);
        memset(RxResponse,0,sizeof(NACK));
    }
   UART_close(handle);
    break;
  }


case EngineStop_Button :
{
    Start_timer_100msec=0;
    Counter_retry=0;
    ACK_Flag=0;

    // Max 500msec wait time
   while(ACK_Flag == 0)
    {

       if((Start_timer_100msec == 0) && (Counter_retry < 5))
       {
           Counter_retry++;
           Start_timer_100msec = 1;

           UART_write(handle,"#<24AC0424AD072001>",19);

           //Start a timer of 100 msec
           Util_startClock((Clock_Struct *)Wait_Timer_100ms);
       }
       else if(Counter_retry >= 5)
       {
           ACK_Flag = 1;
           Start_timer_100msec=0;
           Counter_retry=0;
       }



       //Start Reading Response
        UART_read(handle, rxBuf, sizeof(rxBuf));

        //Wait for Acknowledgment from FMCU side
        //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);

        //Check the Received Data is ACK ?
        if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
        {
            PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
            ACK_Flag=1;
            Start_timer_100msec=0;
            Counter_retry=0;
        }

        //Check the Received Data is NACK ?
        else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
        {
           //Send the 1st default packet Received String to FMCU
           PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
           ACK_Flag=0;
        }
        memset(Buffer,0,RxDataLength);
        memset(RxResponse,0,sizeof(NACK));
    }
   UART_close(handle);
    break;
  }


 default:
    return;

}

    default:
        return;

 } // switch statement end

} //Function end


/*
 * @brief   Handle a CCCD (configuration change) write received from a peer
 *          device. This tells us whether the peer device wants us to send
 *          Notifications or Indications.
 *
 * @param   pCharData  pointer to malloc'd char write data
 *
 * @return  None.
 */
void ProjectZero_DataService_CfgChangeHandler(pzCharacteristicData_t *pCharData)
{
    Log_info0(" Inside ProjectZero_DataService_CfgChangeHandler ");

    // Cast received data to uint16, as that's the format for CCCD writes.
    uint16_t configValue = *(uint16_t *)pCharData->data;
    char *configValString;

    // Determine what to tell the user
    switch(configValue)
    {
    case GATT_CFG_NO_OPERATION:
        configValString = "Noti/Ind disabled";
        break;
    case GATT_CLIENT_CFG_NOTIFY:
        configValString = "Notifications enabled";
        break;
    case GATT_CLIENT_CFG_INDICATE:
        configValString = "Indications enabled";
        break;
    default:
        configValString = "Unsupported operation";
    }

    switch(pCharData->paramID)
    {
    case DS_STREAM_ID:
        Log_info3("CCCD Change msg: %s %s: %s",
                  (uintptr_t)"Data Service",
                  (uintptr_t)"Stream",
                  (uintptr_t)configValString);
        // -------------------------
        // Do something useful with configValue here. It tells you whether someone
        // wants to know the state of this characteristic.
        // ...
        break;
    }
}



/*
 * @brief  Convenience function for updating characteristic data via pzCharacteristicData_t
 *         structured message.
 *
 * @note   Must run in Task context in case BLE Stack APIs are invoked.
 *
 * @param  *pCharData  Pointer to struct with value to update.
 */
static void ProjectZero_updateCharVal(pzCharacteristicData_t *pCharData)
{
 Log_info0(" Inside ProjectZero_updateCharVal ");
 switch(pCharData->svcUUID)
    {
#ifndef FMCU_APP

    case LED_SERVICE_SERV_UUID:
        LedService_SetParameter(pCharData->paramID, pCharData->dataLen,
                                pCharData->data);
        break;

    case BUTTON_SERVICE_SERV_UUID:
        ButtonService_SetParameter(pCharData->paramID, pCharData->dataLen,
                                   pCharData->data);
        break;
#endif
    }
}


/******************************************************************************
 *****************************************************************************
 *
 *  Handlers of direct system callbacks.
 *
 *  Typically enqueue the information or request as a message for the
 *  application Task for handling.
 *
 ****************************************************************************
 *****************************************************************************/

/*
 *  Callbacks from the Stack Task context (GAP or Service changes)
 *****************************************************************************/

/*********************************************************************
 * @fn      ProjectZero_advCallback
 *
 * @brief   GapAdv module callback
 *
 * @param   pMsg - message to process
 *          pBuf - data potentially accompanying event
 *          arg - not used
 */
static void ProjectZero_advCallback(uint32_t event, void *pBuf, uintptr_t arg)
{
   // Log_info0(" Inside ProjectZero_advCallback ");
    pzGapAdvEventData_t *eventData = ICall_malloc(sizeof(pzGapAdvEventData_t));

    if(eventData != NULL)
    {
        eventData->event = event;
        eventData->pBuf = pBuf;

        if(ProjectZero_enqueueMsg(PZ_ADV_EVT, eventData) != SUCCESS)
        {
          ICall_free(eventData);
        }
    }
}

/*********************************************************************
 * @fn      ProjectZero_pairStateCb
 *
 * @brief   Pairing state callback.
 *
 * @param   connHandle - connection handle
 *          state - pair state
 *          status - pair status
 */
static void ProjectZero_pairStateCb(uint16_t connHandle, uint8_t state,
                                    uint8_t status)
{
    Log_info0(" Inside ProjectZero_pairStateCb ");
    pzPairStateData_t *pairState =
        (pzPairStateData_t *)ICall_malloc(sizeof(pzPairStateData_t));

    if(pairState != NULL)
    {
        pairState->state = state;
        pairState->connHandle = connHandle;
        pairState->status = status;

        if(ProjectZero_enqueueMsg(PZ_PAIRSTATE_EVT, pairState) != SUCCESS)
        {
          ICall_free(pairState);
        }
    }
}

/*********************************************************************
 * @fn      ProjectZero_passcodeCb
 *
 * @brief   Passcode callback.
 *
 * @param   pDeviceAddr - not used
 *          connHandle - connection handle
 *          uiInpuits - if TRUE, the local device should accept a passcode input
 *          uiOutputs - if TRUE, the local device should display the passcode
 *          numComparison - the code that should be displayed for numeric
 *          comparison pairing. If this is zero, then passcode pairing is occurring.
 */
static void ProjectZero_passcodeCb(uint8_t *pDeviceAddr,
                                   uint16_t connHandle,
                                   uint8_t uiInputs,
                                   uint8_t uiOutputs,
                                   uint32_t numComparison)
{

    Log_info0(" Inside ProjectZero_passcodeCb ");
    pzPasscodeReq_t *req =
        (pzPasscodeReq_t *)ICall_malloc(sizeof(pzPasscodeReq_t));
    if(req != NULL)
    {
        req->connHandle = connHandle;
        req->uiInputs = uiInputs;
        req->uiOutputs = uiOutputs;
        req->numComparison = numComparison;

        if(ProjectZero_enqueueMsg(PZ_PASSCODE_EVT, req) != SUCCESS)
        {
          ICall_free(req);
        }
    }
    ;
}

/*********************************************************************
 * @fn      ProjectZero_DataService_ValueChangeCB
 *
 * @brief   Callback for characteristic change when a peer writes to us
 *
 * @param   connHandle - connection handle
 *          paramID - the parameter ID maps to the characteristic written to
 *          len - length of the data written
 *          pValue - pointer to the data written
 */
static void ProjectZero_DataService_ValueChangeCB(uint16_t connHandle,
                                                  uint8_t paramID, uint16_t len,
                                                  uint8_t *pValue)
{
    // See the service header file to compare paramID with characteristic.
//    Log_info1("(CB) Data Svc Characteristic value change: paramID(%d). "
//              "Sending msg to app.", paramID);

    pzCharacteristicData_t *pValChange =
        ICall_malloc(sizeof(pzCharacteristicData_t) + len);

    if(pValChange != NULL)
    {
        pValChange->svcUUID = DATA_SERVICE_SERV_UUID;
        pValChange->paramID = paramID;
        memcpy(pValChange->data, pValue, len);
        pValChange->dataLen = len;

        if(ProjectZero_enqueueMsg(PZ_SERVICE_WRITE_EVT, pValChange) != SUCCESS)
        {
          ICall_free(pValChange);
        }
    }
}

/*********************************************************************
 * @fn      ProjectZero_DataService_CfgChangeCB
 *
 * @brief   Callback for when a peer enables or disables the CCCD attribute,
 *          indicating they are interested in notifications or indications.
 *
 * @param   connHandle - connection handle
 *          paramID - the parameter ID maps to the characteristic written to
 *          len - length of the data written
 *          pValue - pointer to the data written
 */
static void ProjectZero_DataService_CfgChangeCB(uint16_t connHandle,
                                                uint8_t paramID, uint16_t len,
                                                uint8_t *pValue)
{
    Log_info1("(CB) Data Svc Char config change paramID(%d). "
              "Sending msg to app.", paramID);

    pzCharacteristicData_t *pValChange =
        ICall_malloc(sizeof(pzCharacteristicData_t) + len);

    if(pValChange != NULL)
    {
        pValChange->svcUUID = DATA_SERVICE_SERV_UUID;
        pValChange->paramID = paramID;
        memcpy(pValChange->data, pValue, len);
        pValChange->dataLen = len;

        if(ProjectZero_enqueueMsg(PZ_SERVICE_CFG_EVT, pValChange) != SUCCESS)
        {
          ICall_free(pValChange);
        }
    }
}

/*
 *  Callbacks from Swi-context
 *****************************************************************************/

/*********************************************************************
 * @fn      ProjectZero_paramUpdClockHandler
 *
 * @brief   Handler function for clock timeouts.
 *
 * @param   arg - app message pointer
 */
static void ProjectZero_paramUpdClockHandler(UArg arg)
{
    pzSendParamReq_t *req =
        (pzSendParamReq_t *)ICall_malloc(sizeof(pzSendParamReq_t));
    if(req)
    {
        req->connHandle = (uint16_t)arg;
        if(ProjectZero_enqueueMsg(PZ_SEND_PARAM_UPD_EVT, req) != SUCCESS)
        {
          ICall_free(req);
        }
    }
}

/******************************************************************************
 *****************************************************************************
 *
 *  Utility functions
 *
 ****************************************************************************
 *****************************************************************************/

/*********************************************************************
 * @fn     ProjectZero_enqueueMsg
 *
 * @brief  Utility function that sends the event and data to the application.
 *         Handled in the task loop.
 *
 * @param  event    Event type
 * @param  pData    Pointer to message data
 */
static status_t ProjectZero_enqueueMsg(uint8_t event, void *pData)
{
    uint8_t success;
    pzMsg_t *pMsg = ICall_malloc(sizeof(pzMsg_t));

    if(pMsg)
    {
        pMsg->event = event;
        pMsg->pData = pData;

        success = Util_enqueueMsg(appMsgQueueHandle, syncEvent, (uint8_t *)pMsg);
        return (success) ? SUCCESS : FAILURE;
    }

    return(bleMemAllocError);
}

/*********************************************************************
 * @fn     util_arrtohex
 *
 * @brief   Convert {0x01, 0x02} to "01:02"
 *
 * @param   src - source byte-array
 * @param   src_len - length of array
 * @param   dst - destination string-array
 * @param   dst_len - length of array
 *
 * @return  array as string
 */
char * util_arrtohex(uint8_t const *src, uint8_t src_len,
                     uint8_t *dst, uint8_t dst_len, uint8_t reverse)
{
    char hex[] = "0123456789ABCDEF";
    uint8_t *pStr = dst;
    uint8_t avail = dst_len - 1;
    int8_t inc = 1;
    if(reverse)
    {
        src = src + src_len - 1;
        inc = -1;
    }

    memset(dst, 0, avail);

    while(src_len && avail > 3)
    {
        if(avail < dst_len - 1)
        {
            *pStr++ = ':';
            avail -= 1;
        }

        *pStr++ = hex[*src >> 4];
        *pStr++ = hex[*src & 0x0F];
        src += inc;
        avail -= 2;
        src_len--;
    }

    if(src_len && avail)
    {
        *pStr++ = ':'; // Indicate not all data fit on line.
    }
    return((char *)dst);
}

/*********************************************************************
 * @fn     util_getLocalNameStr
 *
 * @brief   Extract the LOCALNAME from Scan/AdvData
 *
 * @param   data - Pointer to the advertisement or scan response data
 * @param   len  - Length of advertisment or scan repsonse data
 *
 * @return  Pointer to null-terminated string with the adv local name.
 */
static char * util_getLocalNameStr(const uint8_t *data, uint8_t len)
{
    uint8_t nuggetLen = 0;
    uint8_t nuggetType = 0;
    uint8_t advIdx = 0;

    static char localNameStr[32] = { 0 };
    memset(localNameStr, 0, sizeof(localNameStr));

    for(advIdx = 0; advIdx < len; )
    {
        nuggetLen = data[advIdx++];
        nuggetType = data[advIdx];
        if((nuggetType == GAP_ADTYPE_LOCAL_NAME_COMPLETE ||
            nuggetType == GAP_ADTYPE_LOCAL_NAME_SHORT) )
        {
            uint8_t len_temp = nuggetLen < (sizeof(localNameStr)-1)? (nuggetLen - 1):(sizeof(localNameStr)-2);
            // Only copy the first 31 characters, if name bigger than 31.
            memcpy(localNameStr, &data[advIdx + 1], len_temp);
            break;
        }
        else
        {
            advIdx += nuggetLen;
        }
    }

    return(localNameStr);
}

/*********************************************************************
*********************************************************************/

  • Hi Mohitt,

    I'm asking an expert to look into that. In the meantime, what is the SDK version you are using and in using custom 128bits UUID what is the characteristic you are using.
    And, please label the change you have made, that would be easier for both of us.

  • /*
     ******************************************************************************
     *****************************************************************************/
    
    /*******************************************************************************
     * INCLUDES
     */
    #define FMCU_APP
    #define DEVINFO_SYSTEM_ID_LEN 8
    
    #include <string.h>
    
    #if !(defined __TI_COMPILER_VERSION__)
    #include <intrinsics.h>
    #endif
    
    
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/drivers/UART.h>
    #include <ti/drivers/uart/UARTCC26X2.h>
    
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Queue.h>
    #include <ti/drivers/utils/List.h>
    
    //#include <xdc/runtime/Log.h> // Comment this in to use xdc.runtime.Log
    #include <uartlog/UartLog.h>  // Comment out if using xdc Log
    
    #include <ti/display/AnsiColor.h>
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(driverlib/sys_ctrl.h)
    
    #include <icall.h>
    #include <bcomdef.h>
    /* This Header file contains all BLE API and icall structure definition */
    #include <icall_ble_api.h>
    
    /* Bluetooth Profiles */
    //#include <devinfoservice.h>
    
    #ifndef FMCU_APP
      #include <services/button_service.h>
      #include <services/led_service.h>
    #endif
    
    #define USE_RCOSC
    
    
    /* Stack size in bytes */
    #define THREADSTACKSIZE    1024
    
    
    UART_Handle temp_handle;
    uint8_t Start_timer_100msec=0;
    
    
    #include <services/data_service.h>
    
    
    /* Application specific includes */
    #include <Board.h>
    
    #include <project_zero.h>
    #include <util.h>
    
    #ifdef USE_RCOSC
     #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    
    
    /*********************************************************************
     * MACROS
     */
    
    // Spin if the expression is not true
    #define APP_ASSERT(expr) if(!(expr)) {project_zero_spin();}
    
    #define UTIL_ARRTOHEX_REVERSE     1
    #define UTIL_ARRTOHEX_NO_REVERSE  0
    
    /*********************************************************************
     * CONSTANTS
     */
    
    uint8_t Wake_Event_Sts=0;
    uint8_t TX_Count=0;
    
    // Task configuration
    #define PZ_TASK_PRIORITY                     1
    
    #ifndef PZ_TASK_STACK_SIZE
    #define PZ_TASK_STACK_SIZE                   2048
    #endif
    
    // Internal Events for RTOS application
    #define PZ_ICALL_EVT                         ICALL_MSG_EVENT_ID  // Event_Id_31
    #define PZ_APP_MSG_EVT                       Event_Id_30
    
    // Bitwise OR of all RTOS events to pend on
    #define PZ_ALL_EVENTS                        ( PZ_ICALL_EVT | PZ_APP_MSG_EVT )
    
    // Types of messages that can be sent to the user application task from other
    // tasks or interrupts. Note: Messages from BLE Stack are sent differently.
    #define PZ_SERVICE_WRITE_EVT     0  /* A characteristic value has been written     */
    #define PZ_SERVICE_CFG_EVT       1  /* A characteristic configuration has changed  */
    #define PZ_UPDATE_CHARVAL_EVT    2  /* Request from ourselves to update a value    */
    #define PZ_BUTTON_DEBOUNCED_EVT  3  /* A button has been debounced with new value  */
    #define PZ_PAIRSTATE_EVT         4  /* The pairing state is updated                */
    #define PZ_PASSCODE_EVT          5  /* A pass-code/PIN is requested during pairing */
    #define PZ_ADV_EVT               6  /* A subscribed advertisement activity         */
    #define PZ_START_ADV_EVT         7  /* Request advertisement start from task ctx   */
    #define PZ_SEND_PARAM_UPD_EVT    8  /* Request parameter update req be sent        */
    #define PZ_CONN_EVT              9  /* Connection Event End notice                 */
    
    // General discoverable mode: advertise indefinitely
    #define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL
    
    // Minimum connection interval (units of 1.25ms, 80=100ms) for parameter update request
    #define DEFAULT_DESIRED_MIN_CONN_INTERVAL     12
    
    // Maximum connection interval (units of 1.25ms, 800=1000ms) for  parameter update request
    #define DEFAULT_DESIRED_MAX_CONN_INTERVAL     36
    
    // Slave latency to use for parameter update request
    #define DEFAULT_DESIRED_SLAVE_LATENCY         0
    
    // Supervision timeout value (units of 10ms, 1000=10s) for parameter update request
    #define DEFAULT_DESIRED_CONN_TIMEOUT          200
    
    // Supervision timeout conversion rate to miliseconds
    #define CONN_TIMEOUT_MS_CONVERSION            10
    
    // Connection interval conversion rate to miliseconds
    #define CONN_INTERVAL_MS_CONVERSION           1.25
    
    // Pass parameter updates to the app for it to decide.
    #define DEFAULT_PARAM_UPDATE_REQ_DECISION     GAP_UPDATE_REQ_PASS_TO_APP
    
    // Delay (in ms) after connection establishment before sending a parameter update requst
    #define PZ_SEND_PARAM_UPDATE_DELAY            6000//6000
    
    /*********************************************************************
     * TYPEDEFS
     */
    // Struct for messages sent to the application task
    typedef struct
    {
        uint8_t event;
        void    *pData;
    } pzMsg_t;
    
    // Struct for messages about characteristic data
    typedef struct
    {
        uint16_t svcUUID; // UUID of the service
        uint16_t dataLen; //
        uint8_t paramID; // Index of the characteristic
        uint8_t data[]; // Flexible array member, extended to malloc - sizeof(.)
    } pzCharacteristicData_t;
    
    // Struct for message about sending/requesting passcode from peer.
    typedef struct
    {
        uint16_t connHandle;
        uint8_t uiInputs;
        uint8_t uiOutputs;
        uint32_t numComparison;
    } pzPasscodeReq_t;
    
    // Struct for message about a pending parameter update request.
    typedef struct
    {
        uint16_t connHandle;
    } pzSendParamReq_t;
    
    #ifndef FMCU_APP
    // Struct for message about button state
    typedef struct
    {
        PIN_Id pinId;
        uint8_t state;
    } pzButtonState_t;
    #endif
    
    // Container to store passcode data when passing from gapbondmgr callback
    // to app event. See the pfnPairStateCB_t documentation from the gapbondmgr.h
    // header file for more information on each parameter.
    typedef struct
    {
        uint8_t state;
        uint16_t connHandle;
        uint8_t status;
    } pzPairStateData_t;
    
    // Container to store passcode data when passing from gapbondmgr callback
    // to app event. See the pfnPasscodeCB_t documentation from the gapbondmgr.h
    // header file for more information on each parameter.
    typedef struct
    {
        uint8_t deviceAddr[B_ADDR_LEN];
        uint16_t connHandle;
        uint8_t uiInputs;
        uint8_t uiOutputs;
        uint32_t numComparison;
    } pzPasscodeData_t;
    
    // Container to store advertising event data when passing from advertising
    // callback to app event. See the respective event in GapAdvScan_Event_IDs
    // in gap_advertiser.h for the type that pBuf should be cast to.
    typedef struct
    {
        uint32_t event;
        void *pBuf;
    } pzGapAdvEventData_t;
    
    // List element for parameter update and PHY command status lists
    typedef struct
    {
        List_Elem elem;
        uint16_t *connHandle;
    } pzConnHandleEntry_t;
    
    // Connected device information
    typedef struct
    {
        uint16_t connHandle;                    // Connection Handle
        Clock_Struct* pUpdateClock;             // pointer to clock struct
        bool phyCngRq;                          // Set to true if PHY change request is in progress
        uint8_t currPhy;                        // The active PHY for a connection
        uint8_t rqPhy;                          // The requested PHY for a connection
        uint8_t phyRqFailCnt;                   // PHY change request fail count
    } pzConnRec_t;
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    // Task configuration
    Task_Struct pzTask;
    #if defined __TI_COMPILER_VERSION__
    #pragma DATA_ALIGN(appTaskStack, 8)
    #else
    #pragma data_alignment=8
    #endif
    uint8_t appTaskStack[PZ_TASK_STACK_SIZE];
    
    static uint8_t ResponseStatus=0;
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    // Entity ID globally used to check for source and/or destination of messages
    static ICall_EntityID selfEntity;
    
    // Event globally used to post local events and pend on system and
    // local events.
    static ICall_SyncHandle syncEvent;
    
    // Queue object used for app messages
    static Queue_Struct appMsgQueue;
    static Queue_Handle appMsgQueueHandle;
    
    // GAP GATT Attributes
    static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "FMCU MML";
    
    /*
    // Advertisement data
    static uint8_t advertData[] =
    {
        0x02, // length of this data
        GAP_ADTYPE_FLAGS,
        DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
    
        // complete name
       14, // length of this data
        GAP_ADTYPE_LOCAL_NAME_COMPLETE,
        'T',
        'T',
        'T',
        'T',
        '-',
        'B',
        'L',
        'E',
        '-',
        'T',
        'T',
        'T',
        'T',
    };
    
    // Scan Response Data
    static uint8_t scanRspData[] =
    {
    //     service UUID, to notify central devices what services are included
    //     in this peripheral
      //(ATT_UUID_SIZE + 0x01),   // length of this data, LED service UUID + header
      //GAP_ADTYPE_128BIT_MORE,   // some of the UUID's, but not all
    
     // (ATT_UUID_SIZE),
     // GAP_ADTYPE_128BIT_COMPLETE,
     // DATA_SERVICE_SERV_UUID_BASE128(DATA_SERVICE_SERV_UUID),
    };
    */
    
    
    // Advertisement data
    static uint8_t advertData[] =
    {
      0x02,   // length of this data
      GAP_ADTYPE_FLAGS,
      DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
    
      // service UUID, to notify central devices what services are included
      // in this peripheral
      0x03,   // length of this data //0x03
      GAP_ADTYPE_16BIT_MORE,      // some of the UUID's, but not all //GAP_ADTYPE_16BIT_MORE
      //GAP_ADTYPE_16BIT_COMPLETE,
      //DATA_SERVICE_SERV_UUID_BASE128(DATA_SERVICE_SERV_UUID),
      LO_UINT16(DATA_SERVICE_SERV_UUID),
      HI_UINT16(DATA_SERVICE_SERV_UUID),
    
      // ID nugget
        0x06,
        GAP_ADTYPE_MANUFACTURER_SPECIFIC,
        // Texas Instruments company ID
        0x0D,
        0x00,
        // Custom data identifier
        0xC0,//0xC0
        0xFF,
        0xEE
    };
    
    // Scan Response Data
    static uint8_t scanRspData[] =
    {
      // complete name
      14,   // length of this data
      GAP_ADTYPE_LOCAL_NAME_COMPLETE,
      'F',
      'M',
      'C',
      'U',
      '-',
      'B',
      'L',
      'E',
      '-',
      'V',
      '3',
      '.',
      '1',
    
      // connection interval range
      5,   // length of this data
      GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
      LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),   // 100ms
      HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
      LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),   // 1s
      HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
    
      // Tx power level
      2,   // length of this data
      GAP_ADTYPE_POWER_LEVEL,
      0       // 0dBm
    };
    
    
    
    // Advertising handles
    static uint8_t advHandleLegacy;
    
    // Per-handle connection info
    static pzConnRec_t connList[MAX_NUM_BLE_CONNS];
    
    // List to store connection handles for set phy command status's
    static List_List setPhyCommStatList;
    
    // List to store connection handles for queued param updates
    static List_List paramUpdateList;
    
    #ifndef FMCU_APP
    
    /* Pin driver handles */
    static PIN_Handle buttonPinHandle;
    static PIN_Handle ledPinHandle;
    
    /* Global memory storage for a PIN_Config table */
    static PIN_State buttonPinState;
    static PIN_State ledPinState;
    
    #endif
    
    //#ifdef FMCU_APP_WAKEUP
     static PIN_Handle ledPinHandle;
     static PIN_State ledPinState;
    //#endif
    
    /*
     * Initial LED pin configuration table
     *   - LEDs Board_PIN_LED0 & Board_PIN_LED1 are off.
     */
    PIN_Config ledPinTable[] =
    {
        Board_PIN_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |   PIN_DRVSTR_MAX,
        Board_PIN_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |   PIN_DRVSTR_MAX,
        WakeUp_Event | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |   PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    #ifdef FMCU_APP
    /*
     * Application button pin configuration table:
     *   - Buttons interrupts are configured to trigger on falling edge.
     */
    PIN_Config buttonPinTable[] = {
        Board_PIN_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        Board_PIN_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        PIN_TERMINATE
    };
    
    // Clock objects for debouncing the buttons
    static Clock_Struct button0DebounceClock;
    static Clock_Struct button1DebounceClock;
    static Clock_Handle button0DebounceClockHandle;
    static Clock_Handle button1DebounceClockHandle;
    
    // State of the buttons
    static uint8_t button0State = 0;
    static uint8_t button1State = 0;
    #endif
    
    static Clock_Struct Wait_Timer_100ms_Clock;
    static Clock_Handle Wait_Timer_100ms;
    
    // Create the FMCU WakeUp Event clock objects
    static void WakeupEventFunction();
    
    
    static void WakeupEventFunction()
    {
     Start_timer_100msec=0;
    }
    
    //Util_startClock((Clock_Struct *)LeadMe_WakeUpClockHandle);
    //Util_startClock((Clock_Struct *)EngineStart_WakeUpClockHandle);
    
    
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    
    void Send_Packet(UART_Handle handle);
    char* itoa(int num, char* str, int base);
    
    /* Task functions */
    static void ProjectZero_init(void);
    static void ProjectZero_taskFxn(UArg a0,UArg a1);
    
    /* Event message processing functions */
    static void ProjectZero_processStackEvent(uint32_t stack_event);
    //static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg,UART_Handle handle);
    static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg);
    static uint8_t ProjectZero_processGATTMsg(gattMsgEvent_t *pMsg);
    static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg);
    
    static void ProjectZero_processHCIMsg(ICall_HciExtEvt *pMsg);
    //static void ProjectZero_processHCIMsg(ICall_HciExtEvt *pMsg,UART_Handle Uart_handle);
    static void ProjectZero_processPairState(pzPairStateData_t *pPairState);
    static void ProjectZero_processPasscode(pzPasscodeReq_t *pReq);
    static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
    //static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg,UART_Handle Uart_handle);
    static void ProjectZero_processAdvEvent(pzGapAdvEventData_t *pEventData);
    
    /* Profile value change handlers */
    static void ProjectZero_updateCharVal(pzCharacteristicData_t *pCharData);
    
    #ifdef FMCU_APP
    static void ProjectZero_LedService_ValueChangeHandler(pzCharacteristicData_t *pCharData);
    static void ProjectZero_ButtonService_CfgChangeHandler(pzCharacteristicData_t *pCharData);
    #endif
    
    static void ProjectZero_DataService_ValueChangeHandler(pzCharacteristicData_t *pCharData);
    
    //static void ProjectZero_DataService_ValueChangeHandler(pzCharacteristicData_t *pCharData,UART_Handle handle);
    static void ProjectZero_DataService_CfgChangeHandler(pzCharacteristicData_t *pCharData);
    
    /* Stack or profile callback function */
    static void ProjectZero_advCallback(uint32_t event,
                                        void *pBuf,
                                        uintptr_t arg);
    static void ProjectZero_passcodeCb(uint8_t *pDeviceAddr,
                                       uint16_t connHandle,
                                       uint8_t uiInputs,
                                       uint8_t uiOutputs,
                                       uint32_t numComparison);
    static void ProjectZero_pairStateCb(uint16_t connHandle,
                                        uint8_t state,
                                        uint8_t status);
    #ifndef FMCU_APP
    static void ProjectZero_LedService_ValueChangeCB(uint16_t connHandle,
                                                     uint8_t paramID,
                                                     uint16_t len,
                                                     uint8_t *pValue);
    #endif
    
    static void ProjectZero_DataService_ValueChangeCB(uint16_t connHandle,
                                                      uint8_t paramID,
                                                      uint16_t len,
                                                      uint8_t *pValue);
    #ifndef FMCU_APP
    static void ProjectZero_ButtonService_CfgChangeCB(uint16_t connHandle,
                                                      uint8_t paramID,
                                                      uint16_t len,
                                                      uint8_t *pValue);
    #endif
    static void ProjectZero_DataService_CfgChangeCB(uint16_t connHandle,
                                                    uint8_t paramID,
                                                    uint16_t len,
                                                    uint8_t *pValue);
    
    /* Connection handling functions */
    static uint8_t ProjectZero_getConnIndex(uint16_t connHandle);
    static uint8_t ProjectZero_clearConnListEntry(uint16_t connHandle);
    static uint8_t ProjectZero_addConn(uint16_t connHandle);
    static uint8_t ProjectZero_removeConn(uint16_t connHandle);
    
    static void ProjectZero_updatePHYStat(uint16_t eventCode,uint8_t *pMsg);
    static void ProjectZero_handleUpdateLinkParamReq(gapUpdateLinkParamReqEvent_t *pReq);
    static void ProjectZero_sendParamUpdate(uint16_t connHandle);
    static void ProjectZero_handleUpdateLinkEvent(gapLinkUpdateEvent_t *pEvt);
    static void ProjectZero_paramUpdClockHandler(UArg arg);
    static void ProjectZero_processConnEvt(Gap_ConnEventRpt_t *pReport);
    
    #ifndef FMCU_APP
    
    /* Button handling functions */
    static void buttonDebounceSwiFxn(UArg buttonId);
    static void buttonCallbackFxn(PIN_Handle handle,PIN_Id pinId);
    static void ProjectZero_handleButtonPress(pzButtonState_t *pState);
    
    #endif
    
    /* Utility functions */
    static status_t ProjectZero_enqueueMsg(uint8_t event,void *pData);
    
    
    static char * util_arrtohex(uint8_t const *src,
                                uint8_t src_len,
                                uint8_t       *dst,
                                uint8_t dst_len,
                                uint8_t reverse);
    static char * util_getLocalNameStr(const uint8_t *advData, uint8_t len);
    static void ProjectZero_processL2CAPMsg(l2capSignalEvent_t *pMsg);
    
    /*********************************************************************
     * EXTERN FUNCTIONS
     */
    extern void AssertHandler(uint8_t assertCause,
                              uint8_t assertSubcause);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    // GAP Bond Manager Callbacks
    static gapBondCBs_t ProjectZero_BondMgrCBs =
    {
        ProjectZero_passcodeCb,     // Passcode callback
        ProjectZero_pairStateCb     // Pairing/Bonding state Callback
    };
    
    /*
     * Callbacks in the user application for events originating from BLE services.
     */
    #ifndef FMCU_APP
    
    // LED Service callback handler.
    // The type LED_ServiceCBs_t is defined in led_service.h
    static LedServiceCBs_t ProjectZero_LED_ServiceCBs =
    {
        .pfnChangeCb = ProjectZero_LedService_ValueChangeCB,  // Characteristic value change callback handler
        .pfnCfgChangeCb = NULL, // No notification-/indication enabled chars in LED Service
    };
    
    // Button Service callback handler.
    // The type Button_ServiceCBs_t is defined in button_service.h
    static ButtonServiceCBs_t ProjectZero_Button_ServiceCBs =
    {
        .pfnChangeCb = NULL,  // No writable chars in Button Service, so no change handler.
        .pfnCfgChangeCb = ProjectZero_ButtonService_CfgChangeCB, // Noti/ind configuration callback handler
    };
    #endif
    
    // Data Service callback handler.
    // The type Data_ServiceCBs_t is defined in data_service.h
    static DataServiceCBs_t ProjectZero_Data_ServiceCBs =
    {
        .pfnChangeCb = ProjectZero_DataService_ValueChangeCB,  // Characteristic value change callback handler
        .pfnCfgChangeCb = ProjectZero_DataService_CfgChangeCB, // Noti/ind configuration callback handler
    };
    
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*********************************************************************
     * @fn     project_zero_spin
     *
     * @brief   Spin forever
     */
    static void project_zero_spin(void)
    {
      volatile uint8_t x = 0;;
    
      while(1)
      {
        x++;
      }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_createTask
     *
     * @brief   Task creation function for the Project Zero.
     */
    void ProjectZero_createTask()
      {
    
        Task_Params taskParams;
    
       //  Configure task
        Task_Params_init(&taskParams);
        taskParams.stack = appTaskStack;
        taskParams.stackSize = PZ_TASK_STACK_SIZE;
        taskParams.priority = PZ_TASK_PRIORITY;
    
        Task_construct(&pzTask, ProjectZero_taskFxn, &taskParams, NULL);
    }
    
    
    /*********************************************************************
     * @fn      ProjectZero_init
     *
     * @brief   Called during initialization and contains application
     *          specific initialization (ie. hardware initialization/setup,
     *          table initialization, power up notification, etc), and
     *          profile initialization/setup.
     */
    static void ProjectZero_init(void)
    {
    
    
        //Log_info0( "Entering in ProjectZero_init");
        // ******************************************************************
        // NO STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
        // ******************************************************************
        // Register the current thread as an ICall dispatcher application
        // so that the application can send and receive messages.
        ICall_registerApp(&selfEntity, &syncEvent);
    
        // Initialize queue for application messages.
        // Note: Used to transfer control to application thread from e.g. interrupts.
        Queue_construct(&appMsgQueue, NULL);
        appMsgQueueHandle = Queue_handle(&appMsgQueue);
    
        // ******************************************************************
        // Hardware initialization
        // ******************************************************************
    
    #ifdef USE_RCOSC
         RCOSC_enableCalibration();
    #endif // USE_RCOSC
    
    #ifndef FMCU_APP_WAKEUP
    
         Wait_Timer_100ms = Util_constructClock(&Wait_Timer_100ms_Clock,
                                                    WakeupEventFunction,100,
                                                    0,
                                                    0,
                                                    0);
    #endif
    
    
        // Set the Device Name characteristic in the GAP GATT Service
        // For more information, see the section in the User's Guide:
        // http://software-dl.ti.com/lprf/ble5stack-latest/
    
    //    Log_info1("Line 636","Entering in GGS_SetParameter");
        GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
    
        // Configure GAP for param update
        {
            uint16_t paramUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION;
    
            // Pass all parameter update requests to the app for it to decide
            GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision);
        }
    
        // Setup the GAP Bond Manager. For more information see the GAP Bond Manager
        // section in the User's Guide:
        // http://software-dl.ti.com/lprf/ble5stack-latest/
        {
            // Don't send a pairing request after connecting (the peer device must
            // initiate pairing)
            uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
            // Use authenticated pairing: require passcode.
            uint8_t mitm = TRUE;
            // This device only has display capabilities. Therefore, it will display the
            // passcode during pairing. However, since the default passcode is being
            // used, there is no need to display anything.
            uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
            // Request bonding (storing long-term keys for re-encryption upon subsequent
            // connections without repairing)
            uint8_t bonding = TRUE;
    
            // For Authentication
            uint8_t gapbondSecure = GAPBOND_SECURE_CONNECTION_ONLY;//Only Secure connection only
            GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &gapbondSecure);
    
            GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t),     &pairMode);
            GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t),  &mitm);
            GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t),  &ioCap);
            GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t),  &bonding);
        }
    
        // ******************************************************************
        // BLE Service initialization
        // ******************************************************************
      //  Log_info0("BLE Service initialization");
    
        GGS_AddService(GATT_ALL_SERVICES);         // GAP GATT Service
        GATTServApp_AddService(GATT_ALL_SERVICES); // GATT Service
    #ifndef FMCU_APP
        //DevInfo_AddService();                      // Device Information Service
    
    
        // Add services to GATT server and give ID of this task for Indication acks.
        LedService_AddService(selfEntity);
        ButtonService_AddService(selfEntity);
    #endif
         //DevInfo_AddService();                      // Device Information Service
        //Log_info0(" Entering in DataService_AddService");
        DataService_AddService(selfEntity);
    
    #ifndef FMCU_APP
    
        // Register callbacks with the generated services that
        // can generate events (writes received) to the application
       LedService_RegisterAppCBs(&ProjectZero_LED_ServiceCBs);
       ButtonService_RegisterAppCBs(&ProjectZero_Button_ServiceCBs);
    #endif
        //Log_info0("Entering in DataService_RegisterAppCBs");
        DataService_RegisterAppCBs(&ProjectZero_Data_ServiceCBs);
    
        // Placeholder variable for characteristic intialization
        uint8_t initVal[40] = {0};
        uint8_t initString[] = "This is a pretty long string, isn't it!";
    
    #ifndef FMCU_APP
    
        // Initalization of characteristics in LED_Service that can provide data.
      LedService_SetParameter(LS_LED0_ID, LS_LED0_LEN, initVal);
      LedService_SetParameter(LS_LED1_ID, LS_LED1_LEN, initVal);
    
        // Initalization of characteristics in Button_Service that can provide data.
      ButtonService_SetParameter(BS_BUTTON0_ID, BS_BUTTON0_LEN, initVal);
      ButtonService_SetParameter(BS_BUTTON1_ID, BS_BUTTON1_LEN, initVal);
    
    #endif
        // Initalization of characteristics in Data_Service that can provide data.
      //DataService_SetParameter(DS_STRING_ID, sizeof(initString), initString);
        //Log_info0("Entering in DataService_SetParameter");
        DataService_SetParameter(DS_STREAM_ID, DS_STREAM_LEN, initVal);
    
        // Start Bond Manager and register callback
        VOID GAPBondMgr_Register(&ProjectZero_BondMgrCBs);
    
        // Register with GAP for HCI/Host messages. This is needed to receive HCI
        // events. For more information, see the HCI section in the User's Guide:
        // http://software-dl.ti.com/lprf/ble5stack-latest/
        GAP_RegisterForMsgs(selfEntity);
    
        // Register for GATT local events and ATT Responses pending for transmission
        GATT_RegisterForMsgs(selfEntity);
    
        // Set default values for Data Length Extension
        // Extended Data Length Feature is already enabled by default
        {
          // Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
          // Some brand smartphone is essentially needing 251/2120, so we set them here.
          #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
          #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)
    
          // This API is documented in hci.h
          // See the LE Data Length Extension section in the BLE5-Stack User's Guide for information on using this command:
          // http://software-dl.ti.com/lprf/ble5stack-latest/
          HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
        }
    
        // Initialize GATT Client, used by GAPBondMgr to look for RPAO characteristic for network privacy
        GATT_InitClient();
    
        // Initialize Connection List
        ProjectZero_clearConnListEntry(CONNHANDLE_ALL);
    
        //Initialize GAP layer for Peripheral role and register to receive GAP events
        GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, selfEntity, ADDRMODE_PUBLIC, NULL);
    
        HCI_EXT_SetTxPowerCmd(LL_EXT_TX_POWER_5_DBM); //set 5dbm tx power
    }
    
    /*********************************************************************
     * @fn      ProjectZero_taskFxn
     *
     * @brief   Application task entry point for the Project Zero.
     *
     * @param   a0, a1 - not used.
     */
    
    
    
    
    
    Semaphore_Struct sem;
    Semaphore_Handle hSem;
    
    
    static void uartRxCb(UART_Handle handle, void *buf, size_t count);
    
    static void ProjectZero_taskFxn(UArg a0, UArg a1)
    {
       // Initialize application
        ProjectZero_init();
    
    
        Semaphore_Params sParams;
        Semaphore_Params_init(&sParams);
        sParams.mode = Semaphore_Mode_BINARY;
    
        Semaphore_construct(&sem, 0, &sParams);
        hSem = Semaphore_handle(&sem);
    
        // Application main loop
        for(;; )
        {
            uint32_t events;
    
            // Waits for an event to be posted associated with the calling thread.
            // Note that an event associated with a thread is posted when a
            // message is queued to the message receive queue of the thread
            events = Event_pend(syncEvent, Event_Id_NONE, PZ_ALL_EVENTS,ICALL_TIMEOUT_FOREVER);
    
    
            if(events)
            {
                // Log_info1("Events %d %s",events);
                ICall_EntityID dest;
                ICall_ServiceEnum src;
                ICall_HciExtEvt *pMsg = NULL;
    
                // Fetch any available messages that might have been sent from the stack
                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)
                        {
                            // Process stack events
                            ProjectZero_processStackEvent(pEvt->event_flag);
                        }
                        else
                        {
                            switch(pMsg->hdr.event)
                            {
                            case GAP_MSG_EVENT:
                                // Process GAP message
                                // Log_info0(" Entering ProjectZero_processGapMessage "); //only fmcu debug
                                ProjectZero_processGapMessage((gapEventHdr_t*) pMsg);
                                // Log_info0(" Exit from ProjectZero_processGapMessage "); //only fmcu debug
                                break;
    
                            case GATT_MSG_EVENT:
                                // Process GATT message
                                // Log_info0(" Entering ProjectZero_processGATTMsg "); //only fmcu debug
                                safeToDealloc = ProjectZero_processGATTMsg((gattMsgEvent_t *)pMsg);
                                // Log_info0(" Exit from ProjectZero_processGATTMsg "); //only fmcu debug
                                break;
    
                            case HCI_GAP_EVENT_EVENT:
                                ProjectZero_processHCIMsg(pMsg);//,hUART);
                                break;
    
                            case L2CAP_SIGNAL_EVENT:
                                // Process L2CAP free buffer notification
                                ProjectZero_processL2CAPMsg((l2capSignalEvent_t *)pMsg);
                                break;
    
                            default:
                                // do nothing
                                break;
                            }
                        }
                    }
    
                    if(pMsg && safeToDealloc)
                    {
                        ICall_freeMsg(pMsg);
                    }
                }
    
                // Process messages sent from another task or another context.
                while(!Queue_empty(appMsgQueueHandle))
                {
                    pzMsg_t *pMsg = (pzMsg_t *)Util_dequeueMsg(appMsgQueueHandle);
                    if(pMsg)
                    {
                        // Log_info0(" Entering ProjectZero_processApplicationMessage "); //only fmcu debug
                        // Process application-layer message probably sent from ourselves.
                        //ProjectZero_processApplicationMessage(pMsg,hUART);
                        ProjectZero_processApplicationMessage(pMsg);
                        // Free the received message.
                        ICall_free(pMsg);
                    }
                }
            }
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processL2CAPMsg
     *
     * @brief   Process L2CAP messages and events.
     *
     * @param   pMsg - L2CAP signal buffer from stack
     *
     * @return  None
     */
    static void ProjectZero_processL2CAPMsg(l2capSignalEvent_t *pMsg)
    {
        switch(pMsg->opcode)
        {
          case L2CAP_NUM_CTRL_DATA_PKT_EVT:
              break;
          default:
              break;
        }
    }
    
    
    /*********************************************************************
     * @fn      ProjectZero_processStackEvent
     *
     * @brief   Process stack event. The event flags received are user-selected
     *          via previous calls to stack APIs.
     *
     * @param   stack_event - mask of events received
     *
     * @return  none
     */
    static void ProjectZero_processStackEvent(uint32_t stack_event)
    {
        // Intentionally blank
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processGATTMsg
     *
     * @brief   Process GATT messages and events.
     *
     * @param   pMsg - message to process
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static uint8_t ProjectZero_processGATTMsg(gattMsgEvent_t *pMsg)
    {
        if(pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
        {
            // ATT request-response or indication-confirmation flow control is
            // violated. All subsequent ATT requests or indications will be dropped.
            // The app is informed in case it wants to drop the connection.
    
            // Display the opcode of the message that caused the violation.
            Log_error1("FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
        }
        else if(pMsg->method == ATT_MTU_UPDATED_EVENT)
        {
            // MTU size updated
            Log_info1("MTU Size: %d", pMsg->msg.mtuEvt.MTU);
        }
    
        // Free message payload. Needed only for ATT Protocol messages
        GATT_bm_free(&pMsg->msg, pMsg->method);
    
        // It's safe to free the incoming message
        return(TRUE);
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processApplicationMessage
     *
     * @brief   Handle application messages
     *
     *          These are messages not from the BLE stack, but from the
     *          application itself.
     *
     *          For example, in a Software Interrupt (Swi) it is not possible to
     *          call any BLE APIs, so instead the Swi function must send a message
     *          to the application Task for processing in Task context.
     *
     * @param   pMsg  Pointer to the message of type pzMsg_t.
     */
    //static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg,UART_Handle handle)
    static void ProjectZero_processApplicationMessage(pzMsg_t *pMsg)
    {
        // Cast to pzCharacteristicData_t* here since it's a common message pdu type.
        pzCharacteristicData_t *pCharData = (pzCharacteristicData_t *)pMsg->pData;
    
        Log_info2("Inside Process application message %s %d ",pMsg->event,pMsg->event);
    
        switch(pMsg->event)
        {
          case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
              AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
              break;
    
          case PZ_SERVICE_WRITE_EVT: /* Message about received value write */
              /* Call different handler per service */
    
              Log_info0("PZ_SERVICE_WRITE_EVT");
    
              switch(pCharData->svcUUID)
              {
    #ifndef FMCU_APP
    
              case LED_SERVICE_SERV_UUID:
                    ProjectZero_LedService_ValueChangeHandler(pCharData);
                    break;
    #endif
              case DATA_SERVICE_SERV_UUID:
                  //Log_info1("Line 956","Entering in ProjectZero_DataService_ValueChangeHandler");
                    Log_info0("Entering in ProjectZero_DataService_ValueChangeHandler ");
                    ProjectZero_DataService_ValueChangeHandler(pCharData);
                    break;
              }
              /****Added RSSI Read Value ***/
              // HCI_ReadRssiCmd(advHandleLegacy);
              break;
    
          case PZ_SERVICE_CFG_EVT: /* Message about received CCCD write */
              /* Call different handler per service */
              switch(pCharData->svcUUID)
              {
    #ifndef FMCU_APP
              case BUTTON_SERVICE_SERV_UUID:
                    ProjectZero_ButtonService_CfgChangeHandler(pCharData);
                    break;
    #endif
              case DATA_SERVICE_SERV_UUID:
                  Log_info1("Line 972","Entering in ProjectZero_DataService_CfgChangeHandler");
                    ProjectZero_DataService_CfgChangeHandler(pCharData);
                    break;
              }
              break;
    
          case PZ_UPDATE_CHARVAL_EVT: /* Message from ourselves to send  */
              ProjectZero_updateCharVal(pCharData);
              break;
    
    #ifndef FMCU_APP
          case PZ_BUTTON_DEBOUNCED_EVT: /* Message from swi about pin change */
          {
              pzButtonState_t *pButtonState = (pzButtonState_t *)pMsg->pData;
              ProjectZero_handleButtonPress(pButtonState);
          }
          break;
    #endif
    
          case PZ_ADV_EVT:
              ProjectZero_processAdvEvent((pzGapAdvEventData_t*)(pMsg->pData));
              break;
    
          case PZ_SEND_PARAM_UPD_EVT:
          {
              // Send connection parameter update
              pzSendParamReq_t* req = (pzSendParamReq_t *)pMsg->pData;
              ProjectZero_sendParamUpdate(req->connHandle);
          }
          break;
    
          case PZ_START_ADV_EVT:
              if(linkDB_NumActive() < MAX_NUM_BLE_CONNS)
              {
                  // Enable advertising if there is room for more connections
                  GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
              }
              break;
    
          case PZ_PAIRSTATE_EVT: /* Message about the pairing state */
              ProjectZero_processPairState((pzPairStateData_t*)(pMsg->pData));
              break;
    
          case PZ_PASSCODE_EVT: /* Message about pairing PIN request */
          {
              pzPasscodeReq_t *pReq = (pzPasscodeReq_t *)pMsg->pData;
              ProjectZero_processPasscode(pReq);
          }
          break;
    
          case PZ_CONN_EVT:
            ProjectZero_processConnEvt((Gap_ConnEventRpt_t *)(pMsg->pData));
            break;
    
          default:
            break;
        }
    
        if(pMsg->pData != NULL)
        {
            ICall_free(pMsg->pData);
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processGapMessage
     *
     * @brief   Process an incoming GAP event.
     *
     * @param   pMsg - message to process
     */
    static void ProjectZero_processGapMessage(gapEventHdr_t *pMsg)
    {
        switch(pMsg->opcode)
        {
        case GAP_DEVICE_INIT_DONE_EVENT:
        {
            bStatus_t status = FAILURE;
    
            gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
    
            if(pPkt->hdr.status == SUCCESS)
            {
    
                //Store the system ID
                uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
    
                // use 6 bytes of device address for 8 bytes of system ID value
                systemId[0] = pPkt->devAddr[0];
                systemId[1] = pPkt->devAddr[1];
                systemId[2] = pPkt->devAddr[2];
    
                // set middle bytes to zero
                systemId[4] = 0x00;
                systemId[3] = 0x00;
    
                // shift three bytes up
                systemId[7] = pPkt->devAddr[5];
                systemId[6] = pPkt->devAddr[4];
                systemId[5] = pPkt->devAddr[3];
    
                // Set Device Info Service Parameter
          //DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN,systemId);
    
                // Display device address
                // Need static so string persists until printed in idle thread.
                static uint8_t addrStr[3 * B_ADDR_LEN + 1];
                util_arrtohex(pPkt->devAddr, B_ADDR_LEN, addrStr, sizeof addrStr,
                              UTIL_ARRTOHEX_REVERSE);
              Log_info1("GAP is started. Our address: " \
                          ANSI_COLOR(FG_GREEN) "%s" ANSI_COLOR(ATTR_RESET),
                          (uintptr_t)addrStr);
    
                // Setup and start Advertising
                // For more information, see the GAP section in the User's Guide:
                // http://software-dl.ti.com/lprf/ble5stack-latest/
    
                // Temporary memory for advertising parameters for set #1. These will be copied
                // by the GapAdv module
                GapAdv_params_t advParamLegacy = GAPADV_PARAMS_LEGACY_SCANN_CONN;
    
                // Create Advertisement set #1 and assign handle
                status = GapAdv_create(&ProjectZero_advCallback, &advParamLegacy,
                                       &advHandleLegacy);
                APP_ASSERT(status == SUCCESS);
    
                Log_info1("Name in advertData array: " \
                          ANSI_COLOR(FG_YELLOW) "%s" ANSI_COLOR(ATTR_RESET),
                          (uintptr_t)util_getLocalNameStr(advertData,
                                                          sizeof(advertData)));
    
                // Load advertising data for set #1 that is statically allocated by the app
                status = GapAdv_loadByHandle(advHandleLegacy, GAP_ADV_DATA_TYPE_ADV,
                                             sizeof(advertData), advertData);
                APP_ASSERT(status == SUCCESS);
    
                // Load scan response data for set #1 that is statically allocated by the app
                status =
                    GapAdv_loadByHandle(advHandleLegacy, GAP_ADV_DATA_TYPE_SCAN_RSP,
                                        sizeof(scanRspData),
                                        scanRspData);
                APP_ASSERT(status == SUCCESS);
    
    
                // Set event mask for set #1
                status = GapAdv_setEventMask(advHandleLegacy,
                                             GAP_ADV_EVT_MASK_START_AFTER_ENABLE |
                                             GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
                                             GAP_ADV_EVT_MASK_SET_TERMINATED);
    
                // Enable legacy advertising for set #1
                status =
                    GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX,
                                  0);
                APP_ASSERT(status == SUCCESS);
            }
    
            break;
        }
    
        case GAP_LINK_ESTABLISHED_EVENT:
        {
            gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;
    
            // Display the amount of current connections
            Log_info2("Link establish event, status 0x%02x. Num Conns: %d",
                      pPkt->hdr.status,
                      linkDB_NumActive());
    
            if(pPkt->hdr.status == SUCCESS)
            {
                // Add connection to list
                ProjectZero_addConn(pPkt->connectionHandle);
    
                // Display the address of this connection
                static uint8_t addrStr[3 * B_ADDR_LEN + 1];
                util_arrtohex(pPkt->devAddr, B_ADDR_LEN, addrStr, sizeof addrStr,
                              UTIL_ARRTOHEX_REVERSE);
    //            Log_info1("Connected. Peer address: " \
    //                        ANSI_COLOR(FG_GREEN)"%s"ANSI_COLOR(ATTR_RESET),
    //                      (uintptr_t)addrStr);
    
                //Set Dio_7 High to Know FMCU that mobile is connected
                PIN_setOutputValue(ledPinHandle, WakeUp_Event,1);
                PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
                 uint32_t sleepUs = 500000;
                 Task_sleep(sleepUs / Clock_tickPeriod);
                 PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
                 PIN_setOutputValue(ledPinHandle, WakeUp_Event,0);
            }
    
            if(linkDB_NumActive() < MAX_NUM_BLE_CONNS)
            {
    //            Log_info1("Continue to Advertise, %d possible connection remain", MAX_NUM_BLE_CONNS - linkDB_NumActive());
                // Start advertising since there is room for more connections
                GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
            }
            else
            {
    //            Log_info1("Max Number of Connection reach: %d, Adv. will not be enable again", linkDB_NumActive());
            }
        }
        break;
    
        case GAP_LINK_TERMINATED_EVENT:
        {
            gapTerminateLinkEvent_t *pPkt = (gapTerminateLinkEvent_t *)pMsg;
    
            // Set DIO_7 Low For FMCU to know device is disconnected or out of range
            PIN_setOutputValue(ledPinHandle, WakeUp_Event,0);
    
            // Display the amount of current connections
            Log_info0("Device Disconnected!");
            Log_info1("Num Conns: %d", linkDB_NumActive());
    
            // Remove the connection from the list and disable RSSI if needed
            ProjectZero_removeConn(pPkt->connectionHandle);
    /*******************************/
            HCI_EXT_DisconnectImmedCmd(pPkt->connectionHandle); //Terminate the connection
    
            // GapAdv_enable will return success only if the maximum number of connections 
            // has been reached, and adv was not re-enable in GAP_LINK_ESTABLISHED_EVENT
            // switch case.
            // If less connection were in used, Advertisement will have been restart in 
            // the GAP_LINK_ESTABLISHED_EVENT switch case and calling GapAdv_enable will
            // just return an error.
            if ( GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0) == SUCCESS)
            {
    //          Log_info1("Restart Advertising, %d possible connection remain", MAX_NUM_BLE_CONNS - linkDB_NumActive());
            }
        }
        break;
    
        case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
    //        Log_info0("GAP_UPDATE_LINK_PARAM_REQ_EVENT");
            ProjectZero_handleUpdateLinkParamReq((gapUpdateLinkParamReqEvent_t *)pMsg);
            break;
    
        case GAP_LINK_PARAM_UPDATE_EVENT:
           // Log_info0("GAP_LINK_PARAM_UPDATE_EVENT");//Only Debug FMCU Mux
            ProjectZero_handleUpdateLinkEvent((gapLinkUpdateEvent_t *)pMsg);
            //Log_info0(" coming out of GAP_LINK_PARAM_UPDATE_EVENT");//Only Debug FMCU Mux
            break;
    
        case GAP_PAIRING_REQ_EVENT:
            // Disable advertising so that the peer device can be added to
            // the resolving list
            GapAdv_disable(advHandleLegacy);
            break;
    
        default:
            break;
        }
    }
    void ProjectZero_processHCIMsg(ICall_HciExtEvt *pEvt)
    //void ProjectZero_processHCIMsg(ICall_HciExtEvt *pEvt,UART_Handle hUART)
    {
        ICall_Hdr *pMsg = (ICall_Hdr *)pEvt;
    
        // Process HCI message
        switch(pMsg->status)
        {
        case HCI_COMMAND_COMPLETE_EVENT_CODE:
            // Process HCI Command Complete Events here
            ProjectZero_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
            //UART_write(hUART,"Going",5);
            //ProjectZero_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg, hUART);
    
            break;
    
        case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
            AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
            break;
    
        // HCI Commands Events
        case HCI_COMMAND_STATUS_EVENT_CODE:
        {
            hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
            switch(pMyMsg->cmdOpcode)
            {
            case HCI_LE_SET_PHY:
            {
                if(pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
                {
    //                Log_info0("PHY Change failure, peer does not support this");
                }
                else
                {
    //                Log_info1("PHY Update Status Event: 0x%x",
    //                          pMyMsg->cmdStatus);
                }
    
                ProjectZero_updatePHYStat(HCI_LE_SET_PHY, (uint8_t *)pMsg);
            }
            break;
    
            default:
                break;
            }
        }
        break;
    
        // LE Events
        case HCI_LE_EVENT_CODE:
        {
            hciEvt_BLEPhyUpdateComplete_t *pPUC =
                (hciEvt_BLEPhyUpdateComplete_t*) pMsg;
    
            // A Phy Update Has Completed or Failed
            if(pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
            {
                if(pPUC->status != SUCCESS)
                {
    //                Log_info0("PHY Change failure");
                }
                else
                {
                    // Only symmetrical PHY is supported.
                    // rxPhy should be equal to txPhy.
                    Log_info1("PHY Updated to %s",
                              (uintptr_t)((pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_1M) ? "1M" :
                                          (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_2M) ? "2M" :
                                          (pPUC->rxPhy == PHY_UPDATE_COMPLETE_EVENT_CODED) ? "CODED" : "Unexpected PHY Value"));
                }
    
                ProjectZero_updatePHYStat(HCI_BLE_PHY_UPDATE_COMPLETE_EVENT,
                                          (uint8_t *)pMsg);
            }
        }
        break;
    
        default:
            break;
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processAdvEvent
     *
     * @brief   Process advertising event in app context
     *
     * @param   pEventData
     *
     * @return  TRUE if safe to deallocate incoming message, FALSE otherwise.
     */
    static void ProjectZero_processAdvEvent(pzGapAdvEventData_t *pEventData)
    {
        switch(pEventData->event)
        {
        /* Sent on the first advertisement after a GapAdv_enable */
        case GAP_EVT_ADV_START_AFTER_ENABLE:
       //     Log_info1("Adv Set %d Enabled", *(uint8_t *)(pEventData->pBuf));
            break;
    
        /* Sent after advertising stops due to a GapAdv_disable */
        case GAP_EVT_ADV_END_AFTER_DISABLE:
        //    Log_info1("Adv Set %d Disabled", *(uint8_t *)(pEventData->pBuf));
            break;
    
        /* Sent at the beginning of each advertisement. (Note that this event
         * is not enabled by default, see GapAdv_setEventMask). */
        case GAP_EVT_ADV_START:
            break;
    
        /* Sent after each advertisement. (Note that this event is not enabled
         * by default, see GapAdv_setEventMask). */
        case GAP_EVT_ADV_END:
            break;
    
        /* Sent when an advertisement set is terminated due to a
         * connection establishment */
        case GAP_EVT_ADV_SET_TERMINATED:
        {
            GapAdv_setTerm_t *advSetTerm = (GapAdv_setTerm_t *)(pEventData->pBuf);
    
    //        Log_info2("Adv Set %d disabled after conn %d",
    //                  advSetTerm->handle, advSetTerm->connHandle);
        }
        break;
    
        /* Sent when a scan request is received. (Note that this event
         * is not enabled by default, see GapAdv_setEventMask). */
        case GAP_EVT_SCAN_REQ_RECEIVED:
            break;
    
        /* Sent when an operation could not complete because of a lack of memory.
           This message is not allocated on the heap and must not be freed */
        case GAP_EVT_INSUFFICIENT_MEMORY:
            break;
    
        default:
            break;
        }
    
      // All events have associated memory to free except the insufficient memory
      // event
      if (pEventData->event != GAP_EVT_INSUFFICIENT_MEMORY)
      {
        ICall_free(pEventData->pBuf);
      }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processPairState
     *
     * @brief   Process the new paring state.
     *
     * @param   pPairData - pointer to pair state data container
     */
    static void ProjectZero_processPairState(pzPairStateData_t *pPairData)
    {
        uint8_t state = pPairData->state;
        uint8_t status = pPairData->status;
    
        switch(state)
        {
        case GAPBOND_PAIRING_STATE_STARTED:
            Log_info0("Pairing started");
            break;
    
        case GAPBOND_PAIRING_STATE_COMPLETE:
            if(status == SUCCESS)
            {
    //            Log_info0("Pairing success");
            }
            else
            {
    //            Log_info1("Pairing fail: %d", status);
            }
            break;
    
        case GAPBOND_PAIRING_STATE_ENCRYPTED:
            if(status == SUCCESS)
            {
    //            Log_info0("Encryption success");
            }
            else
            {
    //            Log_info1("Encryption failed: %d", status);
            }
            break;
    
        case GAPBOND_PAIRING_STATE_BOND_SAVED:
            if(status == SUCCESS)
            {
    //            Log_info0("Bond save success");
            }
            else
            {
    //            Log_info1("Bond save failed: %d", status);
            }
            break;
    
        default:
            break;
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_processPasscode
     *
     * @brief   Process the Passcode request.
     *
     * @param   pReq - pointer to passcode req
     */
    static void ProjectZero_processPasscode(pzPasscodeReq_t *pReq)
    {
    //    Log_info2("BondMgr Requested passcode. We are %s passcode %06d",
    //              (uintptr_t)(pReq->uiInputs ? "Sending" : "Displaying"),
    //              B_APP_DEFAULT_PASSCODE);
    
        // Send passcode response.
        GAPBondMgr_PasscodeRsp(pReq->connHandle, SUCCESS, B_APP_DEFAULT_PASSCODE);
    }
    /*********************************************************************
     * @fn      ProjectZero_processConnEvt
     *
     * @brief   Process connection event.
     *
     * @param pReport pointer to connection event report
     */
    static void ProjectZero_processConnEvt(Gap_ConnEventRpt_t *pReport)
    {
    //  Log_info1("Connection event done for connHandle: %d", pReport->handle);
    }
    
    
    
    char rev[5];
    
    // Implementation of itoa()
    char* itoa(int num, char* str, int base)
    {
        int i = 0;
        bool isNegative = false;
    
        /* Handle 0 explicitely, otherwise empty string is printed for 0 */
        if (num == 0)
        {
            str[i++] = '0';
            str[i] = '\0';
            return str;
        }
    
        // In standard itoa(), negative numbers are handled only with
        // base 10. Otherwise numbers are considered unsigned.
        if (num < 0 && base == 10)
        {
            isNegative = true;
            num = -num;
        }
    
        // Process individual digits
        while (num != 0)
        {
            int rem = num % base;
            str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
            num = num/base;
        }
    
        // If number is negative, append '-'
        if (isNegative)
            str[i++] = '-';
    
        str[i] = '\0'; // Append string terminator
    
        // Reverse the string
        //reverse(str, i);
    
        return str;
    }
    
    
    
    
    /*********************************************************************
     * @fn      ProjectZero_processCmdCompleteEvt
     *
     * @brief   Process an incoming OSAL HCI Command Complete Event.
     *
     * @param   pMsg - message to process
     */
    //static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg,UART_Handle hUART)
    
    static void ProjectZero_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
    {
        uint8_t status = pMsg->pReturnParam[0];
    
        //Find which command this command complete is for
        switch(pMsg->cmdOpcode)
        {
        case HCI_READ_RSSI:
        {
            char buf [5];
                int8 rssi = (int8)pMsg->pReturnParam[3];
        
            // Display RSSI value, if RSSI is higher than threshold, change to faster PHY
            if(status == SUCCESS)
            {
                uint16_t handle = BUILD_UINT16(pMsg->pReturnParam[1],
                                               pMsg->pReturnParam[2]);
    
                Log_info2("RSSI:%d, connHandle %d",
                          (uint32_t)(rssi),
                          (uint32_t)handle);
    
                //UART_write(hUART,"Inside :",8);
    
                itoa(rssi,buf,10);
    
                           int length=4,k=0;
                           int j= length-1;
    
                             //reversing the string by swapping
                             for (k = 0; k < length; k++)
                                 {
                                   rev[k] = buf[j];
                                   j--;
                                 }
    
                             rev[k] = '\0';
    
                           //UART_write(hUART,rev,5);
    
                //UART_write(hUART,"ok",2);
    
            } // end of if (status == SUCCESS)
            break;
        }
    
        case HCI_LE_READ_PHY:
        {
            if(status == SUCCESS)
            {
    //            Log_info2("RXPh: %d, TXPh: %d",
    //                      pMsg->pReturnParam[3], pMsg->pReturnParam[4]);
            }
            break;
        }
    
        default:
            break;
        } // end of switch (pMsg->cmdOpcode)
    }
    
    /*********************************************************************
     * @fn      ProjectZero_handleUpdateLinkParamReq
     *
     * @brief   Receive and respond to a parameter update request sent by
     *          a peer device
     *
     * @param   pReq - pointer to stack request message
     */
    static void ProjectZero_handleUpdateLinkParamReq(gapUpdateLinkParamReqEvent_t *pReq)
    {
     //   Log_info0("Inside the ProjectZero_handleUpdateLinkParamReq");
        gapUpdateLinkParamReqReply_t rsp;
    
        rsp.connectionHandle = pReq->req.connectionHandle;
        rsp.signalIdentifier = pReq->req.signalIdentifier;
    
        // Only accept connection intervals with slave latency of 0
        // This is just an example of how the application can send a response
        if(pReq->req.connLatency == 0)
        {
            rsp.intervalMin = pReq->req.intervalMin;
            rsp.intervalMax = pReq->req.intervalMax;
            rsp.connLatency = pReq->req.connLatency;
            rsp.connTimeout = pReq->req.connTimeout;
            rsp.accepted = TRUE;
        }
        else
        {
            Log_info0("rsp_accepted = FALSE");//Only Debug FMCU Mux
            rsp.accepted = FALSE;
        }
    
        // Send Reply
       // Log_info0("Entering GAP_UpdateLinkParamReqReply ");//Only Debug FMCU Mux
        VOID GAP_UpdateLinkParamReqReply(&rsp);
       // Log_info0("Exiting GAP_UpdateLinkParamReqReply ");//Only Debug FMCU Mux
    
    }
    
    /*********************************************************************
     * @fn      ProjectZero_handleUpdateLinkEvent
     *
     * @brief   Receive and parse a parameter update that has occurred.
     *
     * @param   pEvt - pointer to stack event message
     */
    static void ProjectZero_handleUpdateLinkEvent(gapLinkUpdateEvent_t *pEvt)
    {
       // Log_info0("Entering ProjectZero_handleUpdateLinkEvent ");//Only Debug FMCU Mux
        // Get the address from the connection handle
        linkDBInfo_t linkInfo;
        linkDB_GetInfo(pEvt->connectionHandle, &linkInfo);
      //  Log_info1("Link DB_info0 %d ",(uintptr_t)pEvt->connectionHandle);//Only Debug FMCU Mux
    
        static uint8_t addrStr[3 * B_ADDR_LEN + 1];
        util_arrtohex(linkInfo.addr, B_ADDR_LEN, addrStr, sizeof addrStr,
                      UTIL_ARRTOHEX_REVERSE);
    
        if(pEvt->status == SUCCESS)
        {
            //Log_info0("Entered ProjectZero_handleUpdateLinkEvent"  );//Only Debug FMCU Mux
    
            uint8_t ConnIntervalFracture = 25*(pEvt->connInterval % 4);
            // Display the address of the connection update
           /* Log_info5(
                "Updated params for %s, interval: %d.%d ms, latency: %d, timeout: %d ms",
                (uintptr_t)addrStr,
                (uintptr_t)(pEvt->connInterval*CONN_INTERVAL_MS_CONVERSION),
                ConnIntervalFracture,
                pEvt->connLatency,
                pEvt->connTimeout*CONN_TIMEOUT_MS_CONVERSION);*/
        }
        else
        {
            // Display the address of the connection update failure
          //  Log_info2("Update Failed 0x%02x: %s", pEvt->opcode, (uintptr_t)addrStr);
        }
    
        // Check if there are any queued parameter updates
        pzConnHandleEntry_t *connHandleEntry = (pzConnHandleEntry_t *)List_get(&paramUpdateList);
    
        if(connHandleEntry != NULL)
        {
            // Attempt to send queued update now
            ProjectZero_sendParamUpdate(*(connHandleEntry->connHandle));
    
            // Free list element
            ICall_free(connHandleEntry->connHandle);
            ICall_free(connHandleEntry);
            //Log_info0("Exit ProjectZero_handleUpdateLinkEvent ");//Only Debug FMCU Mux
    
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_addConn
     *
     * @brief   Add a device to the connected device list
     *
     * @param   connHandle - connection handle
     *
     * @return  bleMemAllocError if a param update event could not be sent. Else SUCCESS.
     */
    static uint8_t ProjectZero_addConn(uint16_t connHandle)
    {
        uint8_t i;
        uint8_t status = bleNoResources;
    
        // Try to find an available entry
        for(i = 0; i < MAX_NUM_BLE_CONNS; i++)
        {
            if(connList[i].connHandle == CONNHANDLE_INVALID)
            {
                // Found available entry to put a new connection info in
                connList[i].connHandle = connHandle;
    
                // Create a clock object and start
                connList[i].pUpdateClock
                  = (Clock_Struct*) ICall_malloc(sizeof(Clock_Struct));
    
                if (connList[i].pUpdateClock)
                {
                  Util_constructClock(connList[i].pUpdateClock,
                                      ProjectZero_paramUpdClockHandler,
                                      PZ_SEND_PARAM_UPDATE_DELAY, 0, true,
                                      (uintptr_t)connHandle);
                }
    
                // Set default PHY to 1M
                connList[i].currPhy = HCI_PHY_1_MBPS; // TODO: Is this true, neccessarily?
    
                break;
            }
        }
    
        return(status);
    }
    
    /*********************************************************************
     * @fn      ProjectZero_getConnIndex
     *
     * @brief   Find index in the connected device list by connHandle
     *
     * @param   connHandle - connection handle
     *
     * @return  the index of the entry that has the given connection handle.
     *          if there is no match, MAX_NUM_BLE_CONNS will be returned.
     */
    static uint8_t ProjectZero_getConnIndex(uint16_t connHandle)
    {
        uint8_t i;
    
        for(i = 0; i < MAX_NUM_BLE_CONNS; i++)
        {
            if(connList[i].connHandle == connHandle)
            {
              //  Log_info1("Inside ProjectZero_getConnIndex ",connList[i].connHandle); //Only for FMCU_Debug
                return(i);
            }
    
        }
    
        return(MAX_NUM_BLE_CONNS);
    }
    
    /*********************************************************************
     * @fn      ProjectZero_clearConnListEntry
     *
     * @brief   Clear the connection information structure held locally.
     *
     * @param   connHandle - connection handle
     *
     * @return  SUCCESS if connHandle found valid index or bleInvalidRange
     *          if index wasn't found. LINKDB_CONNHANDLE_ALL will always succeed.
     */
    static uint8_t ProjectZero_clearConnListEntry(uint16_t connHandle)
    {
       // Log_info0("Inside ProjectZero_clearConnListEntry ");// only for FMCU_Debug
    
        uint8_t i;
        // Set to invalid connection index initially
        uint8_t connIndex = MAX_NUM_BLE_CONNS;
    
        if(connHandle != CONNHANDLE_ALL)
        {
            // Get connection index from handle
            connIndex = ProjectZero_getConnIndex(connHandle);
            if(connIndex >= MAX_NUM_BLE_CONNS)
            {
                return(bleInvalidRange);
            }
        }
    
        // Clear specific handle or all handles
        for(i = 0; i < MAX_NUM_BLE_CONNS; i++)
        {
            if((connIndex == i) || (connHandle == CONNHANDLE_ALL))
            {
                connList[i].connHandle = CONNHANDLE_INVALID;
                connList[i].currPhy = 0;
                connList[i].phyCngRq = 0;
                connList[i].phyRqFailCnt = 0;
                connList[i].rqPhy = 0;
            }
        }
    
        return(SUCCESS);
    }
    
    /*********************************************************************
     * @fn      ProjectZero_removeConn
     *
     * @brief   Remove a device from the connected device list
     *
     * @param   connHandle - connection handle
     *
     * @return  index of the connected device list entry where the new connection
     *          info is removed from.
     *          if connHandle is not found, MAX_NUM_BLE_CONNS will be returned.
     */
    static uint8_t ProjectZero_removeConn(uint16_t connHandle)
    {
      //  Log_info0("Inside ProjectZero_removeConn ");// only for FMCU_Debug
    
        uint8_t connIndex = ProjectZero_getConnIndex(connHandle);
    
        if(connIndex < MAX_NUM_BLE_CONNS)
        {
          Clock_Struct* pUpdateClock = connList[connIndex].pUpdateClock;
    
          if (pUpdateClock != NULL)
          {
            // Stop and destruct the RTOS clock if it's still alive
            if (Util_isActive(pUpdateClock))
            {
              Util_stopClock(pUpdateClock);
            }
    
            // Destruct the clock object
            Clock_destruct(pUpdateClock);
            // Free clock struct
            ICall_free(pUpdateClock);
          }
          // Clear Connection List Entry
          ProjectZero_clearConnListEntry(connHandle);
        }
    
        return connIndex;
    }
    
    /*********************************************************************
     * @fn      ProjectZero_sendParamUpdate
     *
     * @brief   Remove a device from the connected device list
     *
     * @param   connHandle - connection handle
     */
    static void ProjectZero_sendParamUpdate(uint16_t connHandle)
    {
        gapUpdateLinkParamReq_t req;
        uint8_t connIndex;
    
        req.connectionHandle = connHandle;
        req.connLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
        req.connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
        req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
        req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    
        connIndex = ProjectZero_getConnIndex(connHandle);
        APP_ASSERT(connIndex < MAX_NUM_BLE_CONNS);
    
        // Deconstruct the clock object
        Clock_destruct(connList[connIndex].pUpdateClock);
        // Free clock struct
        ICall_free(connList[connIndex].pUpdateClock);
        connList[connIndex].pUpdateClock = NULL;
    
        // Send parameter update
        bStatus_t status = GAP_UpdateLinkParamReq(&req);
    
        // If there is an ongoing update, queue this for when the update completes
        if(status == bleAlreadyInRequestedMode)
        {
            pzConnHandleEntry_t *connHandleEntry =
                ICall_malloc(sizeof(pzConnHandleEntry_t));
            if(connHandleEntry)
            {
                connHandleEntry->connHandle = ICall_malloc(sizeof(uint16_t));
    
                if(connHandleEntry->connHandle)
                {
                    *(connHandleEntry->connHandle) = connHandle;
    
                    List_put(&paramUpdateList, (List_Elem *)&connHandleEntry);
                }
            }
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_updatePHYStat
     *
     * @brief   Update the auto phy update state machine
     *
     * @param   eventCode - HCI LE Event code
     *          pMsg - message to process
     */
    static void ProjectZero_updatePHYStat(uint16_t eventCode, uint8_t *pMsg)
    {
        uint8_t connIndex;
        pzConnHandleEntry_t *connHandleEntry;
    
        switch(eventCode)
        {
        case HCI_LE_SET_PHY:
        {
            // Get connection handle from list
            connHandleEntry = (pzConnHandleEntry_t *)List_get(&setPhyCommStatList);
    
            if(connHandleEntry)
            {
                // Get index from connection handle
                connIndex = ProjectZero_getConnIndex(*(connHandleEntry->connHandle));
                APP_ASSERT(connIndex < MAX_NUM_BLE_CONNS);
    
                ICall_free(connHandleEntry->connHandle);
                ICall_free(connHandleEntry);
    
                hciEvt_CommandStatus_t *pMyMsg = (hciEvt_CommandStatus_t *)pMsg;
    
                if(pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
                {
                    // Update the phy change request status for active RSSI tracking connection
                    connList[connIndex].phyCngRq = FALSE;
                    connList[connIndex].phyRqFailCnt++;
                }
            }
            break;
        }
    
        // LE Event - a Phy update has completed or failed
        case HCI_BLE_PHY_UPDATE_COMPLETE_EVENT:
        {
            hciEvt_BLEPhyUpdateComplete_t *pPUC =
                (hciEvt_BLEPhyUpdateComplete_t*) pMsg;
    
            if(pPUC)
            {
                // Get index from connection handle
                uint8_t index = ProjectZero_getConnIndex(pPUC->connHandle);
                APP_ASSERT(index < MAX_NUM_BLE_CONNS);
    
                // Update the phychange request status for active RSSI tracking connection
                connList[index].phyCngRq = FALSE;
    
                if(pPUC->status == SUCCESS)
                {
                    connList[index].currPhy = pPUC->rxPhy;
                }
                if(pPUC->rxPhy != connList[index].rqPhy)
                {
                    connList[index].phyRqFailCnt++;
                }
                else
                {
                    // Reset the request phy counter and requested phy
                    connList[index].phyRqFailCnt = 0;
                    connList[index].rqPhy = 0;
                }
            }
    
            break;
        }
    
        default:
            break;
        } // end of switch (eventCode)
    }
    
    
    //static void uartRxCb(UART_Handle handle, void *buf, size_t count)
    //{
    //  //Copy rxBuf to txBuf
    //  memset(txBuf, 0, BUFSIZE);
    //
    //  memcpy(txBuf, rxBuf, count);
    //  //Wake task to echo
    //  Semaphore_post(hSem);
    //}
    
    
    
    //MobileApp Button data
    char EngineStart[8]={36, 172, 4, 36, 173, 7, 32,  0};  //EngineStart String    36 172 4 36 173 7 32 0
    char EngineStop[8]= {36, 172, 4, 36, 173, 7, 32,  1};  //EngineSTOP            36 172 4 36 173 7 32 1
    char LeadMe_ON[8]=  {36, 172, 4, 36, 173, 1,  0, 138};  //LEAD ME ON            36 172 4 36 173 1 0 138
    char LeadMe_OFF[8]= {36, 172, 4, 36, 173, 1,  0, 139};  //LEAD ME OFF           36 172 4 36 173 1 0 139
    
    #define Rx_Size               4
    #define LeadMeButton_ON       10
    #define LeadMeButton_OFF      20
    #define EngineStart_Button    30
    #define EngineStop_Button     40
    
    char rxBuf[Rx_Size];
    char txBuf[Rx_Size];
    
    static uint8_t Button=0;
    uint8_t RXcount=0;
    
    uint8_t ACK_Flag = 0;
    uint8_t Counter_retry=0;
    
    #define Maximum_Number_of_Try 3
    
    char RxResponse[Rx_Size];
    
    char PACK[Rx_Size] =   {"PACK"};
    char NACK[Rx_Size] =   {"NACK"};
    
    //char  PACK[Rx_Size]  =   {0x41,0x41};
    //char NACK[Rx_Size]  =   {0x4B,0x4B};
    //
    
    
    static void uartRxCb(UART_Handle handle, void *buf, size_t count)
     {
      if(count>=Rx_Size)
         {
          //Clear RxResponse
          memset(RxResponse, 0, count);
    
          //Store rx data in other memory
          memcpy(RxResponse, buf, count);
    
          //UART_write(handle,RxString,sizeof(RxString));
    
          //UART_write(handle,RxString, count);
    
         }
      else
           memcpy(RxResponse, "NO-DATA", count);
    
      Semaphore_post(hSem);
     }
    
    //**************************************************************************************
    /*
     * PACKET STRUTURE FROM BLE TO FMCU
     * Start_Byte    : 0x23 (1 Byte)
     * Packet_Length : 0x31 0x36 (1 Byte) (16 bytes of data by default)
     * DATA_START_ID : 0x3C (1 Byte)
     * PayLoad       : xxxx (16 Bytes)
     * DATA_STOP_ID  : 0x3E (1 Byte)
     **************************************************************************************/
    
    
    void Send_Packet(UART_Handle handle)
     {
        //0x23      ----> #
        //0x31 0x36 ----> data of 16 bytes
        //0x3C    ------> <
        //0x3E     -----> >
    
        static uint8_t Packet_array[3]={0X23,16,0X3C};
    
        UART_write(handle,&Packet_array[0],3);
    
     }
    
    void ProjectZero_DataService_ValueChangeHandler( pzCharacteristicData_t *pCharData)
    {
      //  Log_info0(" Inside ProjectZero_DataService_ValueChangeHandler ");
    
      //  Value to hold the received string for printing via Log, as Log printouts
      //  happen in the Idle task, and so need to refer to a global/static variable.
      //  static uint8_t received_string[DS_STRING_LEN] = {0};
      //  static uint8_t received_string[DS_STREAM_LEN] = {0};
    
        // Rx buffer size
        uint8_t RxDataLength = pCharData->dataLen;
    
        // Buffer to hold RX data from Mobile App
        uint8_t Buffer[(RxDataLength + 1)];
    
        uint8_t RxCount = 0;
    
     switch(pCharData->paramID)
        {
        case DS_STREAM_ID:
                   // Log_info0("Value Change msg:");
                   memset(Buffer,0,RxDataLength);
    
                 for(int i=0;i<RxDataLength;i++)
                     {
                     Buffer[i]=pCharData->data[i];
                     //Log_info1("%02x",pCharData->data[i]);
                     }
    
    
    
    //             UART_write(handle,&Buffer[0],8);
    
    
    //          // Display rx data in array
    //              for(int i=0;i<RxDataLength;i++)     //  36 172 4 36 173 1 0 138
    //                 {
    //                //  Log_info1("Received data : %d ",Buffer[i]);
    //                 }
    
                 //UART initialization
               /* Call driver init functions */
                   UART_init();
                   UART_Params params;
                   UART_Params_init(&params);
                   UART_Handle handle;
                   uint32_t timeoutUs = 100000; //1second // 5000;  // 5ms timeout, default timeout is no timeout (BIOS_WAIT_FOREVER)
    
    
               params.readMode     = UART_MODE_CALLBACK;
               params.writeMode    = UART_MODE_BLOCKING;
               params.readCallback = uartRxCb;
               params.readTimeout   = timeoutUs / ClockP_getSystemTickPeriod(); // Default tick period is 10us
               params.baudRate     = 115200;
    
               handle = UART_open(Board_UART0, &params);
    
               // Enable RETURN_PARTIAL
               // UART_control(hUART, UARTCC26X2_CMD_RETURN_PARTIAL_ENABLE, NULL);
    
              if(handle==NULL)
                {
    
                }
    
              /****Added RSSI Read Value ***/
              HCI_ReadRssiCmd(advHandleLegacy);
    
    //          int Pcount=0;
    //          char Lead[16]={"24AC"};
    //          for(int i=0;i<4;i++)
    //              {
    //               if(Buffer[i]==Lead[i])
    //                    Pcount++;
    //               else
    //                    Pcount=0;
    //              }
    //          if (Pcount>=3)
    //              UART_write(handle,"Hello",5);
    //
    //            Pcount=0;
    //    }//remove me
    //}//remove me
                //Check for Button Press ?
    
    if((memcmp(LeadMe_ON,Buffer,RxDataLength))==0)
            {
             Button=LeadMeButton_ON;
            }
    
    else if((memcmp(LeadMe_OFF,Buffer,RxDataLength))==0)
            {
             Button=LeadMeButton_OFF;
            }
    else if((memcmp(EngineStart,Buffer,RxDataLength))==0)
            {
             Button=EngineStart_Button;
            }
    
    else if((memcmp(EngineStop,Buffer,RxDataLength))==0)
            {
             Button=EngineStop_Button;
            }
    
    //Start Process
    
    switch(Button)
    {
     case LeadMeButton_ON :
       {
            PIN_setOutputValue(ledPinHandle, WakeUp_Event,1);
            PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
            uint32_t sleepUs = 500000;
            Task_sleep(sleepUs / Clock_tickPeriod);
            PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
            PIN_setOutputValue(ledPinHandle, WakeUp_Event,0);
    
         Start_timer_100msec=0;
         Counter_retry=0;
         ACK_Flag=0;
    
         // Max 500msec wait time
        while(ACK_Flag == 0)
         {
    
            if((Start_timer_100msec == 0) && (Counter_retry < 5))
            {
                Counter_retry++;
                Start_timer_100msec = 1;
    
                UART_write(handle,"#<24AC0424AD01008A>",19);
    
                //Start a timer of 100 msec
                Util_startClock((Clock_Struct *)Wait_Timer_100ms);
            }
            else if(Counter_retry >= 5)
            {
                ACK_Flag = 1;
                Start_timer_100msec=0;
                Counter_retry=0;
            }
    
    
    
            //Start Reading Response
             UART_read(handle, rxBuf, sizeof(rxBuf));
    
             //Wait for Acknowledgment from FMCU side
             //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);
    
             //Check the Received Data is ACK ?
             if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
             {
                // PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
                 ACK_Flag=1;
                 Start_timer_100msec=0;
                 Counter_retry=0;
             }
    
             //Check the Received Data is NACK ?
             else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
             {
                //Send the 1st default packet Received String to FMCU
                PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
                ACK_Flag=0;
             }
             memset(Buffer,0,RxDataLength);
             memset(RxResponse,0,sizeof(NACK));
         }
         UART_close(handle);
         break;
       }
    case LeadMeButton_OFF :
    {
    //    PIN_setOutputValue(ledPinHandle, Board_PIN_GLED, 1);
    //     uint32_t sleepUs = 500000;
    //     Task_sleep(sleepUs / Clock_tickPeriod);
    //     PIN_setOutputValue(ledPinHandle, Board_PIN_GLED, 0);
      Start_timer_100msec=0;
      Counter_retry=0;
      ACK_Flag=0;
    
      // Max 500msec wait time
     while(ACK_Flag == 0)
      {
    
         if((Start_timer_100msec == 0) && (Counter_retry < 5))
         {
             Counter_retry++;
             Start_timer_100msec = 1;
    
             UART_write(handle,"#<24AC0424AD01008B>",19);
    
             //Start a timer of 100 msec
             Util_startClock((Clock_Struct *)Wait_Timer_100ms);
         }
         else if(Counter_retry >=5)
         {
             ACK_Flag = 1;
             Start_timer_100msec=0;
             Counter_retry=0;
         }
    
    
    
         //Start Reading Response
          UART_read(handle, rxBuf, sizeof(rxBuf));
    
          //Wait for Acknowledgment from FMCU side
          //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);
    
          //Check the Received Data is ACK ?
          if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
          {
              PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
              ACK_Flag=1;
              Start_timer_100msec=0;
              Counter_retry=0;
          }
    
          //Check the Received Data is NACK ?
          else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
          {
             //Send the 1st default packet Received String to FMCU
             PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
             ACK_Flag=0;
          }
          memset(Buffer,0,RxDataLength);
          memset(RxResponse,0,sizeof(NACK));
      }
     UART_close(handle);
      break;
    }
    
    case EngineStart_Button :
    {
        PIN_setOutputValue(ledPinHandle, WakeUp_Event,1);
        PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
        Start_timer_100msec=0;
        Counter_retry=0;
        ACK_Flag=0;
    
        // Max 500msec wait time
       while(ACK_Flag == 0)
        {
    
           if((Start_timer_100msec == 0) && (Counter_retry < 5))
           {
               Counter_retry++;
               Start_timer_100msec = 1;
    
               UART_write(handle,"#<24AC0424AD072000>",19);
    
               //Start a timer of 100 msec
               Util_startClock((Clock_Struct *)Wait_Timer_100ms);
           }
           else if(Counter_retry >=5)
           {
               ACK_Flag = 1;
               Start_timer_100msec=0;
               Counter_retry=0;
           }
    
    
    
           //Start Reading Response
            UART_read(handle, rxBuf, sizeof(rxBuf));
    
            //Wait for Acknowledgment from FMCU side
            //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);
    
            //Check the Received Data is ACK ?
            if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
            {
                PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
                ACK_Flag=1;
                Start_timer_100msec=0;
                Counter_retry=0;
            }
    
            //Check the Received Data is NACK ?
            else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
            {
               //Send the 1st default packet Received String to FMCU
               PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
               ACK_Flag=0;
            }
            memset(Buffer,0,RxDataLength);
            memset(RxResponse,0,sizeof(NACK));
        }
       UART_close(handle);
        break;
      }
    
    
    case EngineStop_Button :
    {
        PIN_setOutputValue(ledPinHandle, WakeUp_Event,0);
        PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
        Start_timer_100msec=0;
        Counter_retry=0;
        ACK_Flag=0;
    
        // Max 500msec wait time
       while(ACK_Flag == 0)
        {
    
           if((Start_timer_100msec == 0) && (Counter_retry < 5))
           {
               Counter_retry++;
               Start_timer_100msec = 1;
    
               UART_write(handle,"#<24AC0424AD072001>",19);
    
               //Start a timer of 100 msec
               Util_startClock((Clock_Struct *)Wait_Timer_100ms);
           }
           else if(Counter_retry >= 5)
           {
               ACK_Flag = 1;
               Start_timer_100msec=0;
               Counter_retry=0;
           }
    
    
    
           //Start Reading Response
            UART_read(handle, rxBuf, sizeof(rxBuf));
    
            //Wait for Acknowledgment from FMCU side
            //Semaphore_pend(hSem, BIOS_WAIT_FOREVER);
    
            //Check the Received Data is ACK ?
            if((memcmp(PACK,RxResponse,sizeof(PACK)))==0)
            {
                PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,1);     // DIO 16 LED ON
                ACK_Flag=1;
                Start_timer_100msec=0;
                Counter_retry=0;
            }
    
            //Check the Received Data is NACK ?
            else if((memcmp(NACK,RxResponse,sizeof(NACK)))==0)
            {
               //Send the 1st default packet Received String to FMCU
               PIN_setOutputValue(ledPinHandle, Board_PIN_RLED,0);     // DIO 16 LED OFF
               ACK_Flag=0;
            }
            memset(Buffer,0,RxDataLength);
            memset(RxResponse,0,sizeof(NACK));
        }
       UART_close(handle);
        break;
      }
    
    
     default:
        return;
    
    }
    
        default:
            return;
    
     } // switch statement end
    
    } //Function end
    
    
    /*
     * @brief   Handle a CCCD (configuration change) write received from a peer
     *          device. This tells us whether the peer device wants us to send
     *          Notifications or Indications.
     *
     * @param   pCharData  pointer to malloc'd char write data
     *
     * @return  None.
     */
    void ProjectZero_DataService_CfgChangeHandler(pzCharacteristicData_t *pCharData)
    {
        Log_info0(" Inside ProjectZero_DataService_CfgChangeHandler ");
    
        // Cast received data to uint16, as that's the format for CCCD writes.
        uint16_t configValue = *(uint16_t *)pCharData->data;
        char *configValString;
    
        // Determine what to tell the user
        switch(configValue)
        {
        case GATT_CFG_NO_OPERATION:
            configValString = "Noti/Ind disabled";
            break;
        case GATT_CLIENT_CFG_NOTIFY:
            configValString = "Notifications enabled";
            break;
        case GATT_CLIENT_CFG_INDICATE:
            configValString = "Indications enabled";
            break;
        default:
            configValString = "Unsupported operation";
        }
    
        switch(pCharData->paramID)
        {
        case DS_STREAM_ID:
            Log_info3("CCCD Change msg: %s %s: %s",
                      (uintptr_t)"Data Service",
                      (uintptr_t)"Stream",
                      (uintptr_t)configValString);
            // -------------------------
            // Do something useful with configValue here. It tells you whether someone
            // wants to know the state of this characteristic.
            // ...
            break;
        }
    }
    
    
    
    /*
     * @brief  Convenience function for updating characteristic data via pzCharacteristicData_t
     *         structured message.
     *
     * @note   Must run in Task context in case BLE Stack APIs are invoked.
     *
     * @param  *pCharData  Pointer to struct with value to update.
     */
    static void ProjectZero_updateCharVal(pzCharacteristicData_t *pCharData)
    {
     Log_info0(" Inside ProjectZero_updateCharVal ");
     switch(pCharData->svcUUID)
        {
    #ifndef FMCU_APP
    
        case LED_SERVICE_SERV_UUID:
            LedService_SetParameter(pCharData->paramID, pCharData->dataLen,
                                    pCharData->data);
            break;
    
        case BUTTON_SERVICE_SERV_UUID:
            ButtonService_SetParameter(pCharData->paramID, pCharData->dataLen,
                                       pCharData->data);
            break;
    #endif
        }
    }
    
    
    /******************************************************************************
     *****************************************************************************
     *
     *  Handlers of direct system callbacks.
     *
     *  Typically enqueue the information or request as a message for the
     *  application Task for handling.
     *
     ****************************************************************************
     *****************************************************************************/
    
    /*
     *  Callbacks from the Stack Task context (GAP or Service changes)
     *****************************************************************************/
    
    /*********************************************************************
     * @fn      ProjectZero_advCallback
     *
     * @brief   GapAdv module callback
     *
     * @param   pMsg - message to process
     *          pBuf - data potentially accompanying event
     *          arg - not used
     */
    static void ProjectZero_advCallback(uint32_t event, void *pBuf, uintptr_t arg)
    {
       // Log_info0(" Inside ProjectZero_advCallback ");
        pzGapAdvEventData_t *eventData = ICall_malloc(sizeof(pzGapAdvEventData_t));
    
        if(eventData != NULL)
        {
            eventData->event = event;
            eventData->pBuf = pBuf;
    
            if(ProjectZero_enqueueMsg(PZ_ADV_EVT, eventData) != SUCCESS)
            {
              ICall_free(eventData);
            }
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_pairStateCb
     *
     * @brief   Pairing state callback.
     *
     * @param   connHandle - connection handle
     *          state - pair state
     *          status - pair status
     */
    static void ProjectZero_pairStateCb(uint16_t connHandle, uint8_t state,
                                        uint8_t status)
    {
        Log_info0(" Inside ProjectZero_pairStateCb ");
        pzPairStateData_t *pairState =
            (pzPairStateData_t *)ICall_malloc(sizeof(pzPairStateData_t));
    
        if(pairState != NULL)
        {
            pairState->state = state;
            pairState->connHandle = connHandle;
            pairState->status = status;
    
            if(ProjectZero_enqueueMsg(PZ_PAIRSTATE_EVT, pairState) != SUCCESS)
            {
              ICall_free(pairState);
            }
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_passcodeCb
     *
     * @brief   Passcode callback.
     *
     * @param   pDeviceAddr - not used
     *          connHandle - connection handle
     *          uiInpuits - if TRUE, the local device should accept a passcode input
     *          uiOutputs - if TRUE, the local device should display the passcode
     *          numComparison - the code that should be displayed for numeric
     *          comparison pairing. If this is zero, then passcode pairing is occurring.
     */
    static void ProjectZero_passcodeCb(uint8_t *pDeviceAddr,
                                       uint16_t connHandle,
                                       uint8_t uiInputs,
                                       uint8_t uiOutputs,
                                       uint32_t numComparison)
    {
    
        Log_info0(" Inside ProjectZero_passcodeCb ");
        pzPasscodeReq_t *req =
            (pzPasscodeReq_t *)ICall_malloc(sizeof(pzPasscodeReq_t));
        if(req != NULL)
        {
            req->connHandle = connHandle;
            req->uiInputs = uiInputs;
            req->uiOutputs = uiOutputs;
            req->numComparison = numComparison;
    
            if(ProjectZero_enqueueMsg(PZ_PASSCODE_EVT, req) != SUCCESS)
            {
              ICall_free(req);
            }
        }
        ;
    }
    
    /*********************************************************************
     * @fn      ProjectZero_DataService_ValueChangeCB
     *
     * @brief   Callback for characteristic change when a peer writes to us
     *
     * @param   connHandle - connection handle
     *          paramID - the parameter ID maps to the characteristic written to
     *          len - length of the data written
     *          pValue - pointer to the data written
     */
    static void ProjectZero_DataService_ValueChangeCB(uint16_t connHandle,
                                                      uint8_t paramID, uint16_t len,
                                                      uint8_t *pValue)
    {
        // See the service header file to compare paramID with characteristic.
    //    Log_info1("(CB) Data Svc Characteristic value change: paramID(%d). "
    //              "Sending msg to app.", paramID);
    
        pzCharacteristicData_t *pValChange =
            ICall_malloc(sizeof(pzCharacteristicData_t) + len);
    
        if(pValChange != NULL)
        {
            pValChange->svcUUID = DATA_SERVICE_SERV_UUID;
            pValChange->paramID = paramID;
            memcpy(pValChange->data, pValue, len);
            pValChange->dataLen = len;
    
            if(ProjectZero_enqueueMsg(PZ_SERVICE_WRITE_EVT, pValChange) != SUCCESS)
            {
              ICall_free(pValChange);
            }
        }
    }
    
    /*********************************************************************
     * @fn      ProjectZero_DataService_CfgChangeCB
     *
     * @brief   Callback for when a peer enables or disables the CCCD attribute,
     *          indicating they are interested in notifications or indications.
     *
     * @param   connHandle - connection handle
     *          paramID - the parameter ID maps to the characteristic written to
     *          len - length of the data written
     *          pValue - pointer to the data written
     */
    static void ProjectZero_DataService_CfgChangeCB(uint16_t connHandle,
                                                    uint8_t paramID, uint16_t len,
                                                    uint8_t *pValue)
    {
        Log_info1("(CB) Data Svc Char config change paramID(%d). "
                  "Sending msg to app.", paramID);
    
        pzCharacteristicData_t *pValChange =
            ICall_malloc(sizeof(pzCharacteristicData_t) + len);
    
        if(pValChange != NULL)
        {
            pValChange->svcUUID = DATA_SERVICE_SERV_UUID;
            pValChange->paramID = paramID;
            memcpy(pValChange->data, pValue, len);
            pValChange->dataLen = len;
    
            if(ProjectZero_enqueueMsg(PZ_SERVICE_CFG_EVT, pValChange) != SUCCESS)
            {
              ICall_free(pValChange);
            }
        }
    }
    
    /*
     *  Callbacks from Swi-context
     *****************************************************************************/
    
    /*********************************************************************
     * @fn      ProjectZero_paramUpdClockHandler
     *
     * @brief   Handler function for clock timeouts.
     *
     * @param   arg - app message pointer
     */
    static void ProjectZero_paramUpdClockHandler(UArg arg)
    {
        pzSendParamReq_t *req =
            (pzSendParamReq_t *)ICall_malloc(sizeof(pzSendParamReq_t));
        if(req)
        {
            req->connHandle = (uint16_t)arg;
            if(ProjectZero_enqueueMsg(PZ_SEND_PARAM_UPD_EVT, req) != SUCCESS)
            {
              ICall_free(req);
            }
        }
    }
    
    /******************************************************************************
     *****************************************************************************
     *
     *  Utility functions
     *
     ****************************************************************************
     *****************************************************************************/
    
    /*********************************************************************
     * @fn     ProjectZero_enqueueMsg
     *
     * @brief  Utility function that sends the event and data to the application.
     *         Handled in the task loop.
     *
     * @param  event    Event type
     * @param  pData    Pointer to message data
     */
    static status_t ProjectZero_enqueueMsg(uint8_t event, void *pData)
    {
        uint8_t success;
        pzMsg_t *pMsg = ICall_malloc(sizeof(pzMsg_t));
    
        if(pMsg)
        {
            pMsg->event = event;
            pMsg->pData = pData;
    
            success = Util_enqueueMsg(appMsgQueueHandle, syncEvent, (uint8_t *)pMsg);
            return (success) ? SUCCESS : FAILURE;
        }
    
        return(bleMemAllocError);
    }
    
    /*********************************************************************
     * @fn     util_arrtohex
     *
     * @brief   Convert {0x01, 0x02} to "01:02"
     *
     * @param   src - source byte-array
     * @param   src_len - length of array
     * @param   dst - destination string-array
     * @param   dst_len - length of array
     *
     * @return  array as string
     */
    char * util_arrtohex(uint8_t const *src, uint8_t src_len,
                         uint8_t *dst, uint8_t dst_len, uint8_t reverse)
    {
        char hex[] = "0123456789ABCDEF";
        uint8_t *pStr = dst;
        uint8_t avail = dst_len - 1;
        int8_t inc = 1;
        if(reverse)
        {
            src = src + src_len - 1;
            inc = -1;
        }
    
        memset(dst, 0, avail);
    
        while(src_len && avail > 3)
        {
            if(avail < dst_len - 1)
            {
                *pStr++ = ':';
                avail -= 1;
            }
    
            *pStr++ = hex[*src >> 4];
            *pStr++ = hex[*src & 0x0F];
            src += inc;
            avail -= 2;
            src_len--;
        }
    
        if(src_len && avail)
        {
            *pStr++ = ':'; // Indicate not all data fit on line.
        }
        return((char *)dst);
    }
    
    /*********************************************************************
     * @fn     util_getLocalNameStr
     *
     * @brief   Extract the LOCALNAME from Scan/AdvData
     *
     * @param   data - Pointer to the advertisement or scan response data
     * @param   len  - Length of advertisment or scan repsonse data
     *
     * @return  Pointer to null-terminated string with the adv local name.
     */
    static char * util_getLocalNameStr(const uint8_t *data, uint8_t len)
    {
        uint8_t nuggetLen = 0;
        uint8_t nuggetType = 0;
        uint8_t advIdx = 0;
    
        static char localNameStr[32] = { 0 };
        memset(localNameStr, 0, sizeof(localNameStr));
    
        for(advIdx = 0; advIdx < len; )
        {
            nuggetLen = data[advIdx++];
            nuggetType = data[advIdx];
            if((nuggetType == GAP_ADTYPE_LOCAL_NAME_COMPLETE ||
                nuggetType == GAP_ADTYPE_LOCAL_NAME_SHORT) )
            {
                uint8_t len_temp = nuggetLen < (sizeof(localNameStr)-1)? (nuggetLen - 1):(sizeof(localNameStr)-2);
                // Only copy the first 31 characters, if name bigger than 31.
                memcpy(localNameStr, &data[advIdx + 1], len_temp);
                break;
            }
            else
            {
                advIdx += nuggetLen;
            }
        }
    
        return(localNameStr);
    }
    
    /*********************************************************************
    *********************************************************************/
    

    i am able to connect and GATT read/write data with simple central and project zero , when i am using 2bit UUID. Can you please guide me what all changes required to connect Simple central and project zero ,when we are using custom 128bit uuid .

     

    /******************************************************************************
    
       @file  data_service.c
    
       @brief   This file contains the implementation of the service.
    
       Group: CMCU, LPRF
       Target Device: cc2640r2
    
     ******************************************************************************
       
     Copyright (c) 2015-2021, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
     ******************************************************************************
       
       
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    //#include <xdc/runtime/Log.h> // Comment this in to use xdc.runtime.Log
    #include <uartlog/UartLog.h>  // Comment out if using xdc Log
    
    #include <icall.h>
    
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "data_service.h"
    
    #define FMCU_APP
    
    /*********************************************************************
     * MACROS
     */
    
    /*********************************************************************
     * CONSTANTS
     */
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    
    
    
    
    #define FMCU_16BIT_UUID
    
    
    #ifdef FMCU_16BIT_UUID
    /*
       #define GATT_PRIMARY_SERVICE_UUID                  0x2800 // Primary Service
       #define GATT_SECONDARY_SERVICE_UUID                0x2801 // Secondary Service
       #define GATT_INCLUDE_UUID                          0x2802 // Include
       #define GATT_CHARACTER_UUID                        0x2803 // Characteristic
     */
    
    
    // Data_Service Service UUID
    CONST uint8_t DataServiceUUID[ATT_BT_UUID_SIZE] =
    {
     LO_UINT16(DATA_SERVICE_SERV_UUID), HI_UINT16(DATA_SERVICE_SERV_UUID)
    };
    
    // Stream UUID
    CONST uint8_t ds_StreamUUID[ATT_BT_UUID_SIZE] =
    {
     LO_UINT16(DS_STREAM_UUID), HI_UINT16(DS_STREAM_UUID)
    };
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    static DataServiceCBs_t *pAppCBs = NULL;
    static uint8_t ds_icall_rsp_task_id = INVALID_TASK_ID;
    
    /*********************************************************************
     * Profile Attributes - variables
     */
    // Service declaration
    static CONST gattAttrType_t DataServiceDecl = {ATT_BT_UUID_SIZE, DataServiceUUID };
    
    // Characteristic "Stream" Properties (for declaration)
    static uint8_t ds_StreamProps = GATT_PROP_READ | GATT_PROP_WRITE;
    
    // Characteristic "Stream" Value variable
    static uint8_t ds_StreamVal[DS_STREAM_LEN] = {0};
    // Characteristic 1 Value
    //static uint8 ds_StreamVal = 0;
    
    
    // Length of data in characteristic "Stream" Value variable, initialized to minimal size.
    static uint16_t ds_StreamValLen = DS_STREAM_LEN_MIN;
    
    // Characteristic "Stream" Client Characteristic Configuration Descriptor
    static gattCharCfg_t *ds_StreamConfig;
    
    //static uint8 Read_array[8] = {4,0,0,0,0,0,0,0};
    //static uint8 Write_array[5] = {0x57,0x72,0x69, 0x74 ,0x65};
    
    //static uint8 Write_array[5] = {"Mohit"};
    // Simple Profile Characteristic 1 User Description
    
    // static uint8 profileUserDesp[5] = "MOHIT";
    // Simple Profile Characteristic 1 User Description
    static uint8 profileUserDesp[17] = "Characteristic 1";
    
    /*********************************************************************
     * Profile Attributes - Table
     */
    
    
    // Simple Profile Service
    
    
    
    
    
    
    
    
    static gattAttribute_t Data_ServiceAttrTbl[] =
    {
     // Data_Service primary Service Declaration
        {
           { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* 2800 */
            GATT_PERMIT_READ,
            0,
            (uint8_t *)&DataServiceDecl
        },
    
    
        // Stream write Characteristic Declaration
        {
            { ATT_BT_UUID_SIZE, characterUUID },  //Service UUID
            GATT_PERMIT_READ ,
            0,
            &ds_StreamProps
        },
    
        // Stream Value Characteristic Value 1
        {
            { ATT_BT_UUID_SIZE, ds_StreamUUID }, //Write Characteristic ID
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            ds_StreamVal
        },
    
    //    // Stream CCCD
    //    {
    //        { ATT_BT_UUID_SIZE, charFormatUUID },//clientCharCfgUUID // 2904
    //         GATT_PERMIT_READ,
    //         0,
    //         (uint8_t *)&Read_array
    //    },
    
         // Stream Description
        {
            { ATT_BT_UUID_SIZE, charUserDescUUID }, //2901 GATT_CHAR_USER_DESC_UUID
              GATT_PERMIT_READ ,
              0,
              profileUserDesp //(uint8_t *)&Write_array
        },
    };
    
    #else /****** Working *******/
    
    // Data_Service Service UUID
    CONST uint8_t DataServiceUUID[ATT_UUID_SIZE] =
    {
        DATA_SERVICE_SERV_UUID_BASE128(DATA_SERVICE_SERV_UUID)
    };
    
    // Stream UUID
    CONST uint8_t ds_StreamUUID[ATT_UUID_SIZE] =
    {
        DS_STREAM_UUID_BASE128(DS_STREAM_UUID)
    };
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    static DataServiceCBs_t *pAppCBs = NULL;
    static uint8_t ds_icall_rsp_task_id = INVALID_TASK_ID;
    
    /*********************************************************************
     * Profile Attributes - variables
     */
    // Service declaration
    static CONST gattAttrType_t DataServiceDecl = {ATT_UUID_SIZE,DataServiceUUID };
    
    // Characteristic "Stream" Properties (for declaration)
    static uint8_t ds_StreamProps = GATT_PROP_READ | GATT_PROP_WRITE;// GATT_PROP_NOTIFY | GATT_PROP_WRITE_NO_RSP;
    
    // Characteristic "Stream" Value variable
    static uint8_t ds_StreamVal[DS_STREAM_LEN] = {0};
    
    // Length of data in characteristic "Stream" Value variable, initialized to minimal size.
    static uint16_t ds_StreamValLen = DS_STREAM_LEN_MIN;
    
    // Characteristic "Stream" Client Characteristic Configuration Descriptor
    static gattCharCfg_t *ds_StreamConfig;
    
    static uint8 Read_array[8] = {4,0,0,0,0,0,0,0};
    static uint8 Write_array[5] = {0x57,0x72,0x69, 0x74 ,0x65};
    
    
    
    
    /*********************************************************************
     * Profile Attributes - Table
     */
    
    static gattAttribute_t Data_ServiceAttrTbl[] =
    {
     // Data_Service Service Declaration
        {
           { ATT_BT_UUID_SIZE, primaryServiceUUID },
            GATT_PERMIT_READ,
            0,
            (uint8_t *)&DataServiceDecl
        },
    
        // Stream write Characteristic Declaration
        {
            { ATT_BT_UUID_SIZE, characterUUID },  //Service UUID
            GATT_PERMIT_READ,
            0,
            &ds_StreamProps
        },
    
        // Stream Characteristic Value
        {
            { ATT_BT_UUID_SIZE, ds_StreamUUID }, //Write Characteristic ID
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            ds_StreamVal
        },
    
    //    // Stream CCCD
    //    {
    //        { ATT_BT_UUID_SIZE, charFormatUUID },//clientCharCfgUUID // 2904
    //         GATT_PERMIT_READ,
    //         0,
    //         (uint8_t *)&Read_array
    //    },
    
        // Stream CCCD
        {
            { ATT_BT_UUID_SIZE, charUserDescUUID }, //2901 GATT_CHAR_USER_DESC_UUID
              GATT_PERMIT_READ ,
              0,
              (uint8_t *)&Write_array
        },
    };
    
    
    #endif
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static bStatus_t Data_Service_ReadAttrCB(uint16_t connHandle,
                                             gattAttribute_t *pAttr,
                                             uint8_t *pValue,
                                             uint16_t *pLen,
                                             uint16_t offset,
                                             uint16_t maxLen,
                                             uint8_t method);
    static bStatus_t Data_Service_WriteAttrCB(uint16_t connHandle,
                                              gattAttribute_t *pAttr,
                                              uint8_t *pValue,
                                              uint16_t len,
                                              uint16_t offset,
                                              uint8_t method);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    // Simple Profile Service Callbacks
    CONST gattServiceCBs_t Data_ServiceCBs =
    {
        Data_Service_ReadAttrCB, // Read callback function pointer
        Data_Service_WriteAttrCB, // Write callback function pointer
        NULL                     // Authorization callback function pointer
    };
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*
     * DataService_AddService- Initializes the DataService service by registering
     *          GATT attributes with the GATT server.
     *
     *    rspTaskId - The ICall Task Id that should receive responses for Indications.
     */
    extern bStatus_t DataService_AddService(uint8_t rspTaskId)
    {
        uint8_t status;
    
        // Allocate Client Characteristic Configuration table
        ds_StreamConfig = (gattCharCfg_t *)ICall_malloc(sizeof(gattCharCfg_t) *linkDBNumConns);
    
        if(ds_StreamConfig == NULL)
        {
            return(bleMemAllocError);
        }
    
        // Initialize Client Characteristic Configuration attributes
        GATTServApp_InitCharCfg(CONNHANDLE_INVALID, ds_StreamConfig);
    
    
    // Register GATT attribute list and CBs with GATT Server App
        status = GATTServApp_RegisterService(Data_ServiceAttrTbl,
                                             GATT_NUM_ATTRS(Data_ServiceAttrTbl),
                                             GATT_MAX_ENCRYPT_KEY_SIZE,
                                             &Data_ServiceCBs);
        Log_info1("Registered service, %d attributes",
                   GATT_NUM_ATTRS(Data_ServiceAttrTbl));
        ds_icall_rsp_task_id = rspTaskId;
    
        return(status);
    }
    
    /*
     * DataService_RegisterAppCBs - Registers the application callback function.
     *                    Only call this function once.
     *
     *    appCallbacks - pointer to application callbacks.
     */
    bStatus_t DataService_RegisterAppCBs(DataServiceCBs_t *appCallbacks)
    {
        if(appCallbacks)
        {
            pAppCBs = appCallbacks;
          // Log_info1("Registered callbacks to application. Struct %p",
          //             (uintptr_t)appCallbacks);
            return(SUCCESS);
        }
        else
        {
        //     Log_warning0("Null pointer given for app callbacks.");
            return(FAILURE);
        }
    }
    
    /*
     * DataService_SetParameter - Set a DataService parameter.
     *
     *    param - Profile parameter ID
     *    len   - length of data to write
     *    value - pointer to data to write.  This is dependent on
     *            the parameter ID and may be cast to the appropriate
     *            data type (example: data type of uint16_t will be cast to
     *            uint16_t pointer).
     */
    bStatus_t DataService_SetParameter(uint8_t param, uint16_t len, void *value)
    {
        bStatus_t ret = SUCCESS;
        uint8_t  *pAttrVal;
        uint16_t *pValLen;
        uint16_t valMinLen;
        uint16_t valMaxLen;
        uint8_t sendNotiInd = FALSE;
        gattCharCfg_t *attrConfig;
        uint8_t needAuth;
    
        switch(param)
        {
        case DS_STREAM_ID:
            pAttrVal = ds_StreamVal;
            pValLen = &ds_StreamValLen;
            valMinLen = DS_STREAM_LEN_MIN;
            valMaxLen = DS_STREAM_LEN;
            sendNotiInd = TRUE;
            attrConfig = ds_StreamConfig;
            needAuth = FALSE;  // Change if authenticated link is required for sending.
          //  Log_info2("SetParameter : %s len: %d", (uintptr_t)"Stream", len);
            break;
    
        default:
            //Log_error1("SetParameter: Parameter #%d not valid.", param);
            return(INVALIDPARAMETER);
        }
    
        // Check bounds, update value and send notification or indication if possible.
        if(len <= valMaxLen && len >= valMinLen)
        {
            memcpy(pAttrVal, value, len);
            *pValLen = len; // Update length for read and get.
    
            if(sendNotiInd)
            {
              //Log_info2("Trying to send noti/ind: connHandle %x, %s",
               //           attrConfig[0].connHandle,
               //           (uintptr_t)((attrConfig[0].value ==
                 //                      0) ? "\x1b[33mNoti/ind disabled\x1b[0m" :
                   //                   (attrConfig[0].value ==
                     //                  1) ? "Notification enabled" :
                       //               "Indication enabled"));
                // Try to send notification.
              GATTServApp_ProcessCharCfg(attrConfig, pAttrVal, needAuth,
                                           Data_ServiceAttrTbl,
                                           GATT_NUM_ATTRS(
                                               Data_ServiceAttrTbl),
                                           ds_icall_rsp_task_id,
                                           Data_Service_ReadAttrCB);
            }
        }
        else
        {
    //        Log_error3("Length outside bounds: Len: %d MinLen: %d MaxLen: %d.", len,
    //                   valMinLen,
    //                   valMaxLen);
            ret = bleInvalidRange;
        }
    
        return(ret);
    }
    
    /*
     * DataService_GetParameter - Get a DataService parameter.
     *
     *    param - Profile parameter ID
     *    len   - pointer to a variable that contains the maximum length that can be written to *value.
                  After the call, this value will contain the actual returned length.
     *    value - pointer to data to write.  This is dependent on
     *            the parameter ID and may be cast to the appropriate
     *            data type (example: data type of uint16_t will be cast to
     *            uint16_t pointer).
     */
    bStatus_t DataService_GetParameter(uint8_t param, uint16_t *len, void *value)
    {
        bStatus_t ret = SUCCESS;
        switch(param)
        {
        case DS_STREAM_ID:
            *len = MIN(*len, ds_StreamValLen);
            memcpy(value, ds_StreamVal, *len);
          //  Log_info2("GetParameter : %s returning %d bytes", (uintptr_t)"Stream",*len);
            break;
    
        default:
         //   Log_error1("GetParameter: Parameter #%d not valid.", param);
            ret = INVALIDPARAMETER;
            break;
        }
        return(ret);
    }
    
    /*********************************************************************
     * @internal
     * @fn          Data_Service_findCharParamId
     *
     * @brief       Find the logical param id of an attribute in the service's attr table.
     *
     *              Works only for Characteristic Value attributes and
     *              Client Characteristic Configuration Descriptor attributes.
     *
     * @param       pAttr - pointer to attribute
     *
     * @return      uint8_t paramID (ref data_service.h) or 0xFF if not found.
     */
    static uint8_t Data_Service_findCharParamId(gattAttribute_t *pAttr)
    {
    #ifdef FMCU_16BIT_UUID
        // Is this a Client Characteristic Configuration Descriptor?
        if(ATT_BT_UUID_SIZE == pAttr->type.len && GATT_CLIENT_CHAR_CFG_UUID == /* Eariler it was ATT_BT_UUID_SIZE */
           *(uint16_t *)pAttr->type.uuid)
        {
           // Log_info2("pAttr->type.len = %d , *(uint16_t *)pAttr->type.uuid =%d ",pAttr->type.len,*(uint16_t *)pAttr->type.uuid);
            return(Data_Service_findCharParamId(pAttr - 1)); // Assume the value attribute precedes CCCD and recurse
        }
        // Is this attribute in "Stream"?
        else if(ATT_BT_UUID_SIZE == pAttr->type.len &&  /* Eariler it was ATT_UUID_SIZE */
                !memcmp(pAttr->type.uuid, ds_StreamUUID, pAttr->type.len))
        {
            Log_info0("Return DS_STREAM_ID");
            return(DS_STREAM_ID);
        }
    #else
        // Is this a Client Characteristic Configuration Descriptor?
        if(ATT_BT_UUID_SIZE == pAttr->type.len && GATT_CLIENT_CHAR_CFG_UUID == /* Eariler it was ATT_BT_UUID_SIZE */
           *(uint16_t *)pAttr->type.uuid)
        {
           // Log_info2("pAttr->type.len = %d , *(uint16_t *)pAttr->type.uuid =%d ",pAttr->type.len,*(uint16_t *)pAttr->type.uuid);
            return(Data_Service_findCharParamId(pAttr - 1)); // Assume the value attribute precedes CCCD and recurse
        }
        // Is this attribute in "Stream"?
        else if(ATT_UUID_SIZE == pAttr->type.len &&  /* Eariler it was ATT_UUID_SIZE */
                !memcmp(pAttr->type.uuid, ds_StreamUUID, pAttr->type.len))
        {
            Log_info0("Return DS_STREAM_ID");
            return(DS_STREAM_ID);
        }
    #endif
        else
        {
            return(0xFF); // Not found. Return invalid.
        }
    }
    
    /*********************************************************************
     * @fn          Data_Service_ReadAttrCB
     *
     * @brief       Read an attribute.
     *
     * @param       connHandle - connection message was received on
     * @param       pAttr - pointer to attribute
     * @param       pValue - pointer to data to be read
     * @param       pLen - length of data to be read
     * @param       offset - offset of the first octet to be read
     * @param       maxLen - maximum length of data to be read
     * @param       method - type of read message
     *
     * @return      SUCCESS, blePending or Failure
     */
    static bStatus_t Data_Service_ReadAttrCB(uint16_t connHandle,
                                             gattAttribute_t *pAttr,
                                             uint8_t *pValue, uint16_t *pLen,
                                             uint16_t offset,
                                             uint16_t maxLen,
                                             uint8_t method)
    {
        bStatus_t status = SUCCESS;
        uint16_t valueLen;
        uint8_t paramID = 0xFF;
    
        // Find settings for the characteristic to be read.
        paramID = Data_Service_findCharParamId(pAttr);
        switch(paramID)
        {
        case DS_STREAM_ID:
            valueLen = ds_StreamValLen;
    
    //        Log_info4("ReadAttrCB : %s connHandle: %d offset: %d method: 0x%02x",
    //                  (uintptr_t)"Stream",
    //                  connHandle,
    //                  offset,
    //                  method);
            /* Other considerations for Stream can be inserted here */
            break;
    
        default:
          ///  Log_error0("Attribute was not found.");
            return(ATT_ERR_ATTR_NOT_FOUND);
        }
        // Check bounds and return the value
        if(offset > valueLen)   // Prevent malicious ATT ReadBlob offsets.
        {
          // Log_error0("An invalid offset was requested.");
            status = ATT_ERR_INVALID_OFFSET;
        }
        else
        {
            *pLen = MIN(maxLen, valueLen - offset); // Transmit as much as possible
            memcpy(pValue, pAttr->pValue + offset, *pLen);
        }
    
        return(status);
    }
    
    /*********************************************************************
     * @fn      Data_Service_WriteAttrCB
     *
     * @brief   Validate attribute data prior to a write operation
     *
     * @param   connHandle - connection message was received on
     * @param   pAttr - pointer to attribute
     * @param   pValue - pointer to data to be written
     * @param   len - length of data
     * @param   offset - offset of the first octet to be written
     * @param   method - type of write message
     *
     * @return  SUCCESS, blePending or Failure
     */
    static bStatus_t Data_Service_WriteAttrCB(uint16_t connHandle,
                                              gattAttribute_t *pAttr,
                                              uint8_t *pValue, uint16_t len,
                                              uint16_t offset,
                                              uint8_t method)
    {
        bStatus_t status = SUCCESS;
        uint8_t paramID = 0xFF;
        uint8_t changeParamID = 0xFF;
        uint16_t writeLenMin;
        uint16_t writeLenMax;
        uint16_t *pValueLenVar;
    
        // See if request is regarding a Client Characterisic Configuration
        if(ATT_BT_UUID_SIZE == pAttr->type.len && GATT_CLIENT_CHAR_CFG_UUID ==
           *(uint16_t *)pAttr->type.uuid)
        {
           // Log_info3("WriteAttrCB (CCCD): param: %d connHandle: %d %s",
    //                  Data_Service_findCharParamId(pAttr),
    //                  connHandle,
    //                  (uintptr_t)(method ==
    //                              GATT_LOCAL_WRITE ? "- restoring bonded state" :
    //                              "- OTA write"));
    
            // Allow notification and indication, but do not check if really allowed per CCCD.
            status = GATTServApp_ProcessCCCWriteReq(
                connHandle, pAttr, pValue, len,
                offset,
                GATT_CLIENT_CFG_NOTIFY |
                GATT_CLIENT_CFG_INDICATE);
            if(SUCCESS == status && pAppCBs && pAppCBs->pfnCfgChangeCb)
            {
                pAppCBs->pfnCfgChangeCb(connHandle,
                                        Data_Service_findCharParamId(
                                            pAttr), len, pValue);
            }
    
            return(status);
        }
    
        // Find settings for the characteristic to be written.
        paramID = Data_Service_findCharParamId(pAttr);
        switch(paramID)
        {
    
        case DS_STREAM_ID:
            writeLenMin = DS_STREAM_LEN_MIN;
            writeLenMax = DS_STREAM_LEN;
            pValueLenVar = &ds_StreamValLen;
    
    //        Log_info5(
    //            "WriteAttrCB : %s connHandle(%d) len(%d) offset(%d) method(0x%02x)",
    //            (uintptr_t)"Stream",
    //            connHandle,
    //            len,
    //            offset,
    //            method);
            /* Other considerations for Stream can be inserted here */
            break;
    
        default:
           // Log_error0("Attribute was not found.");
            return(ATT_ERR_ATTR_NOT_FOUND);
        }
        // Check whether the length is within bounds.
        if(offset >= writeLenMax)
        {
         //  Log_error0("An invalid offset was requested.");
            status = ATT_ERR_INVALID_OFFSET;
        }
        else if(offset + len > writeLenMax)
        {
         //  Log_error0("Invalid value length was received.");
            status = ATT_ERR_INVALID_VALUE_SIZE;
        }
        else if(offset + len < writeLenMin &&
                (method == ATT_EXECUTE_WRITE_REQ || method == ATT_WRITE_REQ))
        {
            // Refuse writes that are lower than minimum.
            // Note: Cannot determine if a Reliable Write (to several chars) is finished, so those will
            //       only be refused if this attribute is the last in the queue (method is execute).
            //       Otherwise, reliable writes are accepted and parsed piecemeal.
         //   Log_error0("Invalid value length was received.");
            status = ATT_ERR_INVALID_VALUE_SIZE;
        }
        else
        {
            // Copy pValue into the variable we point to from the attribute table.
            memcpy(pAttr->pValue + offset, pValue, len);
    
            // Only notify application and update length if enough data is written.
            //
            // Note: If reliable writes are used (meaning several attributes are written to using ATT PrepareWrite),
            //       the application will get a callback for every write with an offset + len larger than _LEN_MIN.
            // Note: For Long Writes (ATT Prepare + Execute towards only one attribute) only one callback will be issued,
            //       because the write fragments are concatenated before being sent here.
            if(offset + len >= writeLenMin)
            {
                changeParamID = paramID;
                *pValueLenVar = offset + len; // Update data length.
            }
        }
    
        // Let the application know something changed (if it did) by using the
        // callback it registered earlier (if it did).
        if(changeParamID != 0xFF)
        {
            if(pAppCBs && pAppCBs->pfnChangeCb)
            {
                pAppCBs->pfnChangeCb(connHandle, paramID, len + offset, pValue); // Call app function from stack task context.
            }
        }
        return(status);
    }
    
    /******************************************************************************
    
     @file  simple_central.c
    
     @brief This file contains the Simple Central sample application for use
            with the CC2650 Bluetooth Low Energy Protocol Stack.
    
     Group: WCS, BTS
     Target Device: cc2640r2
    
     ******************************************************************************
    
     Copyright (c) 2013-2021, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
     ******************************************************************************
    
    
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    
    #include <driverlib/sys_ctrl.h>
    
    #include <string.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Queue.h>
    #include <ti/display/Display.h>
    
    #if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
    #include <driverlib/ioc.h>
    #endif // USE_FPGA | DEBUG_SW_TRACE
    
    #include "bcomdef.h"
    
    #include <icall.h>
    #include "util.h"
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "central.h"
    #include "simple_gatt_profile.h"
    
    #include "board_key.h"
    #include "board.h"
    
    #include "simple_central.h"
    
    #include "ble_user_config.h"
    
    #define USE_RCOSC
    
    #ifdef USE_RCOSC
     #include "rcosc_calibration.h"
    #endif //USE_RCOSC
    
    /* Semaphore used to gate for shutdown */
    Semaphore_Struct shutdownSem;
    
    uint8_t ACK =0;
    
    #ifdef FMCU_128bit
    CONST uint8 simpleProfileServUUID[ATT_UUID_SIZE] =
    {
     SIMPLEPROFILE_SERV_UUID_BASE128(SIMPLEPROFILE_SERV_UUID)
    };
    #endif
    
    #define Wakeup_ID        01
    
    #define Lead_ME_ID       04
    #define Engine_ON_ID     05
    #define Engine_OFF_ID    06
    #define GoHome_ID        07
    
    //Mauf data
    static const uint8_t ManufData[6] = {0x0D,0x00,0xC0,0xFF,0xEE};
    
    #define KEYFOB_DISCONNECT_TIME_TH  10000    /* 60000=1 minute, 600000 = 10 Minute timer */
    uint8_t Diconnect_Flag=0;
    
    static PIN_State ledPinState;
    static PIN_Handle ledPinHandle;
    //MobileApp Button data
    uint8_t EngineStart_Cmd[8]={36, 172, 4, 36, 173, 7, 32,  0};  //EngineStart String    36 172 4 36 173 7 32 0
    uint8_t EngineStop_Cmd[8]= {36, 172, 4, 36, 173, 7, 32,  1};  //EngineSTOP            36 172 4 36 173 7 32 1
    uint8_t GoHome_Cmd[8]= {36, 172, 4, 36, 173, 1,  0, 139};     //LEAD ME OFF           36 172 4 36 173 1 0 139
    uint8_t LeadMe_Cmd[8]= {36, 172, 4, 36, 173, 1,  0, 138};     //{"24AC0424AD01008A"};
    
    uint8_t Wakeup_Cmd[8]= {36, 172, 4, 36, 173, 1,  0, 140};     //{"24AC0424AD01008A"};
    //TODO
    //  unsigned char Local_Address[6] = {0XFA,0XFF,0XA2,0XCF,0X61,0X0C};  //
     unsigned char Local_Address[6] = {0XFE,0X06,0X52,0XCF,0X61,0X0C};  // LaunchPad
     //  unsigned char Local_Address[6] = {0X01,0XE7,0XE8,0XD8,0X93,0X58};  // Our_Part
     //  unsigned char Local_Address[6] = {0XB0,0X52,0XBE,0X4D,0X71,0XD8};  //
    
    //  LaunchPad
    
    
    /*
     * Initial LED pin configuration table
     *   - LEDs Board_PIN_LED0 & Board_PIN_LED1 are off.
     */
    PIN_Config ledPinTable[] = {
        Board_PIN_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |
        PIN_DRVSTR_MAX,
        Board_PIN_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL |
        PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    /*********************************************************************
     * MACROS
     */
    
    #define FMCU_APP
    /*********************************************************************
     * CONSTANTS
     */
    unsigned char var_Count;
    
    
    
    #define SBC_STATE_CHANGE_EVT                  0x0001
    #define SBC_KEY_CHANGE_EVT                    0x0002
    #define SBC_RSSI_READ_EVT                     0x0004
    #define SBC_PAIRING_STATE_EVT                 0x0008
    #define SBC_PASSCODE_NEEDED_EVT               0x0010
    
    #define SSSC_EVT_SCAN_ENABLED                 0x0014
    #define SSSC_EVT_SCAN_DISABLED                0x0016
    #define SSSC_EVT_ADV_REPORT                   0x0018
    
    
    // Simple Central Task Events
    #define SBC_ICALL_EVT                         ICALL_MSG_EVENT_ID // Event_Id_31
    #define SBC_QUEUE_EVT                         UTIL_QUEUE_EVENT_ID // Event_Id_30
    #define SBC_START_DISCOVERY_EVT               Event_Id_00
    #define SBC_CONN_EST_TIMEOUT_EVT              Event_Id_01
    #define Keyfob_EST_TIMEOUT_EVT                Event_Id_02
    
    #define SBC_ALL_EVENTS                        (SBC_ICALL_EVT            | \
                                                   SBC_QUEUE_EVT            | \
                                                   SBC_CONN_EST_TIMEOUT_EVT | \
                                                   SBC_START_DISCOVERY_EVT)
    
    
    
    
    // Enable/Disable Unlimited Scanning Feature
    #define ENABLE_UNLIMITED_SCAN_RES             FALSE
    
    // Maximum number of scan responses
    #define DEFAULT_MAX_SCAN_RES                  8
    
    // Scan duration in ms
    #define DEFAULT_SCAN_DURATION                 40//4000
    
    // Discovery mode (limited, general, all)
    #define DEFAULT_DISCOVERY_MODE                DEVDISC_MODE_ALL
    
    // TRUE to use active scan
    #define DEFAULT_DISCOVERY_ACTIVE_SCAN         TRUE
    
    // Set desired policy to use during discovery (use values from GAP_Disc_Filter_Policies)
    #define DEFAULT_DISCOVERY_WHITE_LIST          GAP_DISC_FILTER_POLICY_ALL
    
    // TRUE to use high scan duty cycle when creating link
    #define DEFAULT_LINK_HIGH_DUTY_CYCLE          FALSE
    
    // TRUE to use white list when creating link
    #define DEFAULT_LINK_WHITE_LIST               FALSE
    
    // Default RSSI polling period in ms
    #define DEFAULT_RSSI_PERIOD                   1000
    
    // After the connection is formed, the central will accept connection parameter
    // update requests from the peripheral
    #define DEFAULT_ENABLE_UPDATE_REQUEST         GAPCENTRALROLE_PARAM_UPDATE_REQ_AUTO_ACCEPT
    
    // Minimum connection interval (units of 1.25ms) if automatic parameter update
    // request is enabled
    #define DEFAULT_UPDATE_MIN_CONN_INTERVAL     12//400
    
    // Maximum connection interval (units of 1.25ms) if automatic parameter update
    // request is enabled
    #define DEFAULT_UPDATE_MAX_CONN_INTERVAL      36//800
    
    // Slave latency to use if automatic parameter update request is enabled
    #define DEFAULT_UPDATE_SLAVE_LATENCY          0
    
    // Supervision timeout value (units of 10ms) if automatic parameter update
    // request is enabled
    #define DEFAULT_UPDATE_CONN_TIMEOUT           100//600
    
    // Default GAP pairing mode
    //#define DEFAULT_PAIRING_MODE                  GAPBOND_PAIRING_MODE_INITIATE//GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
    #define DEFAULT_PAIRING_MODE                  GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
    
    
    // Default MITM mode (TRUE to require passcode or OOB when paissring)
    #define DEFAULT_MITM_MODE                     FALSE
    
    // Default bonding mode, TRUE to bond
    #define DEFAULT_BONDING_MODE                  TRUE
    
    // Default GAP bonding I/O capabilities
    #define DEFAULT_IO_CAPABILITIES               GAPBOND_IO_CAP_DISPLAY_ONLY
    
    // Default service discovery timer delay in ms
    #define DEFAULT_SVC_DISCOVERY_DELAY           1000
    
    // TRUE to filter discovery results on desired service UUID
    #define DEFAULT_DEV_DISC_BY_SVC_UUID          TRUE
    
    // Length of bd addr as a string
    #define B_ADDR_STR_LEN                        15
    
    // Connection esablishement timeout
    #define DEFAULT_CONN_SETUP_TIMEOUT            50000
    
    // Type of Display to open
    #if !defined(Display_DISABLE_ALL)
      #if defined(BOARD_DISPLAY_USE_LCD) && (BOARD_DISPLAY_USE_LCD!=0)
        #define SBC_DISPLAY_TYPE Display_Type_LCD
      #elif defined (BOARD_DISPLAY_USE_UART) && (BOARD_DISPLAY_USE_UART!=0)
        #define SBC_DISPLAY_TYPE Display_Type_UART
      #else // !BOARD_DISPLAY_USE_LCD && !BOARD_DISPLAY_USE_UART
        #define SBC_DISPLAY_TYPE 0 // Option not supported
      #endif // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART
    #else // Display_DISABLE_ALL
      #define SBC_DISPLAY_TYPE 0 // No Display
    #endif // Display_DISABLE_ALL
    
    // Task configuration
    #define SBC_TASK_PRIORITY                     1
    
    #ifndef SBC_TASK_STACK_SIZE
    #define SBC_TASK_STACK_SIZE                   864
    #endif
    
    // Application states
    enum
    {
      BLE_STATE_IDLE,
      BLE_STATE_CONNECTING,
      BLE_STATE_CONNECTED,
      BLE_STATE_DISCONNECTING
    };
    
    // Discovery states
    enum
    {
      BLE_DISC_STATE_IDLE,                // Idle
      BLE_DISC_STATE_MTU,                 // Exchange ATT MTU size
      BLE_DISC_STATE_SVC,                 // Service discovery
      BLE_DISC_STATE_CHAR                 // Characteristic discovery
    };
    
    // Key states for connections
    typedef enum {
      GATT_RW,                 // Perform GATT Read/Write
      RSSI,                    // Toggle RSSI updates
      CONN_UPDATE,             // Send Connection Parameter Update
      GET_CONN_INFO,           // Display Current Connection Information
      DISCONNECT               // Disconnect
    } keyPressConnOpt_t;
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    // App event passed from profiles.
    typedef struct
    {
      appEvtHdr_t hdr; // event header
      uint8_t *pData;  // event data
    } sbcEvt_t;
    
    // RSSI read data structure
    typedef struct
    {
      uint16_t period;      // how often to read RSSI
      uint16_t connHandle;  // connection handle
      Clock_Struct *pClock; // pointer to clock struct
    } readRssi_t;
    
    
    
    /* Wake-up Button pin table */
    PIN_Config ButtonTableWakeUp[] = {
        Board_PIN_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
        Board_PIN_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
        Board_PIN_BUTTON2 | PIN_INPUT_EN | PIN_PULLUP | PINCC26XX_WAKEUP_NEGEDGE,
        PIN_TERMINATE                                 /* Terminate list */
    };
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    // Display Interface
    Display_Handle dispHandle = NULL;
    
    /*********************************************************************
     * EXTERNAL VARIABLES
     */
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    // Entity ID globally used to check for source and/or destination of messages
    static ICall_EntityID selfEntity;
    
    // Event globally used to post local events and pend on system and
    // local events.
    static ICall_SyncHandle syncEvent;
    
    // Clock object used to signal timeout
    static Clock_Struct startDiscClock;
    
    // Clock object used to establishement connection timeout
    static Clock_Struct startLinkEstClock;
    
    // Clock object used to establishement connection timeout
    static Clock_Struct KeyfobDisconnectTimer_Clock;
    static Clock_Handle KeyfobDisconnectTimer_Handle;
    
    // Queue object used for app messages
    static Queue_Struct appMsg;
    static Queue_Handle appMsgQueue;
    
    // Task configuration
    Task_Struct sbcTask;
    Char sbcTaskStack[SBC_TASK_STACK_SIZE];
    
    // GAP GATT Attributes
    static const uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Central";
    
    // Number of scan results and scan result index
    static uint8_t scanRes = 0;
    static int8_t scanIdx = -1;
    
    // Scan result list
    static gapDevRec_t devList[DEFAULT_MAX_SCAN_RES];
    
    // Scanning state
    static bool scanningStarted = FALSE;
    
    //Scan State
    static bool scanningStarted_F = FALSE;
    
    
    // Connection handle of current connection
    static uint16_t connHandle = GAP_CONNHANDLE_INIT;
    
    // Application state
    static uint8_t state = BLE_STATE_IDLE;
    
    // Discovery state
    static uint8_t discState = BLE_DISC_STATE_IDLE;
    
    // Discovered service start and end handle
    static uint16_t svcStartHdl = 0;
    static uint16_t svcEndHdl = 0;
    
    // Discovered characteristic handle
    static uint16_t charHdl = 0;
    
    // Value to write
    static uint8_t charVal = 0;
    
    // Value read/write toggle
    static bool doWrite = FALSE;
    
    // GATT read/write procedure state
    static bool procedureInProgress = FALSE;
    
    // Maximum PDU size (default = 27 octets)
    static uint16 maxPduSize;
    
    // Array of RSSI read structures
    static readRssi_t readRssi[MAX_NUM_BLE_CONNS];
    
    // Key option state.
    static keyPressConnOpt_t keyPressConnOpt = DISCONNECT;
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static void SimpleCentral_init(void);
    static void SimpleCentral_taskFxn(UArg a0, UArg a1);
    
    static void SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg);
    static void SimpleCentral_handleKeys(uint8_t shift, uint8_t keys);
    static void SimpleCentral_processStackMsg(ICall_Hdr *pMsg);
    static void SimpleCentral_processAppMsg(sbcEvt_t *pMsg);
    static void SimpleCentral_processRoleEvent(gapCentralRoleEvent_t *pEvent);
    static void SimpleCentral_processGATTDiscEvent(gattMsgEvent_t *pMsg);
    static void SimpleCentral_startDiscovery(void);
    static void SimpleCentral_stopEstablishing(void);
    
    /***********************/
    #ifdef FMCU_APP
      static void Keyfob_connectToFirstDevice(void);
      //static void Send_ButtonPacket(uint8_t *Packet_Data);
      static void Send_ButtonPacket_01(uint8_t Packet_ID);
      static void keyfob_startGapDiscovery(void);
    #endif
    
    static bool SimpleCentral_findUuid(const uint8_t *uuid, const uint8_t *pManufData ,uint8_t manDataLen ,uint8_t *pData,
                                               uint8_t dataLen);
    
    //static bool SimpleCentral_findSvcUuid(uint16_t uuid, uint8_t *pData,
    //                                         uint8_t dataLen);
    static void SimpleCentral_addDeviceInfo(uint8_t *pAddr, uint8_t addrType);
    static void SimpleCentral_processPairState(uint8_t state, uint8_t status);
    static void SimpleCentral_processPasscode(uint16_t connectionHandle,
                                                 uint8_t uiOutputs);
    
    static void SimpleCentral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg);
    static bStatus_t SimpleCentral_StartRssi(uint16_t connHandle, uint16_t period);
    static bStatus_t SimpleCentral_CancelRssi(uint16_t connHandle);
    static readRssi_t *SimpleCentral_RssiAlloc(uint16_t connHandle);
    static readRssi_t *SimpleCentral_RssiFind(uint16_t connHandle);
    static void SimpleCentral_RssiFree(uint16_t connHandle);
    
    static uint8_t SimpleCentral_eventCB(gapCentralRoleEvent_t *pEvent);
    static void SimpleCentral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,
                                         uint8_t uiInputs, uint8_t uiOutputs,
                                         uint32_t numComparison);
    static void SimpleCentral_pairStateCB(uint16_t connHandle, uint8_t state,
                                             uint8_t status);
    
    void SimpleCentral_startDiscHandler(UArg a0);
    void SimpleCentral_linkEstClockHandler(UArg a0);
    void SimpleCentral_DisconnectClockHandler(UArg a0);
    void SimpleCentral_keyChangeHandler(uint8 keys);
    void SimpleCentral_readRssiHandler(UArg a0);
    
    static uint8_t SimpleCentral_enqueueMsg(uint8_t event, uint8_t status,
                                               uint8_t *pData);
    
    #ifdef FPGA_AUTO_CONNECT
    static void SimpleCentral_startGapDiscovery(void);
    static void SimpleCentral_connectToFirstDevice(void);
    #endif // FPGA_AUTO_CONNECT
    
    /*********************************************************************
     * EXTERN FUNCTIONS
     */
    extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // Central GAPRole Callbacks
    static gapCentralRoleCB_t SimpleCentral_roleCB =
    {
      SimpleCentral_eventCB     // GAPRole Event Callback
    };
    
    // Bond Manager Callbacks
    static gapBondCBs_t SimpleCentral_bondCB =
    {
      SimpleCentral_passcodeCB, // Passcode callback
      SimpleCentral_pairStateCB // Pairing / Bonding state Callback
    };
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    #ifdef FPGA_AUTO_CONNECT
    /*********************************************************************
     * @fn      SimpleCentral_startGapDiscovery
     *
     * @brief   Start discovering devices
     *
     * @param   none
     *
     * @return  none
     */
    static void SimpleCentral_startGapDiscovery(void)
    {
      // Start discovery
      if ((state != BLE_STATE_CONNECTED) && (!scanningStarted))
      {
        scanningStarted = TRUE;
        scanRes = 0;
    
        Display_print0(dispHandle, 2, 0, "Discovering...");
        Display_clearLines(dispHandle, 3, 4);
    
        GAPCentralRole_StartDiscovery(DEFAULT_DISCOVERY_MODE,
                                      DEFAULT_DISCOVERY_ACTIVE_SCAN,
                                      DEFAULT_DISCOVERY_WHITE_LIST);
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_connectToFirstDevice
     *
     * @brief   Connect to first device in list of discovered devices
     *
     * @param   none
     *
     * @return  none
     */
    static void SimpleCentral_connectToFirstDevice(void)
    {
      uint8_t addrType;
      uint8_t *peerAddr;
    
      scanIdx = 0;
    
      if (state == BLE_STATE_IDLE)
      {
        // connect to current device in scan result
        peerAddr = devList[scanIdx].addr;
        addrType = devList[scanIdx].addrType;
    
        state = BLE_STATE_CONNECTING;
    
        GAPCentralRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
                                     DEFAULT_LINK_WHITE_LIST,
                                     addrType, peerAddr);
    
        Display_print0(dispHandle, 2, 0, "Connecting");
        Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddr));
        Display_clearLine(dispHandle, 4);
      }
    }
    #endif // FPGA_AUTO_CONNECT
    
    /*********************************************************************
     * @fn      SimpleCentral_createTask
     *
     * @brief   Task creation function for the Simple Central.
     *
     * @param   none
     *
     * @return  none
     */
    void SimpleCentral_createTask(void)
    {
      Task_Params taskParams;
    
      // Configure task
      Task_Params_init(&taskParams);
      taskParams.stack = sbcTaskStack;
      taskParams.stackSize = SBC_TASK_STACK_SIZE;
      taskParams.priority = SBC_TASK_PRIORITY;
    
      Task_construct(&sbcTask, SimpleCentral_taskFxn, &taskParams, NULL);
    }
    
    /**********************************************************************
     *                          FMCU APPLICATION                          *
     **********************************************************************/
    #ifdef  FMCU_APP
    
    //Todo
    static void SimpleCentral_handleKeys(uint8_t shift, uint8_t keys)
    //static void Keyfob_ButtonisPressed(void)
    {
       hciActiveConnInfo_t *pConnInfo; // pointer to hold return connection information
       (void)shift;  // Intentionally unreferenced parameter
    //TODO :
    
       if (state != BLE_STATE_CONNECTED)/* && (scanningStarted_F == FALSE )*/
                       {
                          Event_post(syncEvent, SBC_START_DISCOVERY_EVT);
                          keyfob_startGapDiscovery();
                          //Util_stopClock((Clock_Struct *)KeyfobDisconnectTimer_Handle);
                          Keyfob_connectToFirstDevice();
                          // scanningStarted_F= TRUE ;
                        }
    
       if (state == BLE_STATE_CONNECTED)
            {
            // Display_print0(dispHandle, 7, 0, "Timer started");
            // Util_startClock((Clock_Struct *)KeyfobDisconnectTimer_Handle);
            }
    
       if(connHandle!=0)
            HCI_EXT_DisconnectImmedCmd(connHandle); //Terminate the connection
    
       if (keys & KEY_ENGINE_ON) //KEY_LEFT
           {
            //clear excess lines to keep display clean if another option chosen
           Display_doClearLines(dispHandle, 7, 16);
           Display_print0(dispHandle, 5, 0, "ENGINE_ON_BUTTON DETECTED ");
           if (state == BLE_STATE_CONNECTED ) // ButtonPressedTimer >= ButtonPressShortTH
                 {
                  //Long press of Start button detected
                  Display_doClearLines(dispHandle, 7, 16);
                  Display_print0(dispHandle, 5, 0, "ENGINE_ON_BUTTON DETECTED ");
                  Send_ButtonPacket_01(Engine_ON_ID);
                  Display_print0(dispHandle, 6, 0, "SENT ENGINE_ON_BUTTON CMD ");
    
    
                  //Display_print0(dispHandle, 7, 0, "Timer started");
                  //Util_startClock((Clock_Struct *)KeyfobDisconnectTimer_Handle);
    
                 }
            }
    
       if (keys & KEY_ENGINE_OFF ) //KEY_RIGHT)
           {
           //clear excess lines to keep display clean if another option chosen
            Display_doClearLines(dispHandle, 7, 16);
            Display_print0(dispHandle, 5, 0, "ENGINE_OFF_BUTTON DETECTED ");
            if (state == BLE_STATE_CONNECTED)
               {
                //HCI_EXT_DisconnectImmedCmd(connHandle); //Terminate the connection
                Send_ButtonPacket_01(Engine_OFF_ID);
                Display_print0(dispHandle, 6, 0, "SENT ENGINE_OFF_BUTTON  CMD");
               }
           }
    
       if (keys & KEY_LEAD_ME)
           {
            //clear excess lines to keep display clean if another option chosen
             Display_doClearLines(dispHandle, 7, 16);
             Display_print0(dispHandle, 5, 0, "ENGINE_LEAD_ME_BUTTON DETECTED");
    
             if (state == BLE_STATE_CONNECTED)
                 {
                  Send_ButtonPacket_01(Lead_ME_ID);
                  Display_print0(dispHandle, 6, 0, "SENT LEAD_ME_BUTTON  CMD");
    
                 }
           }
       /******************** TWO BUTTON PRESSED ********************/
       if (keys & KEY_GO_HOME)
           {
            //clear excess lines to keep display clean if another option chosen
             Display_doClearLines(dispHandle, 7, 16);
             Display_print0(dispHandle, 5, 0, "GO HOME BUTTON DETECTED");
    
             if (state == BLE_STATE_CONNECTED )
                 {
                  Send_ButtonPacket_01(GoHome_ID);
                  Display_print0(dispHandle, 6, 0, "SENT GO_HOME BUTTON  CMD");
                 }
           }
    
       /******************** THREE BUTTON PRESSED ********************/
       if (keys & KEY_RESET)
           {
            //clear excess lines to keep display clean if another option chosen
             Display_doClearLines(dispHandle, 7, 16);
             Display_print0(dispHandle, 5, 0, "RESET DETECTED");
    
            // if (state == BLE_STATE_CONNECTED ) /* No need to check whether device is connected or not */
                 {
                 PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
                  GAPCentralRole_TerminateLink(connHandle);
                 }
           }
    /*
        if (keys & KEY_LEFT)
            {
            ButtonPressedTimer_var=0;
    
            //Start a clock
            //Util_startClock((Clock_Struct *)ButtonPressedTimer_Handle);
    
            if(ButtonPressedTimer_var == 0)
            {
    
            //clear excess lines to keep display clean if another option chosen
              Keyfob_connectToFirstDevice();   //  User require to first connect with Device
              if (state == BLE_STATE_CONNECTED )// ButtonPressedTimer < ButtonPressShortTH
                  {
                   //Short press of Start button detected
                   Display_doClearLines(dispHandle, 7, 16);
                   Send_ButtonPacket_01(Wakeup_ID);
                   Display_print0(dispHandle, 6, 0, "SENDING WAKEUP PACKET ");
                  }
    
            }
            else if(ButtonPressedTimer_var == 10)
             {
              if (state == BLE_STATE_CONNECTED ) // ButtonPressedTimer >= ButtonPressShortTH
                  {
                   //Long press of Start button detected
                   Display_doClearLines(dispHandle, 7, 16);
                   Send_ButtonPacket_01(Engine_ON_ID);
                   Display_print0(dispHandle, 6, 0, "SENDING ENGINE ON PACKET ");
                  }
              }//elseif
            }
    */
    
            }
    #endif // FMCU_APP
    
    
    #ifdef FMCU_APP
    //todo
    static void keyfob_startGapDiscovery(void)
    {
        // Start discovery
        if ((state != BLE_STATE_CONNECTED) && (!scanningStarted))
        {
          scanningStarted = TRUE;
          scanRes = 0;
    
          Display_print0(dispHandle, 2, 0, "Discovering...");
          Display_clearLines(dispHandle, 3, 4);
    
          GAPCentralRole_StartDiscovery(DEFAULT_DISCOVERY_MODE,
                                        DEFAULT_DISCOVERY_ACTIVE_SCAN,
                                        DEFAULT_DISCOVERY_WHITE_LIST);
    
        }
    }
    #endif // FMCU_APP
    
    
    #ifdef FMCU_APP
    static void Keyfob_connectToFirstDevice(void)
    {
        uint8_t addrType;
        uint8_t *peerAddr;
    
        scanIdx = 0;
    
        if ((state == BLE_STATE_IDLE) || (state == BLE_STATE_CONNECTING) )
        {
          // connect to current device in scan result
          peerAddr = devList[scanIdx].addr;
          addrType = devList[scanIdx].addrType;
    
          state = BLE_STATE_CONNECTING;
    
    //      GAPCentralRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
    //                                   DEFAULT_LINK_WHITE_LIST,
    //                                   addrType, peerAddr);
            GAPCentralRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
                                            DEFAULT_LINK_WHITE_LIST,
                                            ADDRTYPE_PUBLIC, Local_Address);
    
          Display_print0(dispHandle, 2, 0, "Connecting");
          Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddr));
          Display_clearLine(dispHandle, 4);
        }
      }
    
    #endif
    
    
    #ifdef FMCU_APP
    static void Send_ButtonPacket_01(uint8_t Packet_ID)
     {
        switch(Packet_ID)
        {
        case Lead_ME_ID :
         {
         var_Count=0;// ReStart from initial count
         if (charHdl != 0 && procedureInProgress == FALSE)
          {
            Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
            uint8_t status;
    
              // Do a write as long as no other write is in progress
              Display_print0(dispHandle, 7, 0, "Inside doWrite ");
              // Do a write
              attWriteReq_t req;
    
              req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 8, NULL);
           if ( req.pValue != NULL)
              {
                req.handle = charHdl;
                req.len = 8;
                for(int i=0;i<8;i++)
                  req.pValue[i] = LeadMe_Cmd[i];
    
                req.sig = 0;
                req.cmd = 0;
    
                status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    
                if ( status != SUCCESS )
                {
                  Display_print0(dispHandle, 8, 0, " GATT Write not success ");
                  GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                }
              }
              else
              {
                Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
                status = bleMemAllocError;
              }
          }
         }//case
         break;
    
        case Engine_ON_ID  :
         {
            var_Count=0;// ReStart from initial count
            if (charHdl != 0 && procedureInProgress == FALSE)
             {
               Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
               uint8_t status;
    
                 // Do a write as long as no other write is in progress
                 Display_print0(dispHandle, 7, 0, "Inside doWrite ");
                 // Do a write
                 attWriteReq_t req;
    
                 req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
               if ( req.pValue != NULL)
                 {
                   req.handle = charHdl;
                   req.len = 8;
                   for(int i=0;i<8;i++)
                     req.pValue[i] = EngineStart_Cmd[i];
                   req.sig = 0;
                   req.cmd = 0;
    
                   status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    
                   if ( status != SUCCESS )
                   {
                     Display_print0(dispHandle, 8, 0, " GATT Write not success ");
                     GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                   }
                 }
                 else
                 {
                   Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
                   status = bleMemAllocError;
                 }
             }
            }//case
            break;
    
        case Engine_OFF_ID   :
         {
            var_Count=0;// ReStart from initial count
            if (charHdl != 0 && procedureInProgress == FALSE)
             {
               Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
               uint8_t status;
    
                 // Do a write as long as no other write is in progress
                 Display_print0(dispHandle, 7, 0, "Inside doWrite ");
                 // Do a write
                 attWriteReq_t req;
    
                 req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
               if ( req.pValue != NULL)
                 {
                   //TODO
                   req.handle = charHdl;
                   req.len = 8;
                   for(int i=0;i<8;i++)
                     req.pValue[i] = EngineStop_Cmd[i];
                   req.sig = 0;
                   req.cmd = 0;
    
                   status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    
                   if ( status != SUCCESS )
                   {
                     Display_print0(dispHandle, 8, 0, " GATT Write not success ");
                     GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                   }
                 }
                 else
                 {
                   Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
                   status = bleMemAllocError;
                 }
             }
            }//case
            break;
    
    //    case Wakeup_ID   :
    //     {
    //        var_Count=0;// ReStart from initial count
    //        if (charHdl != 0 && procedureInProgress == FALSE)
    //         {
    //           Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
    //           uint8_t status;
    //
    //             // Do a write as long as no other write is in progress
    //             Display_print0(dispHandle, 7, 0, "Inside doWrite ");
    //             // Do a write
    //             attWriteReq_t req;
    //
    //             req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
    //           if ( req.pValue != NULL)
    //             {
    //
    //               req.handle = charHdl;
    //               req.len = 8;
    //               for(int i=0;i<8;i++)
    //                 req.pValue[i] = Wakeup_Cmd[i];
    //               req.sig = 0;
    //               req.cmd = 0;
    //
    //               status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    //
    //               if ( status != SUCCESS )
    //               {
    //                 Display_print0(dispHandle, 8, 0, " GATT Write not success ");
    //                 GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
    //               }
    //             }
    //             else
    //             {
    //               Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
    //               status = bleMemAllocError;
    //             }
    //         }
    //        }//case
    //        break;
    
        case GoHome_ID   :
         {
            var_Count=0;// ReStart from initial count
            if (charHdl != 0 && procedureInProgress == FALSE)
             {
               Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
               uint8_t status;
    
                 // Do a write as long as no other write is in progress
                 Display_print0(dispHandle, 7, 0, "Inside doWrite ");
                 // Do a write
                 attWriteReq_t req;
    
                 req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
               if ( req.pValue != NULL)
                 {
                   req.handle = charHdl;
                   req.len = 8;
                   for(int i=0;i<8;i++)
                     req.pValue[i] = GoHome_Cmd[i];
                   req.sig = 0;
                   req.cmd = 0;
    
                   status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    
                   if ( status != SUCCESS )
                   {
                     Display_print0(dispHandle, 8, 0, " GATT Write not success ");
                     GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                   }
                 }
                 else
                 {
                   Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
                   status = bleMemAllocError;
                 }
             }
            }//case
            break;
    
        }//sw end
    }//function end
    
    
    //static void Send_ButtonPacket(uint8_t *Packet_Data)
    // {
    //
    //    var_Count=0;// ReStart from initial count
    //     if (charHdl != 0 && procedureInProgress == FALSE)
    //      {
    //        Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
    //        uint8_t status;
    //
    //          // Do a write as long as no other write is in progress
    //          Display_print0(dispHandle, 7, 0, "Inside doWrite ");
    //          // Do a write
    //          attWriteReq_t req;
    //
    //          req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
    //        if ( req.pValue != NULL)
    //          {
    //
    //            req.handle = charHdl;
    //            req.len = 1;
    //            req.pValue[0] = Packet_Data[var_Count];
    //            req.sig = 0;
    //            req.cmd = 0;
    //            var_Count++;
    //
    //            status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    //
    //            if ( status != SUCCESS )
    //            {
    //              Display_print0(dispHandle, 8, 0, " GATT Write not success ");
    //              GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
    //            }
    //          }
    //          else
    //          {
    //            Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
    //            status = bleMemAllocError;
    //          }
    //      }
    //
    //}//function end
    
    #endif
    
    //TODO ?????
    void KeyfobDisconnectTimerFunction(UArg a0)
    {
        Display_print0(dispHandle, 2, 0, "KeyfobDisconnectTimerFunction : Disconnecting ");
    
        PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
        uint32_t sleepUs = 500000;
        Task_sleep(sleepUs / Clock_tickPeriod);
    //    PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
    
        Display_print0(dispHandle, 6, 0, "WENT TO SLEEP 1");
        //GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
    
        PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
                  //GAPCentralRole_TerminateLink(connHandle);
              /* Configure DIO for wake up from shutdown */
        PINCC26XX_setWakeup(ButtonTableWakeUp);
                 //GAPBondMgr_LinkTerm(connHandle);
        Power_shutdown(0, 0);
                //GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
    
        //Diconnect_Flag=0;
    
    //    if (pUpdateClock != NULL)
    //    {
    //      // Stop and destruct the RTOS clock if it's still alive
    //      if (Util_isActive(pUpdateClock))
    //      {
    //        Util_stopClock(pUpdateClock);
    //      }
    //
    //      // Destruct the clock object
    //      Clock_destruct(pUpdateClock);
    //      // Free clock struct
    //      ICall_free(pUpdateClock);
    //    }
    
    
        //Util_stopClock((Clock_Struct *)KeyfobDisconnectTimer_Handle);
        // Destruct the clock object
        // Clock_destruct((Clock_Struct *)KeyfobDisconnectTimer_Handle);
    
        connHandle = GAP_CONNHANDLE_INIT;
        discState = BLE_DISC_STATE_IDLE;
        charHdl = 0;
        procedureInProgress = FALSE;
        scanIdx = -1;
    
        Diconnect_Flag=10;
    
    
    
        //GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
        //state = BLE_STATE_DISCONNECTING;
    
    
        /* Pend on semaphore before going to shutdown */
        //Semaphore_pend(Semaphore_handle(&shutdownSem), BIOS_WAIT_FOREVER);
    
        /* Configure DIO for wake up from shutdown */
       // PINCC26XX_setWakeup(ButtonTableWakeUp);
    
       // Power_shutdown(0, 0);
        //GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
    
    
    
        //Display_print0(dispHandle, 2, 0, "KeyfobDisconnectTimerFunction : Disconnecting ");
    }
    
    
    /*********************************************************************
     * @fn      SimpleCentral_Init
     *
     * @brief   Initialization function for the Simple Central App Task.
     *          This is called during initialization and should contain
     *          any application specific initialization (ie. hardware
     *          initialization/setup, table initialization, power up
     *          notification).
     *
     * @param   none
     *
     * @return  none
     */
    static void SimpleCentral_init(void)
    {
    
    
      uint8_t i;
    
      // ******************************************************************
      // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
      // ******************************************************************
      // Register the current thread as an ICall dispatcher application
      // so that the application can send and receive messages.
      ICall_registerApp(&selfEntity, &syncEvent);
    
    #if defined( USE_FPGA )
      // configure RF Core SMI Data Link
      IOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);
      IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);
    
      // configure RF Core SMI Command Link
      IOCPortConfigureSet(IOID_10, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_OUT, IOC_STD_OUTPUT);
      IOCPortConfigureSet(IOID_9, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_IN, IOC_STD_INPUT);
    
      // configure RF Core tracer IO
      IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
    #else // !USE_FPGA
      #if defined( DEBUG_SW_TRACE )
        // configure RF Core tracer IO
        IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);
      #endif // DEBUG_SW_TRACE
    #endif // USE_FPGA
    
      // Create an RTOS queue for message from profile to be sent to app.
      appMsgQueue = Util_constructQueue(&appMsg);
    
      // Open LED pins
         ledPinHandle = PIN_open(&ledPinState, ledPinTable);
         if(!ledPinHandle)
         {
    
             Task_exit();
         }
    
    
    #ifdef USE_RCOSC
         RCOSC_enableCalibration();
    #endif // USE_RCOSC
    
      // Setup discovery delay as a one-shot timer
      Util_constructClock(&startDiscClock, SimpleCentral_startDiscHandler,
                          DEFAULT_SVC_DISCOVERY_DELAY, 0, false, 0);
    
      Util_constructClock(&startLinkEstClock, SimpleCentral_linkEstClockHandler,
                          DEFAULT_CONN_SETUP_TIMEOUT, 0, false, 0);
    
    //  Util_constructClock(&KeyfobDisconnectTimer_Clock, SimpleCentral_DisconnectClockHandler,
    //                      KEYFOB_DISCONNECT_TIME_TH, 0, false, 0);
    
      KeyfobDisconnectTimer_Handle = Util_constructClock(&KeyfobDisconnectTimer_Clock,
                                                         KeyfobDisconnectTimerFunction,
                                                         KEYFOB_DISCONNECT_TIME_TH,
                                                         0,
                                                         false,
                                                         0);
      Board_initKeys(SimpleCentral_keyChangeHandler);
    
      dispHandle = Display_open(SBC_DISPLAY_TYPE, NULL);
    
      // Initialize internal data
      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      {
        readRssi[i].connHandle = GAP_CONNHANDLE_ALL;
        readRssi[i].pClock = NULL;
      }
    
      // Setup the Central GAPRole Profile. For more information see the GAP section
      // in the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html/
      {
        uint8_t scanRes = 0;
    
        // In case that the Unlimited Scanning feature is disabled
        // send the number of scan results to the GAP
        if(ENABLE_UNLIMITED_SCAN_RES == FALSE)
        {
            scanRes = DEFAULT_MAX_SCAN_RES;
        }
    
        GAPCentralRole_SetParameter(GAPCENTRALROLE_MAX_SCAN_RES, sizeof(uint8_t),
                                    &scanRes);
      }
    
      // Set GAP Parameters to set the discovery duration
      // For more information, see the GAP section of the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html/
      GAP_SetParamValue(TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION);
      GAP_SetParamValue(TGAP_LIM_DISC_SCAN, DEFAULT_SCAN_DURATION);
      GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN,
                       (void *)attDeviceName);
    
      // Setup the GAP Bond Manager. For more information see the GAP Bond Manager
      // section in the User's Guide:
      // http://software-dl.ti.com/lprf/sdg-latest/html/
      {
        // Don't send a pairing request after connecting; the device waits for the
        // application to start pairing
        uint8_t pairMode = DEFAULT_PAIRING_MODE;
        // Do not use authenticated pairing
        uint8_t mitm = DEFAULT_MITM_MODE;
        // This is a display only device
        uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
        // Create a bond during the pairing process
        uint8_t bonding = DEFAULT_BONDING_MODE;
        // Whether to replace the least recently used entry when bond list is full,
        // and a new device is bonded.
        // Alternative is pairing succeeds but bonding fails, unless application has
        // manually erased at least one bond.
        uint8_t replaceBonds = FALSE;
    
        GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
        GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
        GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
        GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
        GAPBondMgr_SetParameter(GAPBOND_LRU_BOND_REPLACEMENT, sizeof(uint8_t), &replaceBonds);
    
    //    uint8_t autoSyncWhiteList = TRUE;
    //    GAPBondMgr_SetParameter(GAPBOND_AUTO_SYNC_WL, sizeof(uint8_t), &autoSyncWhiteList);
    //    GAP_ConfigDeviceAddr(ADDRMODE_PRIVATE_RESOLVE, NULL);
    //    //Set timeout value to 5 minutes
    //    GAP_SetParamValue( TGAP_PRIVATE_ADDR_INT , 1);
      }
    
      // Initialize GATT Client
      VOID GATT_InitClient();
    
      // Register to receive incoming ATT Indications/Notifications
      GATT_RegisterForInd(selfEntity);
    
      // Initialize GATT attributes
      GGS_AddService(GATT_ALL_SERVICES);         // GAP
      GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
    
      // Start the Device
      VOID GAPCentralRole_StartDevice(&SimpleCentral_roleCB);
    
      // Register with bond manager after starting device
      GAPBondMgr_Register(&SimpleCentral_bondCB);
    
      // Register with GAP for HCI/Host messages (for RSSI)
      GAP_RegisterForMsgs(selfEntity);
    
      // Register for GATT local events and ATT Responses pending for transmission
      GATT_RegisterForMsgs(selfEntity);
    
      //Set default values for Data Length Extension
      {
        //Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
        #define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
        #define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)
    
        //This API is documented in hci.h
        //See the LE Data Length Extension section in the BLE-Stack User's Guide for information on using this command:
        //http://software-dl.ti.com/lprf/sdg-latest/html/cc2640/index.html
        //HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
      }
    
      Display_print0(dispHandle, 0, 0, "BLE Central");
    
      HCI_EXT_SetTxPowerCmd(LL_EXT_TX_POWER_5_DBM); //set 5dbm tx power
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_taskFxn
     *
     * @brief   Application task entry point for the Simple Central.
     *
     * @param   none
     *
     * @return  events not processed
     */
    static void SimpleCentral_taskFxn(UArg a0, UArg a1)
    {
      Semaphore_Params semParams;
    
      // Initialize application
      SimpleCentral_init();
    
      /* Configure shutdown semaphore. */
      Semaphore_Params_init(&semParams);
      semParams.mode = Semaphore_Mode_BINARY;
      Semaphore_construct(&shutdownSem, 0, &semParams);
    
      // Application main loop
      for (;;)
      {
        uint32_t events;
    
        events = Event_pend(syncEvent, Event_Id_NONE, SBC_ALL_EVENTS,
                            ICALL_TIMEOUT_FOREVER);
    
        if (events)
        {
          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))
            {
              // Process inter-task message
              SimpleCentral_processStackMsg((ICall_Hdr *)pMsg);
            }
    
            if (pMsg)
            {
              ICall_freeMsg(pMsg);
            }
          }
    
          // If RTOS queue is not empty, process app message
          if (events & SBC_QUEUE_EVT)
          {
            while (!Queue_empty(appMsgQueue))
            {
              sbcEvt_t *pMsg = (sbcEvt_t *)Util_dequeueMsg(appMsgQueue);
              if (pMsg)
              {
                // Process message
                 SimpleCentral_processAppMsg(pMsg);
    //todo
                //To automate Connection with dedicated device .
    //           GAPCentralRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
    //                                         DEFAULT_LINK_WHITE_LIST,
    //                                         ADDRTYPE_PUBLIC, Local_Address);
    
    
    //             /* Pend on semaphore before going to shutdown */
    //             Semaphore_pend(Semaphore_handle(&shutdownSem), BIOS_WAIT_FOREVER);
    
    
    //             if (state == BLE_STATE_CONNECTED  )
    //             {
    //              uint32_t sleepUs = 1000;//6seconds //500000;
    //              Task_sleep(sleepUs);
    //              Display_print0(dispHandle, 6, 0, "WENT TO SLEEP 1");
    //              /* Go to shutdown */
    //              //Power_shutdown(0, 0);
    //              GAPCentralRole_TerminateLink(connHandle);
    //             }
    
                 if ( Diconnect_Flag >= 10 )
                 {
                     Display_print0(dispHandle, 6, 0, "WENT TO SLEEP 2");
                     //GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
    
                     PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
                               //GAPCentralRole_TerminateLink(connHandle);
                           /* Configure DIO for wake up from shutdown */
                     PINCC26XX_setWakeup(ButtonTableWakeUp);
                              //GAPBondMgr_LinkTerm(connHandle);
                     Power_shutdown(0, 0);
                             //GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
    
                     Diconnect_Flag=0;
    
                     while(1);
                 }
    
    
                  // Free the space from the message
                ICall_free(pMsg);
              }
            }
          }
    
          if (events & SBC_START_DISCOVERY_EVT)
          {
            SimpleCentral_startDiscovery();
          }
    
          if (events & SBC_CONN_EST_TIMEOUT_EVT)
          {
    
            SimpleCentral_stopEstablishing();
          }
    
       }
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_processStackMsg
     *
     * @brief   Process an incoming task message.
     *
     * @param   pMsg - message to process
     *
     * @return  none
     */
    #ifdef FMCU_APP
    static void SimpleCentral_processStackMsg(ICall_Hdr *pMsg)
    {
      switch (pMsg->event)
      {
        case GAP_MSG_EVENT:
          SimpleCentral_processRoleEvent((gapCentralRoleEvent_t *)pMsg);
          break;
    
        case GATT_MSG_EVENT:
          SimpleCentral_processGATTMsg((gattMsgEvent_t *)pMsg);
          break;
    
        case HCI_GAP_EVENT_EVENT:
          {
            // Process HCI message
            switch(pMsg->status)
            {
              case HCI_COMMAND_COMPLETE_EVENT_CODE:
                SimpleCentral_processCmdCompleteEvt((hciEvt_CmdComplete_t *)pMsg);
                break;
    
              case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
                AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
                break;
    
              default:
                break;
            }
          }
          break;
    
        default:
          break;
      }
    }
    #else
    static void SimpleCentral_processStackMsg(ICall_Hdr *pMsg)
    {
      switch (pMsg->event)
      {
        case GAP_MSG_EVENT:
          SimpleCentral_processRoleEvent((gapCentralRoleEvent_t *)pMsg);
          break;
    
        case GATT_MSG_EVENT:
          SimpleCentral_processGATTMsg((gattMsgEvent_t *)pMsg);
          break;
    
        case HCI_GAP_EVENT_EVENT:
          {
            // Process HCI message
            switch(pMsg->status)
            {
              case HCI_COMMAND_COMPLETE_EVENT_CODE:
                SimpleCentral_processCmdCompleteEvt((hciEvt_CmdComplete_t *)pMsg);
                break;
    
              case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
                AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
                break;
    
              default:
                break;
            }
          }
          break;
    
        default:
          break;
      }
    }
    #endif
    
    #ifdef FMCU_APP
    static void SimpleCentral_processAppMsg(sbcEvt_t *pMsg)
    {
    
        if (state != BLE_STATE_CONNECTED)/* && (scanningStarted_F == FALSE )*/
                        {
                          // Event_post(syncEvent, SBC_START_DISCOVERY_EVT);
                          // keyfob_startGapDiscovery();
                          //Util_stopClock((Clock_Struct *)KeyfobDisconnectTimer_Handle);
                           Keyfob_connectToFirstDevice();
                          // scanningStarted_F= TRUE ;
                         }
      switch (pMsg->hdr.event)
      {
        case SBC_STATE_CHANGE_EVT:
            Display_print0(dispHandle, 2, 0, "SBC_STATE_CHANGE_EVT");
          SimpleCentral_processStackMsg((ICall_Hdr *)pMsg->pData);
    
          // Free the stack message
          ICall_freeMsg(pMsg->pData);
          break;
    
        case SBC_KEY_CHANGE_EVT:
            Display_print0(dispHandle, 2, 0, "SBC_KEY_CHANGE_EVT");
          SimpleCentral_handleKeys(0, pMsg->hdr.state);
    
          break;
    
        case SBC_RSSI_READ_EVT:
          {
            readRssi_t *pRssi = (readRssi_t *)pMsg->pData;
    
            // If link is up and RSSI reads active
            if (pRssi->connHandle != GAP_CONNHANDLE_ALL &&
                linkDB_Up(pRssi->connHandle))
            {
              // Restart timer
              Util_restartClock(pRssi->pClock, pRssi->period);
    
              // Read RSSI
              VOID HCI_ReadRssiCmd(pRssi->connHandle);
            }
          }
          break;
    
        // Pairing event
        case SBC_PAIRING_STATE_EVT:
          {
            SimpleCentral_processPairState(pMsg->hdr.state, *pMsg->pData);
    
            ICall_free(pMsg->pData);
            break;
          }
    //
    //    // Passcode event
    //    case SBC_PASSCODE_NEEDED_EVT:
    //      {
    //        SimpleCentral_processPasscode(connHandle, *pMsg->pData);
    //
    //        ICall_free(pMsg->pData);
    //        break;
    //      }
    
        default:
          // Do nothing.
          break;
      }
    }
    
    
    #else
    /*********************************************************************
     * @fn      SimpleCentral_processAppMsg
     *
     * @brief   Central application event processing function.
     *
     * @param   pMsg - pointer to event structure
     *
     * @return  none
     */
    static void SimpleCentral_processAppMsg(sbcEvt_t *pMsg)
    {
      switch (pMsg->hdr.event)
      {
        case SBC_STATE_CHANGE_EVT:
          SimpleCentral_processStackMsg((ICall_Hdr *)pMsg->pData);
    
          // Free the stack message
          ICall_freeMsg(pMsg->pData);
          break;
    
        case SBC_KEY_CHANGE_EVT:
          SimpleCentral_handleKeys(0, pMsg->hdr.state);
          break;
    
        case SBC_RSSI_READ_EVT:
          {
            readRssi_t *pRssi = (readRssi_t *)pMsg->pData;
    
            // If link is up and RSSI reads active
            if (pRssi->connHandle != GAP_CONNHANDLE_ALL &&
                linkDB_Up(pRssi->connHandle))
            {
              // Restart timer
              Util_restartClock(pRssi->pClock, pRssi->period);
    
              // Read RSSI
              VOID HCI_ReadRssiCmd(pRssi->connHandle);
            }
          }
          break;
    
        // Pairing event
        case SBC_PAIRING_STATE_EVT:
          {
            SimpleCentral_processPairState(pMsg->hdr.state, *pMsg->pData);
    
            ICall_free(pMsg->pData);
            break;
          }
    
        // Passcode event
        case SBC_PASSCODE_NEEDED_EVT:
          {
            SimpleCentral_processPasscode(connHandle, *pMsg->pData);
    
            ICall_free(pMsg->pData);
            break;
          }
    
        default:
          // Do nothing.
          break;
      }
    }
    #endif
    
    #ifdef FMCU_APP
    static void SimpleCentral_processRoleEvent(gapCentralRoleEvent_t *pEvent)
    {
      switch (pEvent->gap.opcode)
        {
          case GAP_DEVICE_INIT_DONE_EVENT:
            {
              maxPduSize = pEvent->initDone.dataPktLen;
    
              Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(pEvent->initDone.devAddr));
              Display_print0(dispHandle, 2, 0, "Initialized");
    
              // Prompt user to begin scanning.
              Display_print0(dispHandle, 5, 0, "Discover ->");
    
              keyfob_startGapDiscovery();
            }
            break;
    
          case GAP_DEVICE_INFO_EVENT:
            {
              uint8 bAddDevice = FALSE;
    #ifdef FMCU_128Bit
                  if (SimpleCentral_findUuid(simpleProfileServUUID,
                                             ManufData,
                                             sizeof(ManufData),
                                             pEvent->deviceInfo.pEvtData,
                                             pEvent->deviceInfo.dataLen))
    #else
                   if (SimpleCentral_findUuid(SIMPLEPROFILE_SERV_UUID,
                                                 ManufData,
                                                 sizeof(ManufData),
                                                 pEvent->deviceInfo.pEvtData,
                                                 pEvent->deviceInfo.dataLen))
    #endif
                      {
                        bAddDevice = TRUE;
                        Display_print0(dispHandle, 7, 0, " Return True SimpleCentral_findUuid");
                      }
    
              if(bAddDevice)
              {
                Display_print0(dispHandle, 8, 0, " SimpleCentral_addDeviceInfo ");
                SimpleCentral_addDeviceInfo(pEvent->deviceInfo.addr,pEvent->deviceInfo.addrType);
              }
            }
            break;
    
          case GAP_DEVICE_DISCOVERY_EVENT:
            {
              if(pEvent->gap.hdr.status == SUCCESS)
              {
                  // discovery complete
                  scanningStarted = FALSE;
    
                  Display_print1(dispHandle, 2, 0, "Devices Found %d", scanRes);
    
                  if (scanRes > 0)
                  {
                     Display_print0(dispHandle, 3, 0, "<- To Select");
                  }
    
                  // Initialize scan index.
                  scanIdx = -1;
    
                  // Prompt user that re-performing scanning at this state is possible.
                  Display_print0(dispHandle, 5, 0, "Discover ->");
    
                  Keyfob_connectToFirstDevice();
    
                }
              else
              {
                  if(pEvent->gap.hdr.status == GAP_LLERROR_INVALID_PARAMETERS)
                  {
                      Display_print0(dispHandle, 3, 0, "INVALID PARAMETERS");
                  }
                  else if(pEvent->gap.hdr.status == GAP_LLERROR_COMMAND_DISALLOWED)
                  {
                      Display_print0(dispHandle, 3, 0, "COMMAND DISALLOWED");
                  }
                  else
                  {
                      Display_print0(dispHandle, 3, 0, "ERROR");
                  }
              }
            }
            break;
    
          case GAP_LINK_ESTABLISHED_EVENT:
            {
              Util_stopClock(&startLinkEstClock);
              if (pEvent->gap.hdr.status == SUCCESS)
              {
                state = BLE_STATE_CONNECTED;
                connHandle = pEvent->linkCmpl.connectionHandle;
                procedureInProgress = TRUE;
    
                // If service discovery not performed initiate service discovery
                if (charHdl == 0)
                {
                  Util_startClock(&startDiscClock);
                }
    
                Display_print0(dispHandle, 2, 0, "Connected");
                Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(pEvent->linkCmpl.devAddr));
                HCI_LE_ReadRemoteUsedFeaturesCmd(connHandle);
                SimpleCentral_handleKeys(0, KEY_LEAD_ME);
              }
              else
              {
                state = BLE_STATE_IDLE;
                connHandle = GAP_CONNHANDLE_INIT;
                discState = BLE_DISC_STATE_IDLE;
    
                Display_print0(dispHandle, 2, 0, "Connect Failed");
                Display_print1(dispHandle, 3, 0, "Reason: %d", pEvent->gap.hdr.status);
              }
            }
            break;
    
          case GAP_LINK_TERMINATED_EVENT:
            {
              state = BLE_STATE_IDLE;
              connHandle = GAP_CONNHANDLE_INIT;
              discState = BLE_DISC_STATE_IDLE;
              charHdl = 0;
              procedureInProgress = FALSE;
              keyPressConnOpt = DISCONNECT;
              scanIdx = -1;
    
              // Cancel RSSI reads
              SimpleCentral_CancelRssi(pEvent->linkTerminate.connectionHandle);
    
              Display_print0(dispHandle, 2, 0, "Disconnected");
              Display_print1(dispHandle, 3, 0, "Reason: %d", pEvent->linkTerminate.reason);
              Display_clearLine(dispHandle, 4);
              Display_clearLine(dispHandle, 6);
    
              HCI_EXT_DisconnectImmedCmd(connHandle); //Terminate the connection
    
              // Prompt user to begin scanning.
              Display_print0(dispHandle, 5, 0, "Discover ->");
            }
            break;
    
          case GAP_LINK_PARAM_UPDATE_EVENT:
            {
              Display_print1(dispHandle, 2, 0, "Param Update: %d", pEvent->linkUpdate.status);
              PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
              uint32_t sleepUs = 50000;
              Task_sleep(sleepUs / Clock_tickPeriod);
              PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
              Task_sleep(sleepUs / Clock_tickPeriod);
              PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
              Task_sleep(sleepUs / Clock_tickPeriod);
              PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
            }
            break;
    
          default:
            break;
        }
      }
    #else
    /*********************************************************************
     * @fn      SimpleCentral_processRoleEvent
     *
     * @brief   Central role event processing function.
     *
     * @param   pEvent - pointer to event structure
     *
     * @return  none
     */
    static void SimpleCentral_processRoleEvent(gapCentralRoleEvent_t *pEvent)
    {
      switch (pEvent->gap.opcode)
      {
        case GAP_DEVICE_INIT_DONE_EVENT:
          {
            maxPduSize = pEvent->initDone.dataPktLen;
    
            Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(pEvent->initDone.devAddr));
            Display_print0(dispHandle, 2, 0, "Initialized");
    
            // Prompt user to begin scanning.
            Display_print0(dispHandle, 5, 0, "Discover ->");
    
    #ifdef FPGA_AUTO_CONNECT
            SimpleCentral_startGapDiscovery();
    #endif // FPGA_AUTO_CONNECT
    
    #ifdef FMCU_APP
    
    #endif
           //keyfob_startGapDiscovery();
          }
          break;
    
        case GAP_DEVICE_INFO_EVENT:
          {
            uint8 bAddDevice = FALSE;
    
            if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
            {
                if (SimpleCentral_findSvcUuid(SIMPLEPROFILE_SERV_UUID,
                                              pEvent->deviceInfo.pEvtData,
                                              pEvent->deviceInfo.dataLen))
                {
                    bAddDevice = TRUE;
                    Display_print0(dispHandle, 7, 0, " Return True SimpleCentral_findSvcUuid");
                }
            }
    
            if((ENABLE_UNLIMITED_SCAN_RES == TRUE) && (DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE))
            {
                bAddDevice = TRUE;
            }
    
            if(bAddDevice)
            {
              Display_print0(dispHandle, 8, 0, " SimpleCentral_addDeviceInfo ");
              SimpleCentral_addDeviceInfo(pEvent->deviceInfo.addr,
                                            pEvent->deviceInfo.addrType);
            }
          }
          break;
    
        case GAP_DEVICE_DISCOVERY_EVENT:
          {
            if(pEvent->gap.hdr.status == SUCCESS)
            {
                // discovery complete
                scanningStarted = FALSE;
    
                // if not filtering device discovery results based on service UUID
                if ((DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE) && (ENABLE_UNLIMITED_SCAN_RES == FALSE))
                {
                  // Copy results
                  scanRes = pEvent->discCmpl.numDevs;
                  memcpy(devList, pEvent->discCmpl.pDevList,
                         (sizeof(gapDevRec_t) * scanRes));
                }
    
                Display_print1(dispHandle, 2, 0, "Devices Found %d", scanRes);
    
                if (scanRes > 0)
                {
    #ifndef FPGA_AUTO_CONNECT
                  Display_print0(dispHandle, 3, 0, "<- To Select");
                }
    
                // Initialize scan index.
                scanIdx = -1;
    
                // Prompt user that re-performing scanning at this state is possible.
                Display_print0(dispHandle, 5, 0, "Discover ->");
    
                //Keyfob_connectToFirstDevice();
    
    #else // FPGA_AUTO_CONNECT
                  SimpleCentral_connectToFirstDevice();
                }
    #endif // FPGA_AUTO_CONNECT
              }
            else
            {
                if(pEvent->gap.hdr.status == GAP_LLERROR_INVALID_PARAMETERS)
                {
                    Display_print0(dispHandle, 3, 0, "INVALID PARAMETERS");
                }
                else if(pEvent->gap.hdr.status == GAP_LLERROR_COMMAND_DISALLOWED)
                {
                    Display_print0(dispHandle, 3, 0, "COMMAND DISALLOWED");
                }
                else
                {
                    Display_print0(dispHandle, 3, 0, "ERROR");
                }
            }
          }
          break;
    
        case GAP_LINK_ESTABLISHED_EVENT:
          {
            Util_stopClock(&startLinkEstClock);
            if (pEvent->gap.hdr.status == SUCCESS)
            {
              state = BLE_STATE_CONNECTED;
              connHandle = pEvent->linkCmpl.connectionHandle;
              procedureInProgress = TRUE;
    
              // If service discovery not performed initiate service discovery
              if (charHdl == 0)
              {
                Util_startClock(&startDiscClock);
              }
    
              Display_print0(dispHandle, 2, 0, "Connected");
              Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(pEvent->linkCmpl.devAddr));
              HCI_LE_ReadRemoteUsedFeaturesCmd(connHandle);
              // Display the initial options for a Right key press.
              SimpleCentral_handleKeys(0, KEY_LEFT);
            }
            else
            {
              state = BLE_STATE_IDLE;
              connHandle = GAP_CONNHANDLE_INIT;
              discState = BLE_DISC_STATE_IDLE;
    
              Display_print0(dispHandle, 2, 0, "Connect Failed");
              Display_print1(dispHandle, 3, 0, "Reason: %d", pEvent->gap.hdr.status);
            }
          }
          break;
    
        case GAP_LINK_TERMINATED_EVENT:
          {
            state = BLE_STATE_IDLE;
            connHandle = GAP_CONNHANDLE_INIT;
            discState = BLE_DISC_STATE_IDLE;
            charHdl = 0;
            procedureInProgress = FALSE;
            keyPressConnOpt = DISCONNECT;
            scanIdx = -1;
    
            // Cancel RSSI reads
            SimpleCentral_CancelRssi(pEvent->linkTerminate.connectionHandle);
    
            Display_print0(dispHandle, 2, 0, "Disconnected");
            Display_print1(dispHandle, 3, 0, "Reason: %d", pEvent->linkTerminate.reason);
            Display_clearLine(dispHandle, 4);
            Display_clearLine(dispHandle, 6);
    
            // Prompt user to begin scanning.
            Display_print0(dispHandle, 5, 0, "Discover ->");
          }
          break;
    
        case GAP_LINK_PARAM_UPDATE_EVENT:
          {
            Display_print1(dispHandle, 2, 0, "Param Update: %d", pEvent->linkUpdate.status);
          }
          break;
    
        default:
          break;
      }
    }
    #endif
    /*********************************************************************
     * @fn      SimpleCentral_handleKeys
     *
     * @brief   Handles all key events for this device.
     *
     * @param   shift - true if in shift/alt.
     * @param   keys - bit field for key events. Valid entries:
     *                 HAL_KEY_SW_2
     *                 HAL_KEY_SW_1
     *
     * @return  none
     */
    
    #ifndef FMCU_APP
    static void SimpleCentral_handleKeys(uint8_t shift, uint8_t keys)
    {
      hciActiveConnInfo_t *pConnInfo; // pointer to hold return connection information
      (void)shift;  // Intentionally unreferenced parameter
    
      if (keys & KEY_LEFT)
      {
        // If not connected
        if (state == BLE_STATE_IDLE)
        {
          // If not currently scanning
          if (!scanningStarted)
          {
            // Increment index of current result.
            scanIdx++;
    
            // If there are no scanned devices
            if (scanIdx >= scanRes)
            {
              // Prompt the user to begin scanning again.
              scanIdx = -1;
              Display_print0(dispHandle, 2, 0, "");
              Display_print0(dispHandle, 3, 0, "");
              Display_print0(dispHandle, 5, 0, "Discover ->");
            }
            else
            {
              //Display the indexed scanned device.
              Display_print1(dispHandle, 2, 0, "Device %d", (scanIdx + 1));
              Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(devList[scanIdx].addr));
              Display_print0(dispHandle, 5, 0, "Connect ->");
              Display_print0(dispHandle, 6, 0, "<- Next Option");
            }
          }
        }
        else if (state == BLE_STATE_CONNECTED)
        {
          keyPressConnOpt = (keyPressConnOpt == DISCONNECT) ? GATT_RW :
                                              (keyPressConnOpt_t) (keyPressConnOpt + 1);
    
          //clear excess lines to keep display clean if another option chosen
          Display_doClearLines(dispHandle, 7, 16);
    
          switch (keyPressConnOpt)
          {
            case GATT_RW:
              Display_print0(dispHandle, 5, 0, "GATT Read/Write ->");
              break;
    
            case RSSI:
              Display_print0(dispHandle, 5, 0, "Toggle Read RSSI ->");
              break;
    
            case CONN_UPDATE:
              Display_print0(dispHandle, 5, 0, "Connection Update ->");
              break;
    
            case GET_CONN_INFO:
              Display_print0(dispHandle, 5, 0, "Connection Info ->");
              break;
    
            case DISCONNECT:
              Display_print0(dispHandle, 5, 0, "Disconnect ->");
              break;
    
            default:
              break;
          }
    
          Display_print0(dispHandle, 6, 0, "<- Next Option");
        }
    
        return;
      }
    
      if (keys & KEY_RIGHT)
      {
        if (state == BLE_STATE_IDLE)
        {
          if (scanIdx == -1)
          {
            if (!scanningStarted)
            {
              scanningStarted = TRUE;
              scanRes = 0;
    
              Display_print0(dispHandle, 2, 0, "Discovering...");
              Display_print0(dispHandle, 3, 0, "");
              Display_print0(dispHandle, 4, 0, "");
              Display_print0(dispHandle, 5, 0, "");
              Display_print0(dispHandle, 6, 0, "");
    
              GAPCentralRole_StartDiscovery(DEFAULT_DISCOVERY_MODE,
                                            DEFAULT_DISCOVERY_ACTIVE_SCAN,
                                            DEFAULT_DISCOVERY_WHITE_LIST);
            }
          }
          // Connect if there is a scan result
          else
          {
            // connect to current device in scan result
            uint8_t *peerAddr = devList[scanIdx].addr;
            uint8_t addrType = devList[scanIdx].addrType;
    
            state = BLE_STATE_CONNECTING;
    
            // Set a timelimit on the connection establishement
            Util_startClock(&startLinkEstClock);
    
            GAPCentralRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
                                         DEFAULT_LINK_WHITE_LIST,
                                         addrType, peerAddr);
    
    //        GAPCentralRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
    //                                                 DEFAULT_LINK_WHITE_LIST,
    //                                                 ADDRTYPE_PUBLIC, Local_Address);
    
            Display_print0(dispHandle, 2, 0, "Connecting");
            Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddr));
            Display_clearLine(dispHandle, 4);
    
            // Forget the scan results.
            scanRes = 0;
            scanIdx = -1;
          }
        }
        else if (state == BLE_STATE_CONNECTED)
        {
          switch (keyPressConnOpt)
          {
            case GATT_RW:
                Display_print0(dispHandle, 6, 0, "Inside GATT_RW");
           if (charHdl != 0 && procedureInProgress == FALSE)
              {
                Display_print0(dispHandle, 6, 0, "Inside charHdl and procedureInProgress ");
                uint8_t status;
    
                // Do a read or write as long as no other read or write is in progress
               if (doWrite)
                {
                 Display_print0(dispHandle, 7, 0, "Inside doWrite ");
                  // Do a write
                  attWriteReq_t req;
    
                  req.pValue = GATT_bm_alloc(connHandle, ATT_WRITE_REQ, 1, NULL);
                if ( req.pValue != NULL )
                 //if (var_Count <=9 )
                  {
                    //TODO
                    req.handle = charHdl;
                    req.len = 1;
                   // var_Count[0] = charVal;
    //                req.pValue[0] = LeadMe_Cmd[var_Count];
                    req.pValue[0]=charVal;
                    req.sig = 0;
                    req.cmd = 0;
                    //var_Count++;
                    Display_print0(dispHandle, 8, 0, "Going to read ");
                    status = GATT_WriteCharValue(connHandle, &req, selfEntity);
    
                    if ( status != SUCCESS )
                    {
                      Display_print0(dispHandle, 8, 0, " GATT Write not success ");
                      GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
                    }
                  }
                  else
                  {
                    Display_print0(dispHandle, 8, 0, " bleMemAllocError  ");
                    status = bleMemAllocError;
                  }
                }
           else
                {
                   //Do a read
                  attReadReq_t req;
    
                  Display_print0(dispHandle, 8, 0, " inside read ");
                  req.handle = charHdl;
                  status = GATT_ReadCharValue(connHandle, &req, selfEntity);
                }
    
                if (status == SUCCESS)
                {
                  Display_print0(dispHandle, 8, 0, " status == SUCCESS ");
                  procedureInProgress = TRUE;
                  doWrite = !doWrite;
                }
              }
              break;
    
            case RSSI:
              // Start or cancel RSSI polling
              if (SimpleCentral_RssiFind(connHandle) == NULL)
              {
                SimpleCentral_StartRssi(connHandle, DEFAULT_RSSI_PERIOD);
              }
              else
              {
                SimpleCentral_CancelRssi(connHandle);
    
                Display_print0(dispHandle, 4, 0, "RSSI Cancelled");
              }
              break;
    
            case CONN_UPDATE:
               // Connection update
               GAPCentralRole_UpdateLink(connHandle,
                                         DEFAULT_UPDATE_MIN_CONN_INTERVAL,
                                         DEFAULT_UPDATE_MAX_CONN_INTERVAL,
                                         DEFAULT_UPDATE_SLAVE_LATENCY,
                                         DEFAULT_UPDATE_CONN_TIMEOUT);
               break;
    
            case GET_CONN_INFO:
                 pConnInfo= ICall_malloc(sizeof(hciActiveConnInfo_t));
    
              if (pConnInfo != NULL)
              {
                // This is hard coded to assume we want connection info for a single
                // valid connection as is the normal use case for simple central.
                // A full featured application may chose to use HCI_EXT_GetConnInfoCmd()
                // to obtain a full list of all active connections and their connId's
                // to retrive more specific conneciton information if more than one
                // valid connectin is expected to exist.
                HCI_EXT_GetActiveConnInfoCmd(0, pConnInfo);
                Display_print1(dispHandle, 7, 0, "AccessAddress: 0x%x", pConnInfo->accessAddr);
                Display_print1(dispHandle, 8, 0, "Connection Interval: %d", pConnInfo->connInterval);
                Display_print3(dispHandle, 9, 0, "HopVal:%d, nxtCh:%d, mSCA:%d", \
                               pConnInfo->hopValue, pConnInfo->nextChan, \
                               pConnInfo->mSCA);
                Display_print5(dispHandle, 10, 0, "ChanMap: \"%x:%x:%x:%x:%x\"",\
                               pConnInfo->chanMap[4], pConnInfo->chanMap[3],\
                               pConnInfo->chanMap[2], pConnInfo->chanMap[1],\
                               pConnInfo->chanMap[0]);
    
                ICall_free(pConnInfo);
              }
              else
              {
                Display_print0(dispHandle, 4, 0, "ERROR: Failed to allocate memory for return connection information");
              }
              break;
    
            case DISCONNECT:
              state = BLE_STATE_DISCONNECTING;
    
              GAPCentralRole_TerminateLink(connHandle);
    
              Display_print0(dispHandle, 2, 0, "Disconnecting");
              Display_print0(dispHandle, 3, 0, "");
              Display_print0(dispHandle, 4, 0, "");
              Display_print0(dispHandle, 5, 0, "");
    
              keyPressConnOpt = GATT_RW;
              break;
    
            default:
              break;
          }
        }
    
        return;
      }
    }
    
    #endif
    
    /*********************************************************************
     * @fn      SimpleCentral_processGATTMsg
     *
     * @brief   Process GATT messages and events.
     *
     * @return  none
     */
    #ifdef FMCU_APP
    
    static void SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg)
    {//Todo
      if (state == BLE_STATE_CONNECTED)
      {
        // See if GATT server was unable to transmit an ATT response
        if (pMsg->hdr.status == blePending)
        {
          // No HCI buffer was available. App can try to retransmit the response
          // on the next connection event. Drop it for now.
          Display_print1(dispHandle, 4, 0, "ATT Rsp dropped %d", pMsg->method);
        }
        else if ((pMsg->method == ATT_READ_RSP)   ||
                 ((pMsg->method == ATT_ERROR_RSP) &&
                  (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
        {
          if (pMsg->method == ATT_ERROR_RSP)
          {
            Display_print1(dispHandle, 4, 0, "Read Error %d", pMsg->msg.errorRsp.errCode);
          }
          else
          {
            // After a successful read, display the read value
            Display_print1(dispHandle, 4, 0, "Read rsp: %d", pMsg->msg.readRsp.pValue[0]);
          }
    
          procedureInProgress = FALSE;
        }
        else if ((pMsg->method == ATT_WRITE_RSP)  ||
                 ((pMsg->method == ATT_ERROR_RSP) &&
                  (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
        {
          if (pMsg->method == ATT_ERROR_RSP)
          {
            Display_print1(dispHandle, 4, 0, "Write Error %d", pMsg->msg.errorRsp.errCode);
          }
          else
          {
            // After a successful write, display the value that was written and
            // increment value
              //  Display_print1(dispHandle, 4, 0, "Write sent: %d", LeadMe_Cmd[var_Count]);
             Display_print1(dispHandle, 4, 0, "Write sent: %d", charVal++);
    
             PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 1);
             uint32_t sleepUs = 500000;
             Task_sleep(sleepUs / Clock_tickPeriod);
             PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
    
             procedureInProgress = FALSE;//added 2:02pm
    
          }
    
          procedureInProgress = FALSE;
    
        }
        else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
        {
          // ATT request-response or indication-confirmation flow control is
          // violated. All subsequent ATT requests or indications will be dropped.
          // The app is informed in case it wants to drop the connection.
    
          // Display the opcode of the message that caused the violation.
          Display_print1(dispHandle, 4, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
        }
        else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
        {
          // MTU size updated
          Display_print1(dispHandle, 4, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
        }
        else if (discState != BLE_DISC_STATE_IDLE)
        {
          SimpleCentral_processGATTDiscEvent(pMsg);
        }
      } // else - in case a GATT message came after a connection has dropped, ignore it.
    
      // Needed only for ATT Protocol messages
      GATT_bm_free(&pMsg->msg, pMsg->method);
    }
    #else
    static void SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg)
    {
      if (state == BLE_STATE_CONNECTED)
      {
        // See if GATT server was unable to transmit an ATT response
        if (pMsg->hdr.status == blePending)
        {
          // No HCI buffer was available. App can try to retransmit the response
          // on the next connection event. Drop it for now.
          Display_print1(dispHandle, 4, 0, "ATT Rsp dropped %d", pMsg->method);
        }
        else if ((pMsg->method == ATT_READ_RSP)   ||
                 ((pMsg->method == ATT_ERROR_RSP) &&
                  (pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
        {
          if (pMsg->method == ATT_ERROR_RSP)
          {
            Display_print1(dispHandle, 4, 0, "Read Error %d", pMsg->msg.errorRsp.errCode);
          }
          else
          {
            // After a successful read, display the read value
            Display_print1(dispHandle, 4, 0, "Read rsp: %d", pMsg->msg.readRsp.pValue[0]);
          }
    
          procedureInProgress = FALSE;
        }
        else if ((pMsg->method == ATT_WRITE_RSP)  ||
                 ((pMsg->method == ATT_ERROR_RSP) &&
                  (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
        {
          if (pMsg->method == ATT_ERROR_RSP)
          {
            Display_print1(dispHandle, 4, 0, "Write Error %d", pMsg->msg.errorRsp.errCode);
          }
          else
          {
            // After a successful write, display the value that was written and
            // increment value
              //  Display_print1(dispHandle, 4, 0, "Write sent: %d", LeadMe_Cmd[var_Count]);
             Display_print1(dispHandle, 4, 0, "Write sent: %d", charVal++);
    
             procedureInProgress = FALSE;//added 2:02pm
              //TODo
          }
    
          procedureInProgress = FALSE;
    
        }
        else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
        {
          // ATT request-response or indication-confirmation flow control is
          // violated. All subsequent ATT requests or indications will be dropped.
          // The app is informed in case it wants to drop the connection.
    
          // Display the opcode of the message that caused the violation.
          Display_print1(dispHandle, 4, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
        }
        else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
        {
          // MTU size updated
          Display_print1(dispHandle, 4, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
        }
        else if (discState != BLE_DISC_STATE_IDLE)
        {
          SimpleCentral_processGATTDiscEvent(pMsg);
        }
      } // else - in case a GATT message came after a connection has dropped, ignore it.
    
      // Needed only for ATT Protocol messages
      GATT_bm_free(&pMsg->msg, pMsg->method);
    }
    #endif
    
    /*********************************************************************
     * @fn      SimpleCentral_processCmdCompleteEvt
     *
     * @brief   Process an incoming OSAL HCI Command Complete Event.
     *
     * @param   pMsg - message to process
     *
     * @return  none
     */
    static void SimpleCentral_processCmdCompleteEvt(hciEvt_CmdComplete_t *pMsg)
    {
      switch (pMsg->cmdOpcode)
      {
        case HCI_READ_RSSI:
          {
    #ifndef Display_DISABLE_ALL
            int8 rssi = (int8)pMsg->pReturnParam[3];
    
            Display_print1(dispHandle, 4, 0, "RSSI dB: %d", (uint32_t)(rssi));
    #endif
          }
          break;
    
        default:
          break;
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_StartRssi
     *
     * @brief   Start periodic RSSI reads on a link.
     *
     * @param   connHandle - connection handle of link
     * @param   period - RSSI read period in ms
     *
     * @return  SUCCESS: Terminate started
     *          bleIncorrectMode: No link
     *          bleNoResources: No resources
     */
    static bStatus_t SimpleCentral_StartRssi(uint16_t connHandle, uint16_t period)
    {
      readRssi_t *pRssi;
    
      // Verify link is up
      if (!linkDB_Up(connHandle))
      {
        return bleIncorrectMode;
      }
    
      // If already allocated
      if ((pRssi = SimpleCentral_RssiFind(connHandle)) != NULL)
      {
        // Stop timer
        Util_stopClock(pRssi->pClock);
    
        pRssi->period = period;
      }
      // Allocate structure
      else if ((pRssi = SimpleCentral_RssiAlloc(connHandle)) != NULL)
      {
        pRssi->period = period;
      }
      // Allocate failed
      else
      {
        return bleNoResources;
      }
    
      // Start timer
      Util_restartClock(pRssi->pClock, period);
    
      return SUCCESS;
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_CancelRssi
     *
     * @brief   Cancel periodic RSSI reads on a link.
     *
     * @param   connHandle - connection handle of link
     *
     * @return  SUCCESS: Operation successful
     *          bleIncorrectMode: No link
     */
    static bStatus_t SimpleCentral_CancelRssi(uint16_t connHandle)
    {
      readRssi_t *pRssi;
    
      if ((pRssi = SimpleCentral_RssiFind(connHandle)) != NULL)
      {
        // Stop timer
        Util_stopClock(pRssi->pClock);
    
        // Free RSSI structure
        SimpleCentral_RssiFree(connHandle);
    
        return SUCCESS;
      }
    
      // Not found
      return bleIncorrectMode;
    }
    
    /*********************************************************************
     * @fn      gapCentralRole_RssiAlloc
     *
     * @brief   Allocate an RSSI structure.
     *
     * @param   connHandle - Connection handle
     *
     * @return  pointer to structure or NULL if allocation failed.
     */
    static readRssi_t *SimpleCentral_RssiAlloc(uint16_t connHandle)
    {
      uint8_t i;
    
      // Find free RSSI structure
      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      {
        if (readRssi[i].connHandle == GAP_CONNHANDLE_ALL)
        {
          readRssi_t *pRssi = &readRssi[i];
    
          pRssi->pClock = (Clock_Struct *)ICall_malloc(sizeof(Clock_Struct));
          if (pRssi->pClock)
          {
            Util_constructClock(pRssi->pClock, SimpleCentral_readRssiHandler,
                                0, 0, false, i);
            pRssi->connHandle = connHandle;
    
            return pRssi;
          }
        }
      }
    
      // No free structure found
      return NULL;
    }
    
    /*********************************************************************
     * @fn      gapCentralRole_RssiFind
     *
     * @brief   Find an RSSI structure.
     *
     * @param   connHandle - Connection handle
     *
     * @return  pointer to structure or NULL if not found.
     */
    static readRssi_t *SimpleCentral_RssiFind(uint16_t connHandle)
    {
      uint8_t i;
    
      // Find free RSSI structure
      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      {
        if (readRssi[i].connHandle == connHandle)
        {
          return &readRssi[i];
        }
      }
    
      // Not found
      return NULL;
    }
    
    /*********************************************************************
     * @fn      gapCentralRole_RssiFree
     *
     * @brief   Free an RSSI structure.
     *
     * @param   connHandle - Connection handle
     *
     * @return  none
     */
    static void SimpleCentral_RssiFree(uint16_t connHandle)
    {
      uint8_t i;
    
      // Find RSSI structure
      for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
      {
        if (readRssi[i].connHandle == connHandle)
        {
          readRssi_t *pRssi = &readRssi[i];
          if (pRssi->pClock)
          {
            Clock_destruct(pRssi->pClock);
    
            // Free clock struct
            ICall_free(pRssi->pClock);
            pRssi->pClock = NULL;
          }
    
          pRssi->connHandle = GAP_CONNHANDLE_ALL;
          break;
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_processPairState
     *
     * @brief   Process the new paring state.
     *
     * @return  none
     */
    static void SimpleCentral_processPairState(uint8_t state, uint8_t status)
    {
      if (state == GAPBOND_PAIRING_STATE_STARTED)
      {
        Display_print0(dispHandle, 2, 0, "Pairing started");
      }
      else if (state == GAPBOND_PAIRING_STATE_COMPLETE)
      {
        if (status == SUCCESS)
        {
          Display_print0(dispHandle, 2, 0, "Pairing success");
        }
        else
        {
          Display_print1(dispHandle, 2, 0, "Pairing fail: %d", status);
        }
      }
      else if (state == GAPBOND_PAIRING_STATE_BONDED)
      {
        if (status == SUCCESS)
        {
          Display_print0(dispHandle, 2, 0, "Bonding success");
        }
      }
      else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED)
      {
        if (status == SUCCESS)
        {
          Display_print0(dispHandle, 2, 0, "Bond save success");
        }
        else
        {
          Display_print1(dispHandle, 2, 0, "Bond save failed: %d", status);
        }
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_processPasscode
     *
     * @brief   Process the Passcode request.
     *
     * @return  none
     */
    static void SimpleCentral_processPasscode(uint16_t connectionHandle,
                                                 uint8_t uiOutputs)
    {
      // This app uses a default passcode. A real-life scenario would handle all
      // pairing scenarios and likely generate this randomly.
      uint32_t passcode = B_APP_DEFAULT_PASSCODE;
    
      // Display passcode to user
      if (uiOutputs != 0)
      {
        Display_print1(dispHandle, 4, 0, "Passcode: %d", passcode);
      }
    
      // Send passcode response
      GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_startDiscovery
     *
     * @brief   Start service discovery.
     *
     * @return  none
     */
    static void SimpleCentral_startDiscovery(void)
    {
      attExchangeMTUReq_t req;
    
      // Initialize cached handles
      svcStartHdl = svcEndHdl = charHdl = 0;
    
      discState = BLE_DISC_STATE_MTU;
    
      // Discover GATT Server's Rx MTU size
      req.clientRxMTU = maxPduSize - L2CAP_HDR_SIZE;
    
      // ATT MTU size should be set to the minimum of the Client Rx MTU
      // and Server Rx MTU values
      VOID GATT_ExchangeMTU(connHandle, &req, selfEntity);
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_stopEstablishing
     *
     * @brief   Stop Connection Establishement.
     *
     * @return  none
     */
    static void SimpleCentral_stopEstablishing(void)
    {
      PIN_setOutputValue(ledPinHandle, Board_PIN_RLED, 0);
      GAPCentralRole_TerminateLink(GAP_CONNHANDLE_INIT);
      Display_print0(dispHandle, 4, 0, "Conn. Establishement Timeout");
      state = BLE_STATE_IDLE;
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_processGATTDiscEvent
     *
     * @brief   Process GATT discovery event
     *
     * @return  none
     */
    static void SimpleCentral_processGATTDiscEvent(gattMsgEvent_t *pMsg)
    {
      if (discState == BLE_DISC_STATE_MTU)
      {
        // MTU size response received, discover simple service
        if (pMsg->method == ATT_EXCHANGE_MTU_RSP)
        {
            uint8_t status = 10;
    
    #ifdef FMCU_128Bit
            uint8_t uuid[ATT_UUID_SIZE] = { simpleProfileServUUID };
    #else
           uint8_t uuid[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_SERV_UUID),
                                              HI_UINT16(SIMPLEPROFILE_SERV_UUID) };
    #endif
    
    
          // Just in case we're using the default MTU size (23 octets)
          Display_print1(dispHandle, 4, 0, "MTU Size: %d", ATT_MTU_SIZE);
    
          discState = BLE_DISC_STATE_SVC;
    #ifdef FMCU_128Bit
          status = GATT_DiscPrimaryServiceByUUID(connHandle, uuid, ATT_UUID_SIZE,selfEntity);
    #else
          status = GATT_DiscPrimaryServiceByUUID(connHandle, uuid, ATT_BT_UUID_SIZE,selfEntity);
    #endif
          if(status == SUCCESS)
              {
               Display_print1(dispHandle, 8, 0, "GATT_DiscPrimaryServiceByUUID %d ",status);
               status=10;
              }
    
          // Discovery simple service
         // VOID GATT_DiscPrimaryServiceByUUID(connHandle, uuid, ATT_BT_UUID_SIZE,selfEntity);
        }
      }
      else if (discState == BLE_DISC_STATE_SVC)
      {
          Display_print0(dispHandle, 4, 0, "Inside discState == BLE_DISC_STATE_SVC");
        // Service found, store handles
    
          Display_print1(dispHandle, 8, 0, "pMsg->method %d ",pMsg->method);
          if (pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
            pMsg->msg.findByTypeValueRsp.numInfo > 0)
        {
          svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
          svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
        }
          Display_print1(dispHandle, 9, 0, "pMsg->method %d ",pMsg->method);
          Display_print1(dispHandle, 10, 0, "svcStartHdl %d ",svcStartHdl);
          Display_print1(dispHandle, 11, 0, "svcEndHdl %d ",svcEndHdl);
    
        // If procedure complete
        if (((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP) &&
             (pMsg->hdr.status == bleProcedureComplete))  ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          if (svcStartHdl != 0)
          {
            attReadByTypeReq_t req;
    
            // Discover characteristic
            discState = BLE_DISC_STATE_CHAR;
    
            Display_print0(dispHandle, 8, 0, "Discover characteristic ");
    
            req.startHandle = svcStartHdl;
            req.endHandle = svcEndHdl;
    #ifdef FMCU_128Bit
            req.type.len = ATT_UUID_SIZE;
            req.type.uuid[12] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
            req.type.uuid[13] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
    #else
            req.type.len = ATT_BT_UUID_SIZE;
            req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
            req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
    #endif
            VOID GATT_DiscCharsByUUID(connHandle, &req, selfEntity);
           }
        }
      }
      //Todo : ???
      else if (discState == BLE_DISC_STATE_CHAR)
      {
    
          Display_print0(dispHandle, 4, 0, "Inside discState == BLE_DISC_STATE_CHAR");
    
        // Characteristic found, store handle
        if ((pMsg->method == ATT_READ_BY_TYPE_RSP) &&
            (pMsg->msg.readByTypeRsp.numPairs > 0))
        {
          charHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[3],
                                 pMsg->msg.readByTypeRsp.pDataList[4]);
    
         Display_print0(dispHandle, 2, 0, "Simple Svc Found");
         procedureInProgress = FALSE;
        }
    
        discState = BLE_DISC_STATE_IDLE;
      }
      }
    
    #ifdef FMCU_128Bit
    /*********************************************************************
     * @fn      SimpleCentral_findUuid
     *
     * @brief   Find a given UUID in an advertiser's service UUID list.
     *
     * @return  TRUE if service UUID found
     */
    static bool SimpleCentral_findUuid(const uint8_t *uuid, const uint8_t *pManufData ,uint8_t manDataLen ,uint8_t *pData,
                                             uint8_t dataLen)
    {
       uint8_t matchingIdUuid =0;
       uint8_t adLen;
       uint8_t adType;
       uint8_t *pEnd;
    
       pEnd = pData + dataLen - 1;
    
       // while end of data not reached
     while ((dataLen > 0) && (pData <pEnd))
      {
          // Get length of next AD item
          adLen = *pData++;
          if (adLen > 0)
          {
            adType = *pData;
    
            // If AD type is for 128-bit service UUID
            if ((adType == GAP_ADTYPE_128BIT_MORE) ||
                (adType == GAP_ADTYPE_128BIT_COMPLETE))
            {
              pData++;
              adLen--;
    
              // For each UUID in list
              while (adLen >= 2 && pData < pEnd)
              {
                // Check for match
               if(!memcmp(pData,uuid,ATT_UUID_SIZE))
                {
                   matchingIdUuid++;
                }
    
                // Go to next
                pData += 2;
                adLen -= 2;
              }
    
              // Handle possible erroneous extra byte in UUID list
              if (adLen == 1)
              {
                pData++;
              }
            }
    
            if(adType== GAP_ADTYPE_MANUFACTURER_SPECIFIC)
            {
               uint8_t len = adLen;
               if(manDataLen < len)
               {
                   len = manDataLen;
               }
               // Check for match
             if(memcmp(pManufData,pData,len))
              {
               matchingIdUuid++;
              }
            }
    
    
        if(matchingIdUuid<2) // 2 when we are cheking manuf data
              {
                // Go to next item
                pData += adLen;
              }
        else
            {
              return TRUE;
            }
          }
        }
    
      // Match not found
      return FALSE;
    }
    
    #else
    static bool SimpleCentral_findUuid(const uint8_t *uuid, const uint8_t *pManufData ,uint8_t manDataLen ,uint8_t *pData,
                                             uint8_t dataLen)
    {
       uint8_t matchingIdUuid =0;
       uint8_t adLen;
       uint8_t adType;
       uint8_t *pEnd;
    
       pEnd = pData + dataLen - 1;
    
       // while end of data not reached
     while ((dataLen > 0) && (pData <pEnd))
      {
          // Get length of next AD item
          adLen = *pData++;
          if (adLen > 0)
          {
            adType = *pData;
    
            // If AD type is for 16-bit service UUID
            if ((adType == GAP_ADTYPE_16BIT_MORE) ||
                (adType == GAP_ADTYPE_16BIT_COMPLETE))
            {
              pData++;
              adLen--;
    
              // For each UUID in list
              while (adLen >= 2 && pData < pEnd)
              {
                // Check for match
               if(!memcmp(pData,uuid,ATT_BT_UUID_SIZE))
                {
                   matchingIdUuid++;
                }
    
                // Go to next
                pData += 2;
                adLen -= 2;
              }
    
              // Handle possible erroneous extra byte in UUID list
              if (adLen == 1)
              {
                pData++;
              }
            }
    
            if(adType== GAP_ADTYPE_MANUFACTURER_SPECIFIC)
            {
               uint8_t len = adLen;
               if(manDataLen < len)
               {
                   len = manDataLen;
               }
               // Check for match
             if(memcmp(pManufData,pData,len))
              {
               matchingIdUuid++;
              }
            }
    
    
        if(matchingIdUuid<2) // 2 when we are cheking manuf data
              {
                // Go to next item
                pData += adLen;
              }
        else
            {
              return TRUE;
            }
          }
        }
    
      // Match not found
      return FALSE;
    }
    
    //static bool SimpleCentral_findSvcUuid(uint16_t uuid, uint8_t *pData,
    //                                         uint8_t dataLen)
    //{
    //  uint8_t adLen;
    //  uint8_t adType;
    //  uint8_t *pEnd;
    //
    //  if (dataLen > 0)
    //  {
    //    pEnd = pData + dataLen - 1;
    //
    //    // While end of data not reached
    //    while (pData < pEnd)
    //    {
    //      // Get length of next AD item
    //      adLen = *pData++;
    //      if (adLen > 0)
    //      {
    //        adType = *pData;
    //
    //        // If AD type is for 16-bit service UUID
    //        if ((adType == GAP_ADTYPE_16BIT_MORE) ||
    //            (adType == GAP_ADTYPE_16BIT_COMPLETE))
    //        {
    //          pData++;
    //          adLen--;
    //
    //          // For each UUID in list
    //          while (adLen >= 2 && pData < pEnd)
    //          {
    //            // Check for match
    //            if ((pData[0] == LO_UINT16(uuid)) && (pData[1] == HI_UINT16(uuid)))
    //            {
    //              // Match found
    //              return TRUE;
    //            }
    //
    //            // Go to next
    //            pData += 2;
    //            adLen -= 2;
    //          }
    //
    //          // Handle possible erroneous extra byte in UUID list
    //          if (adLen == 1)
    //          {
    //            pData++;
    //          }
    //        }
    //        else
    //        {
    //          // Go to next item
    //          pData += adLen;
    //        }
    //      }
    //    }
    //  }
    //
    //  // Match not found
    //  return FALSE;
    //}
    #endif
    
    /*********************************************************************
     * @fn      SimpleCentral_addDeviceInfo
     *
     * @brief   Add a device to the device discovery result list
     *
     * @return  none
     */
    static void SimpleCentral_addDeviceInfo(uint8_t *pAddr, uint8_t addrType)
    {
      uint8_t i;
    
      // If result count not at max
      if (scanRes < DEFAULT_MAX_SCAN_RES)
      {
        // Check if device is already in scan results
        for (i = 0; i < scanRes; i++)
        {
          if (memcmp(pAddr, devList[i].addr , B_ADDR_LEN) == 0)
          {
            return;
          }
        }
    
        // Add addr to scan result list
        memcpy(devList[scanRes].addr, pAddr, B_ADDR_LEN);
        devList[scanRes].addrType = addrType;
    
        // Increment scan result count
        scanRes++;
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_eventCB
     *
     * @brief   Central event callback function.
     *
     * @param   pEvent - pointer to event structure
     *
     * @return  TRUE if safe to deallocate event message, FALSE otherwise.
     */
    static uint8_t SimpleCentral_eventCB(gapCentralRoleEvent_t *pEvent)
    {
      // Forward the role event to the application
      if (SimpleCentral_enqueueMsg(SBC_STATE_CHANGE_EVT,
                                      SUCCESS, (uint8_t *)pEvent))
      {
        // App will process and free the event
        return FALSE;
      }
    
      // Caller should free the event
      return TRUE;
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_pairStateCB
     *
     * @brief   Pairing state callback.
     *
     * @return  none
     */
    static void SimpleCentral_pairStateCB(uint16_t connHandle, uint8_t state,
                                             uint8_t status)
    {
      uint8_t *pData;
    
      // Allocate space for the event data.
      if ((pData = ICall_malloc(sizeof(uint8_t))))
      {
        *pData = status;
    
        // Queue the event.
        SimpleCentral_enqueueMsg(SBC_PAIRING_STATE_EVT, state, pData);
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_passcodeCB
     *
     * @brief   Passcode callback.
     *
     * @return  none
     */
    static void SimpleCentral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,
                                         uint8_t uiInputs, uint8_t uiOutputs,
                                         uint32_t numComparison)
    {
      uint8_t *pData;
    
      // Allocate space for the passcode event.
      if ((pData = ICall_malloc(sizeof(uint8_t))))
      {
        *pData = uiOutputs;
    
        // Enqueue the event.
        SimpleCentral_enqueueMsg(SBC_PASSCODE_NEEDED_EVT, 0, pData);
      }
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_linkEstClockHandler
     *
     * @brief   Clock handler function
     *
     * @param   a0 - ignored
     *
     * @return  none
     */
    void SimpleCentral_linkEstClockHandler(UArg a0)
    {
      Event_post(syncEvent, SBC_CONN_EST_TIMEOUT_EVT);
    }
    
    //void SimpleCentral_DisconnectClockHandler(UArg a0)
    //{//todo
    //  Display_print0(dispHandle, 2, 0, "SimpleCentral_DisconnectClockHandler");
    //  Diconnect_Flag=10;
    //  // GAPCentralRole_TerminateLink(connHandle);
    //  // Event_post(syncEvent, Keyfob_EST_TIMEOUT_EVT);
    //}
    
    /*********************************************************************
     * @fn      SimpleCentral_startDiscHandler
     *
     * @brief   Clock handler function
     *
     * @param   a0 - ignored
     *
     * @return  none
     */
    void SimpleCentral_startDiscHandler(UArg a0)
    {
      Event_post(syncEvent, SBC_START_DISCOVERY_EVT);
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_keyChangeHandler
     *
     * @brief   Key event handler function
     *
     * @param   a0 - ignored
     *
     * @return  none
     */
    void SimpleCentral_keyChangeHandler(uint8 keys)
    {
      SimpleCentral_enqueueMsg(SBC_KEY_CHANGE_EVT, keys, NULL);
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_readRssiHandler
     *
     * @brief   Read RSSI handler function
     *
     * @param   a0 - read RSSI index
     *
     * @return  none
     */
    void SimpleCentral_readRssiHandler(UArg a0)
    {
      SimpleCentral_enqueueMsg(SBC_RSSI_READ_EVT, SUCCESS,
                                  (uint8_t *)&readRssi[a0]);
    }
    
    /*********************************************************************
     * @fn      SimpleCentral_enqueueMsg
     *
     * @brief   Creates a message and puts the message in RTOS queue.
     *
     * @param   event - message event.
     * @param   state - message state.
     * @param   pData - message data pointer.
     *
     * @return  TRUE or FALSE
     */
    static uint8_t SimpleCentral_enqueueMsg(uint8_t event, uint8_t state,
                                               uint8_t *pData)
    {
      sbcEvt_t *pMsg = ICall_malloc(sizeof(sbcEvt_t));
    
      // Create dynamic pointer to message.
      if (pMsg)
      {
        pMsg->hdr.event = event;
        pMsg->hdr.state = state;
        pMsg->pData = pData;
    
        // Enqueue the message.
        return Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);
      }
    
      return FALSE;
    }
    
    /*********************************************************************
    *********************************************************************/
    
    /******************************************************************************
    
     @file  simple_gatt_profile.c
    
     @brief This file contains the Simple GATT profile sample GATT service profile
            for use with the BLE sample application.
    
     Group: WCS, BTS
     Target Device: cc2640r2
    
     ******************************************************************************
     
     Copyright (c) 2010-2021, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
     ******************************************************************************
     
     
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    #include <icall.h>
    #include "util.h"
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "simple_gatt_profile.h"
    
    /*********************************************************************
     * MACROS
     */
    
    /*********************************************************************
     * CONSTANTS
     */
    
    #define SERVAPP_NUM_ATTR_SUPPORTED        17
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    
    //TODO : Change Macro
    //#define FMCU_128BIT_UUID
    
    #ifdef FMCU_128BIT_UUID
    *************************************************************/
    // Simple GATT Profile Service UUID: 0xFFF0
    CONST uint8 simpleProfileServUUID[ATT_UUID_SIZE] =
    {
     SIMPLEPROFILE_SERV_UUID_BASE128(SIMPLEPROFILE_SERV_UUID)
    };
    
    #else /********** NORMAL **************/
    
    // Simple GATT Profile Service UUID: 0xFFF0
    CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
    };
    
    #endif
    
    /*********************************************************************
     * EXTERNAL VARIABLES
     */
    
    /*********************************************************************
     * EXTERNAL FUNCTIONS
     */
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;
    
    /*********************************************************************
     * Profile Attributes - variables
     */
    
    
    // Simple Profile Service attribute
    #ifdef FMCU_128BIT_UUID
       static CONST gattAttrType_t simpleProfileService = { ATT_UUID_SIZE, simpleProfileServUUID };
    #else
       static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };
    #endif
    
    // Simple Profile Characteristic 1 Properties
    static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE;
    
    // Characteristic 1 Value
    static uint8 simpleProfileChar1 = 0;
    // Characteristic "Stream" Value variable
    
    //static uint8_t ds_StreamVal[DS_STREAM_LEN] = {0};
    
    
    // Simple Profile Characteristic 1 User Description
    static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1";
    
    
    
    /*********************************************************************
     * Profile Attributes - Table
     */
    #ifdef FMCU_128BIT_UUID
    static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
    {
      // Simple Profile Service
      {
        { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
        GATT_PERMIT_READ,                         /* permissions */
        0,                                        /* handle */
        (uint8 *)&simpleProfileService            /* pValue */
      },
    
        // Characteristic 1 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ ,
          0,
          &simpleProfileChar1Props
        },
    
          // Characteristic Value 1
          {
            { ATT_UUID_SIZE, simpleProfilechar1UUID },
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            &simpleProfileChar1
          },
    
          // Characteristic 1 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_READ,
            0,
            simpleProfileChar1UserDesp
          },
    
    };
    
    #else
    
    static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
    {
      // Simple Profile Service
      {
        { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
        GATT_PERMIT_READ,                         /* permissions */
        0,                                        /* handle */
        (uint8 *)&simpleProfileService            /* pValue */
      },
    
        // Characteristic 1 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &simpleProfileChar1Props
        },
    
          // Characteristic Value 1
          {
            { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            &simpleProfileChar1
          },
    
          // Characteristic 1 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_READ,
            0,
            simpleProfileChar1UserDesp
          },
    
    
    };
    #endif
    
    
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                              gattAttribute_t *pAttr,
                                              uint8_t *pValue, uint16_t *pLen,
                                              uint16_t offset, uint16_t maxLen,
                                              uint8_t method);
    static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                               gattAttribute_t *pAttr,
                                               uint8_t *pValue, uint16_t len,
                                               uint16_t offset, uint8_t method);
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // Simple Profile Service Callbacks
    // Note: When an operation on a characteristic requires authorization and
    // pfnAuthorizeAttrCB is not defined for that characteristic's service, the
    // Stack will report a status of ATT_ERR_UNLIKELY to the client.  When an
    // operation on a characteristic requires authorization the Stack will call
    // pfnAuthorizeAttrCB to check a client's authorization prior to calling
    // pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be
    // made within these functions.
    CONST gattServiceCBs_t simpleProfileCBs =
    {
      simpleProfile_ReadAttrCB,  // Read callback function pointer
      simpleProfile_WriteAttrCB, // Write callback function pointer
      NULL                       // Authorization callback function pointer
    };
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      SimpleProfile_AddService
     *
     * @brief   Initializes the Simple Profile service by registering
     *          GATT attributes with the GATT server.
     *
     * @param   services - services to add. This is a bit map and can
     *                     contain more than one service.
     *
     * @return  Success or Failure
     */
    bStatus_t SimpleProfile_AddService( uint32 services )
    {
      uint8 status;
    
      // Allocate Client Characteristic Configuration table
      simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
                                                                linkDBNumConns );
      if ( simpleProfileChar4Config == NULL )
      {
        return ( bleMemAllocError );
      }
    
      // Initialize Client Characteristic Configuration attributes
      GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar4Config );
    
      if ( services & SIMPLEPROFILE_SERVICE )
      {
        // Register GATT attribute list and CBs with GATT Server App
        status = GATTServApp_RegisterService( simpleProfileAttrTbl,
                                              GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                              GATT_MAX_ENCRYPT_KEY_SIZE,
                                              &simpleProfileCBs );
      }
      else
      {
        status = SUCCESS;
      }
    
      return ( status );
    }
    
    /*********************************************************************
     * @fn      SimpleProfile_RegisterAppCBs
     *
     * @brief   Registers the application callback function. Only call
     *          this function once.
     *
     * @param   callbacks - pointer to application callbacks.
     *
     * @return  SUCCESS or bleAlreadyInRequestedMode
     */
    bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks )
    {
      if ( appCallbacks )
      {
        simpleProfile_AppCBs = appCallbacks;
    
        return ( SUCCESS );
      }
      else
      {
        return ( bleAlreadyInRequestedMode );
      }
    }
    
    /*********************************************************************
     * @fn      SimpleProfile_SetParameter
     *
     * @brief   Set a Simple Profile parameter.
     *
     * @param   param - Profile parameter ID
     * @param   len - length of data to write
     * @param   value - pointer to data to write.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     *
     * @return  bStatus_t
     */
    bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
    {
      bStatus_t ret = SUCCESS;
    
          if ( len == sizeof ( uint8 ) )
          {
            simpleProfileChar1 = *((uint8*)value);
          }
          else
          {
            ret = bleInvalidRange;
          }
    
    
      return ( ret );
    }
    
    /*********************************************************************
     * @fn      SimpleProfile_GetParameter
     *
     * @brief   Get a Simple Profile parameter.
     *
     * @param   param - Profile parameter ID
     * @param   value - pointer to data to put.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     *
     * @return  bStatus_t
     */
    bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
    {
      bStatus_t ret = SUCCESS;
    
          *((uint8*)value) = simpleProfileChar1;
    
          return ( ret );
    }
    
    /*********************************************************************
     * @fn          simpleProfile_ReadAttrCB
     *
     * @brief       Read an attribute.
     *
     * @param       connHandle - connection message was received on
     * @param       pAttr - pointer to attribute
     * @param       pValue - pointer to data to be read
     * @param       pLen - length of data to be read
     * @param       offset - offset of the first octet to be read
     * @param       maxLen - maximum length of data to be read
     * @param       method - type of read message
     *
     * @return      SUCCESS, blePending or Failure
     */
    static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                              gattAttribute_t *pAttr,
                                              uint8_t *pValue, uint16_t *pLen,
                                              uint16_t offset, uint16_t maxLen,
                                              uint8_t method)
    {
      bStatus_t status = SUCCESS;
    
      // Make sure it's not a blob operation (no attributes in the profile are long)
      if ( offset > 0 )
      {
        return ( ATT_ERR_ATTR_NOT_LONG );
      }
    #ifdef FMCU_128BIT_UUID
      if (pAttr->type.len == ATT_UUID_SIZE) //ATT_BT_UUID_SIZE
      {
        *pLen = 1;
         pValue[0] = *pAttr->pValue;
      }
    #else
      if (pAttr->type.len == ATT_BT_UUID_SIZE) //ATT_BT_UUID_SIZE
      {
        *pLen = 1;
         pValue[0] = *pAttr->pValue;
      }
    #endif
      else
      {
        // 128-bit UUID
        *pLen = 0;
        status = ATT_ERR_INVALID_HANDLE;
      }
    
      return ( status );
    }
    
    /*********************************************************************
     * @fn      simpleProfile_WriteAttrCB
     *
     * @brief   Validate attribute data prior to a write operation
     *
     * @param   connHandle - connection message was received on
     * @param   pAttr - pointer to attribute
     * @param   pValue - pointer to data to be written
     * @param   len - length of data
     * @param   offset - offset of the first octet to be written
     * @param   method - type of write message
     *
     * @return  SUCCESS, blePending or Failure
     */
    static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                               gattAttribute_t *pAttr,
                                               uint8_t *pValue, uint16_t len,
                                               uint16_t offset, uint8_t method)
    {
      bStatus_t status = SUCCESS;
      uint8 notifyApp = 0xFF;
    #ifdef FMCU_128BIT_UUID
        if (pAttr->type.len == ATT_UUID_SIZE)
    #else
        if (pAttr->type.len == ATT_BT_UUID_SIZE)
    #endif
    
      {
    #ifdef FMCU_128BIT_UUID
          // 128-bit UUID
           uint16 uuid = BUILD_UINT16( pAttr->type.uuid[12], pAttr->type.uuid[13]);
    #else
          // 16-bit UUID
           uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
    #endif
          if ( offset == 0 )
            {
              if ( len != 1 )
              {
                status = ATT_ERR_INVALID_VALUE_SIZE;
                Display_print1(dispHandle, 4, 0, "ATT_ERR_INVALID_VALUE_SIZE % d ", status);
              }
            }
            else
            {
              status = ATT_ERR_ATTR_NOT_LONG;
              Display_print1(dispHandle, 4, 0, "ATT_ERR_ATTR_NOT_LONG % d ", status);
            }
    
            //Write the value
            if ( status == SUCCESS )
            {
              uint8 *pCurValue = (uint8 *)pAttr->pValue;
              *pCurValue = pValue[0];
    
              if( pAttr->pValue == &simpleProfileChar1 )
              {
                notifyApp = SIMPLEPROFILE_CHAR1;
              }
              else
              {
                notifyApp = SIMPLEPROFILE_CHAR3;
              }
            }
    
      }
      else
      {
        // 128-bit UUID
        status = ATT_ERR_INVALID_HANDLE;
      }
    
      // If a characteristic value changed then callback function to notify application of change
      if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
      {
        simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
      }
    
      return ( status );
    }
    
    /*********************************************************************
    *********************************************************************/
    

    SDK version : cc2640r2f_4_40_00_010

  • Hi,

    Thank you for reaching out. I have a few questions that will help us resolve this as efficiently as possible. Could you provide the SDK version you are using? In the provided code, can you specify which sections were modified and which remained untouched? If possible, could you provide a diff between the original files and the modified files? Have you taken a look at the following SimpleLink Academy Labs?

    Custom Profile - I believe this one will be the most relevant.

    Connections

    Bluetooth Low Energy Fundamentals

    Best Regards,

    Jan

  • Jan i have already shared all the details .

  • Hi,

    The Custom Profile SLA lab contains a service generator which you can use to implement custom services with custom UUIDs (16 and 128 bit). Can you verify if your implementation matches what is generated by the service generator? How are you attempting to write and read to your device? As a quick test, can you use a BLE Scanner mobile application to connect to the device and to read and write to your desired characteristic?

    Best Regards,

    Jan

  • Hi jan,  i am able to read write with 128bit custom UUID using Mobile app . Please correct if i have implemented it correctly for 128bit UUID , Because i am getting write ERROR  every time . Please suggest me what parameters , i require to update in the simple central  ?

    static void SimpleCentral_processGATTDiscEvent(gattMsgEvent_t *pMsg)
    {
      if (discState == BLE_DISC_STATE_MTU)
      {
        // MTU size response received, discover simple service
        if (pMsg->method == ATT_EXCHANGE_MTU_RSP)
        {
           uint8_t uuid[ATT_UUID_SIZE] = { SIMPLE_SERV_UUID };
    
          // Just in case we're using the default MTU size (23 octets)
          Display_print1(dispHandle, 4, 0, "default MTU Size: %d", ATT_MTU_SIZE);
    
          discState = BLE_DISC_STATE_SVC;
          
          // Discovery simple service
         VOID GATT_DiscPrimaryServiceByUUID(connHandle, uuid, ATT_UUID_SIZE,selfEntity);
         }
      }
      else if (discState == BLE_DISC_STATE_SVC)
      {
          Display_print0(dispHandle, 4, 0, "Inside discState == BLE_DISC_STATE_SVC");
        // Service found, store handles
    
          Display_print1(dispHandle, 8, 0, "pMsg->method %d ",pMsg->method);
          if (pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
            pMsg->msg.findByTypeValueRsp.numInfo > 0)
        {
          svcStartHdl =ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
          svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
        }
          Display_print1(dispHandle, 9, 0, "pMsg->method %d ",pMsg->method);
          Display_print1(dispHandle, 10, 0, "svcStartHdl %d ",svcStartHdl);
          Display_print1(dispHandle, 11, 0, "svcEndHdl %d ",svcEndHdl);
    
        // If procedure complete
        if (((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP) &&
             (pMsg->hdr.status == bleProcedureComplete))  ||
            (pMsg->method == ATT_ERROR_RSP))
        {
          if (svcStartHdl != 0)
          {
            attReadByTypeReq_t req;
    
            // Discover characteristic
            discState = BLE_DISC_STATE_CHAR;
    
            Display_print0(dispHandle, 8, 0, "Discover characteristic ");
    
            req.startHandle = svcStartHdl;
            req.endHandle = svcEndHdl;
    #ifdef FMCU_128bit
            req.type.len = ATT_UUID_SIZE;
            req.type.uuid[0] = 0xAA ;
            req.type.uuid[1] = 0xAA ;
            req.type.uuid[2] = 0xDD ;
            req.type.uuid[3] = 0xCC ;
            req.type.uuid[4] = 0xBB ;
            req.type.uuid[5] = 0xAA ;
            req.type.uuid[6] = 0x34 ;
            req.type.uuid[7] = 0x12 ;
            req.type.uuid[8] = 0x34 ;
            req.type.uuid[9] = 0x12 ;
            req.type.uuid[10] = 0x34 ;
            req.type.uuid[11] = 0x12 ;
            req.type.uuid[12] = 0x01;
            req.type.uuid[13] = 0x20 ;
            req.type.uuid[14] = 0x12 ;
            req.type.uuid[15] = 0x50 ;
            //req.type.uuid[12] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
            //req.type.uuid[13] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
    #else
            req.type.len = ATT_BT_UUID_SIZE;
            req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
            req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
    #endif
           VOID GATT_DiscCharsByUUID(connHandle, &req, selfEntity);
           }
        }
      }
      //Todo : ???
      else if (discState == BLE_DISC_STATE_CHAR)
      {
    
          Display_print0(dispHandle, 4, 0, "Inside discState == BLE_DISC_STATE_CHAR");
    
        // Characteristic found, store handle
        if ((pMsg->method == ATT_READ_BY_TYPE_RSP) &&
            (pMsg->msg.readByTypeRsp.numPairs > 0))
        {
          charHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[12],//3
                                 pMsg->msg.readByTypeRsp.pDataList[13]);//4
    
         Display_print0(dispHandle, 12, 0, "Simple Svc Found");
         procedureInProgress = FALSE;
        }
    
        discState = BLE_DISC_STATE_IDLE;
      }
      }

    The error where i am getting is inside SimpleCentral_processGATTMsg(gattMsgEvent_t *pMsg)() function :

    else if ((pMsg->method == ATT_WRITE_RSP) ||
    ((pMsg->method == ATT_ERROR_RSP) &&
    (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
    {
    if (pMsg->method == ATT_ERROR_RSP)
    {
      Display_print1(dispHandle, 4, 0, "Write Error %d", pMsg->msg.errorRsp.errCode);
    }

  • in simpleGattProfile.c you have a function simpleProfileAttrTable.

    In that function you have the underlying storage for the gatt characteristic you are writing to as this:

    // Characteristic 1 User Description
    {
    { ATT_BT_UUID_SIZE, charUserDescUUID },
    GATT_PERMIT_READ,
    0,
    simpleProfileChar1UserDesp
    },

    Try changing GATT_PERMIT_READ to GATT_PERMIT_READ | GATT_PERMIT_WRITE

  • i tried changing GATT_PERMIT_READ to GATT_PERMIT_READ | GATT_PERMIT_WRITE , but this does not solve my issue ..

  • What could be the possible reason i am getting ( pMsg-<method ==ATT_ERROR_RSP) as true , during each write .

    else if ((pMsg->method == ATT_WRITE_RSP) ||
    ((pMsg->method == ATT_ERROR_RSP) &&
    (pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
    {
    if (pMsg->method == ATT_ERROR_RSP)
    {
    Display_print1(dispHandle, 4, 0, "Write Error %d", pMsg->msg.errorRsp.errCode);
    }

  • Hi,

    Got it. I quickly generated a test service that contains a 128-bit UUID. Can you verify if your code matches the output of the generated code shown below?

    /**********************************************************************************************
     * Filename:       myService.h
     *
     * Description:    This file contains the myService service definitions and
     *                 prototypes.
     *
     * Copyright (c) 2015-2020, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *************************************************************************************************/
    
    
    #ifndef _MYSERVICE_H_
    #define _MYSERVICE_H_
    
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
    /*********************************************************************
     * INCLUDES
     */
    
    /*********************************************************************
    * CONSTANTS
    */
    // Service UUID
    #define MYSERVICE_SERV_UUID 0xC0DE
    
    //  Characteristic defines
    #define MYSERVICE_MYNICECHAR_ID   0
    #define MYSERVICE_MYNICECHAR_UUID 0xBEEF
    #define MYSERVICE_MYNICECHAR_LEN  5
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * MACROS
     */
    
    /*********************************************************************
     * Profile Callbacks
     */
    
    // Callback when a characteristic value has changed
    typedef void (*myServiceChange_t)(uint16_t connHandle, uint16_t svcUuid, uint8_t paramID, uint16_t len, uint8_t *pValue);
    
    typedef struct
    {
      myServiceChange_t        pfnChangeCb;  // Called when characteristic value changes
      myServiceChange_t        pfnCfgChangeCb;
    } myServiceCBs_t;
    
    
    
    /*********************************************************************
     * API FUNCTIONS
     */
    
    
    /*
     * MyService_AddService- Initializes the MyService service by registering
     *          GATT attributes with the GATT server.
     *
     */
    extern bStatus_t MyService_AddService( uint8_t rspTaskId);
    
    /*
     * MyService_RegisterAppCBs - Registers the application callback function.
     *                    Only call this function once.
     *
     *    appCallbacks - pointer to application callbacks.
     */
    extern bStatus_t MyService_RegisterAppCBs( myServiceCBs_t *appCallbacks );
    
    /*
     * MyService_SetParameter - Set a MyService parameter.
     *
     *    param - Profile parameter ID
     *    len - length of data to right
     *    value - pointer to data to write.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     */
    extern bStatus_t MyService_SetParameter(uint8_t param, uint16_t len, void *value);
    
    /*
     * MyService_GetParameter - Get a MyService parameter.
     *
     *    param - Profile parameter ID
     *    value - pointer to data to write.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     */
    extern bStatus_t MyService_GetParameter(uint8_t param, uint16_t *len, void *value);
    
    /*********************************************************************
    *********************************************************************/
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* _MYSERVICE_H_ */

    /**********************************************************************************************
     * Filename:       myService.c
     *
     * Description:    This file contains the implementation of the service.
     *
     * Copyright (c) 2015-2020, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *************************************************************************************************/
    
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    
    #include <icall.h>
    
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "myService.h"
    
    /*********************************************************************
     * MACROS
     */
    
    /*********************************************************************
     * CONSTANTS
     */
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
    * GLOBAL VARIABLES
    */
    
    // myService Service UUID
    CONST uint8_t myServiceUUID[ATT_UUID_SIZE] =
    {
      TI_BASE_UUID_128(MYSERVICE_SERV_UUID)
    };
    
    // myNiceChar UUID
    CONST uint8_t myService_MyNiceCharUUID[ATT_UUID_SIZE] =
    {
      TI_BASE_UUID_128(MYSERVICE_MYNICECHAR_UUID)
    };
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    static myServiceCBs_t *pAppCBs = NULL;
    
    /*********************************************************************
    * Profile Attributes - variables
    */
    
    // Service declaration
    static CONST gattAttrType_t myServiceDecl = { ATT_UUID_SIZE, myServiceUUID };
    
    // Characteristic "MyNiceChar" Properties (for declaration)
    static uint8_t myService_MyNiceCharProps = GATT_PROP_READ | GATT_PROP_WRITE;
    
    // Characteristic "MyNiceChar" Value variable
    static uint8_t myService_MyNiceCharVal[MYSERVICE_MYNICECHAR_LEN] = {0};
    
    /*********************************************************************
    * Profile Attributes - Table
    */
    
    static gattAttribute_t myServiceAttrTbl[] =
    {
      // myService Service Declaration
      {
        { ATT_BT_UUID_SIZE, primaryServiceUUID },
        GATT_PERMIT_READ,
        0,
        (uint8_t *)&myServiceDecl
      },
        // MyNiceChar Characteristic Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &myService_MyNiceCharProps
        },
          // MyNiceChar Characteristic Value
          {
            { ATT_UUID_SIZE, myService_MyNiceCharUUID },
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            myService_MyNiceCharVal
          },
    };
    
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    static bStatus_t myService_ReadAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
                                               uint8_t *pValue, uint16_t *pLen, uint16_t offset,
                                               uint16_t maxLen, uint8_t method );
    static bStatus_t myService_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
                                                uint8_t *pValue, uint16_t len, uint16_t offset,
                                                uint8_t method );
    
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    // Simple Profile Service Callbacks
    CONST gattServiceCBs_t myServiceCBs =
    {
      myService_ReadAttrCB,  // Read callback function pointer
      myService_WriteAttrCB, // Write callback function pointer
      NULL                       // Authorization callback function pointer
    };
    
    /*********************************************************************
    * PUBLIC FUNCTIONS
    */
    
    /*
     * MyService_AddService- Initializes the MyService service by registering
     *          GATT attributes with the GATT server.
     *
     */
    extern bStatus_t MyService_AddService( uint8_t rspTaskId )
    {
      uint8_t status;
    
      // Register GATT attribute list and CBs with GATT Server App
      status = GATTServApp_RegisterService( myServiceAttrTbl,
                                            GATT_NUM_ATTRS( myServiceAttrTbl ),
                                            GATT_MAX_ENCRYPT_KEY_SIZE,
                                            &myServiceCBs );
    
      return ( status );
    }
    
    /*
     * MyService_RegisterAppCBs - Registers the application callback function.
     *                    Only call this function once.
     *
     *    appCallbacks - pointer to application callbacks.
     */
    bStatus_t MyService_RegisterAppCBs( myServiceCBs_t *appCallbacks )
    {
      if ( appCallbacks )
      {
        pAppCBs = appCallbacks;
    
        return ( SUCCESS );
      }
      else
      {
        return ( bleAlreadyInRequestedMode );
      }
    }
    
    /*
     * MyService_SetParameter - Set a MyService parameter.
     *
     *    param - Profile parameter ID
     *    len - length of data to right
     *    value - pointer to data to write.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     */
    bStatus_t MyService_SetParameter( uint8_t param, uint16_t len, void *value )
    {
      bStatus_t ret = SUCCESS;
      switch ( param )
      {
        case MYSERVICE_MYNICECHAR_ID:
          if ( len == MYSERVICE_MYNICECHAR_LEN )
          {
            memcpy(myService_MyNiceCharVal, value, len);
          }
          else
          {
            ret = bleInvalidRange;
          }
          break;
    
        default:
          ret = INVALIDPARAMETER;
          break;
      }
      return ret;
    }
    
    
    /*
     * MyService_GetParameter - Get a MyService parameter.
     *
     *    param - Profile parameter ID
     *    value - pointer to data to write.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     */
    bStatus_t MyService_GetParameter( uint8_t param, uint16_t *len, void *value )
    {
      bStatus_t ret = SUCCESS;
      switch ( param )
      {
        case MYSERVICE_MYNICECHAR_ID:
          memcpy(value, myService_MyNiceCharVal, MYSERVICE_MYNICECHAR_LEN);
          break;
    
        default:
          ret = INVALIDPARAMETER;
          break;
      }
      return ret;
    }
    
    
    /*********************************************************************
     * @fn          myService_ReadAttrCB
     *
     * @brief       Read an attribute.
     *
     * @param       connHandle - connection message was received on
     * @param       pAttr - pointer to attribute
     * @param       pValue - pointer to data to be read
     * @param       pLen - length of data to be read
     * @param       offset - offset of the first octet to be read
     * @param       maxLen - maximum length of data to be read
     * @param       method - type of read message
     *
     * @return      SUCCESS, blePending or Failure
     */
    static bStatus_t myService_ReadAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
                                           uint8_t *pValue, uint16_t *pLen, uint16_t offset,
                                           uint16_t maxLen, uint8_t method )
    {
      bStatus_t status = SUCCESS;
    
      // See if request is regarding the MyNiceChar Characteristic Value
    if ( ! memcmp(pAttr->type.uuid, myService_MyNiceCharUUID, pAttr->type.len) )
      {
        if ( offset > MYSERVICE_MYNICECHAR_LEN )  // Prevent malicious ATT ReadBlob offsets.
        {
          status = ATT_ERR_INVALID_OFFSET;
        }
        else
        {
          *pLen = MIN(maxLen, MYSERVICE_MYNICECHAR_LEN - offset);  // Transmit as much as possible
          memcpy(pValue, pAttr->pValue + offset, *pLen);
        }
      }
      else
      {
        // If we get here, that means you've forgotten to add an if clause for a
        // characteristic value attribute in the attribute table that has READ permissions.
        *pLen = 0;
        status = ATT_ERR_ATTR_NOT_FOUND;
      }
    
      return status;
    }
    
    
    /*********************************************************************
     * @fn      myService_WriteAttrCB
     *
     * @brief   Validate attribute data prior to a write operation
     *
     * @param   connHandle - connection message was received on
     * @param   pAttr - pointer to attribute
     * @param   pValue - pointer to data to be written
     * @param   len - length of data
     * @param   offset - offset of the first octet to be written
     * @param   method - type of write message
     *
     * @return  SUCCESS, blePending or Failure
     */
    static bStatus_t myService_WriteAttrCB( uint16_t connHandle, gattAttribute_t *pAttr,
                                            uint8_t *pValue, uint16_t len, uint16_t offset,
                                            uint8_t method )
    {
      bStatus_t status  = SUCCESS;
      uint8_t   paramID = 0xFF;
    
      // See if request is regarding a Client Characterisic Configuration
      if ( ! memcmp(pAttr->type.uuid, clientCharCfgUUID, pAttr->type.len) )
      {
        // Allow only notifications.
        status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                 offset, GATT_CLIENT_CFG_NOTIFY);
      }
      // See if request is regarding the MyNiceChar Characteristic Value
      else if ( ! memcmp(pAttr->type.uuid, myService_MyNiceCharUUID, pAttr->type.len) )
      {
        if ( offset + len > MYSERVICE_MYNICECHAR_LEN )
        {
          status = ATT_ERR_INVALID_OFFSET;
        }
        else
        {
          // Copy pValue into the variable we point to from the attribute table.
          memcpy(pAttr->pValue + offset, pValue, len);
    
          // Only notify application if entire expected value is written
          if ( offset + len == MYSERVICE_MYNICECHAR_LEN)
            paramID = MYSERVICE_MYNICECHAR_ID;
        }
      }
      else
      {
        // If we get here, that means you've forgotten to add an if clause for a
        // characteristic value attribute in the attribute table that has WRITE permissions.
        status = ATT_ERR_ATTR_NOT_FOUND;
      }
    
      // Let the application know something changed (if it did) by using the
      // callback it registered earlier (if it did).
      if (paramID != 0xFF)
        if ( pAppCBs && pAppCBs->pfnChangeCb )
        {
          uint16_t svcUuid = MYSERVICE_SERV_UUID;
          pAppCBs->pfnChangeCb(connHandle, svcUuid, paramID, len, pValue); // Call app function from stack task context.
        }
      return status;
    }

    /**********************************************************************************************
     * Filename:       appsnippets.c
     *
     * Description:    This file contains snippets needed to utilize the generated services.
     *
     * Copyright (c) 2015-2020, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *************************************************************************************************/
    
    //...
    #include "myService.h"
    
    //...
    
    // Declaration of service callback handlers
    static void user_myService_ValueChangeCB(uint16_t connHandle, uint16_t svcUuid,
                                          uint8_t paramID,
                                          uint16_t len,
                                          uint8_t *pValue); // Callback from the service.
    static void user_myService_ValueChangeHandler(
                                char_data_t *pCharData
                            ); // Local handler called from the Task context of this task.
    
    // Service callback function implementation
    // MyService callback handler. The type myServiceCBs_t is defined in myService.h
    static myServiceCBs_t user_myServiceCBs =
    {
      .pfnChangeCb = user_myService_ValueChangeCB, // Characteristic value change callback handler
      .pfnCfgChangeCb = NULL, // No CCCD change handler implemented
    };
    
    
    // ProjectZero_init(..)
    // {
    
      // ...
    
      MyService_AddService( selfEntity );
      MyService_RegisterAppCBs(&user_myServiceCBs);
    
      // Initalization of characteristics in myService that are readable.
      uint8_t myService_myNiceChar_initVal[MYSERVICE_MYNICECHAR_LEN] = {0};
      MyService_SetParameter(MYSERVICE_MYNICECHAR_ID, MYSERVICE_MYNICECHAR_LEN, myService_myNiceChar_initVal);
    
    //}
    
    
    // static void user_processApplicationMessage(app_msg_t *pMsg)
    // {
    //     // Cast to char_data_t* here since it's a common message pdu type.
    //     char_data_t *pCharData = (char_data_t *)pMsg->pdu;
    
        // ...
    
    //     case APP_MSG_SERVICE_WRITE: /* Message about received value write */
    //         /* Call different handler per service */
    //         switch(pCharData->svcUUID)
    //         {
              // ...
                case MYSERVICE_SERV_UUID:
                  user_myService_ValueChangeHandler(pCharData);
                  break;
                // ...
        // ...
    // }
    
    // ...
    
    void user_myService_ValueChangeHandler(char_data_t *pCharData)
    {
      switch (pCharData->paramID)
      {
            case MYSERVICE_MYNICECHAR_ID:
            Log_info0("Value Change msg for myService :: myNiceChar received");
            // Do something useful with pCharData->data here
            // -------------------------
            break;
          }
    
    }
    
    // ...
    
    static void user_myService_ValueChangeCB(uint16_t connHandle, uint16_t svcUuid,
                                  uint8_t paramID, uint16_t len,
                                  uint8_t *pValue)
    {
      user_enqueueCharDataMsg(APP_MSG_SERVICE_CFG, connHandle, svcUuid,
                              paramID, pValue, len);
    }
    

    Best Regards,

    Jan

  • What is the error code being returned when ATT_ERROR_RSP is the method?  Can you see the output of Display_print1?

  • Hello Jan , i am following the same , and my peripheral gets connected with mobile apk and i am able to read and write data .

  • error code is 1 , when ATT_ERROR_RSP is the method .

  • Hello Jan, My issue is resolved .