主要介紹下藍芽協定棧(bluetooth stack) 串列埠協定(bluetooth SPP)Serial Port Profile 協定概念介紹。
本專欄文章我們會以連載的方式持續更新,本專欄計劃更新內容如下:
第一篇:藍芽綜合介紹 ,主要介紹藍芽的一些概念,產生背景,發展軌跡,市面藍芽介紹,以及藍芽開發板介紹。
第二篇: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
--------------------------------------------------------------------------------------------------------------------------
SPP是Serial Port Profile(串列埠協定)的縮寫,其定義了使用藍芽進行RS232(或類似)序列電纜模擬的裝置應使用的協定和過程。簡單來說就是在藍芽裝置之間建立虛擬的串列埠進行資料通訊。說白了就是可以兩個裝置對端傳送自定義資料,NOTED:蘋果不支援SPP協定。
目前SIG最新的版本是V1.2,之前更早的版本在官網只有V1.1可以下載到,但是這兩份檔案沒有功能上的差別,所以不做介紹
Device A (DevA) – This is the device that takes initiative to form a connection to another device
Device B (DevB) – This is the device that waits for another device to take initiative to connect.
說白了就是就是兩臺裝置連線,誰發起的連線角色就是Device A,被連線的就是Device B,但是這個和其他協定不同,兩臺裝置之前的code基本都是一樣,角色只是區分兩臺裝置。
Device A是發起連線的主動房,所以Device A要至少支援Establish link and set up virtual serial connection.,Device B是被連線的乙方,所以要至少支援Accept link and establish virtual serial connection和Register Service record for application in local SDP database.以便Device A查詢服務並且連線,但是此協定漏掉最主要的兩個功能,傳送資料,接收資料,或者SIG是覺得rfcomm做到了這個功能,所以不寫在SPP協定中吧,但是我還是決定要在SPP介紹收發功能。
This procedure refers to performing the steps necessary to establish a connection to an emulated serial port (or equivalent) in a remote device. The steps in this procedure are:
1)Submit a query using SDP to find out the RFCOMM Server channel number of the desired application in the remote device. This might include a browsing capability to let the user select among available ports (or services) in the peer device. Alternatively, if it is known exactly which service to contact, it is sufficient look up the necessary parameters using the Service Class ID associated with the desired service.
2)Optionally, require authentication of the remote device to be performed. Also optionally, require encryption to be turned on.
3) Request a new L2CAP channel to the remote RFCOMM entity.
4) Initiate an RFCOMM session on the L2CAP channel.
5) Start a new data link connection on the RFCOMM session, using the aforementioned server channel number.After step 5, the virtual serial cable connection is ready to be used for communication between applications on both sides.
This procedure refers to taking part in the following steps:
1)If requested by the remote device, take part in authentication procedure and, upon
further request, turn on encryption.
2) Accept a new channel establishment indication from L2CAP.
3) Accept an RFCOMM session establishment on that channel.
4) Accept a new data link connection on the RFCOMM session. This may trigger a local request to authenticate the remote device and turn on encryption, if the user has required that for the emulated serial port being connected to (and authentication/encryption procedures have not already been carried out).
This procedure refers to registration of a service record for an emulated serial port (or equivalent) in the SDP database. This implies the existence of a Service Database, and the ability to respond to SDP queries.
NOTED:SPP只有安卓手機支援,並且部分安卓手機必須有SPP APP才可以連線,iphone手機不能直接SPP,但是又一個替代協定IAP,此協定需要買MFI chip才能用
我看下我們的SDP註冊:
static const uint8_t spp_service_record[] =
{
/* 1.ServiceClassIDList */
SDP_DES_SIZE8, 0x8,
SDP_UINT16, BT_ATTRIBUTE_SERVICE_CLASS_ID_LIST>>8&0xff, BT_ATTRIBUTE_SERVICE_CLASS_ID_LIST&0xff, /* Service class ID list attribute */
SDP_DES_SIZE8, 3,
SDP_UUID16, BT_SERVICE_CLASS_SERIAL_PORT>>8&0xff, BT_SERVICE_CLASS_SERIAL_PORT&0xff,
/* 2.ProtocolDescriptorList */
SDP_DES_SIZE8, 0x11,
SDP_UINT16, BT_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST>>8&0xff, BT_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST&0xff,/* Protocol descriptor list attribute */
SDP_DES_SIZE8, 0xc,
SDP_DES_SIZE8, 0x3,
SDP_UUID16, BT_PROTOCOL_L2CAP>>8&0xff, BT_PROTOCOL_L2CAP&0xff, /*L2CAP*/
SDP_DES_SIZE8, 0x5,
SDP_UUID16, BT_PROTOCOL_RFCOMM>>8&0xff, BT_PROTOCOL_RFCOMM&0xff, /*RFCOMM*/
SDP_UINT8, RFCOMM_SPP_SERVER_CHNL, /*RFCOMM channel*/
/* BluetoothProfileDescriptorList */
SDP_DES_SIZE8, 0xd,
SDP_UINT16, BT_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST>>8&0xff, BT_ATTRIBUTE_BLUETOOTH_PROFILE_DESCRIPTOR_LIST&0xff, /* profile descriptor List */
SDP_DES_SIZE8, 0x8,
SDP_DES_SIZE8,0x06,
SDP_UUID16,BT_SERVICE_CLASS_SERIAL_PORT>>8&0xff, BT_SERVICE_CLASS_SERIAL_PORT&0xff,
SDP_UINT16,0x01,0x02, /* V1.2 */
};