BLE_TYQ_BJQ_CH584M/APP/multiCentral.c

1257 lines
44 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*********************************************************************
* INCLUDES
*/
#include "CONFIG.h"
#include "gattprofile.h"
#include "multiCentral.h"
#include "bsp_uart.h"
#include "log.h"
#include "bsp_valve.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 // 2400*0.625 = 1500ms
// Connection min interval in 1.25ms
#define DEFAULT_MIN_CONNECTION_INTERVAL 80
// Connection max interval in 1.25ms
#define DEFAULT_MAX_CONNECTION_INTERVAL 80 * 5
// Connection supervision timeout in 10ms
/*修改为最大值*/
#define DEFAULT_CONNECTION_TIMEOUT 100 // 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
// 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 20
// Maximum connection interval (units of 1.25ms)
#define DEFAULT_UPDATE_MAX_CONN_INTERVAL 100
// Slave latency to use parameter update
#define DEFAULT_UPDATE_SLAVE_LATENCY 5
// Supervision timeout value (units of 10ms)
#define DEFAULT_UPDATE_CONN_TIMEOUT 600
// 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 1600
// 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},
{0xb6, 0xb4, 0x8f, 0x10, 0x53, 0x5c},
// {0x03, 0x02, 0x03, 0xE4, 0xC2, 0x84},
};
// Connection item list
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);
/*********************************************************************
* 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, 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;
uint8_t pairMode = DEFAULT_PAIRING_MODE;
uint8_t mitm = DEFAULT_MITM_MODE;
uint8_t ioCap = DEFAULT_IO_CAPABILITIES;
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++)
{
// 每个连接的任务通过taskID区分
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, &centralBondCB, &centralRoleCB);
return (events ^ START_DEVICE_EVT);
}
if (events & ESTABLISH_LINK_TIMEOUT_EVT)
{
GAPRole_TerminateLink(INVALID_CONNHANDLE);
return (events ^ ESTABLISH_LINK_TIMEOUT_EVT);
}
// 连接0的任务处理
if (task_id == centralConnList[CONNECT0_ITEM].taskID)
{
return connect0_ProcessEvent(task_id, events);
}
// 连接1的任务处理
else if (task_id == centralConnList[CONNECT1_ITEM].taskID)
{
}
// 连接2的任务处理
// else if(task_id == centralConnList[CONNECT2_ITEM].taskID)
// {
// }
// 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 & CH2_READ_EVT)
{
logDebug("CH2_READ_EVT\r\n");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
// read
attReadReq_t req;
req.handle = centralConnList[CONNECT0_ITEM].charHd2;
if (GATT_ReadCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
{
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH2_READ_EVT, 160000);
}
}
return (events ^ CH2_READ_EVT);
}
if (events & CH3_WRITE_EVT)
{
logDebug("CH3_WRITE_EVT\r\n");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
logDebug("centralConnList CH3_WRITE_EVT\n");
static uint8_t sendcnt = 0;
attWriteReq_t req;
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[CONNECT0_ITEM].charHd3;
logDebug("handle:%x\r\n", req.handle);
req.len = 3;
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if (req.pValue != NULL)
{
logDebug("req.pValue != NULL\r\n");
req.pValue[0] = 0x11;
req.pValue[1] = 0x22;
req.pValue[2] = sendcnt++;
if (GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS)
{
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH3_WRITE_EVT, 3200);
logDebug("GATT_WriteCharValue\r\n");
}
else
{
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
}
}
}
return (events ^ CH3_WRITE_EVT);
}
if (events & CH4_NOTI_EVT)
{
logDebug("CH4_NOTI_EVT\r\n");
if (centralConnList[CONNECT0_ITEM].procedureInProgress == FALSE)
{
// Do a write
attWriteReq_t req;
logDebug("CH4_NOTI_EVT handle:%x\r\n", req.handle);
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[CONNECT0_ITEM].charHd4;
req.len = 2;
req.pValue = GATT_bm_alloc(centralConnList[CONNECT0_ITEM].connHandle, ATT_WRITE_REQ, req.len, NULL, 0); // 内存申请
if (req.pValue != NULL)
{
logDebug("CH4_NOTI_EVT req.pValue != NULL\r\n");
req.pValue[0] = 1;
req.pValue[1] = 0;
if (GATT_WriteCharValue(centralConnList[CONNECT0_ITEM].connHandle, &req, centralTaskId) == SUCCESS) // 发送
{
logDebug("GATT_WriteCharValue CH4_NOTI_EVT\r\n");
centralConnList[CONNECT0_ITEM].procedureInProgress = TRUE;
}
else
{
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ); // 释放内存
}
}
}
return (events ^ CH4_NOTI_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);
}
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);
}
// 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;
logDebug("Exchange MTU Error: %x\r\n", status);
}
centralConnList[connItem].procedureInProgress = FALSE;
}
if (pMsg->method == ATT_MTU_UPDATED_EVENT)
{
logDebug("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;
logDebug("Read Error: %x\r\n", status);
}
else
{
// After a successful read, display the read value
logDebug("Read rsp: ");
logHexDumpAll(pMsg->msg.readRsp.pValue, pMsg->msg.readRsp.len);
}
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;
logDebug("Write Error: %x\r\n", status);
}
else
{
// After a succesful write, display the value that was written and increment value
logDebug("Write sent: %x\r\n", centralCharVal);
}
centralConnList[connItem].procedureInProgress = FALSE;
}
else if (pMsg->method == ATT_HANDLE_VALUE_NOTI)
{
logDebug("Noti: ");
logHexDumpAll(pMsg->msg.handleValueNoti.pValue, pMsg->msg.handleValueNoti.len);
}
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)
{
logDebug("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)
{
switch (pEvent->gap.opcode)
{
case GAP_DEVICE_INIT_DONE_EVENT:
{
logDebug("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)
{
logDebug("Device not found...\r\n");
centralScanRes = 0;
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
logDebug("Discovering...\r\n");
}
// Peer device found
else
{
logDebug("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);
logDebug("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);
logDebug("Connection max...\r\n");
}
else
{
centralConnList[connItem].state = BLE_STATE_CONNECTED;
centralConnList[connItem].connHandle = pEvent->linkCmpl.connectionHandle;
logDebug("Conn %x - Int %x \r\n", pEvent->linkCmpl.connectionHandle, pEvent->linkCmpl.connInterval);
// 连接0
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);
}
// 连接1
else if (connItem == CONNECT1_ITEM)
{
}
// 连接2
// else if(connItem == CONNECT2_ITEM)
// {
// }
logDebug("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)
{
logDebug("Discovering...\r\n");
centralScanRes = 0;
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
}
}
}
else
{
logDebug("Connect Failed...Reason:%X\r\n", pEvent->gap.hdr.status);
logDebug("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
}
logDebug(" %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);
logDebug("Discovering...\r\n");
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
}
break;
case GAP_LINK_PARAM_UPDATE_EVENT:
{
logDebug("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)
{
logDebug("Connection %04x - Pairing started:%d\r\n", connHandle, status);
}
else if (state == GAPBOND_PAIRING_STATE_COMPLETE)
{
if (status == SUCCESS)
{
logDebug("Connection %04x - Pairing success\r\n", connHandle);
}
else
{
logDebug("Connection %04x - Pairing fail\r\n", connHandle);
}
}
else if (state == GAPBOND_PAIRING_STATE_BONDED)
{
if (status == SUCCESS)
{
logDebug("Connection %04x - Bonding success\r\n", connHandle);
}
}
else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED)
{
if (status == SUCCESS)
{
logDebug("Connection %04x - Bond save success\r\n", connHandle);
}
else
{
logDebug("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)
{
logDebug("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 centralGATTDiscoveryEvent
*
* @brief Process GATT discovery event
*
* @return none
*/
static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg)
{
attReadByTypeReq_t req;
// 连接0的枚举
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
logDebug("Found Profile Service handle : %x ~ %x \r\n", centralConnList[connItem].svcStartHdl, centralConnList[connItem].svcEndHdl);
#if 0
for (uint16_t i = 0; i < pMsg->msg.readByGrpTypeRsp.numGrps; i++)
{
// uuid
printf("uuid = %x", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 4],
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]));
// Primary Service UUID Length
printf("%02d bit x", pMsg->msg.readByGrpTypeRsp.len - 4);
// printf("att len = %d\n", pMsg->msg.readByGrpTypeRsp.len);
printf("start handle:%04x", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i],
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 1]));
// Attribute End Group Handle
printf("end handle:%04x\r\n", BUILD_UINT16(
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 2],
pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 3]));
}
#endif
}
// If procedure complete
if ((pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->hdr.status == bleProcedureComplete) ||
(pMsg->method == ATT_ERROR_RSP))
{
// Discover characteristic
centralConnList[connItem].discState = BLE_DISC_STATE_CHAR;
uint8_t ret = GATT_DiscAllChars(centralConnList[connItem].connHandle, 0x01, 0xFFFF, centralTaskId);
logDebug("GATT_DiscAllChars:%02x\r\n", ret);
}
}
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)
{
for (unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs; i++)
{
// characteristic properties
uint8_t char_properties = pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 2];
uint16_t char_value_handle = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 3],
pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 4]);
// characteristic uuid length
uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5;
// uuid
uint8_t *char_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]);
logDebug("|-------------------------------------|");
logDebug("char_uuid\t:");
for (uint8_t i = 0; i < char_uuid_length; i++)
{
logDebug("%02x ", char_uuid[i]);
}
logDebug("char_value_handle\t:%04x\r\n", char_value_handle);
logDebug("char_uuid_length\t:%02d bit\r\n", char_uuid_length);
uint16_t char1uuid = SIMPLEPROFILE_CHAR1_UUID;
uint16_t char2uuid = SIMPLEPROFILE_CHAR2_UUID;
uint16_t char3uuid = SIMPLEPROFILE_CHAR3_UUID;
uint16_t char4uuid = SIMPLEPROFILE_CHAR4_UUID;
if (tmos_memcmp(char_uuid, &char1uuid, 2))
{
if (char_properties & (GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP))
{
centralConnList[connItem].charHdl = char_value_handle;
logDebug("char1 Write handle\t:%04x\r\n", char_value_handle);
centralConnList[connItem].procedureInProgress = FALSE;
// tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, START_READ_OR_WRITE_EVT, 1600);
}
}
else if (tmos_memcmp(char_uuid, &char2uuid, 2))
{
if (char_properties & (GATT_PROP_READ))
{
centralConnList[connItem].charHd2 = char_value_handle;
centralConnList[connItem].procedureInProgress = FALSE;
logDebug("char2 Write handle\t:%04x\r\n", char_value_handle);
// tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH2_READ_EVT, 2400);
}
}
else if (tmos_memcmp(char_uuid, &char3uuid, 2))
{
if (char_properties & (GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP))
{
centralConnList[connItem].charHd3 = char_value_handle;
logDebug("char3 Write handle\t:%04x\r\n", char_value_handle);
centralConnList[connItem].procedureInProgress = FALSE;
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH3_WRITE_EVT, 3200);
}
}
else if (tmos_memcmp(char_uuid, &char4uuid, 2))
{
if (char_properties & (GATT_PROP_NOTIFY))
{
centralConnList[connItem].discState = BLE_DISC_STATE_IDLE;
centralConnList[connItem].charHd4 = char_value_handle + 1;
centralConnList[connItem].procedureInProgress = FALSE;
logDebug("char4 Write handle\t:%04x\r\n", char_value_handle);
tmos_start_task(centralConnList[CONNECT0_ITEM].taskID, CH4_NOTI_EVT, 1600);
}
}
}
}
}
// 连接1的枚举
// else if (connItem == CONNECT1_ITEM)
// {
// }
// 连接2的枚举
// 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
logDebug("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 **************************/
/*用户自定义文件*/
void BSP_Master_Send(centralConnItem_t *centralConnList, uint8_t id, uint8_t *Data, uint8_t Len)
{
attWriteReq_t req;
uint8_t res;
if (centralConnList[id].state == BLE_STATE_CONNECTED) // 检查连接状态是否为连接状态
{
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralConnList[id].charHd3;
req.len = Len;
req.pValue = GATT_bm_alloc(centralConnList[id].connHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if (req.pValue != NULL)
{
tmos_memcpy(req.pValue, Data, Len);
res = GATT_WriteCharValue(centralConnList[id].connHandle, &req, centralTaskId);
if (res == SUCCESS)
{
logDebug("\n Master Write ok");
}
else
{
logDebug("\n Master Write faild= %x", res);
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
}
}
else
{
logDebug("\n alloc Faild");
}
}
}
int BSP_Master_Receive_Data(uint8_t *data, uint16_t len)
{
int ret = 0;
uint16_t index = 0;
uint8_t data_buf[64] = {0};
// 解析接收到的数据帧先寻找AA开头然后再找AA下一个字节其代表了数据长度然后找到代表长度的值的长度的下一位其为校验码校验码后为结束码0x55
// 如果数据正确,则提取数据,不正确,则不处理
if (len < 4)
{ // 至少需要 4 个字节:起始码、长度、校验码、结束码
logError("BT 数据帧长度不足");
logHexDumpAll(data, len);
return 1;
}
while (index < len && data[index] != 0xAA) // 寻找起始码 0xAA
{
index++;
}
if (index >= len - 3) // 不够空间容纳长度、校验码和结束码
{
logError("BT 数据帧起始码错误");
logHexDumpAll(data, len);
return 2;
}
uint16_t datalength = data[index + 1]; // 读取数据长度
if (index + 2 + datalength + 1 >= len) // 检查数据长度是否合理 数据长度 + 校验码 + 结束码
{
logError("BT 数据帧长度错误");
logHexDumpAll(data, len);
return 3; //
}
uint8_t rx_sum = data[index + 2 + datalength]; // 读取校验码
uint8_t calculated_sum = XOR_CheckSum(&data[0], datalength + 2); // 计算校验码
if (rx_sum != calculated_sum)
{
logError("BT 数据帧校验码错误 rx_sum = %02X, calculated_sum = %02X", rx_sum, calculated_sum);
logHexDumpAll(data, len);
return 4;
}
if (data[index + 2 + datalength + 1] != 0x55) // 检查结束码
{
logError("BT 数据帧结束码错误");
logHexDumpAll(data, len);
return 5;
}
// 到这一步说明数据没问题,将接收到的数据通过中心任务发送出去
// uint8_t *p_data;
// p_data = tmos_msg_allocate(length);
// if (p_data)
// {
// tmos_memcpy(p_data, data, length);
// tmos_msg_send(task_id, p_data);
// }
//
// tmos_msg_send(task_id, data);
return ret;
}