零. 概述
主要介紹下藍牙協議堆疊(bluetooth stack)低功耗藍牙廣播的流程以及協議堆疊的實作流程,BLE Advertising flow
btsnoop以及流程在資料中的......\STM32_UBUNTU_BLUETOOTH\2-藍牙資料\藍牙協議分析\BLE廣播.log
一. 宣告
本專欄文章我們會以連載的方式持續更新,本專欄計劃更新內容如下:

第一篇:藍牙綜合介紹 ,主要介紹藍牙的一些概念,產生背景,發展軌跡,市面藍牙介紹,以及藍牙開發板介紹,
第二篇:Transport層介紹,主要介紹藍牙協議堆疊跟藍牙芯片之前的硬體傳輸協議,比如基于UART的H4,H5,BCSP,基于USB的H2等
第三篇:傳統藍牙controller介紹,主要介紹傳統藍牙芯片的介紹,包括射頻層(RF),基帶層(baseband),鏈路管理層(LMP)等
第四篇:傳統藍牙host介紹,主要介紹傳統藍牙的協議堆疊,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的協議吧,
第五篇:低功耗藍牙controller介紹,主要介紹低功耗藍牙芯片,包括物理層(PHY),鏈路層(LL)
第六篇:低功耗藍牙host介紹,低功耗藍牙協議堆疊的介紹,包括HCI,L2CAP,ATT,GATT,SM等
第七篇:藍牙芯片介紹,主要介紹一些藍牙芯片的初始化流程,基于HCI vendor command的擴展
第八篇:附錄,主要介紹以上常用名詞的介紹以及一些特殊流程的介紹等,
另外,開發板如下所示,對于想學習藍牙協議堆疊的最好人手一套,以便更好的學習藍牙協議堆疊,相信我,學完這一套視頻你將擁有修改任何協議堆疊的能力(比如Linux下的bluez,Android下的bluedroid),

-------------------------------------------------------------------------------------------------------------------------
CSDN學院鏈接(進入選擇你想要學習的課程):https://edu.csdn.net/lecturer/5352?spm=1002.2001.3001.4144
藍牙交流扣扣群:970324688
Github代碼:https://github.com/sj15712795029/bluetooth_stack
入手開發板:https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708
藍牙學習目錄:https://blog.csdn.net/XiaoXiaoPengBo/article/details/107727900
--------------------------------------------------------------------------------------------------------------------------
二. BLE廣播command以及event
整個流程如下(注意在初始化的時候有省略的步驟,只列出初始化的關鍵步驟)
![]()
![]()

我們再來看下ellisys的流程(跟Wireshark顯示基本一樣,主要是ellisys在流程中會自帶決議,所以我順便也貼下)
![]()

注意我們在截圖初始化的時候只是截取了兩個command以及event,一個是跟傳統藍牙有差別的set event mask,一個是write le host supported,其他可以參照傳統藍牙的初始化,步驟整理如下:
步驟1)發送設定事件掩碼的command(set event mask)以及收到commnd complete event
步驟2)發送設定支持BLE的command(write le host support)收到command complete event
步驟3)發送BLE 設定廣播引數的command(LE Set Advertising Parameters)
步驟4)發送BLE設定廣播資料的command(LE Set Advertising Data)
步驟5)發送BLE開啟廣播的command(LE Set Advertising Enable)
步驟6)收到步驟4)5)6)的command complete
步驟7)發送BLE關閉廣播的command(LE Set Advertising Enable)以及收到commnd complete event
下面我們就詳細說下每個步驟
步驟1)發送設定事件掩碼的command(set event mask)以及收到commnd complete event
此部分在上一個小節搜索廣播的時候介紹過,不再重復
步驟2)發送設定支持BLE的command(write le host support)收到command complete event
此部分在上一個小節搜索廣播的時候介紹過,不再重復
步驟3)發送BLE 設定廣播引數的command(LE Set Advertising Parameters)
我們來看下這個command的格式:







我們直接來看下btsnoop

對應的代碼如下:
![]()
err_t hci_le_set_adv_param(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
uint8_t own_address_typ, uint8_t peer_address_type,struct bd_addr_t *peer_address, uint8_t channel_map, uint8_t filter_policy)
{
struct bt_pbuf_t *p;
uint8_t offset = 0;
if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_SET_LE_ADV_PARAM_PLEN, BT_PBUF_RAM)) == NULL)
{
BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__);
return BT_ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_LE_SET_ADV_PARAM, HCI_LE, HCI_SET_LE_ADV_PARAM_PLEN);
offset += 3;
bt_le_store_16((uint8_t *)p->payload,offset,adv_int_min);
offset += 2;
bt_le_store_16((uint8_t *)p->payload,offset,adv_int_max);
offset += 2;
((uint8_t *)p->payload)[offset] = adv_type;
offset += 1;
((uint8_t *)p->payload)[offset] = own_address_typ;
offset += 1;
((uint8_t *)p->payload)[offset] = peer_address_type;
offset += 1;
memcpy(((uint8_t *)p->payload)+offset, peer_address->addr, BD_ADDR_LEN);
offset += BD_ADDR_LEN;
((uint8_t *)p->payload)[offset] = channel_map;
offset += 1;
((uint8_t *)p->payload)[offset] = filter_policy;
phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD);
bt_pbuf_free(p);
return BT_ERR_OK;
}
步驟4)發送BLE設定廣播資料的command(LE Set Advertising Data)
我們來看下HCI command格式:


此命令是設定廣播資料的,廣播資料的格式在上個小節,搜索廣播的時候已經說到,我們就不再重復了,我們直接來看下我們設定的代碼以及btsnoop
為了測驗簡單,我自己也就廣播了一個藍牙名稱,廣播資料如下:

廣播呼叫如下:
![]()
實作如下:
err_t hci_le_set_adv_data(uint8_t adv_len,uint8_t *adv_data)
{
struct bt_pbuf_t *p;
uint8_t offset = 0;
if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_SET_LE_ADV_DATA_PLEN, BT_PBUF_RAM)) == NULL)
{
BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__);
return BT_ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_LE_SET_ADV_DATA, HCI_LE, HCI_SET_LE_ADV_DATA_PLEN);
offset += 3;
((uint8_t *)p->payload)[offset] = adv_len;
offset += 1;
memset(((uint8_t *)p->payload) + offset,0,HCI_SET_LE_ADV_DATA_PLEN-offset);
memcpy(((uint8_t *)p->payload)+offset, adv_data, adv_len);
phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD);
bt_pbuf_free(p);
return BT_ERR_OK;
}
此部分要注意的是不管你的廣播資料是什么,都要填滿31Byte,第一個引數廣播資料是你真是的廣播長度
最后來看下btsnoop:

步驟5)發送BLE開啟廣播的command(LE Set Advertising Enable)
我們來看下command格式:


引數很簡單,就是簡單的開啟跟關閉
我們來看下代碼實作:
err_t hci_le_set_adv_enable(uint8_t enable)
{
struct bt_pbuf_t *p;
uint8_t offset = 0;
if((p = bt_pbuf_alloc(BT_TRANSPORT_TYPE, HCI_SET_LE_ADV_ENABLE_PLEN, BT_PBUF_RAM)) == NULL)
{
BT_HCI_TRACE_ERROR("ERROR:file[%s],function[%s],line[%d] bt_pbuf_alloc fail\n",__FILE__,__FUNCTION__,__LINE__);
return BT_ERR_MEM;
}
/* Assembling command packet */
p = hci_cmd_ass(p, HCI_LE_SET_ADV_ENABLE, HCI_LE, HCI_SET_LE_ADV_ENABLE_PLEN);
offset += 3;
((uint8_t *)p->payload)[offset] = enable;
phybusif_output(p, p->tot_len,PHYBUSIF_PACKET_TYPE_CMD);
bt_pbuf_free(p);
return BT_ERR_OK;
}
最后我們來看下btsnoop:

步驟6)收到步驟4)5)6)的command complete
這個command我們已經在傳統藍牙HCI介紹了,我直接貼下這3個command complete的event



步驟7)發送BLE關閉廣播的command(LE Set Advertising Enable)以及收到commnd complete event
這個在步驟5)已經介紹,我們直接來截圖btsnoop


轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/196174.html
標籤:AI
