實戰Linux Bluetooth編程(四) L2CAP層編程

轉載自  http://blog.sina.com.cn/s/blog_602f87700100e902.html

作者:Sam (甄峯) [email protected]

(L2CAP協議簡介,L2CAP在BlueZ中的實現以及L2CAP編程接口)

 

一:L2CAP協議簡介:

Logical Link Control and Adaptation Protocol(L2CAP)

 

邏輯連接控制和適配協議 (L2CAP) 爲上層協議提供面向連接和無連接的數據服務,並提供多協議功能和分割重組操作。L2CAP 充許上層協議和應用軟件傳輸和接收最大長度爲 64K  L2CAP 數據包。

  L2CAP 基於 通道(channel) 的概念。 通道 (Channel) 是位於基帶 (baseband) 連接之上的邏輯連接。每個通道以多對一的方式綁定一個單一協議 (single protocol)。多個通道可以綁定同一個協議,但一個通道不可以綁定多個協議。 每個在通道里接收到的 L2CAP 數據包被傳到相應的上層協議。 多個通道可共享同一個基帶連接。

 

L2CAP處於Bluetooth協議棧的位置如下:

實戰Linux <wbr>Bluetooth編程(四) <wbr>L2CAP層編程

也就是說,所有L2CAP數據均通過HCI傳輸到Remote Device。且上層協議的數據,大都也通過L2CAP來傳送。

 

 

L2CAP可以發送Command。例如連接,斷連等等。

實戰Linux <wbr>Bluetooth編程(四) <wbr>L2CAP層編程

 

下面看Command例子:Connection Request:

實戰Linux <wbr>Bluetooth編程(四) <wbr>L2CAP層編程

 

其中PSM比較需要注意,L2CAP 使用L2CAP連接請求(Connection Request )命令中的PSM字段實現協議複用。L2CAP可以複用發給上層協議的連接請求,這些上層協議包括服務發現協議SDP(PSM = 0x0001)、RFCOMM(PSM = 0x0003)和電話控制(PSM = 0x0005)等。

 

 

Protocol PSM Reference
SDP 0x0001 See Bluetooth Service Discovery Protocol (SDP), Bluetooth SIG.
RFCOMM 0x0003 See RFCOMM with TS 07.10, Bluetooth SIG.
TCS-BIN 0x0005 See Bluetooth Telephony Control Specification / TCS Binary, Bluetooth SIG.
TCS-BIN-CORDLESS 0x0007 See Bluetooth Telephony Control Specification / TCS Binary, Bluetooth SIG.
BNEP 0x000F See Bluetooth Network Encapsulation Protocal, Bluetooth SIG.
HID_Control 0x0011 See Human Interface Device , Bluetooth SIG.
HID_Interrupt 0x0013 See Human Interface Device, Bluetooth SIG.
UPnP 0x0015 See [ESDP] , Bluetooth SIG.
AVCTP 0x0017 See Audio/Video Control Transport Protocol , Bluetooth SIG.
AVDTP 0x0019 See Audio/Video Distribution Transport Protocol , Bluetooth SIG.
AVCTP_Browsing 0x001B See Audio/Video Remote Control Profile, Bluetooth SIG
UDI_C-Plane 0x001D See the Unrestricted Digital Information Profile [UDI], Bluetooth SIG

 

 

 

 

二:L2CAP編程方法:

 

L2CAP編程非常重要,它和HCI基本就是Linux Bluetooth編程的基礎了。幾乎所有協議的連接,斷連,讀寫都是用L2CAP連接來做的。

 

1.創建L2CAP Socket:

socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);

domain=PF_BLUETOOTH, type可以是多種類型。protocol=BTPROTO_L2CAP.

 

2.綁定:

// Bind to local address
 memset(&addr, 0, sizeof(addr));
 addr.l2_family = AF_BLUETOOTH;
 bacpy(&addr.l2_bdaddr, &bdaddr); //bdaddr爲本地Dongle BDAddr

 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  perror("Can't bind socket");
  goto error;
 }

 

3.連接

memset(&addr, 0, sizeof(addr));
addr.l2_family = AF_BLUETOOTH;
bacpy(addr.l2_bdaddr, src);

addr.l2_psm = xxx; 

 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
  perror("Can't connect");
  goto error;
 }

 

注意:

struct sockaddr_l2 {
 sa_family_t l2_family;  //必須爲 AF_BLUETOOTH
 unsigned short l2_psm;  //與前面PSM對應,這一項很重要
 bdaddr_t l2_bdaddr;     //Remote Device BDADDR
 unsigned short l2_cid; 
};

 

4. 發送數據到Remote Device:

send()或write()都可以。

 

5. 接收數據:

revc() 或read()

 

 

以下爲實例:

注:在Bluetooth下,主動去連接的一端作爲主機端。被動等別人連接的作爲Client端。

 

 

 

 

 

 

背景知識1:Bluetooth設備的狀態

之前HCI編程時,是用 ioctl(HCIGETDEVINFO)得到某個Device Info(hci_dev_info).其中flags當時解釋的很簡單。其實它存放着Bluetooth Device(例如:USB Bluetooth Dongle)的當前狀態:

其中,UP,Down狀態表示此Device是否啓動起來。可以使用ioctl(HCIDEVUP)等修改這些狀態。

另外:就是Inquiry Scan, PAGE Scan這些狀態:

Sam在剛開始自己做L2CAP層連接時,使用另一臺Linux機器插USB Bluetooth Dongle作Remote Device。怎麼也沒法使用inquiry掃描到remote設備,也沒法連接remote設備,甚至無法使用l2ping ping到remote設備。覺得非常奇怪,後來才發現Remote Device狀態設置有問題。沒有設置PSCAN和ISCAN。

Inquiry Scan狀態表示設備可被inquiry. Page Scan狀態表示設備可被連接。

#hciconfig hci0 iscan

#hciconfig hci0 pscan

或者:#hciconfig hci0 piscan

就可以設置爲PSCAN或者iSCAN狀態了。

編程則可以使用ioctl(HCISETSCAN) . dev_opt = SCAN_INQUIRY;dr.dev_opt = SCAN_PAGE;dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY;

則可以inquiry或者connect了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章