当前位置:   article > 正文

蓝牙----蓝牙连接建立_连接建立_蓝牙连接过程

蓝牙连接过程


蓝牙连接建立过程图

在这里插入图片描述

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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++;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

当到达最大扫描数目时,执行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);
  • 1

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

其中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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

连接请求回应GAP_UpdateLinkParamReqReply,触发主机的GAP_LINK_PARAM_UPDATE_EVENT事件,对连接参数更新成功与失败情况进行判决。

4.2从机进行连接参数更新

主机向从机连接请求回应GAP_UpdateLinkParamReqReply后,对连接参数更新成功与失败情况进行判决。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/691049
推荐阅读
相关标签
  

闽ICP备14008679号