本文中的分析与软件相关的内容,都是以WinCE中的 Microsoft Bluetooth Core Stack为例进行分析;与协议有关的内容,是基于Bluetooth Core 2.1 + EDR Spec进行分析。
1. 如何获取L2CAP包
- 从HCI_ReadPacket()/HCI_WritePacket()中截获
在HCI_ReadPacket()/HCI_WritePacket()中判断eType为2的即是ACL-u数据,也即L2CAP数据。
ACL-u包中包括了Connection Handle,Flag,Data Length以及Data Domain,如下图所示:
其中,Data Domain即是L2CAP包的数据。
- 从MS-Stack中获取
编译Debug版本的MS-Stack,即btd.dll,并打开Debug Zone DEBUG_L2CAP_PACKETS,即可以截取到L2CAP的数据。
#define DEBUG_L2CAP_PACKETS 0x00040000 |
一个MS-Stack中截获的L2CAP数据形如:
2. 如何分析L2CAP包
L2CAP是基于Packet进行数据传输的,其传输模型基于Channel。 Channel Identifier(CID)的分类如下图所示:
可以将Channel理解为USB协议中的Endpoint,不同的Channel用做不同的传输,总体上可以分为Connection-oriented channel,Connectionless data channel和Singling Channel,如下图所示:
2.1 Signaling Packet分析
- 如何判别一个包为Signaling Packet
如果L2CAP包的CID为0x0001,则该包即为Signaling Packet。
- Signaling包的结构
如下:
其中Commands域的格式如下:
上面的Code域可能的值如下:
- 各个Code的具体分析方式
可以参照BlueCore Spec中有关各个Code的详细格式来对数据进行分析,以Disconnection Request为例,分析如下:
Destination CID - DCID (2 octets)
This field specifies the endpoint of the channel to be disconnected on the
device receiving this request.
Source CID - SCID (2 octets)
This field specifies the endpoint of the channel to be disconnected on the
device sending this request.
Identifier:
该域为1字节长,Request和Response中的该值是一样的,用来在一对设备之间进行通信的时候判别使用。每一组连续的Response-Request命令都必须有一个不一样的Identifier,长度为2个字节。在其它的通信协议中也经常会存在一个类似的Identifier,显然,0~0xff用完的时候,可以回收之前用过的值。
2.2 分析Data Packet
- 如何判别一个包为Data Packet
Data Packet包括Connection-oriented和Connectionless data两种,它们的CID范围不一样,可以通过CID来进行区分。如果CID为0x2,则是Connectionless data,如果介于0x40和0xfff之间,则为Connection-oriented data Packet。
- Data Packet的结构
两者的结构分别如下图所示:
Connection-oriented结构如下图:
Connectionless结构如下图:
可以看到,Connection-oriented Frame包括三种,Basic Frame(B-FRAME),Supervisory Frame(S-FRAME)和Information Frame(I-FRAME)。通过Control域中的Bit0来区分S-FRAME和I-FRAME,即Bit0=0为I-FRAME,为1是S-FRAME。
那么,如何来区分B-FRAME呢?这些就留到以后进行深究吧!