`
mmdev
  • 浏览: 12914941 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

linux下bluetooth编程(四)L2CAP层编程

 
阅读更多

一:L2CAP协议简介:

Logical Link Control and Adaptation Protocol(L2CAP)

<wbr></wbr>

逻辑连接控制和适配协议(L2CAP) 为上层协议提供面向连接和无连接的数据服务,并提供多协议功能和分割重组操作。L2CAP充许上层协议和应用软件传输和接收最大长度为 64K L2CAP数据包。

  L2CAP基于 通道(channel)的概念。 通道 (Channel)是位于基带 (baseband)连接之上的逻辑连接。每个通道以多对一的方式绑定一个单一协议 (single protocol)。多个通道可以绑定同一个协议,但一个通道不可以绑定多个协议。每个在通道里接收到的 L2CAP数据包被传到相应的上层协议。 多个通道可共享同一个基带连接。

<wbr></wbr>

L2CAP处于Bluetooth协议栈的位置如下:

也就是说,所有L2CAP数据均通过HCI传输到Remote Device。且上层协议的数据,大都也通过L2CAP来传送。

<wbr></wbr>

<wbr></wbr>

L2CAP可以发送Command。例如连接,断连等等。

<wbr></wbr>

下面看Command例子:Connection Request:

<wbr></wbr>

其中PSM比较需要注意,L2CAP 使用L2CAP连接请求(Connection Request )命令中的PSM字段实现协议复用。L2CAP可以复用发给上层协议的连接请求,这些上层协议包括服务发现协议SDP(PSM = 0x0001)、RFCOMM(PSM = 0x0003)和电话控制(PSM = 0x0005)等。

<wbr></wbr>

<wbr></wbr>

ProtocolPSMReference
SDP 0x0001 SeeBluetooth Service Discovery Protocol (SDP), Bluetooth SIG.
RFCOMM 0x0003 See RFCOMM with TS 07.10, Bluetooth SIG.
TCS-BIN 0x0005 SeeBluetooth Telephony Control Specification / TCS Binary, Bluetooth SIG.
TCS-BIN-CORDLESS 0x0007 SeeBluetooth Telephony Control Specification / TCS Binary, Bluetooth SIG.
BNEP 0x000F SeeBluetooth 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

<wbr></wbr>

<wbr></wbr>

<wbr></wbr>

<wbr></wbr>

二:L2CAP编程方法:

<wbr></wbr>

L2CAP编程非常重要,它和HCI基本就是Linux Bluetooth编程的基础了。几乎所有协议的连接,断连,读写都是用L2CAP连接来做的。

<wbr></wbr>

1.创建L2CAP Socket:

socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);

domain=PF_BLUETOOTH, type可以是多种类型。protocol=BTPROTO_L2CAP.

<wbr></wbr>

2.绑定:

// Bind to local address
<wbr>memset(&amp;addr, 0, sizeof(addr));<br><wbr>addr.l2_family = AF_BLUETOOTH;<br><wbr>bacpy(&amp;addr.l2_bdaddr, &amp;bdaddr); //bdaddr为本地Dongle BDAddr</wbr></wbr></wbr>

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

<wbr></wbr>

3.连接

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

addr.l2_psm = xxx;<wbr></wbr>

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

<wbr></wbr>

注意:

struct sockaddr_l2 {
<wbr>sa_family_t<wbr>l2_family;<wbr> //必须为 AF_BLUETOOTH<br><wbr>unsigned short<wbr>l2_psm;<wbr> //与前面PSM对应,这一项很重要<br><wbr>bdaddr_t<wbr>l2_bdaddr;<wbr><wbr><wbr><wbr><wbr>//Remote Device BDADDR<br><wbr>unsigned short<wbr>l2_cid;<wbr><br> };</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr></wbr>

4. 发送数据到Remote Device:

send()或write()都可以。

<wbr></wbr>

5. 接收数据:

revc() 或read()

<wbr></wbr>

<wbr></wbr>

以下为实例:

注:在Bluetooth下,主动去连接的一端作为主机端。被动等别人连接的作为Client端。

<wbr></wbr>

<wbr></wbr>

<wbr></wbr>

<wbr></wbr>

<wbr></wbr>

<wbr></wbr>

背景知识1:Bluetooth设备的状态

之前HCI编程时,是用<wbr>ioctl(HCIGETDEVINFO)得到某个Device Info(hci_dev_info).其中flags当时解释的很简单。其实它存放着Bluetooth Device(例如:USB Bluetooth Dongle)的当前状态:</wbr>

其中,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了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics