Académique Documents
Professionnel Documents
Culture Documents
* @file simple_ble_topology.c
*
* @description Application task for the Simple Topology example
*
*
* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
*
*
* 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/Semaphore.h>
#include <ti/sysbios/knl/Queue.h>
#include "hci_tl.h"
#include "gatt.h"
#include "gapgattserver.h"
#include "gattservapp.h"
#include "devinfoservice.h"
#include "simpleGATTprofile.h"
#include "multi.h"
#include "gapbondmgr.h"
#include "osal_snv.h"
#include "ICallBleAPIMSG.h"
#include "util.h"
#include "board_lcd.h"
#include "board_key.h"
#include "Board.h"
#include "linkdb.h"
#include "multi_role.h"
#include <ti/drivers/UART.h>
#include <ti/drivers/lcd/LCDDogm1286.h>
*/
#include <string.h>
#include <cstring>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/sysbios/BIOS.h>
#include <ti/drivers/PIN.h>
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include "hci_tl.h"
#include "gatt.h"
#include "gapgattserver.h"
#include "gattservapp.h"
#include "devinfoservice.h"
#include "simpleGATTprofile.h"
#include "multi.h"
#include "gapbondmgr.h"
#include "osal_snv.h"
#include "ICallBleAPIMSG.h"
#include "util.h"
#include "board_lcd.h"
#include "board_key.h"
#include "Board.h"
#include <stdint.h>
#include "linkdb.h"
#include "multi_role.h"
//#include "battservice.h"
#include <ti/drivers/pin/PINCC26XX.h>
#include <ti/drivers/UART.h>
//#ifdef USE_ICALL
//#include <ICall.h>
//#endif
/*********************************************************************
* CONSTANTS
*/
// Advertising interval when device is discoverable (units of 625us, 160=100ms)
#define DEFAULT_ADVERTISING_INTERVAL 160
//connection parameters
#define DEFAULT_CONN_INT 42
#define DEFAULT_CONN_TIMEOUT 200
#define DEFAULT_CONN_LATENCY 0
// Task configuration
#define SBT_TASK_PRIORITY 1
#ifndef SBT_TASK_STACK_SIZE
#define SBT_TASK_STACK_SIZE 644
#endif
// LCD defines
#define MAIN_MENU 0
#define DEVICE_MENU 1
#define CONNECTED_DEVICES 0
#define DISCOVERED_DEVICES 1
#define BUFTYPE char
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
// structure to store link attributes
extern gapRoleInfo_t multiConnInfo[MAX_NUM_BLE_CONNS];
/*********************************************************************
* LOCAL VARIABLES
*/
// Task configuration
Task_Struct sbmTask;
Char sbmTaskStack[SBT_TASK_STACK_SIZE];
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};
// Discovery state
static uint8_t discState = BLE_DISC_STATE_IDLE;
// Scanning state
static bool scanningStarted = FALSE;
// connecting state
static uint8_t connecting_state = 0;
// Value to write
static uint8_t charVal = 0;
UART_Handle uart;
UART_Params uartParams;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void simpleTopology_init( void );
static void simpleTopology_taskFxn(UArg a0, UArg a1);
static uint8_t simpleTopology_processStackMsg(ICall_Hdr *pMsg);
static uint8_t simpleTopology_processGATTMsg(gattMsgEvent_t *pMsg);
static void simpleTopology_processAppMsg(sbtEvt_t *pMsg);
static void simpleTopology_processCharValueChangeEvt(uint8_t paramID);
static void simpleTopology_processRoleEvent(gapMultiRoleEvent_t *pEvent);
static void simpleTopology_sendAttRsp(void);
static void simpleTopology_freeAttRsp(uint8_t status);
static void simpleTopology_charValueChangeCB(uint8_t paramID);
static uint8_t simpleTopology_enqueueMsg(uint16_t event, uint8_t status, uint8_t
*pData);
static void simpleTopology_startDiscovery(void);
static void simpleTopology_processGATTDiscEvent(gattMsgEvent_t *pMsg);
static bool simpleTopology_findSvcUuid(uint16_t uuid, uint8_t *pData, uint8_t
dataLen);
static void simpleTopology_addDeviceInfo(uint8_t *pAddr, uint8_t addrType);
static void simpleTopology_startDiscovery(void);
static void simpleTopology_handleKeys(uint8_t shift, uint8_t keys);
static uint8_t simpleTopology_eventCB(gapMultiRoleEvent_t *pEvent);
static void simpleTopology_sendAttRsp(void);
static void simpleTopology_freeAttRsp(uint8_t status);
/*********************************************************************
* PROFILE CALLBACKS Board_initKeys
*/
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn simpleTopology_createTask
*
* @brief Task creation function for the Simple BLE Peripheral.
*
* @param None.
*
* @return None.
*/
void SimpleTopology_createTask(void)
{
Task_Params taskParams;
// Configure task
Task_Params_init(&taskParams);
taskParams.stack = sbmTaskStack;
taskParams.stackSize = SBT_TASK_STACK_SIZE;
taskParams.priority = SBT_TASK_PRIORITY;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&initialAdvertEnable, NULL);
GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
&advertOffTime, NULL);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
scanRspData, NULL);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData,
NULL);
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
&desiredMinInterval, NULL);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
&desiredMaxInterval, NULL);
GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
&desiredSlaveLatency, NULL);
GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
&desiredConnTimeout, NULL);
/*--------------CENTRAL-----------------*/
uint8_t scanRes = DEFAULT_MAX_SCAN_RES;
GAPRole_SetParameter(GAPROLE_MAX_SCAN_RES, sizeof(uint8_t),
&scanRes, NULL);
//GATT
{
/*---------------------SERVER------------------------*/
// Set the GAP Characteristics
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
&charValue1);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
&charValue2);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
&charValue3);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
&charValue4);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
charValue5);
}
UART_INIT();
/*-----------------CLIENT------------------*/
// Initialize GATT Client
VOID GATT_InitClient();
// Register for GATT local events and ATT Responses pending for transmission
GATT_RegisterForMsgs(selfEntity);
Util_startClock(&startSendClock);
}
/*********************************************************************
* @fn simpleTopology_taskFxn
*
* @brief Application task entry point for the Simple BLE Multi.
*
* @param a0, a1 - not used.
*
* @return None.
*/
static void simpleTopology_taskFxn(UArg a0, UArg a1)
{
// Initialize application
simpleTopology_init();
if (errno == ICALL_ERRNO_SUCCESS)
{
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt *pMsg = NULL;
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
uint8 safeToDealloc = TRUE;
simpleTopology_startDiscovery();
}
}
}
}
/*********************************************************************
* @fn simpleTopology_processStackMsg
*
* @brief Process an incoming stack message.
*
* @param pMsg - message to process
*
* @return TRUE if safe to deallocate incoming message, FALSE otherwise.
*/
static uint8_t simpleTopology_processStackMsg(ICall_Hdr *pMsg)
{
uint8_t safeToDealloc = TRUE;
switch (pMsg->event)
{
case GATT_MSG_EVENT:
// Process GATT message
safeToDealloc = simpleTopology_processGATTMsg((gattMsgEvent_t *)pMsg);
break;
case HCI_GAP_EVENT_EVENT:
{
// Process HCI message
switch(pMsg->status)
{
case HCI_COMMAND_COMPLETE_EVENT_CODE:
// Process HCI Command Complete Event
break;
default:
break;
}
}
break;
case GAP_MSG_EVENT:
simpleTopology_processRoleEvent((gapMultiRoleEvent_t *)pMsg);
break;
default:
// do nothing
break;
}
return (safeToDealloc);
}
/*********************************************************************
* @fn simpleTopology_processGATTMsg
*
* @brief Process GATT messages and events.
*
* @return TRUE if safe to deallocate incoming message, FALSE otherwise.
*/
static uint8_t simpleTopology_processGATTMsg(gattMsgEvent_t *pMsg)
{
// See if GATT server was unable to transmit an ATT response
if (pMsg->hdr.status == blePending)
{
// No HCI buffer was available. Let's try to retransmit the response
// on the next connection event.
if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity,
SBT_CONN_EVT_END_EVT) == SUCCESS)
{
// First free any pending response
simpleTopology_freeAttRsp(FAILURE);
}
else if ((pMsg->method == ATT_WRITE_RSP) ||
((pMsg->method == ATT_ERROR_RSP) &&
(pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ)))
{
/*********************************************************************
* @fn simpleTopology_sendAttRsp
*
* @brief Send a pending ATT response message.
*
* @param none
*
* @return none
*/
static void simpleTopology_sendAttRsp(void)
{
// See if there's a pending ATT Response to be transmitted
if (pAttRsp != NULL)
{
uint8_t status;
/*********************************************************************
* @fn simpleTopology_freeAttRsp
*
* @brief Free ATT response message.
*
* @param status - response transmit status
*
* @return none
*/
static void simpleTopology_freeAttRsp(uint8_t status)
{
// See if there's a pending ATT response message
if (pAttRsp != NULL)
{
// See if the response was sent out successfully
if (status == SUCCESS)
{
LCD_WRITE_STRING_VALUE("Rsp sent, retry:", rspTxRetry, 10, LCD_PAGE6);
}
else
{
// Free response payload
GATT_bm_free(&pAttRsp->msg, pAttRsp->method);
/*********************************************************************
* @fn simpleTopology_processAppMsg
*
* @brief Process an incoming callback from a profile.
*
* @param pMsg - message to process
*
* @return None.
*/
static void simpleTopology_processAppMsg(sbtEvt_t *pMsg)
{
switch (pMsg->event)
{
case SBT_STATE_CHANGE_EVT:
simpleTopology_processStackMsg((ICall_Hdr *)pMsg->pData);
// Free the stack message
ICall_freeMsg(pMsg->pData);
break;
case SBT_CHAR_CHANGE_EVT:
simpleTopology_processCharValueChangeEvt(pMsg->status);
break;
case SBT_KEY_CHANGE_EVT:
simpleTopology_handleKeys(0, pMsg->status);
break;
default:
// Do nothing.
break;
}
}
/*********************************************************************
* @fn simpleTopology_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 simpleTopology_eventCB(gapMultiRoleEvent_t *pEvent)
{
// Forward the role event to the application
if (simpleTopology_enqueueMsg(SBT_STATE_CHANGE_EVT, SUCCESS, (uint8_t *)pEvent))
{
// App will process and free the event
return FALSE;
}
/*********************************************************************
* @fn simpleTopology_processRoleEvent
*
* @brief Multi role event processing function.
*
* @param pEvent - pointer to event structure
*
* @return none
*/
static void simpleTopology_processRoleEvent(gapMultiRoleEvent_t *pEvent)
{
switch (pEvent->gap.opcode)
{
case GAP_DEVICE_INIT_DONE_EVENT:
{
maxPduSize = pEvent->initDone.dataPktLen;
case GAP_MAKE_DISCOVERABLE_DONE_EVENT:
{
if (gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) > 0)
{
LCD_WRITE_STRING("Advertising", LCD_PAGE2);
}
else
{
LCD_WRITE_STRING("Advertising", LCD_PAGE2);
}
}
break;
case GAP_END_DISCOVERABLE_DONE_EVENT:
{
if (gapRoleNumLinks(GAPROLE_AVAILABLE_LINKS) > 0)
{
LCD_WRITE_STRING("Ready to Advertise", LCD_PAGE2);
}
else
{
LCD_WRITE_STRING("Can't Adv : No links", LCD_PAGE2);
}
}
break;
case GAP_DEVICE_INFO_EVENT:
{
// if filtering device discovery results based on service UUID
if (DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE)
{
if (simpleTopology_findSvcUuid(SIMPLEPROFILE_SERV_UUID,
pEvent->deviceInfo.pEvtData,
pEvent->deviceInfo.dataLen))
{
simpleTopology_addDeviceInfo(pEvent->deviceInfo.addr,
pEvent->deviceInfo.addrType);
}
}
}
break;
case GAP_DEVICE_DISCOVERY_EVENT:
{
// discovery complete
scanningStarted = FALSE;
if (scanRes > 0)
{
LCD_WRITE_STRING("<- To Select", LCD_PAGE4);
}
case GAP_LINK_ESTABLISHED_EVENT:
{
if (pEvent->gap.hdr.status == SUCCESS)
{
LCD_WRITE_STRING("Connected!", LCD_PAGE3);
LCD_WRITE_STRING_VALUE("Connected to ",
gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0);
//update state
connecting_state = 0;
//store connection handle
connHandle = pEvent->linkCmpl.connectionHandle;
case GAP_LINK_TERMINATED_EVENT:
{
connHandle = GAP_CONNHANDLE_INIT;
discState = BLE_DISC_STATE_IDLE;
uint8_t i;
for (i=0; i < MAX_NUM_BLE_CONNS; i++)
{
if (multiConnInfo[i].gapRole_ConnectionHandle ==
GAPROLE_CONN_JUST_TERMINATED)
{
//clear screen, reset discovery info, and return to main menu
multiConnInfo[i].gapRole_ConnectionHandle = INVALID_CONNHANDLE;
charHdl[i] = 0;
LCD_WRITE_STRING_VALUE("Connected to ",
gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) ,10, LCD_PAGE0);
LCD_WRITE_STRING("Disconnected!", LCD_PAGE5);
LCD_WRITE_STRING("Main Menu", LCD_PAGE3);
LCDmenu = MAIN_MENU;
}
if ((gapRoleNumLinks(GAPROLE_ACTIVE_LINKS) == (MAX_NUM_BLE_CONNS-1)))
//now we can advertise again
{
LCD_WRITE_STRING("Ready to Advertise", LCD_PAGE2);
}
}
}
break;
case GAP_LINK_PARAM_UPDATE_EVENT:
{
LCD_WRITE_STRING_VALUE("Param Update:", pEvent->linkUpdate.status,
10, LCD_PAGE2);
}
break;
default:
break;
}
}
/*********************************************************************
* @fn simpleTopology_charValueChangeCB
*
* @brief Callback from Simple Profile indicating a characteristic
* value change.
*
* @param paramID - parameter ID of the value that was changed.
*
* @return None.
*/
static void simpleTopology_charValueChangeCB(uint8_t paramID)
{
simpleTopology_enqueueMsg(SBT_CHAR_CHANGE_EVT, paramID, NULL);
}
/*********************************************************************
* @fn simpleTopology_processCharValueChangeEvt
*
* @brief Process a pending Simple Profile characteristic value change
* event.
*
* @param paramID - parameter ID of the value that was changed.
*
* @return None.
*/
static void simpleTopology_processCharValueChangeEvt(uint8_t paramID)
{
uint8_t newValue;
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
case SIMPLEPROFILE_CHAR3:
SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);
/*********************************************************************
* @fn simpleTopology_startDiscHandler
*
* @brief Clock handler function
*
* @param a0 - ignored
*
* @return none
*/
void simpleTopology_startDiscHandler(UArg a0)
{
events |= SBT_START_DISCOVERY_EVT;
/*********************************************************************
* @fn simpleTopology_enqueueMsg
*
* @brief Creates a message and puts the message in RTOS queue.
*
* @param event - message event.
* @param state - message state.
*
* @return None.
*/
static uint8_t simpleTopology_enqueueMsg(uint16_t event, uint8_t status, uint8_t
*pData)
{
sbtEvt_t *pMsg = ICall_malloc(sizeof(sbtEvt_t));
return FALSE;
}
/*********************************************************************
* @fn simpleTopology_keyChangeHandler
*
* @brief Key event handler function
*
* @param a0 - ignored
*
* @return none
*/
void simpleTopology_keyChangeHandler(uint8 keys)
{
simpleTopology_enqueueMsg(SBT_KEY_CHANGE_EVT, keys, NULL);
}
/*********************************************************************
* @fn simpleTopology_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
*/
static void simpleTopology_handleKeys(uint8_t shift, uint8_t keys)
{
(void)shift; // Intentionally unreferenced parameter
if (LCDmenu == MAIN_MENU)
{
if (keys & KEY_LEFT) //show discovery results
{
selectKey = DISCOVERED_DEVICES;
LCD_WRITE_STRING("Discovering...", LCD_PAGE3);
LCD_WRITE_STRING("", LCD_PAGE4);
LCD_WRITE_STRING("", LCD_PAGE6);
GAPRole_StartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
}
else //cancel scanning
{
LCD_WRITE_STRING("Discovery Cancelled", LCD_PAGE3);
GAPRole_CancelDiscovery();
scanningStarted = FALSE;
}
}
else // can't add more links at this time
{
LCD_WRITE_STRING("Can't scan:no links ", LCD_PAGE3);
}
return;
}
if (keys & KEY_RIGHT) // turn advertising on / off
{
uint8_t adv;
uint8_t adv_status;
GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv_status, NULL);
if (adv_status) //turn off
{
adv = FALSE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL);
}
else //turn on
{
adv = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &adv, NULL);
}
return;
}
GAPRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
DEFAULT_LINK_WHITE_LIST,
addrType, peerAddr);
connecting_state = 1;
LCD_WRITE_STRING("Connecting", LCD_PAGE3);
LCD_WRITE_STRING(Util_convertBdAddr2Str(peerAddr), LCD_PAGE4);
}
}
}
else if (selectKey == CONNECTED_DEVICES) //enter the device menu
{
if (multiConnInfo[connIdx].gapRole_ConnectionHandle != INVALID_CONNHANDLE)
{
LCDmenu = DEVICE_MENU;
LCD_WRITE_STRING("Device Menu", LCD_PAGE3);
LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr),
LCD_PAGE4);
if (multiConnInfo[connIdx].gapRole_ConnRole == GAP_PROFILE_CENTRAL)
{
LCD_WRITE_STRING("Connected as Central", LCD_PAGE5);
LCD_WRITE_STRING("", LCD_PAGE6);
LCD_WRITE_STRING("", LCD_PAGE7);
}
else //PERIPHERAL
{
LCD_WRITE_STRING("Connected as Periph", LCD_PAGE5);
LCD_WRITE_STRING("", LCD_PAGE6);
LCD_WRITE_STRING("", LCD_PAGE7);
}
//use this connection for all functionality
connHandle = multiConnInfo[connIdx].gapRole_ConnectionHandle;
}
else // no active connection here
LCD_WRITE_STRING("No Connection here.", LCD_PAGE3);
}
return;
}
if (keys & KEY_DOWN) //browse connected devices
{
LCD_WRITE_STRING("Connected Device:", LCD_PAGE3);
if (++connIdx >= MAX_NUM_BLE_CONNS) //increment connIdx
{
connIdx = 0;
}
if (multiConnInfo[connIdx].gapRole_ConnectionHandle !=
INVALID_CONNHANDLE) //if there is a connection at this index
{
LCD_WRITE_STRING(Util_convertBdAddr2Str(multiConnInfo[connIdx].gapRole_devAddr),
LCD_PAGE4);
}
else
{
LCD_WRITE_STRING("N/A", LCD_PAGE4);
}
selectKey = CONNECTED_DEVICES;
}
return;
}
if (status == SUCCESS)
{
doWrite = !doWrite;
}
}
return;
}
LCD_WRITE_STRING("Disconnecting", LCD_PAGE5);
LCD_WRITE_STRING("", LCD_PAGE6);
return;
}
connIdx = 0;
return;
}
}
}
/*********************************************************************
* @fn simpleTopology_startDiscovery
*
* @brief Start service discovery.
*
* @return none
*/
static void simpleTopology_startDiscovery(void)
{
attExchangeMTUReq_t req;
discState = BLE_DISC_STATE_MTU;
// 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 simpleTopology_processGATTDiscEvent
*
* @brief Process GATT discovery event
*
* @return none
*/
static void simpleTopology_processGATTDiscEvent(gattMsgEvent_t *pMsg)
{
if (pMsg->method == ATT_MTU_UPDATED_EVENT)
{
// MTU size updated
LCD_WRITE_STRING_VALUE("MTU Size:", pMsg->msg.mtuEvt.MTU, 10, LCD_PAGE4);
}
else if (discState == BLE_DISC_STATE_MTU)
{
// MTU size response received, discover simple BLE 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) };
discState = BLE_DISC_STATE_SVC;
// 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_BT_UUID_SIZE;
req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);
req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);
discState = BLE_DISC_STATE_IDLE;
}
}
/*********************************************************************
* @fn simpleTopology_findSvcUuid
*
* @brief Find a given UUID in an advertiser's service UUID list.
*
* @return TRUE if service UUID found
*/
static bool simpleTopology_findSvcUuid(uint16_t uuid, uint8_t *pData,
uint8_t dataLen)
{
uint8_t adLen;
uint8_t adType;
uint8_t *pEnd;
// Go to next
pData += 2;
adLen -= 2;
}
if (uart == NULL) {
System_abort("Error opening the UART");
}
/*********************************************************************
* @fn simpleTopology_addDeviceInfo
*
* @brief Add a device to the device discovery result list
*
* @return none
*/
static void simpleTopology_addDeviceInfo(uint8_t *pAddr, uint8_t addrType)
{
uint8_t i;
/*********************************************************************
*********************************************************************/