大佬们好
硬件情况:现在手头两块开发板,板1做从机,运行例程的hid_kbd;板2做主从一体机,板2主机连接板1,板2从机运行hid_kbd,并被pc端连接。
遇到问题:当板2从机连接pc端后,开启板1,板2主机发现并连接板1,此时板2从机开始与pc端持续断开重连,一直报错reason13或8。附件上传失败,我在下面提供了板2主机的代码,请各位多多指点。
大佬们好
硬件情况:现在手头两块开发板,板1做从机,运行例程的hid_kbd;板2做主从一体机,板2主机连接板1,板2从机运行hid_kbd,并被pc端连接。
遇到问题:当板2从机连接pc端后,开启板1,板2主机发现并连接板1,此时板2从机开始与pc端持续断开重连,一直报错reason13或8。附件上传失败,我在下面提供了板2主机的代码,请各位多多指点。
/********************************** (C) COPYRIGHT *******************************
* File Name : central.c
* Author : WCH
* Version : V1.1
* Date : 2020/08/06
* Description : 主机例程,主动扫描周围设备,连接至给定的从机设备地址,
* 寻找自定义服务及特征,执行读写命令,需与从机例程配合使用,
并将从机设备地址修改为该例程目标地址,默认为(84:C2:E4:03:02:02)
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "CONFIG.h"
#include "gattprofile.h"
#include "central.h"
/*********************************************************************
* 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
// Connection max interval in 1.25ms
#define DEFAULT_MAX_CONNECTION_INTERVAL 100
// Connection supervision timeout in 10ms
#define DEFAULT_CONNECTION_TIMEOUT 100
// 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 0
// 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_INITIATE
// 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 phy update delay in 0.625ms
#define DEFAULT_PHY_UPDATE_DELAY 2400
// 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 uint8_t PeerAddrDef[B_ADDR_LEN] = {0x2c, 0x5a, 0x83, 0x7b, 0x54, 0xd0};
// RSSI polling state
static uint8_t centralRssi = FALSE;
// Parameter update state
static uint8_t centralParamUpdate = TRUE;
// Phy update state
static uint8_t centralPhyUpdate = FALSE;
// Connection handle of current connection
static uint16_t centralConnHandle = GAP_CONNHANDLE_INIT;
// Application state
static uint8_t centralState = BLE_STATE_IDLE;
// Discovery state
static uint8_t centralDiscState = BLE_DISC_STATE_IDLE;
// Discovered service start and end handle
static uint16_t centralSvcStartHdl = 0;
static uint16_t centralSvcEndHdl = 0;
// Discovered characteristic handle
static uint16_t centralCharHdl = 0;
// Discovered Client Characteristic Configuration handle
static uint16_t centralCCCDHdl = 0;
// Value to write
static uint8_t centralCharVal = 0x5A;
// Value read/write toggle
static uint8_t centralDoWrite = TRUE;
// GATT read/write procedure state
static uint8_t centralProcedureInProgress = FALSE;
/*********************************************************************
* 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 void central_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
static void centralGATTDiscoveryEvent(gattMsgEvent_t *pMsg);
static void centralStartDiscovery(void);
static void centralAddDeviceInfo(uint8_t *pAddr, uint8_t addrType);
/*********************************************************************
* 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);
}
// 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 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(events & START_SVC_DISCOVERY_EVT)
{
// start service discovery
centralStartDiscovery();
return (events ^ START_SVC_DISCOVERY_EVT);
}
if(events & START_PARAM_UPDATE_EVT)
{
// start connect parameter update
GAPRole_UpdateLink(centralConnHandle,
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_PHY_UPDATE_EVT)
{
// start phy update
PRINT("PHY Update %x...\n", GAPRole_UpdatePHY(centralConnHandle, 0,
GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, GAP_PHY_OPTIONS_NOPRE));
return (events ^ START_PHY_UPDATE_EVT);
}
if(events & START_READ_OR_WRITE_EVT)
{
if(centralProcedureInProgress == FALSE)
{
if(centralDoWrite)
{
// Do a write
attWriteReq_t req;
req.cmd = FALSE;
req.sig = FALSE;
req.handle = centralCharHdl;
req.len = 1;
req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if(req.pValue != NULL)
{
*req.pValue = centralCharVal;
if(GATT_WriteCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS)
{
centralProcedureInProgress = TRUE;
centralDoWrite = !centralDoWrite;
tmos_start_task(centralTaskId, 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 = centralCharHdl;
if(GATT_ReadCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS)
{
centralProcedureInProgress = TRUE;
centralDoWrite = !centralDoWrite;
}
}
}
return (events ^ START_READ_OR_WRITE_EVT);
}
if(events & START_WRITE_CCCD_EVT)
{
if(centralProcedureInProgress == FALSE)
{
// Do a write
attWriteReq_t req;
req.cmd = FALSE;
req.sig = FALSE;
req.handle = 0x0039;
PRINT("start_write_cccd: %#x\n",req.handle);
req.len = 2;
req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_REQ, req.len, NULL, 0);
if(req.pValue != NULL)
{
req.pValue[0] = 1;
req.pValue[1] = 0;
if(GATT_WriteCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS)
{
centralProcedureInProgress = 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(centralConnHandle);
tmos_start_task(centralTaskId, 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)
{
if(centralState != 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\n", status);
}
centralProcedureInProgress = FALSE;
}
if(pMsg->method == ATT_MTU_UPDATED_EVENT)
{
PRINT("MTU: %d\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\n", status);
}
else
{
// After a successful read, display the read value
PRINT("Read rsp: %x\n", *pMsg->msg.readRsp.pValue);
}
centralProcedureInProgress = 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)
{
uint8_t status = pMsg->msg.errorRsp.errCode;
PRINT("Write Error: %x\n", status);
}
else
{
// Write success
PRINT("Write success \n");
}
centralProcedureInProgress = FALSE;
}
else if(pMsg->method == ATT_HANDLE_VALUE_NOTI)
{
// PRINT("Receive noti: %#x\n", pMsg->msg.handleValueNoti.pValue);
PRINT("Receive noti:");
for (int i = 0; i < 8; i++) {
if(i) PRINT(" ");
PRINT("%#x", pMsg->msg.handleValueNoti.pValue[i]);
}
PRINT("]\n");
}
else if(centralDiscState != BLE_DISC_STATE_IDLE)
{
centralGATTDiscoveryEvent(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 \n", -rssi);
}
/*********************************************************************
* @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)
{
PRINT(" HCI data length changed, Tx: %d, Rx: %d\n", maxTxOctets, maxRxOctets);
centralProcedureInProgress = TRUE;
}
/*********************************************************************
* @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:
{
PRINT("Discovering...\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(tmos_memcmp(PeerAddrDef, centralDevList[i].addr, B_ADDR_LEN))
break;
}
// Peer device not found
if(i == centralScanRes)
{
PRINT("Device not found...\n");
centralScanRes = 0;
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
PRINT("Discovering...\n");
}
// Peer device found
else
{
PRINT("Device found...\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...\n");
}
}
break;
case GAP_LINK_ESTABLISHED_EVENT:
{
tmos_stop_task(centralTaskId, ESTABLISH_LINK_TIMEOUT_EVT);
if(pEvent->gap.hdr.status == SUCCESS)
{
centralState = BLE_STATE_CONNECTED;
centralConnHandle = pEvent->linkCmpl.connectionHandle;
centralProcedureInProgress = TRUE;
// Update MTU
attExchangeMTUReq_t req = {
.clientRxMTU = BLE_BUFF_MAX_LEN - 4,
};
GATT_ExchangeMTU(centralConnHandle, &req, centralTaskId);
// Initiate service discovery
tmos_start_task(centralTaskId, START_SVC_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY);
// See if initiate connect parameter update
if(centralParamUpdate)
{
tmos_start_task(centralTaskId, START_PARAM_UPDATE_EVT, DEFAULT_PARAM_UPDATE_DELAY);
}
// See if initiate phy update
if(centralPhyUpdate)
{
tmos_start_task(centralTaskId, START_PHY_UPDATE_EVT, DEFAULT_PHY_UPDATE_DELAY);
}
// See if start RSSI polling
if(centralRssi)
{
tmos_start_task(centralTaskId, START_READ_RSSI_EVT, DEFAULT_RSSI_PERIOD);
}
PRINT("Connected...\n");
}
else
{
PRINT("Connect Failed...Reason:%X\n", pEvent->gap.hdr.status);
PRINT("Discovering...\n");
centralScanRes = 0;
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
}
}
break;
case GAP_LINK_TERMINATED_EVENT:
{
centralState = BLE_STATE_IDLE;
centralConnHandle = GAP_CONNHANDLE_INIT;
centralDiscState = BLE_DISC_STATE_IDLE;
centralCharHdl = 0;
centralScanRes = 0;
centralProcedureInProgress = FALSE;
tmos_stop_task(centralTaskId, START_READ_RSSI_EVT);
PRINT("Disconnected...Reason:%x\n", pEvent->linkTerminate.reason);
PRINT("Discovering...\n");
GAPRole_CentralStartDiscovery(DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST);
}
break;
case GAP_LINK_PARAM_UPDATE_EVENT:
{
PRINT("Param Update...\n");
}
break;
case GAP_PHY_UPDATE_EVENT:
{
PRINT("PHY Update...\n");
}
break;
case GAP_EXT_ADV_DEVICE_INFO_EVENT:
{
// Display device addr
PRINT("Recv ext adv \n");
// Add device to list
centralAddDeviceInfo(pEvent->deviceExtAdvInfo.addr, pEvent->deviceExtAdvInfo.addrType);
}
break;
case GAP_DIRECT_DEVICE_INFO_EVENT:
{
// Display device addr
PRINT("Recv direct adv \n");
// Add device to list
centralAddDeviceInfo(pEvent->deviceDirectInfo.addr, pEvent->deviceDirectInfo.addrType);
}
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("Pairing started:%d\n", status);
}
else if(state == GAPBOND_PAIRING_STATE_COMPLETE)
{
if(status == SUCCESS)
{
PRINT("Pairing success\n");
}
else
{
PRINT("Pairing fail\n");
}
}
else if(state == GAPBOND_PAIRING_STATE_BONDED)
{
if(status == SUCCESS)
{
PRINT("Bonding success\n");
}
}
else if(state == GAPBOND_PAIRING_STATE_BOND_SAVED)
{
if(status == SUCCESS)
{
PRINT("Bond save success\n");
}
else
{
PRINT("Bond save failed: %d\n", 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\n", (int)passcode);
}
// Send passcode response
GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
}
/*********************************************************************
* @fn centralStartDiscovery
*
* @brief Start service discovery.
*
* @return none
*/
static void centralStartDiscovery(void)
{
centralSvcStartHdl = centralSvcEndHdl = centralCharHdl = 0;
centralDiscState = BLE_DISC_STATE_SVC;
uint8_t ret = 0;
ret = GATT_DiscAllPrimaryServices(centralConnHandle, centralTaskId);
printf("GATT_DiscAllPrimaryServices ret = %x\n", ret);
}
/*********************************************************************
* @fn centralGATTDiscoveryEvent
*
* @brief Process GATT discovery event
*
* @return none
*/
static void centralGATTDiscoveryEvent(gattMsgEvent_t *pMsg)
{
attReadByTypeReq_t req;
if(centralDiscState == BLE_DISC_STATE_SVC)
{
// Service found, store handles
if(pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&//ATT_FIND_BY_TYPE_VALUE_RSP &&
pMsg->msg.findByTypeValueRsp.numInfo > 0)
{
#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((pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&
pMsg->hdr.status == bleProcedureComplete) ||
(pMsg->method == ATT_ERROR_RSP))
{
// Discover characteristic
centralDiscState = BLE_DISC_STATE_CHAR;
uint8_t ret = GATT_DiscAllChars(centralConnHandle,0x01,0xFFFF,centralTaskId);
PRINT("GATT_DiscAllChars:%02x\r\n",ret);
}
}
else if(centralDiscState == 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]);
PRINT("______________________________\n");
if(char_properties&GATT_PROP_NOTIFY) {
centralCCCDHdl = char_value_handle+1; //通过GATT_DiscAllChars或者handle,noti/indi的handle值需要+1
PRINT("Notify handle:%04x\r\n",char_value_handle);
PRINT("cccd handle:%04x\r\n",centralCCCDHdl);
if (centralCCCDHdl == 0x0039)
tmos_start_task(centralTaskId, START_WRITE_CCCD_EVT, 1600);
}
}
}
}
}
/*********************************************************************
* @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++;
}
}
/************************ endfile @ central **************************/