蓝牙----蓝牙连接建立_连接建立
- 蓝牙连接建立过程图
- 1.主机扫描到广播包
- 1.1判断是否是自己关心的广播包
- 1.2广播地址添加到扫描列表
- 2.主机扫描结束,建立连接
- 3.主从连接成功后,执行连接建立后事件
- 3.1.主机将连接句柄和设备地址添加到连接列表
- 3.2.主机进行GATT服务的发现
- 3.3.从机获取连接句柄,并发起连接参数更新
- 4.从机发起连接参数更新
- 4.1主机收到连接参数更新请求
- 4.2从机进行连接参数更新
蓝牙连接建立过程图
1.主机扫描到广播包
执行注册的回调函数,触发APP层SC_EVT_ADV_REPORT事件
//判断广播包是否是自己关心的
if (SimpleCentral_findSvcUuid(SIMPLEPROFILE_SERV_UUID,
pAdvRpt->pData, pAdvRpt->dataLen))
{
//将广播设备的地址和地址类型添加到扫描列表中
SimpleCentral_addScanInfo(pAdvRpt->addr, pAdvRpt->addrType);
Display_printf(dispHandle, SC_ROW_NON_CONN, 0, "Discovered: %s",
Util_convertBdAddr2Str(pAdvRpt->addr));
}
1.1判断是否是自己关心的广播包
SimpleCentral_findSvcUuid是查看广播包是否包含自己设置的UUID(SIMPLEPROFILE_SERV_UUID)。
广播包的判断有多种也可以对广播数据判断。
从机的广播数据
static uint8_t advertData[] =
{
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
LO_UINT16(SIMPLEPROFILE_SERV_UUID),
HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
主机扫描UUID判断
if ((adType == GAP_ADTYPE_16BIT_MORE) || (adType == GAP_ADTYPE_16BIT_COMPLETE))
{
pData++;
adLen--;
// For each UUID in list
while (adLen >= 2 && pData < pEnd)
{
// Check for match
if ((pData[0] == LO_UINT16(uuid)) && (pData[1] == HI_UINT16(uuid)))
{
// Match found
return TRUE;
}
// Go to next
pData += 2;
adLen -= 2;
}
}
1.2广播地址添加到扫描列表
SimpleCentral_addScanInfo(pAdvRpt->addr, pAdvRpt->addrType);
//添加一个设备到扫描列表
static void SimpleCentral_addScanInfo(uint8_t *pAddr, uint8_t addrType)
{
uint8_t i;
// If result count not at max
// DEFAULT_MAX_SCAN_RES扫描结果的最大数目
if (numScanRes < DEFAULT_MAX_SCAN_RES)
{
// Check if device is already in scan results
for (i = 0; i < numScanRes; i++)
{
if (memcmp(pAddr, scanList[i].addr , B_ADDR_LEN) == 0)
{
return;
}
}
// Add addr to scan result list
memcpy(scanList[numScanRes].addr, pAddr, B_ADDR_LEN);
scanList[numScanRes].addrType = addrType;
// Increment scan result count
numScanRes++;
}
}
当到达最大扫描数目时,执行GapScan_disable(),并执行回调函数,触发SC_EVT_SCAN_DISABLED事件
2.主机扫描结束,建立连接
处理SC_EVT_SCAN_DISABLED事件,进行GAP连接
GapInit_connect(tempMember->addrType & MASK_ADDRTYPE_ID,tempMember->addr, DEFAULT_INIT_PHY, CONNECTION_TIMEOUT);
3.主从连接成功后,执行连接建立后事件
GapInit_connect成功返回GAP层事件GAP_LINK_Estableished,主机及从机进行事件处理
3.1.主机将连接句柄和设备地址添加到连接列表
SimpleCentral_addConnInfo(connHandle, pAddr);
//添加一个设备到 连接列表
static uint8_t SimpleCentral_addConnInfo(uint16_t connHandle, uint8_t *pAddr)
{
uint8_t i;
for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
{
if (connList[i].connHandle == CONNHANDLE_INVALID)
{
// Found available entry to put a new connection info in
connList[i].connHandle = connHandle;
memcpy(connList[i].addr, pAddr, B_ADDR_LEN);
numConn++;
break;
}
}
return i;
}
其中connList[]元素结构体定义如下
//连接设备信息
typedef struct
{
uint16_t connHandle; // Connection Handle 连接句柄
uint8_t addr[B_ADDR_LEN]; // Peer Device Address 连接对端设备地址
uint8_t charHandle; // Characteristic Handle 特征值句柄
Clock_Struct *pRssiClock; // pointer to clock struct
} connRec_t;
3.2.主机进行GATT服务的发现
蓝牙----蓝牙消息传输_GATT服务发现
3.3.从机获取连接句柄,并发起连接参数更新
SimplePeripheral_addConn(pPkt->connectionHandle);
从机获取连接句柄,并判断是否到达连接数目,选择继续/停止广播
连接参数更新在自定义的SP_SEND_PARAM_UPDATE_DELAY(6S)后,从机发起
//从机获取连接句柄,进行连接参数更新
static uint8_t SimplePeripheral_addConn(uint16_t connHandle)
{
uint8_t i;
uint8_t status = bleNoResources;
// Try to find an available entry
for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
{
if (connList[i].connHandle == CONNHANDLE_INVALID)
{
// Found available entry to put a new connection info in
connList[i].connHandle = connHandle;
// Allocate data to send through clock handler
connList[i].pParamUpdateEventData = ICall_malloc(sizeof(spClockEventData_t) +
sizeof (uint16_t));
if(connList[i].pParamUpdateEventData)
{
connList[i].pParamUpdateEventData->event = SP_SEND_PARAM_UPDATE_EVT;
*((uint16_t *)connList[i].pParamUpdateEventData->data) = connHandle;
// Create a clock object and start
connList[i].pUpdateClock
= (Clock_Struct*) ICall_malloc(sizeof(Clock_Struct));
//启动连接参数更新
if (connList[i].pUpdateClock)
{
Util_constructClock(connList[i].pUpdateClock,
SimplePeripheral_clockHandler,
SP_SEND_PARAM_UPDATE_DELAY, 0, true,
(UArg) (connList[i].pParamUpdateEventData));
}
else
{
ICall_free(connList[i].pParamUpdateEventData);
}
}
else
{
status = bleMemAllocError;
}
// Set default PHY to 1M
connList[i].currPhy = HCI_PHY_1_MBPS;
break;
}
}
return status;
}
4.从机发起连接参数更新
从机发送连接参数更新GAP_UpdateLinkParamReq
4.1主机收到连接参数更新请求
主机GAP收到GAP_UPDATE_LINK_PARAM_REQ_EVENT连接请求事件,获取新的连接参数,执行连接请求回应GAP_UpdateLinkParamReqReply。
case GAP_UPDATE_LINK_PARAM_REQ_EVENT:
{
gapUpdateLinkParamReqReply_t rsp;
gapUpdateLinkParamReq_t *pReq;
pReq = &((gapUpdateLinkParamReqEvent_t *)pMsg)->req;
rsp.connectionHandle = pReq->connectionHandle;
rsp.signalIdentifier = pReq->signalIdentifier;
//允许连接参数更新
if (acceptParamUpdateReq)
{
//收到的 新的连接请求参数
rsp.intervalMin = pReq->intervalMin;
rsp.intervalMax = pReq->intervalMax;
rsp.connLatency = pReq->connLatency;
rsp.connTimeout = pReq->connTimeout;
rsp.accepted = TRUE;
}
else
{
// Reject the request.
rsp.accepted = FALSE;
}
// Send Reply
// 连接请求回应
VOID GAP_UpdateLinkParamReqReply(&rsp);
break;
}
连接请求回应GAP_UpdateLinkParamReqReply,触发主机的GAP_LINK_PARAM_UPDATE_EVENT事件,对连接参数更新成功与失败情况进行判决。
4.2从机进行连接参数更新
主机向从机连接请求回应GAP_UpdateLinkParamReqReply后,对连接参数更新成功与失败情况进行判决。