1252 lines
45 KiB
C
1252 lines
45 KiB
C
/*********************************************************************
|
||
* INCLUDES
|
||
*/
|
||
#include "CONFIG.h"
|
||
#include "gattprofile.h"
|
||
#include "multiCentral.h"
|
||
#include "bsp_uart.h"
|
||
#include "log.h"
|
||
|
||
#undef LOG_ENABLE
|
||
#define LOG_ENABLE 1
|
||
|
||
|
||
/*********************************************************************
|
||
* MACROS
|
||
*/
|
||
|
||
// Length of bd addr as a string
|
||
#define B_ADDR_STR_LEN 15
|
||
|
||
/*********************************************************************
|
||
* CONSTANTS
|
||
*/
|
||
// Maximum number of scan responses
|
||
#define DEFAULT_MAX_SCAN_RES 10
|
||
|
||
// Scan duration in 0.625ms 扫描窗口要小于等于扫描间隔
|
||
#define DEFAULT_SCAN_DURATION 2400
|
||
|
||
// Connection min interval in 1.25ms
|
||
#define DEFAULT_MIN_CONNECTION_INTERVAL 20 //25ms连接一次 范围为7.5ms~4s之间
|
||
|
||
// Connection max interval in 1.25ms
|
||
#define DEFAULT_MAX_CONNECTION_INTERVAL 100 //125ms连接一次
|
||
|
||
// Connection supervision timeout in 10ms
|
||
#define DEFAULT_CONNECTION_TIMEOUT 100 //10(100ms)~3200(32s)
|
||
|
||
// Discovey mode (limited, general, all)
|
||
#define DEFAULT_DISCOVERY_MODE DEVDISC_MODE_ALL
|
||
|
||
// TRUE to use active scan
|
||
#define DEFAULT_DISCOVERY_ACTIVE_SCAN TRUE
|
||
|
||
// TRUE to use white list during discovery
|
||
// #define DEFAULT_DISCOVERY_WHITE_LIST FALSE
|
||
#define DEFAULT_DISCOVERY_WHITE_LIST FALSE
|
||
|
||
// 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 read RSSI period in 0.625ms
|
||
#define DEFAULT_RSSI_PERIOD 2400
|
||
|
||
// Minimum connection interval (units of 1.25ms)
|
||
#define DEFAULT_UPDATE_MIN_CONN_INTERVAL 100
|
||
|
||
// Maximum connection interval (units of 1.25ms)
|
||
#define DEFAULT_UPDATE_MAX_CONN_INTERVAL 400
|
||
// Slave latency to use parameter update
|
||
#define DEFAULT_UPDATE_SLAVE_LATENCY 5
|
||
|
||
// Supervision timeout value (units of 10ms)
|
||
#define DEFAULT_UPDATE_CONN_TIMEOUT 200
|
||
|
||
// Default passcode
|
||
#define DEFAULT_PASSCODE 0
|
||
|
||
// Default GAP pairing mode
|
||
#define DEFAULT_PAIRING_MODE GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
|
||
|
||
// Default MITM mode (TRUE to require passcode or OOB when pairing)
|
||
#define DEFAULT_MITM_MODE TRUE
|
||
|
||
// Default bonding mode, TRUE to bond, max bonding 6 devices
|
||
#define DEFAULT_BONDING_MODE TRUE
|
||
|
||
// Default GAP bonding I/O capabilities
|
||
#define DEFAULT_IO_CAPABILITIES GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT
|
||
|
||
// Default service discovery timer delay in 0.625ms
|
||
#define DEFAULT_SVC_DISCOVERY_DELAY 1600
|
||
|
||
// Default parameter update delay in 0.625ms
|
||
#define DEFAULT_PARAM_UPDATE_DELAY 3200
|
||
|
||
// Default read or write timer delay in 0.625ms
|
||
#define DEFAULT_READ_OR_WRITE_DELAY 100
|
||
|
||
// Default write CCCD delay in 0.625ms
|
||
#define DEFAULT_WRITE_CCCD_DELAY 1600
|
||
|
||
// Establish link timeout in 0.625ms
|
||
#define ESTABLISH_LINK_TIMEOUT 3200
|
||
|
||
// 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_SVC, // Service discovery
|
||
BLE_DISC_STATE_CHAR, // Characteristic discovery
|
||
BLE_DISC_STATE_CCCD, // client characteristic configuration discovery
|
||
};
|
||
/*********************************************************************
|
||
* TYPEDEFS
|
||
*/
|
||
|
||
/*********************************************************************
|
||
* GLOBAL VARIABLES
|
||
*/
|
||
|
||
/*********************************************************************
|
||
* EXTERNAL VARIABLES
|
||
*/
|
||
|
||
/*********************************************************************
|
||
* EXTERNAL FUNCTIONS
|
||
*/
|
||
|
||
/*********************************************************************
|
||
* LOCAL VARIABLES
|
||
*/
|
||
|
||
// Task ID for internal task/event processing
|
||
static uint8_t centralTaskId;
|
||
|
||
// Number of scan results
|
||
static uint8_t centralScanRes;
|
||
|
||
// Scan result list
|
||
static gapDevRec_t centralDevList[DEFAULT_MAX_SCAN_RES];
|
||
|
||
// Peer device address
|
||
static peerAddrDefItem_t PeerAddrDef[CENTRAL_MAX_CONNECTION] = {
|
||
// {0xcf, 0xb4, 0x8f, 0x10, 0x53, 0x5c},
|
||
{0xe1, 0X51, 0x89, 0x88, 0x19, 0x70},
|
||
// {0x03, 0x02, 0x03, 0xE4, 0xC2, 0x84},
|
||
};
|
||
|
||
// Connection item list
|
||
static centralConnItem_t centralConnList[CENTRAL_MAX_CONNECTION];
|
||
|
||
// Value to write
|
||
static uint8_t centralCharVal = 0x01;
|
||
|
||
// Value read/write toggle
|
||
static uint8_t centralDoWrite = TRUE;
|
||
|
||
/*********************************************************************
|
||
* LOCAL FUNCTIONS
|
||
*/
|
||
static void centralProcessGATTMsg(gattMsgEvent_t *pMsg);
|
||
static void centralRssiCB(uint16_t connHandle, int8_t rssi);
|
||
static void centralEventCB(gapRoleEvent_t *pEvent);
|
||
static void centralHciMTUChangeCB(uint16_t connHandle, uint16_t maxTxOctets, uint16_t maxRxOctets);
|
||
static void centralPasscodeCB(uint8_t *deviceAddr, uint16_t connectionHandle,
|
||
uint8_t uiInputs, uint8_t uiOutputs);
|
||
static void centralPairStateCB(uint16_t connHandle, uint8_t state, uint8_t status);
|
||
static uint16_t connect0_ProcessEvent(uint8_t task_id, uint16_t events);
|
||
static void central_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
|
||
static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg);
|
||
static void centralConnIistStartDiscovery_0(void);
|
||
static void centralAddDeviceInfo(uint8_t *pAddr, uint8_t addrType);
|
||
static void centralInitConnItem(uint8_t task_id, centralConnItem_t *centralConnList);
|
||
static uint8_t centralAddrCmp(peerAddrDefItem_t *PeerAddrDef, uint8_t *addr);
|
||
|
||
static void centralConnIistStartDiscovery_1(void);
|
||
static uint16_t connect1_ProcessEvent(uint8_t task_id, uint16_t events);
|
||
/*********************************************************************
|
||
* PROFILE CALLBACKS
|
||
*/
|
||
|
||
// GAP Role Callbacks
|
||
static gapCentralRoleCB_t centralRoleCB = {
|
||
centralRssiCB, // RSSI callback
|
||
centralEventCB, // Event callback
|
||
centralHciMTUChangeCB // MTU change callback
|
||
};
|
||
|
||
// Bond Manager Callbacks
|
||
static gapBondCBs_t centralBondCB = {
|
||
centralPasscodeCB,// 连接时需要使用有密码的函数。
|
||
centralPairStateCB//配对时的回调函数
|
||
};
|
||
|
||
/*********************************************************************
|
||
* PUBLIC FUNCTIONS
|
||
*/
|
||
|
||
/*********************************************************************
|
||
* @fn Central_Init
|
||
*
|
||
* @brief Initialization function for the 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 task_id - the ID assigned by TMOS. This ID should be
|
||
* used to send messages and set timers.
|
||
*
|
||
* @return none
|
||
*/
|
||
void Central_Init()
|
||
{
|
||
centralTaskId = TMOS_ProcessEventRegister(Central_ProcessEvent);//注册事件处理函数,将返回的任务赋值给变量
|
||
|
||
// Setup GAP
|
||
GAP_SetParamValue(TGAP_DISC_SCAN_WIND, DEFAULT_SCAN_DURATION);//扫描窗口
|
||
GAP_SetParamValue(TGAP_DISC_SCAN, DEFAULT_SCAN_DURATION);//扫描连续时间,单位0.625ms 4800*0.625ms = 3000ms
|
||
GAP_SetParamValue(TGAP_DISC_SCAN_INT, DEFAULT_SCAN_DURATION);////扫描间隔,需要>=扫描窗口
|
||
GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, DEFAULT_MIN_CONNECTION_INTERVAL);////设置链路层连接间隔,这里是最小连接间隔
|
||
GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_MAX_CONNECTION_INTERVAL);//最大连续间隔
|
||
GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);//连接超时时间
|
||
|
||
// Setup the GAP Bond Manager
|
||
{
|
||
uint32_t passkey = DEFAULT_PASSCODE;//PASSKEY 是在配对过程中用于验证设备身份的一种方式
|
||
uint8_t pairMode = DEFAULT_PAIRING_MODE;//(配对模式)配对模式定义了设备进行配对过程中的行为和要求
|
||
uint8_t mitm = DEFAULT_MITM_MODE;//MIMT模式定义了是否需要保护免受中间人攻击的配对过程
|
||
uint8_t ioCap = DEFAULT_IO_CAPABILITIES;//IO能力定义了设备对配对过程的输入输出能力
|
||
uint8_t bonding = DEFAULT_BONDING_MODE;//(绑定模式)绑定模式定义了设备在配对后是否应该建立安全的绑定关系
|
||
|
||
GAPBondMgr_SetParameter(GAPBOND_CENT_DEFAULT_PASSCODE, sizeof(uint32_t), &passkey);
|
||
GAPBondMgr_SetParameter(GAPBOND_CENT_PAIRING_MODE, sizeof(uint8_t), &pairMode);
|
||
GAPBondMgr_SetParameter(GAPBOND_CENT_MITM_PROTECTION, sizeof(uint8_t), &mitm);
|
||
GAPBondMgr_SetParameter(GAPBOND_CENT_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
|
||
GAPBondMgr_SetParameter(GAPBOND_CENT_BONDING_ENABLED, sizeof(uint8_t), &bonding);
|
||
}
|
||
|
||
// Init Connection Item
|
||
centralInitConnItem(centralTaskId, centralConnList);
|
||
// Initialize GATT Client
|
||
GATT_InitClient();//初始化通用规范属性客户端
|
||
// Register to receive incoming ATT Indications/Notifications
|
||
GATT_RegisterForInd(centralTaskId);
|
||
// Setup a delayed profile startup
|
||
tmos_set_event(centralTaskId, START_DEVICE_EVT);
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralInitConnItem
|
||
*
|
||
* @brief Init Connection Item
|
||
*
|
||
* @param task_id -
|
||
* centralConnList -
|
||
*
|
||
* @return NULL
|
||
*/
|
||
static void centralInitConnItem(uint8_t task_id, centralConnItem_t *centralConnList)
|
||
{
|
||
uint8_t connItem;
|
||
for(connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
|
||
{
|
||
centralConnList[connItem].taskID = TMOS_ProcessEventRegister(Central_ProcessEvent);
|
||
centralConnList[connItem].connHandle = GAP_CONNHANDLE_INIT;
|
||
centralConnList[connItem].state = BLE_STATE_IDLE;
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
centralConnList[connItem].charHdl = 0;
|
||
centralConnList[connItem].svcStartHdl = 0;
|
||
centralConnList[connItem].svcEndHdl = 0;
|
||
centralConnList[connItem].cccHdl = 0;
|
||
}
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn Central_ProcessEvent
|
||
*
|
||
* @brief Central Application Task event processor. This function
|
||
* is called to process all events for the task. Events
|
||
* include timers, messages and any other user defined events.
|
||
*中央应用程序任务事件处理器。调用此函数来处理任务的所有事件。事件包括定时器、消息和任何其他用户定义的事件。
|
||
* @param task_id - The TMOS assigned task ID.
|
||
* @param events - events to process. This is a bit map and can
|
||
* contain more than one event.
|
||
*
|
||
* @return events not processed
|
||
*/
|
||
uint16_t Central_ProcessEvent(uint8_t task_id, uint16_t events)
|
||
{
|
||
if(events & SYS_EVENT_MSG)
|
||
{
|
||
uint8_t *pMsg;
|
||
|
||
if((pMsg = tmos_msg_receive(centralTaskId)) != NULL)
|
||
{
|
||
central_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
|
||
// Release the TMOS message
|
||
tmos_msg_deallocate(pMsg);
|
||
}
|
||
// return unprocessed events
|
||
return (events ^ SYS_EVENT_MSG);
|
||
}
|
||
|
||
if(events & START_DEVICE_EVT)
|
||
{
|
||
// Start the Device 启动设备
|
||
GAPRole_CentralStartDevice(centralTaskId, ¢ralBondCB, ¢ralRoleCB);
|
||
return (events ^ START_DEVICE_EVT);
|
||
}
|
||
//终止现有连接
|
||
if(events & ESTABLISH_LINK_TIMEOUT_EVT)
|
||
{
|
||
GAPRole_TerminateLink(INVALID_CONNHANDLE);
|
||
return (events ^ ESTABLISH_LINK_TIMEOUT_EVT);
|
||
}
|
||
|
||
if(task_id == centralConnList[CONNECT0_ITEM].taskID)
|
||
{
|
||
return connect0_ProcessEvent(task_id, events);
|
||
}
|
||
else if(task_id == centralConnList[CONNECT1_ITEM].taskID)
|
||
{
|
||
return connect1_ProcessEvent(task_id, events);
|
||
}
|
||
// else if(task_id == centralConnList[CONNECT2_ITEM].taskID)
|
||
// {
|
||
// return connect2_ProcessEvent(task_id, events);
|
||
// }
|
||
// Discard unknown events
|
||
return 0;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn connect0_ProcessEvent
|
||
*
|
||
* @brief Process an incoming task message.
|
||
*
|
||
* @param pMsg - message to process
|
||
*
|
||
* @return none
|
||
*/
|
||
static uint16_t connect0_ProcessEvent(uint8_t task_id, uint16_t events)
|
||
{
|
||
if(events & START_SVC_DISCOVERY_EVT)
|
||
{
|
||
// start service discovery
|
||
centralConnIistStartDiscovery_0();
|
||
return (events ^ START_SVC_DISCOVERY_EVT);
|
||
}
|
||
|
||
if(events & START_READ_OR_WRITE_EVT)
|
||
{
|
||
if(centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
|
||
{
|
||
if(centralDoWrite)
|
||
{
|
||
// Do a write
|
||
attWriteReq_t req;
|
||
|
||
req.cmd = FALSE;
|
||
req.sig = FALSE;
|
||
req.handle = centralConnList[CONNECT0_ITEM].charHdl;
|
||
req.len = 1;
|
||
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
|
||
if(req.pValue != NULL)
|
||
{
|
||
*req.pValue = centralCharVal;
|
||
|
||
if(GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
|
||
{
|
||
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
|
||
centralDoWrite = !centralDoWrite;
|
||
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
|
||
}
|
||
else
|
||
{
|
||
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Do a read
|
||
attReadReq_t req;
|
||
|
||
req.handle = centralConnList[CONNECT0_ITEM].charHdl;
|
||
if(GATT_ReadCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
|
||
{
|
||
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
|
||
centralDoWrite = !centralDoWrite;
|
||
}
|
||
}
|
||
}
|
||
return (events ^ START_READ_OR_WRITE_EVT);
|
||
}
|
||
|
||
if(events & START_PARAM_UPDATE_EVT)
|
||
{
|
||
// start connect parameter update
|
||
GAPRole_UpdateLink(centralConnList[CONNECT0_ITEM].connHandle,
|
||
DEFAULT_UPDATE_MIN_CONN_INTERVAL,
|
||
DEFAULT_UPDATE_MAX_CONN_INTERVAL,
|
||
DEFAULT_UPDATE_SLAVE_LATENCY,
|
||
DEFAULT_UPDATE_CONN_TIMEOUT);
|
||
|
||
return (events ^ START_PARAM_UPDATE_EVT);
|
||
}
|
||
|
||
if(events & START_WRITE_CCCD_EVT)
|
||
{
|
||
if(centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
|
||
{
|
||
// Do a write
|
||
attWriteReq_t req;
|
||
|
||
req.cmd = FALSE;
|
||
req.sig = FALSE;
|
||
req.handle = centralConnList[CONNECT0_ITEM].cccHdl;
|
||
req.len = 2;
|
||
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
|
||
if(req.pValue != NULL)
|
||
{
|
||
req.pValue[0] = 1;
|
||
req.pValue[1] = 0;
|
||
|
||
if(GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
|
||
{
|
||
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
|
||
}
|
||
else
|
||
{
|
||
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
|
||
}
|
||
}
|
||
}
|
||
return (events ^ START_WRITE_CCCD_EVT);
|
||
}
|
||
|
||
if(events & START_READ_RSSI_EVT)
|
||
{
|
||
GAPRole_ReadRssiCmd(centralConnList[CONNECT0_ITEM].connHandle);
|
||
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
|
||
return (events ^ START_READ_RSSI_EVT);
|
||
}
|
||
// Discard unknown events
|
||
return 0;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn connect1_ProcessEvent
|
||
*
|
||
* @brief Process an incoming task message.
|
||
*
|
||
* @param pMsg - message to process
|
||
*
|
||
* @return none
|
||
*/
|
||
static uint16_t connect1_ProcessEvent(uint8_t task_id, uint16_t events)
|
||
{
|
||
if(events & START_SVC_DISCOVERY_EVT)
|
||
{
|
||
// start service discovery
|
||
centralConnIistStartDiscovery_1();
|
||
return (events ^ START_SVC_DISCOVERY_EVT);
|
||
}
|
||
|
||
if(events & START_READ_OR_WRITE_EVT)
|
||
{
|
||
if(centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
|
||
{
|
||
if(centralDoWrite)
|
||
{
|
||
// Do a write
|
||
attWriteReq_t req;
|
||
|
||
req.cmd = FALSE;
|
||
req.sig = FALSE;
|
||
req.handle = centralConnList[CONNECT1_ITEM].charHdl;
|
||
req.len = 1;//发送的长度
|
||
req.pValue = GATT_bm_alloc(centralConnList[CONNECT1_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
|
||
if(req.pValue != NULL)
|
||
{
|
||
*req.pValue = centralCharVal;//发送的数据
|
||
|
||
if(GATT_WriteCharValue(centralConnList[CONNECT1_ITEM].connHandle, &req, centralTaskId) == SUCCESS)//发送函数
|
||
{
|
||
centralConnList[CONNECT1_ITEM].procedureInProgress = TRUE;
|
||
centralDoWrite = !centralDoWrite;
|
||
tmos_start_task(centralConnList[CONNECT1_ITEM].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
|
||
}
|
||
else
|
||
{
|
||
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Do a read
|
||
attReadReq_t req;
|
||
|
||
req.handle = centralConnList[CONNECT1_ITEM].charHdl;
|
||
if(GATT_ReadCharValue(centralConnList[CONNECT1_ITEM].connHandle, &req, centralTaskId) == SUCCESS)//读取函数
|
||
{
|
||
centralConnList[CONNECT1_ITEM].procedureInProgress = TRUE;
|
||
centralDoWrite = !centralDoWrite;
|
||
}
|
||
}
|
||
}
|
||
return (events ^ START_READ_OR_WRITE_EVT);
|
||
}
|
||
|
||
if(events & START_PARAM_UPDATE_EVT)
|
||
{
|
||
// start connect parameter update
|
||
GAPRole_UpdateLink(centralConnList[CONNECT1_ITEM].connHandle,
|
||
DEFAULT_UPDATE_MIN_CONN_INTERVAL,
|
||
DEFAULT_UPDATE_MAX_CONN_INTERVAL,
|
||
DEFAULT_UPDATE_SLAVE_LATENCY,
|
||
DEFAULT_UPDATE_CONN_TIMEOUT);
|
||
|
||
return (events ^ START_PARAM_UPDATE_EVT);
|
||
}
|
||
if(events & START_WRITE_CCCD_EVT)
|
||
{
|
||
if(centralConnList[CONNECT1_ITEM].procedureInProgress == FALSE)
|
||
{
|
||
// Do a write
|
||
attWriteReq_t req;
|
||
|
||
req.cmd = FALSE;
|
||
req.sig = FALSE;
|
||
req.handle = centralConnList[CONNECT1_ITEM].cccHdl;
|
||
req.len = 2;
|
||
req.pValue = GATT_bm_alloc(centralConnList[CONNECT1_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
|
||
if(req.pValue != NULL)
|
||
{
|
||
req.pValue[0] = 1;
|
||
req.pValue[1] = 0;
|
||
|
||
if(GATT_WriteCharValue(centralConnList[CONNECT1_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
|
||
{
|
||
centralConnList[CONNECT1_ITEM].procedureInProgress = TRUE;
|
||
}
|
||
else
|
||
{
|
||
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
|
||
}
|
||
}
|
||
}
|
||
return (events ^ START_WRITE_CCCD_EVT);
|
||
}
|
||
|
||
if(events & START_READ_RSSI_EVT)
|
||
{
|
||
GAPRole_ReadRssiCmd(centralConnList[CONNECT1_ITEM].connHandle);
|
||
tmos_start_task(centralConnList[CONNECT1_ITEM].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
|
||
return (events ^ START_READ_RSSI_EVT);
|
||
}
|
||
// Discard unknown events
|
||
return 0;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn central_ProcessTMOSMsg
|
||
*
|
||
* @brief Process an incoming task message.
|
||
*
|
||
* @param pMsg - message to process
|
||
*
|
||
* @return none
|
||
*/
|
||
static void central_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
|
||
{
|
||
switch(pMsg->event)
|
||
{
|
||
case GATT_MSG_EVENT:
|
||
centralProcessGATTMsg((gattMsgEvent_t *)pMsg);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralProcessGATTMsg
|
||
*
|
||
* @brief Process GATT messages
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralProcessGATTMsg(gattMsgEvent_t *pMsg)
|
||
{
|
||
uint8_t connItem;
|
||
for(connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
|
||
{
|
||
if(centralConnList[connItem].connHandle == pMsg->connHandle)
|
||
break;
|
||
}
|
||
if(connItem == CENTRAL_MAX_CONNECTION)
|
||
{
|
||
return;
|
||
// Should not go there
|
||
}
|
||
|
||
if(centralConnList[connItem].state != BLE_STATE_CONNECTED)
|
||
{
|
||
// In case a GATT message came after a connection has dropped,
|
||
// ignore the message
|
||
GATT_bm_free(&pMsg->msg, pMsg->method);
|
||
return;
|
||
}
|
||
|
||
if((pMsg->method == ATT_EXCHANGE_MTU_RSP) || ((pMsg->method == ATT_ERROR_RSP) &&
|
||
(pMsg->msg.errorRsp.reqOpcode == ATT_EXCHANGE_MTU_REQ)))
|
||
{
|
||
if(pMsg->method == ATT_ERROR_RSP)
|
||
{
|
||
uint8_t status = pMsg->msg.errorRsp.errCode;
|
||
|
||
PRINT("Exchange MTU Error: %x\r\n", status);
|
||
}
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
}
|
||
|
||
if(pMsg->method == ATT_MTU_UPDATED_EVENT)
|
||
{
|
||
PRINT("MTU: %x\r\n", pMsg->msg.mtuEvt.MTU);
|
||
}
|
||
|
||
if((pMsg->method == ATT_READ_RSP) ||
|
||
((pMsg->method == ATT_ERROR_RSP) &&
|
||
(pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ)))
|
||
{
|
||
if(pMsg->method == ATT_ERROR_RSP)
|
||
{
|
||
uint8_t status = pMsg->msg.errorRsp.errCode;
|
||
|
||
PRINT("Read Error: %x\r\n", status);
|
||
}
|
||
else
|
||
{
|
||
// After a successful read, display the read value
|
||
PRINT("Read rsp: %x\r\n", *pMsg->msg.readRsp.pValue);
|
||
}
|
||
centralConnList[connItem].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 == ATT_ERROR_RSP)
|
||
{
|
||
uint8_t status = pMsg->msg.errorRsp.errCode;
|
||
|
||
PRINT("Write Error: %x\r\n", status);
|
||
}
|
||
else
|
||
{
|
||
// After a succesful write, display the value that was written and increment value
|
||
PRINT("Write sent: %x\r\n", centralCharVal);
|
||
|
||
}
|
||
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
}
|
||
else if(pMsg->method == ATT_HANDLE_VALUE_NOTI)
|
||
{
|
||
PRINT("Receive noti: %x\r\n", *pMsg->msg.handleValueNoti.pValue);
|
||
}
|
||
else if(centralConnList[connItem].discState != BLE_DISC_STATE_IDLE)
|
||
{
|
||
centralGATTDiscoveryEvent(connItem, pMsg);
|
||
}
|
||
GATT_bm_free(&pMsg->msg, pMsg->method);
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralRssiCB
|
||
*
|
||
* @brief RSSI callback.
|
||
*
|
||
* @param connHandle - connection handle
|
||
* @param rssi - RSSI
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralRssiCB(uint16_t connHandle, int8_t rssi)
|
||
{
|
||
PRINT("RSSI -%d dB Conn - %x \r\n", -rssi, connHandle);
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralHciMTUChangeCB
|
||
*
|
||
* @brief MTU changed callback.
|
||
*
|
||
* @param maxTxOctets - Max tx octets
|
||
* @param maxRxOctets - Max rx octets
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralHciMTUChangeCB(uint16_t connHandle, uint16_t maxTxOctets, uint16_t maxRxOctets)
|
||
{
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralEventCB
|
||
*
|
||
* @brief Central event callback function.
|
||
*
|
||
* @param pEvent - pointer to event structure
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralEventCB(gapRoleEvent_t *pEvent)
|
||
{
|
||
uint8_t advdata[32] = {0};
|
||
switch(pEvent->gap.opcode)
|
||
{
|
||
case GAP_DEVICE_INIT_DONE_EVENT:
|
||
{
|
||
PRINT("Discovering...\r\n");
|
||
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
|
||
DEFAULT_DISCOVERY_ACTIVE_SCAN,
|
||
DEFAULT_DISCOVERY_WHITE_LIST);//开始扫描设备
|
||
}
|
||
break;
|
||
|
||
case GAP_DEVICE_INFO_EVENT:
|
||
{
|
||
// Add device to list
|
||
centralAddDeviceInfo(pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType);
|
||
}
|
||
break;
|
||
case GAP_DEVICE_DISCOVERY_EVENT:
|
||
{
|
||
uint8_t i;
|
||
|
||
// See if peer device has been discovered
|
||
for(i = 0; i < centralScanRes; i++)
|
||
{
|
||
if(centralAddrCmp(PeerAddrDef, centralDevList[i].addr))
|
||
break;
|
||
}
|
||
|
||
/*Peer device not found*/
|
||
if(i == centralScanRes)
|
||
{
|
||
PRINT("Device not found...\r\n");
|
||
|
||
centralScanRes = 0;
|
||
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
|
||
DEFAULT_DISCOVERY_ACTIVE_SCAN,
|
||
DEFAULT_DISCOVERY_WHITE_LIST);
|
||
PRINT("Discovering...\r\n");
|
||
}
|
||
else// Peer device found
|
||
{
|
||
PRINT("Device found...\r\n");
|
||
GAPRole_CentralEstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,
|
||
DEFAULT_LINK_WHITE_LIST,
|
||
centralDevList[i].addrType,
|
||
centralDevList[i].addr);
|
||
|
||
// Start establish link timeout event
|
||
tmos_start_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT, ESTABLISH_LINK_TIMEOUT);
|
||
PRINT("Connecting...\r\n");
|
||
}
|
||
}
|
||
break;
|
||
|
||
case GAP_LINK_ESTABLISHED_EVENT:
|
||
{
|
||
tmos_stop_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT);//关闭连接超时任务
|
||
if(pEvent->gap.hdr.status == SUCCESS)
|
||
{
|
||
uint8_t connItem;
|
||
for(connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
|
||
{
|
||
if(centralConnList[connItem].connHandle == GAP_CONNHANDLE_INIT)
|
||
break;
|
||
}
|
||
if(connItem == CENTRAL_MAX_CONNECTION)
|
||
{
|
||
GAPRole_TerminateLink(pEvent->linkCmpl.connectionHandle);
|
||
PRINT("Connection max...\r\n");
|
||
}
|
||
else
|
||
{
|
||
centralConnList[connItem].state = BLE_STATE_CONNECTED;
|
||
centralConnList[connItem].connHandle = pEvent->linkCmpl.connectionHandle;
|
||
|
||
PRINT("Conn %x - Int %x \r\n", pEvent->linkCmpl.connectionHandle, pEvent->linkCmpl.connInterval);
|
||
|
||
if(connItem == CONNECT0_ITEM)
|
||
{
|
||
centralConnList[connItem].procedureInProgress = TRUE;
|
||
|
||
// Initiate service discovery 开启枚举服务任务
|
||
tmos_start_task(centralConnList[connItem].taskID, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
|
||
|
||
// Initiate connect parameter update 开始连接参数更新任务
|
||
tmos_start_task(centralConnList[connItem].taskID, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
|
||
|
||
// Start RSSI polling
|
||
tmos_start_task(centralConnList[connItem].taskID, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
|
||
}
|
||
|
||
// else if(connItem == CONNECT1_ITEM)
|
||
// {
|
||
// }
|
||
|
||
// else if(connItem == CONNECT2_ITEM)
|
||
// {
|
||
// }
|
||
|
||
PRINT("Connected...\r\n");
|
||
|
||
// See if need discover again
|
||
for(connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
|
||
{
|
||
if(centralConnList[connItem].connHandle == GAP_CONNHANDLE_INIT)
|
||
break;
|
||
}
|
||
if(connItem < CENTRAL_MAX_CONNECTION)
|
||
{
|
||
PRINT("Discovering...\r\n");
|
||
centralScanRes = 0;
|
||
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
|
||
DEFAULT_DISCOVERY_ACTIVE_SCAN,
|
||
DEFAULT_DISCOVERY_WHITE_LIST);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
PRINT("Connect Failed...Reason:%X\r\n", pEvent->gap.hdr.status);
|
||
PRINT("Discovering...\r\n");
|
||
centralScanRes = 0;
|
||
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
|
||
DEFAULT_DISCOVERY_ACTIVE_SCAN,
|
||
DEFAULT_DISCOVERY_WHITE_LIST);//重新开始扫描
|
||
}
|
||
}
|
||
break;
|
||
|
||
case GAP_LINK_TERMINATED_EVENT: //断开连接事件,打印断开连接原因,并重新开始扫描
|
||
{
|
||
uint8_t connItem;
|
||
for(connItem = 0; connItem < CENTRAL_MAX_CONNECTION; connItem++)
|
||
{
|
||
if(centralConnList[connItem].connHandle == pEvent->linkTerminate.connectionHandle)
|
||
break;
|
||
}
|
||
if(connItem == CENTRAL_MAX_CONNECTION)
|
||
{
|
||
// Should not go there
|
||
}
|
||
PRINT(" %x Disconnected...Reason:%x\r\n", centralConnList[connItem].connHandle, pEvent->linkTerminate.reason);
|
||
centralConnList[connItem].state = BLE_STATE_IDLE;
|
||
centralConnList[connItem].connHandle = GAP_CONNHANDLE_INIT;
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
|
||
centralConnList[connItem].charHdl = 0;
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
centralScanRes = 0;
|
||
|
||
tmos_stop_task(centralConnList[connItem].taskID, START_READ_RSSI_EVT);
|
||
|
||
PRINT("Discovering...\r\n");
|
||
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
|
||
DEFAULT_DISCOVERY_ACTIVE_SCAN,
|
||
DEFAULT_DISCOVERY_WHITE_LIST);
|
||
}
|
||
break;
|
||
|
||
case GAP_LINK_PARAM_UPDATE_EVENT:
|
||
{
|
||
PRINT("Update %x - Int %x \r\n", pEvent->linkUpdate.connectionHandle, pEvent->linkUpdate.connInterval);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn pairStateCB
|
||
*
|
||
* @brief Pairing state callback.
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralPairStateCB(uint16_t connHandle, uint8_t state, uint8_t status)
|
||
{
|
||
if(state == GAPBOND_PAIRING_STATE_STARTED)
|
||
{
|
||
PRINT("Connection %04x - Pairing started:%d\r\n", connHandle, status);
|
||
}
|
||
else if(state == GAPBOND_PAIRING_STATE_COMPLETE)
|
||
{
|
||
if(status == SUCCESS)
|
||
{
|
||
PRINT("Connection %04x - Pairing success\r\n", connHandle);
|
||
}
|
||
else
|
||
{
|
||
PRINT("Connection %04x - Pairing fail\r\n", connHandle);
|
||
}
|
||
}
|
||
else if(state == GAPBOND_PAIRING_STATE_BONDED)
|
||
{
|
||
if(status == SUCCESS)
|
||
{
|
||
PRINT("Connection %04x - Bonding success\r\n", connHandle);
|
||
}
|
||
}
|
||
else if(state == GAPBOND_PAIRING_STATE_BOND_SAVED)
|
||
{
|
||
if(status == SUCCESS)
|
||
{
|
||
PRINT("Connection %04x - Bond save success\r\n", connHandle);
|
||
}
|
||
else
|
||
{
|
||
PRINT("Connection %04x - Bond save failed: %d\r\n", connHandle, status);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralPasscodeCB
|
||
*
|
||
* @brief Passcode callback.
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralPasscodeCB(uint8_t *deviceAddr, uint16_t connectionHandle,
|
||
uint8_t uiInputs, uint8_t uiOutputs)
|
||
{
|
||
uint32_t passcode;
|
||
|
||
// Create random passcode
|
||
passcode = tmos_rand();
|
||
passcode %= 1000000;
|
||
// Display passcode to user
|
||
if(uiOutputs != 0)
|
||
{
|
||
PRINT("Passcode:%06d\r\n", (int)passcode);
|
||
}
|
||
// Send passcode response
|
||
GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralConnIistStartDiscovery_0
|
||
*
|
||
* @brief Start connection 0 service discovery.
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralConnIistStartDiscovery_0(void)
|
||
{
|
||
uint8_t uuid[ATT_BT_UUID_SIZE] = {LO_UINT16(SIMPLEPROFILE_SERV_UUID),
|
||
HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
|
||
|
||
// Initialize cached handles
|
||
centralConnList[CONNECT0_ITEM].svcStartHdl = centralConnList[CONNECT0_ITEM].svcEndHdl = centralConnList[CONNECT0_ITEM].charHdl = 0;
|
||
|
||
centralConnList[CONNECT0_ITEM].discState = BLE_DISC_STATE_SVC;
|
||
|
||
// Discovery simple BLE service
|
||
GATT_DiscPrimaryServiceByUUID(centralConnList[CONNECT0_ITEM].connHandle,
|
||
uuid,
|
||
ATT_BT_UUID_SIZE,
|
||
centralTaskId);
|
||
}
|
||
/*********************************************************************
|
||
* @fn centralConnIistStartDiscovery_1
|
||
*
|
||
* @brief Start connection 1 service discovery.
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralConnIistStartDiscovery_1(void)
|
||
{
|
||
uint8_t uuid[ATT_BT_UUID_SIZE] = {LO_UINT16(SIMPLEPROFILE_SERV_UUID),
|
||
HI_UINT16(SIMPLEPROFILE_SERV_UUID)};
|
||
|
||
// Initialize cached handles
|
||
centralConnList[CONNECT1_ITEM].svcStartHdl = centralConnList[CONNECT1_ITEM].svcEndHdl = centralConnList[CONNECT1_ITEM].charHdl = 0;
|
||
|
||
centralConnList[CONNECT1_ITEM].discState = BLE_DISC_STATE_SVC;
|
||
|
||
// Discovery simple BLE service
|
||
GATT_DiscPrimaryServiceByUUID(centralConnList[CONNECT1_ITEM].connHandle,
|
||
uuid,
|
||
ATT_BT_UUID_SIZE,
|
||
centralTaskId);
|
||
}
|
||
/*********************************************************************
|
||
* @fn centralGATTDiscoveryEvent
|
||
*
|
||
* @brief Process GATT discovery event
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg)
|
||
{
|
||
attReadByTypeReq_t req;
|
||
if(connItem == CONNECT0_ITEM)
|
||
{
|
||
if(centralConnList[connItem].discState == BLE_DISC_STATE_SVC)
|
||
{
|
||
// Service found, store handles
|
||
if(pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
|
||
pMsg->msg.findByTypeValueRsp.numInfo > 0)
|
||
{
|
||
centralConnList[connItem].svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
|
||
centralConnList[connItem].svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
|
||
|
||
// Display Profile Service handle range
|
||
PRINT("Found Profile Service handle : %x ~ %x \r\n", centralConnList[connItem].svcStartHdl, centralConnList[connItem].svcEndHdl);
|
||
}
|
||
// If procedure complete
|
||
if((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP && pMsg->hdr.status == bleProcedureComplete) || (pMsg->method == ATT_ERROR_RSP))
|
||
{
|
||
if(centralConnList[connItem].svcStartHdl != 0)
|
||
{
|
||
// Discover characteristic
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_CHAR;
|
||
req.startHandle = centralConnList[connItem].svcStartHdl;
|
||
req.endHandle = centralConnList[connItem].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);
|
||
|
||
GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
|
||
}
|
||
}
|
||
}
|
||
else if(centralConnList[connItem].discState == BLE_DISC_STATE_CHAR)
|
||
{
|
||
// Characteristic found, store handle
|
||
if(pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0)
|
||
{
|
||
centralConnList[connItem].charHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
|
||
pMsg->msg.readByTypeRsp.pDataList[1]);
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
|
||
// Start do read or write
|
||
tmos_start_task(centralConnList[connItem].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);//开启一个读写测试任务
|
||
|
||
// Display Characteristic 1 handle
|
||
PRINT("Found Characteristic 1 handle : %x \r\n", centralConnList[0].charHdl);
|
||
}
|
||
|
||
if((pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->hdr.status == bleProcedureComplete) || (pMsg->method == ATT_ERROR_RSP))
|
||
{
|
||
// Discover characteristic
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_CCCD;
|
||
req.startHandle = centralConnList[connItem].svcStartHdl;
|
||
req.endHandle = centralConnList[connItem].svcEndHdl;
|
||
req.type.len = ATT_BT_UUID_SIZE;
|
||
req.type.uuid[0] = LO_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
|
||
req.type.uuid[1] = HI_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
|
||
|
||
GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);//根据UUID寻找其句柄
|
||
}
|
||
|
||
}
|
||
else if(centralConnList[connItem].discState == BLE_DISC_STATE_CCCD)
|
||
{
|
||
// Characteristic found, store handle
|
||
if(pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0)
|
||
{
|
||
centralConnList[connItem].cccHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
|
||
pMsg->msg.readByTypeRsp.pDataList[1]);
|
||
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
|
||
// Start do write CCCD
|
||
tmos_start_task(centralConnList[connItem].taskID, START_WRITE_CCCD_EVT, DEFAULT_WRITE_CCCD_DELAY);//开启一个使能从机notify的定时器任务
|
||
|
||
// Display Characteristic 1 handle
|
||
PRINT("Found client characteristic configuration handle : %x \r\n", centralConnList[connItem].cccHdl);//输出的句柄值
|
||
}
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
|
||
}
|
||
}
|
||
|
||
else if(connItem == CONNECT1_ITEM)
|
||
{
|
||
if(centralConnList[connItem].discState == BLE_DISC_STATE_SVC)
|
||
{
|
||
// Service found, store handles
|
||
if(pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
|
||
pMsg->msg.findByTypeValueRsp.numInfo > 0)
|
||
{
|
||
centralConnList[connItem].svcStartHdl = ATT_ATTR_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
|
||
centralConnList[connItem].svcEndHdl = ATT_GRP_END_HANDLE(pMsg->msg.findByTypeValueRsp.pHandlesInfo, 0);
|
||
|
||
// Display Profile Service handle range
|
||
PRINT("Found Profile Service handle : %x ~ %x \r\n", centralConnList[connItem].svcStartHdl, centralConnList[connItem].svcEndHdl);
|
||
}
|
||
// If procedure complete
|
||
if((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
|
||
pMsg->hdr.status == bleProcedureComplete) ||
|
||
(pMsg->method == ATT_ERROR_RSP))
|
||
{
|
||
if(centralConnList[connItem].svcStartHdl != 0)
|
||
{
|
||
// Discover characteristic
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_CHAR;
|
||
req.startHandle = centralConnList[connItem].svcStartHdl;
|
||
req.endHandle = centralConnList[connItem].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);
|
||
|
||
GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
|
||
}
|
||
}
|
||
}
|
||
else if(centralConnList[connItem].discState == BLE_DISC_STATE_CHAR)
|
||
{
|
||
// Characteristic found, store handle
|
||
if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
|
||
pMsg->msg.readByTypeRsp.numPairs > 0)
|
||
{
|
||
centralConnList[connItem].charHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
|
||
pMsg->msg.readByTypeRsp.pDataList[1]);
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
|
||
// Start do read or write
|
||
tmos_start_task(centralConnList[connItem].taskID, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY);
|
||
|
||
// Display Characteristic 1 handle
|
||
PRINT("Found Characteristic 1 handle : %x \r\n", centralConnList[0].charHdl);
|
||
}
|
||
|
||
if((pMsg->method == ATT_READ_BY_TYPE_RSP &&
|
||
pMsg->hdr.status == bleProcedureComplete) ||
|
||
(pMsg->method == ATT_ERROR_RSP))
|
||
{
|
||
// Discover characteristic
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_CCCD;
|
||
req.startHandle = centralConnList[connItem].svcStartHdl;
|
||
req.endHandle = centralConnList[connItem].svcEndHdl;
|
||
req.type.len = ATT_BT_UUID_SIZE;
|
||
req.type.uuid[0] = LO_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
|
||
req.type.uuid[1] = HI_UINT16(GATT_CLIENT_CHAR_CFG_UUID);
|
||
|
||
GATT_ReadUsingCharUUID(centralConnList[connItem].connHandle, &req, centralTaskId);
|
||
}
|
||
|
||
}
|
||
else if(centralConnList[connItem].discState == BLE_DISC_STATE_CCCD)
|
||
{
|
||
// Characteristic found, store handle
|
||
if(pMsg->method == ATT_READ_BY_TYPE_RSP &&
|
||
pMsg->msg.readByTypeRsp.numPairs > 0)
|
||
{
|
||
centralConnList[connItem].cccHdl = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[0],
|
||
pMsg->msg.readByTypeRsp.pDataList[1]);
|
||
|
||
centralConnList[connItem].procedureInProgress = FALSE;
|
||
|
||
// Start do write CCCD
|
||
tmos_start_task(centralConnList[connItem].taskID, START_WRITE_CCCD_EVT, DEFAULT_WRITE_CCCD_DELAY);
|
||
|
||
// Display Characteristic 1 handle
|
||
PRINT("Found client characteristic configuration handle : %x \r\n", centralConnList[connItem].cccHdl);
|
||
}
|
||
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
|
||
}
|
||
}
|
||
|
||
// else if(connItem == CONNECT2_ITEM)
|
||
// {
|
||
// }
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralAddDeviceInfo
|
||
*
|
||
* @brief Add a device to the device discovery result list
|
||
*
|
||
* @return none
|
||
*/
|
||
static void centralAddDeviceInfo(uint8_t *pAddr, uint8_t addrType)
|
||
{
|
||
uint8_t i;
|
||
|
||
// If result count not at max
|
||
if(centralScanRes < DEFAULT_MAX_SCAN_RES)
|
||
{
|
||
// Check if device is already in scan results
|
||
for(i = 0; i < centralScanRes; i++)
|
||
{
|
||
if(tmos_memcmp(pAddr, centralDevList[i].addr, B_ADDR_LEN))
|
||
{
|
||
return;
|
||
}
|
||
}
|
||
// Add addr to scan result list
|
||
tmos_memcpy(centralDevList[centralScanRes].addr, pAddr, B_ADDR_LEN);
|
||
centralDevList[centralScanRes].addrType = addrType;
|
||
// Increment scan result count
|
||
centralScanRes++;
|
||
// Display device addr
|
||
PRINT("Device %d - Addr %x %x %x %x %x %x \r\n", centralScanRes,
|
||
centralDevList[centralScanRes - 1].addr[0],
|
||
centralDevList[centralScanRes - 1].addr[1],
|
||
centralDevList[centralScanRes - 1].addr[2],
|
||
centralDevList[centralScanRes - 1].addr[3],
|
||
centralDevList[centralScanRes - 1].addr[4],
|
||
centralDevList[centralScanRes - 1].addr[5]);
|
||
}
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @fn centralAddrCmp
|
||
*
|
||
* @brief none
|
||
*
|
||
* @return none
|
||
*/
|
||
static uint8_t centralAddrCmp(peerAddrDefItem_t *PeerAddrDef, uint8_t *addr)
|
||
{
|
||
uint8_t i;
|
||
for(i = 0; i < CENTRAL_MAX_CONNECTION; i++)
|
||
{
|
||
if(tmos_memcmp(PeerAddrDef[i].peerAddr, addr, B_ADDR_LEN))
|
||
break;
|
||
}
|
||
if(i == CENTRAL_MAX_CONNECTION)
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
/************************ endfile @ central **************************/
|