Bluetooth Overview-- Bluetooth Core System Architecture

[email protected]

Bluetooth Overview
? ? ? ? ? ? ? Bluetooth Core System Architecture Bluetooth Interface BlueZ Android Bluetooth Architecture Android A2dp Profile Android HFP and HSP Profile Android PAN Profile

Bluetooth Core System Architecture

Bluetooth Core System Architecture
蓝牙技术的系统结构分为三大部分:底层硬件模块、中间协议层和高层应用。 底层硬件部分包括无线跳频(RF)、基带(BB)和链路管理(LM)。 RF层 通过2.4GHz无需授权的ISM频段的微波,实现数据位流的过滤和传输,本层协议主要定 义了蓝牙收发器在此频带正常工作所需要满足的条件。 基带 负责跳频以及蓝牙数据和信息帧的传输。 链路管理 负责连接、建立和拆除链路并进行安全控制。 LM (Link Manager) 层是蓝牙协议栈的链路管理层协议, 他负责将上层HCI 命令翻译成基 带能接受的操作, 建立ACL (数据) 和SCO (语音) 链接, 以及使蓝牙设备进入节能状态的工 作模式等。 LC (Link Control) 层负责在一批数据包传送期间, 响应上层LM 命令(如执行建立数据包的 传输链路, 维持链路等功能的LM 命令)。 HCI 位于蓝牙系统的L2CAP(逻辑链路控制与适配协议)层和LMP(链路管理协议)层之间 的一层协议。HCI为上层协议提供了进入LM的统一接口和进入基带的统一方式。 蓝牙的SIG规定了四种与硬件连接的物理总线方式:USB、RS232、UART和PC卡

模块及应用程序接口

模块及应用程序接口
(1)HCI层接口(Host Controller Interface) 主机控制接口(HCI)为主机提供了直接控制蓝牙模块的方法和途径。通过HCI把蓝牙模块 和主机连接在一起。HCI模块由HCI事件管理、HCI命令管理、HCI ACL/SCO数据传输、HCI传 输层API、向上层输出的API模块组成。HCI Firmware通过访问基带命令、链路管理器命令、 硬件状态寄存器、控制寄存器、事件寄存器实现对蓝牙硬件的HCI命令。 (2) L2CAP协议层(Logical Link Control and Adaptation Protocol) 逻辑链路控制与适配协议(L2CAP)是数据链路层的一部分,它向上层提供面向连接和无连 接的服务。 (3) RFCOMM及其接口 RFCOMM是一个基于ETST标准TS 07.10的传输协议,提供了对RS-232串行接口的仿真。它在 两个蓝牙设备之间同时最多提供60条连接,最大可以接收/发送32KB大小的数据分组。 (4)SDP及其接口 服务发现协议(SDP)是蓝牙框架的一个关键部分,它由服务发现代理(SDA)、服务发现 服务器(SDS)、服务数据库管理器(SDM)三个模块组成。 (5) BNEP 网络封装协议(Bluetooth Network Encapsulation Protocol ) 该协议对上层口协议提供了类似于以太网的接口。对于IEEE802.3/Ethemet封装支持的网络 协议,蓝牙网络封装均支持。BNEP协议把这些网络 协议包封装起来,直接通过蓝牙I2CAP 协议进行无线传输。蓝牙网络封装主要应用在蓝牙个人无线局域网(PAN)中,PAN应用是指 由两个或者更多的设备 形成一个特定网络,而且这些设备能通过一个网络接入点来访问远 程网络 (6) AVDTP &AVCTP AVDTP: Audio/Video Distribution Transport Protocol AVCTP: Audio/Video Control Transport Protocol

HCI协议的作用
HCI协议提供了统一访问蓝牙控制器的能力。 主机控制器以HCI命令的形式提供了访问蓝牙硬 件的基带控制器、链路管理器、硬件状态寄存 器、控制寄存器以及事件寄存器的能力,所有 这些功能都要通过内置于蓝牙硬件内部的HCI Firmware来实现。主机通过HCI接口向主机控制 器内的HCI Firmware发送HCI命令,HCI Firmware 再通过基带命令、链路管理器命令、硬件状寄 存器、控制寄存器以及事件寄存器完成该HCI命 令,从而实现对蓝牙硬件的控制。
主机 其他高层协议 HCI驱动 物理总线(串口,USB等)驱动

物理总线
物理总线固件

HCI Firmware LM

RF
蓝牙控制器

HCI 包命令解析

命 令包:命令包中的OCF(Opcode Command Field)和OGF(Opcode Group Field)是用于区分命令的。Parameter Length表示所带参数的长度,以字节数为单位,随后就是所带的参数列表。 * 链路控制命令; OGF 0X01 控制主机控制器对其他设备的连接; * 链路政策和模式命令; OGF 0X02 通过命令改变控制器的链路管理器的管理方式 * 主机控制和基带命令; OGF 0X03 访问和控制蓝牙的硬件设备 * 信息命令; OGF 0X04 发现本地设备的相关信息 * 状态命令; OGF 0X05 读取主机控制器的状态参数 * 测试命令。 OGF 0X06 功能测试命令 事件包也可分为三种类型: * 通用事件,包括命令完成包(Command Complete)和命令状态包(Command Status); * 测试事件; * 出错时发生的事件,如产生丢失(Flush Occured)和数据缓冲区溢出(Data Buffer Overflow)。 数据包则可分为ACL和SCO的数据包。 看HCI log 工具: Hcidump –X hci

L2CAP 协议层
L2CAP协议是一个为高层协议屏蔽基带协议的适配协议,位于基带协议之上,属于数据链路层,为高层提供面 向连接和面向无连接的数据服务,完成协议复用、分段和重组、服务质IQoS(Quality Of Service)传输以及组抽象 等功能: (1)协议复用:多个高层协议共享一个公共的物理连接,从逻辑上看每个协议都有自己独立的数据通道,但由于 基带协议不能识别任何高层协议,所以L2CAP必须支持上层协议复用,它能区分诸如服务发现协议、RFCOMM协 议、电话控制协议等高层协议。 (2)分段与重组:与有线的物理媒质相比,蓝牙基带协议数据包的大小是有限的。最大的基带包只能传输341字节 的信息,这就限制了高层协议带宽的有效使用,因此较大的L2CAP包必须分解成小的基带包来发送。同样,在接 收方,必须将多个基带包重组为一个完整的L2CAP数据包。 (3)服务质量:在L2CAP建立连接的过程中允许改变两台蓝牙设备间的服务质量,每个L2CAP实体必须监视协议使 用的资源并保证服务质量的实现。 (4)组管理:蓝牙的基带协议支持微微网,即一组设备使用同一时钟同步跳频,L2CAP协议的组提取功能可以有 效地将协议的组映射为基带的微微网,以避免高层协议为了有效的管理组而必须与基带协议以及链路管理器直 接联系。

High Layer
request confirm response indication

L2CAP
request confirm response indication

Low Layer(BB or HCI)
L2CAP的层间操作

RFCOMM 协议层
RFCOMM提供对RS-232串口的仿真,包括对数据信号线和非数据信号线的仿真。它既可以仿真 两个设备之间的多个串口,也可以支持多个设备之问的多串口仿真,同时RFCOMM中还提供 了对空调制解调器的仿真。 1.RFCOMM对九针RS-232串口的仿真 RFCOMM提供了对九针RS-232串口的仿真,包括数据信号线和非数据信号线。 2.多串口仿真 两个数据终端设备之间通过RFCOMM通信,可以打开多达60个仿真串口,但是实际打开串口 数还要视设备生产商的具体实现以及实际需要而定。各仿真串口之间通过数据链路连接标示 符DLCI(Data Link Connection Identifier)加以区分,其中DLCI_0用于指示控制信道,DLCI_1不可用, 而DLCI_62和DLCI 63为保留标示符

SDP 发现服务
这个模型分为三个过程:设备发现过程,设备名字发现过程和SDP服务发现
SDP由三大模块组成: 链路维护模块:完成SDP链路的建立,参数配置和拆链。 PDU收发模块:完成请求PDU的封装发送,收到PDU后以socket通讯方式交给SDP解析服务器完成。 SDP解析服务器:完成收到的PDU的解析,对于请求PDU检索数据库得到响应数据后返回给PDU收 发模块,对于响应PDU解析出的结果直接发送给应用程序。

Bluetooth 其余知识
两种链路类型: 面向连接的同步链路(SCO) 面向无连接的异步链路(ACL)。 三种节能状态, 停等(Park)状态 保持(Hold)状态 呼吸(Sniff)状态 三种纠错方案 1/3前向纠错(FEC) 2/3前向纠错 自动重发(ARQ) 在链路层中,蓝牙系统提供了认证、加密和密钥管理等功能。 每个用户都有一个个人标识码(PIN),它会被译成128bit的链路密钥 (Link Key)来进行单双向认证。一 旦认证完毕,链路就会以不同长度的密码(Encryphon Key)来加密(此密码以shit为单位增减,最大 的长度为128bit)链路层安全机制提供了大量的认证方案和一个灵活的加密方案(即允许协商密码的 长度)

BlueZ介绍
? BlueZ 是官方 Linux Bluetooth栈,由主机控 制接口(Host Control Interface ,HCI)层、 Bluetooth协议核心、逻辑链路控制和适配 协议(Logical Link Control and Adaptation Protocol,L2CAP)、SCO 音频层、其他 Bluetooth 服务、用户空间后台进程以及配 置工具组成。 ? BlueZ以标准socket形式封装了hci、l2cap和 rfcomm协议,使得应用调用更加方便。 ? 参考http://www.bluez.org/

Bluetooth protocol layers mapped to BlueZ kernel modules
hciX Hidd
Mice app

sdpd

telnet/app/ftp/ssh
PAND user bnepX

Serial app

dund
pppX

rfcomm
/dev/rfcomm X

Audio app

Bluetooth socket app User space Kernel space

TCP/IP
PPP
rfcomm.ko krfcommd bnep.ko kbnepd

Hidp.ko Transport layer Network layer

Bluetooth.ko (core socket sysfs)

l2cap.ko Logical linker control and adaption layer Hci_uart.ko Hci_usb.ko Host control interface layer

sco.ko Hci_vhci.ko

Bluetooth ChipSet

蓝牙协议体系结构
BlueZ-util 用户区 socket Bluetooth application

内核区

HCI协议

L2cap

Rfcomm

SCO

BlueZ core

驱动接口
Uart driver USB driver Other driver

Bluetooth hardware
蓝牙协议栈bluez可分为两部分:内核代码和用户态程序及工具集,其中内核代码由BLUEZ核心协 议和驱动程序等模块组成的。用户态程序及工具集包括应用程序接口和BLUEZ工具集。 在内核代码中,bluez协议的bluez-kernal和bluez-libs软件实现了主机控制接口(HCI)和套接字接口 的全部功能,内核代码采用模块化设计,由设备驱动程序模块和蓝牙核心协议模块组成,分别 位于Linux内核的代码的drivers子目录和net子目录下,drivers子目录代码包括Linux内核对各种接 口的蓝牙设备的驱动,net子目录下包括蓝牙核心协议和一部分扩展协议的内核代码,如L2CAP, RFCOMM, SCO, SDP, BNEP的协议。

蓝牙协议结构体系

Linux蓝牙驱动
net/hci_core.c
HCI在主机端的驱动主要是为上层提供一个统一的接口,让上层协议不依赖于具 体硬件的实现。HCI在硬件中的固件与HCI在主机端的驱动通信方式有多种,比如 像UART、USB和PC Card等等。hci_core.c相当于一个框架,用于把各种具体通信方 式胶合起来,并提供一些公共函数的实现。
hci_cmd_task是负责发送CMD的任务,它从hdev->cmd_q队列中取CMD,然后调 用hci_send_frame把CMD发送出去,hci_send_frame又会调用实际的HCI驱动的 send函数发送数据。 hci_rx_task是负责接收数据的任务,它从hdev->rx_q队列中取数据,然后根据数 据的类型调用上层函数处理。数据包有三种类型: HCI_EVENT_PKT: 用于处理一些通信事件,比如连接建立,连接断开,认证和加 密等事件,这些事件控制协议状态的改变。 HCI_ACLDATA_PKT: 异步非连接的数据包,通过hci_acldata_packet提交给上层的 L2CAP协议处理(hci_proto[HCI_PROTO_L2CAP])。 HCI_SCODATA_PKT: 同步面向连接的数据包,通过hci_scodata_packet提供给上层 的SCO协议处理(hci_proto[HCI_PROTO_SCO])。

hci_tx_task 是负责发送数据的任务,发送所有connection中的ACL和SCO数据, 以及hdev->raw_q中的数据包。

Linux蓝牙驱动
HCI为上层提供的接口主要有:

hci_send_sco:发送SCO数据包,把要发送的数据包放入connection的发 送队列中,然后调度发送任务去发送。
hci_send_acl:发送ACL数据包,把要发送的数据包放入connection的发送 队列中,然后调度发送任务去发送。 hci_send_cmd:发送命令数据,把要发送的数据包放入hdev->cmd_q队列 中,然后调度命令发送任务去发送。 hci_register_proto/hci_unregister_proto:注册/注销上层协议,HCI会把接 收到的数据转发给这些上层协议。 hci_register_dev/hci_unregister_dev: 注册/注销设备,HCI会把要发送的数 据通过这些设备发送出去。 其它一些公共函数。

Linux蓝牙驱动
net/hci_conn.c 提供了一些连接管理,论证和加密的函数。 net/hci_event.c 事件处理函数,负责状态机的维护,这些事件通常会使连接从一个状态 转换另一个状态。 hci_si_event:用于发送事件。 hci_event_packet:用于处理底层上报的事件,从hci_rx_task处调用过来。 net/hci_sock.c 给上层提供一个socket接口,应用程序可以通过socket的方式来访问HCI。 hci_sock_init:中注册了BTPROTO_HCI类型family。 hci_sock_create:创建sock的函数,它的sock的ops指向hci_sock_ops。 hci_sock_setsockopt/hci_sock_getsockopt:设置/获取sock的一些选项。 hci_sock_sendmsg:发送消息,根据消息的类型把消息放到适当的队列中。 hci_sock_recvmsg:接收消息,从接收队列中取消息。 hci_sock_recvmsg:ioctl函数。

Linux蓝牙驱动
net/hci_sysfs.c 提供一些sysfs文件系统接口。 net/l2cap.c L2CAP是HCI之上的协议,提供诸如QoS,分组,多路复用,分段和组装之类 的功能。 通过bt_sock_register为上层提供一个sock接口: l2cap_sock_create:创建sock的函数,它的sock的ops指向l2cap_sock_ops。 l2cap_sock_setsockopt/l2cap_sock_getsockopt设置/获取sock的一些选项。 l2cap_sock_sendmsg:发送消息,通过HCI提供hci_send_acl函数把消息传递给 下层的设备。 bt_sock_recvmsg:接收消息,从接收队列中取消息。

通过hci_register_proto向其下的HCI注册协议: l2cap_connect_ind:处理连接请求。 l2cap_connect_cfm:确认连接。 l2cap_disconn:处理断开请求。 l2cap_auth_cfm:认证确认。 l2cap_encrypt_cfm:加密确认。 l2cap_recv_acldata:处理来自HCI的数据。

Linux蓝牙驱动
net/sco.c SCO也是运行在HCI之上的协议,它是面向连接的可靠的传输方式,主要 用于声音数据传输。 通过bt_sock_register为上层提供一个sock接口: sco_sock_create:创建sock的函数,它的sock的ops指向sco_sock_ops。 sco_sock_setsockopt/sco_sock_getsockopt设置/获取sock的一些选项。 sco_sock_sendmsg:发送消息,通过HCI提供sco_send_frame函数把消息 传递给下层的设备。 bt_sock_recvmsg:接收消息,从接收队列中取消息。 通过hci_register_proto向其下的HCI注册协议: sco_connect_ind:处理连接请求。 sco_connect_cfm:确认连接。 sco_disconn_ind:处理断开请求。 sco_recv_scodata: 处理来自HCI数据。

Linux蓝牙驱动
rfcomm/* rfcomm是基于l2CAP之上的协议,它在蓝牙协议之上封装传统的RS232串 口。 drivers/bluetooth 前面我们介绍的都是HCI及其上层的协议,HCI下层的实现就是HCI驱动程 序,这些驱动程序用于与蓝牙硬件通信,通信的方式常见的有USB, UART和PC card等几种。这里我们看看USB的方式: drivers/bluetooth/hci_usb.c hci_usb_probe: 调用hci_register_dev向前面说的hci_core注册HCI设备。 hci_usb_send_frame:用于提供给HCI去发送数据包。它把数据包放到传 输队列__transmit_q(husb, bt_cb(skb)->pkt_type)之中,然后调用 hci_usb_tx_process去传输数据。 hci_usb_tx_process:根据数据的类型去调用hci_usb_send_ctrl /hci_usb_send_isoc /hci_usb_send_bulk把数据通过USB发送给硬件。

BlueZ内部结构分析

BlueZ文件结构
? Bluetooth/hcidump:hci command/event的trace工 具,可以监视蓝牙数据的传送情况。 ? BlueZ/libs:应用层对hci command/event的封装, 提供了发送hci command,接收对应的hci event的 接口。 ? BlueZ/src: Bluetooth 服务、用户空间后台进程以 及配置工具
– 主要后台进程:
? hciattach:将蓝牙芯片绑定到/dev/tty*口。 ? sdpd:SDP协议后台进程,负责蓝牙服务注册,查询等。 ? bluetoothd:bluetooth后台监视进程。监听hci event。

Security Mode
● Security mode 1 No active security enforcement Security mode 2 ● Service level security On device level no difference to mode 1 ● Security mode 3 Device level security Enforce security for every low-level connection

Pairing Proces
Pin_help的理念在bluez-util 3.x时已经被移除,并被密钥代理所代替。 现在支持两种类型的密钥代理:默认和设备特定。一个"特定"的密钥代 理处理所有远端的密钥请求,一个默认的密钥代理,处理特定的代理 所没有发现的所有密钥请求 当CreateBonding方法被调用时,bluetoothd守护进程将确认当前的文件系 统中是否保存了链接密钥,若可以找到,就返回一个错误。若找不到, D-Bus消息将被发出来为密钥请求的设备,注册一个密钥代理。每个 密钥代理被D-Bus对象路径所体现,bluetoothd依据唯一的总线名称和 对象路径来区分代理

How pairing works
● First connection (1) HCI_Pin_Code_Request (2) HCI_Pin_Code_Request_Reply (3) HCI_Link_Key_Notification ● Further connections (1) HCI_Link_Key_Request (2) HCI_Link_Key_Request_Reply (3) HCI_Link_Key_Notification (optional)

Link Key
● Used for authentication – Challenge-Response ● Used for encryption – SAFER+ (128bit Blockcipher) ● Generated by Pairing (or Bonding) Process – Passkey (1-16 alphanum. chars) – Never communicated (secret) – Random number – Explicitely communicated (public) – Master BDADDR – Implicitly communicated (public) ● Usually stored on devices

Android Bluetooth 框架图
Application

PhoneApp
bluetoothhandfreeS ervice

Bluetooth OPP
bluetoothOPPService

settings

Bluetooth Interface
Bluetooth FrameWorks

A2dpservice

BondState HIDhandler

BluetoothService
PANhandler eventloop

AdapterProperty

DeviceProperty

JAVA JNI Bluetooth enable

Bluetooth JNI

Open source

BlueZ

Kernal

Bluetooth 启动流程
? Hardware power on ? Load Bluetooth kernel module
1:insmod *.ko 2: compile into kernel

? Load Bluetooth Firmware
1: usb load Bluetooth FW from kernel /drivers/bluetooth/**.c 2: uart interface, will load from init.rc hciattach /system/bin/hciattach -n /dev/ttyMFD0 texas 3500000 // ttyMFD0--- device interface //texas---search uart type from hciattach list // 3500000 –set the urat baud rate

? Set Hci configure
hciconfig hci0 up

? Launcher the bluetooth daemon
/system/bin/bluetoothd -d –n

? Add HF AG channel
/system/bin/sdptool add --channel=10 HFAG

? Add HS AG channel
/system/bin/sdptool add --channel=11 HSAG

Step for work with profile
1:Get the default adapter.
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // Device does not support Bluetooth }

2:Use getProfileProxy() to establish a connection to the profile proxy object associated with the profile
// Establish connection to the proxy. mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);

3:Set up a BluetoothProfile.ServiceListener. This listener notifies BluetoothProfile IPC clients when they have been connected to or disconnected from the service.
private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = (BluetoothHeadset) proxy;} } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = null; } } };

4:In onServiceConnected(), get a handle to the profile proxy object. 5:Once you have the profile proxy object, you can use it to monitor the state of the connection and perform other operations that are relevant to that profile.

Android Bluetooth A2DP Profile

基本概念及缩略语
? A2DP(Advanced Audio Distribute Profile) 它定义了在ACL信道上进行高质量的音频分发的协议和过程 ? SBC(Low Complexity Subband Codec ) SBC是为蓝牙AV(Audio/Video)应用设计的音频编、解码方式,可 以在中等比特率的情况下获得高质量的音频,并且具有低的计算 复杂度 ? Stream Stream代表两个A/V设备之间流多媒体数据的端到端的逻辑连接 ? SRC(Source) SRC指的是音频数据流的源端 ? SNK(Sink) SNK指的是音频数据流的接收端 ? SEP(Stream End Point) SEP指出了注册SEP的应用端所具有的服务传输能力和AV能

概述
? A2DP的实现依赖于GAVDP和GAP,在GAVDP中定义了流连接 的建立过程,在A2DP中定义流的参数和编、解码过程。典型 的应用可以参照下图 ? SRC(信源)端编码后通过微微网把音频数据发送到SNK(信宿) 端

限制: 1 不支持同步的点对 多点的数据分发 2 由于射频信号的传 输、数据流的编、解码 等,在SRC和SNK之间 有延迟(高通参考设计设 置为500ms) 3 音频数据速率必须 小于蓝牙连接的比特率

AVDTP音频流的状态变化
? AVDTP中定义了6种状态:。其中, ? IDLE状态指的是流连接没有IDLE、Configured、OPEN、 STREAMING、Closing、Aborting建立但L2CAP信道已经打开; ? Configured状态指SEP的配置完成; ? OPEN状态指流连接已经建立; ? STREAMING状态指参数已经配置完毕,进行流的分发。 ? Closing状态指关闭SEP的状态 , ? Aborting状态指Abort流连接

A2DP在android的实现
Android系统中,应用程序只能看到AudioSystem这个接口,AudioFlinger是一个实现类,主 要用于音频选路和PCM包的混音与重采样,并把PCM数据包传送给底层。 AudioFlinger在所有进程中只有一个实体,其他进程如需要访问通过Binder进程间通信的方 式进行访问。 AudioHardware是一层硬件抽象层,主要负责音频数据的收发与控制。AudioFlinger把他看 成实际的硬件。当音频路径设置成A2DP时,通过Bluetooth模块收发数据,通过立体声蓝 牙耳机即可听到高保真音乐。 AudioAccessory主要用于事件的监听,并把这些事件发送给AudioFlinger模块进行音频路 径的重新设定。当蓝牙立体声(监听HCI层的事件),然后把音频路径配置成A2DP模式, 这样音频数据就只会发送到蓝 耳机匹配之后,AudioAccessory会从kernel中获得相应的信息 牙耳机当中,如有必要,也可以设置扬声器的音频解码芯片转入休眠状态。

A2DP在android的实现

当有音频数据播放时,由于SBC音频压缩的开源代码只能压缩512bytes大小的数 据因此,AudioHardware每次发送下来4096Bytes,然后把这4096个字节分割成N 个512Bytes的小块,放入一个队列当中。经过SBC压缩之后变成113bytes。另外一 个线程会每次对SBC压缩好的包进行再封装,封装成一个标准的A2DP packet,然 后再把这样的A2DP packet移动到发送队列当中。 最后设定好软件定时器,每隔一段时间回发送一个A2DP包。这个时间间隔是SBC 编码期间返回的推荐值。

Bluetooth HandFree and HeadSet Profile

概念
Headset Profile(耳机模式) 这是最常用的配置,为当前流行支持蓝牙耳机与移动电话使用。 它依赖于在 64kbt/s编码的音频的CVSD的或PCM以及AT命令从GSM 07.07的一个子集,包括ring, incoming call,hand up以及volume control 。 描述了Bluetooth 耳机如何与计算机或其它 Bluetooth 设备(如手机)通信。连接和配置好后,耳机可以作为远程设备的音频输入 和输出接口。 Hand Free Profile(免提模式) 这是常用来让车用免提沟通与车内移动电话。让蓝牙设备可以控制电话,如接听、 挂断、拒接、语音拨号等,拒接、语音拨号要视蓝牙耳机及电话是否支援 。典型配置 如汽车使用手机作为AG设备。在车内,立体声系统用于电话音频,而车内安装的麦克 风则用于通话时发送输出音频。HFP 还可用于个人计算机在家中或办公环境中作为手 机扬声器的情况。 但是HFP在不断的维护过程中一直在得到优化,现在已经支持eSCO,提供了更好的音 频效果,同时支持了更多的控制命令,包括语音拨号,DTMF tone和车载拨号。

大多数HSP蓝牙耳机实现HFP的一部分功能,如使用移动电话最后一个号码重拨,呼叫 等待,语音拨号。

HFP State Transition Diagram
1:Regis tration 2:Connecti on set up
3:Service level connection waiting 4:Outgoi ng call calling 6:Terminat e a call process

7:Connecti on release

5:Incoming call

8:Three way calling

9:Audio connection transfer

10:Remote Audio Volume Control

Head Set 的建链
? 当蓝牙音频网关AG 接收到一个呼叫, 发起与HS 的链接时, 为使 应用层语音通信可靠, 需要蓝牙协议栈建立可靠的通信链路。根 据蓝牙协议栈运行, 从底层到高层的建链一般要经过以下几个过 程: ? (1) 建立ACL 即基带层的链接; ? (2) 建立L2CAP 层的链接; ? (3) 进行SDP 的查询过程; ? (4) 建立RFCOMM 层的链路; ? (5) RFCOMM 链路建好后, 将通过RFCOMM 信道传输HeadSet 控 制层的一些A T命令; ? (6) 建立SCO 链接; ? (7) 根据应用层的动作执行蓝牙HS与AG之间的音频通信。

Head Set 的建链
1 建立ACL 即基带层的链接 AG 接收到一个呼叫时, 首先建立与HS 之间的ACL链接, 此HS 与AG 之间需预先绑定, 或 者把原来处于休眠状态下的HS 唤醒。这是通过page 进程完成的, 在用page 进程建立 ACL 时, 定义AG 是Master 角色, 于是AG首先发起查询, 通过查询, AG 获得HS 的蓝牙地 址。然后AG 在应用层的驱动下向查询到的HS 发起一个page 进程, 当接收到HS 返回 的应答时, 这时AG 与HS 之间的ACL 链接已经成功建立。一旦ACL 链接建立, 他可以被 用来传送振铃信号。振铃信号的发送是通过AT 命令RING 来完成的。振铃信号也可以 在SCO 链路上发送(DTMF tone)。 2 建立L 2CA P 层的链接 ACL 链接好后, 接着建L2CAP 链路. AG 首先在信令信道上发送一个链接请求信令, 要求 建立信道标号为0x0040 的L2CAP(0x0001~ 0x003F 是协议保留不可动态分配的, 0x0040~ 0xFFFF 可以自由分配) , 此信道的PSM (协议服务复用) 标志0001, 当对方返 回链接响应信号, 表明0x0040 信道已经建好。然后对此信道进行配置,配置完信道后, 就可以利用此CID 为0x0040 的L2CAP 信道进行SDP 查询了。 3 进行SDP 的查询过程 利用CID 为0x0040 的L2CAP 信道进行SDP 的查询过程, 首先是AG 在此L2CAP 信道上发 送一个SDP 查询包, SDP 查询包将查询SDP 服务器端HS 是否具有所需要的服务。若查 询成功, 在ACL 链路上再建一条标号为0x0041 的L 2CA P 链路, 此信道的PSM 为0003, 用来传输RFCOMM 数据流的。同时断开用作SDP 查询的标号为0x0040 的L2CAP 链路。

Head Set 的建链
4 建立RFCOMM 层的链路 当C ID 为0x0041的L2CAP 信道建好之后, 接着就是RFCOMM 的建链过程。首先建控制 信道, 建链发起方AG 在信道上发送一个数据包, 即要求建RFCOMM 层上的Channel0, 如果响应方HS 希望建立链接, 返回一个命令, 表明已经建立好了Channel0 这条 RFCOMM 信道。此信道为控制信道, 用来传送携带控制消息和命令. 其次建立数据信道, 先是对数据传送信道的参数进行协商, 协商命令PN 参数包括对将 要建立的信道Channel1的优先级, 最大帧长等, 当双方协商好后建立传输数据的信道 Channel1。 RFCOMM 层的数据信道建好后, 再对HeadSet 控制层的控制命令进行传输。即在数据 传送信道Channel1 上传送A T + CKPD= 200 等命令, 当接收到对方的响应OK 之后, 就可 以开始建立SCO 链接。 5 建立SCO 链接 初始化时HC I 发一个WR ITE_ VO ICE_ SETT IN G命令, 对音频状态进行设置, 当接收到 AG 的建立SCO 链接的请求时, 若HS 允许, 发送一个接收的HC I 命令, 在命令完成之后, 传输音频信号的SCO 链路就建好了, 此时就可以进行语音通信

Bluetooth Hand Free
Settings PhoneApp
BluetoothHeadsetService AudioManager
SetBluetoothScoOn

HeadsetProfile
AIDL

BluetoothHandFree

BluetoothHeadset

Intent

BluetoothEventLoop
framework

HeadsetBase JNI android_bluetooth _headsetBase

BluetoothAudio Getway

ScoSocket JNI
android_blueto oth_SCOSocket

JNI
Android_server_en evtloop

JNI
android_bluetooth_Bl uetoothAudioGateway

JNI

kernel

RFCOMM

1: Android 实现了对Headset 和Handsfree 两种profile 的支持。其实现核心是 BluetoothHeadsetService,在PhoneApp 创建的时候会启动它。
if (getSystemService(Context.BLUETOOTH_SERVICE) != null) { mBtHandsfree = new BluetoothHandsfree(this, phone); startService(new Intent(this, BluetoothHeadsetService.class)); }

2:BluetoothHeadsetService 通过接收ENABLED_ACTION、BONDING_CREATED_ACTION , DISABLED_ACTION 和REMOTE_DEVICE_DISCONNECT_REQUESTEDACTION 来改变状态,它也会监听 Phone 的状态变化。 3: BluetoothHeadsetService 收到ENABLED_ACTION时,会先向BlueZ注册Headset 和Handsfree 两种profile ( 通过执行sdptool 来实现的, 均作为Audio Gateway ),然后让 BluetoothAudioGateway 接收RFCOMM 连接,让BluetoothHandsfree 接收SCO 连接(这些操作都 是为了让蓝牙耳机能主动连上Android)
if (mAdapter.isEnabled()) { mAg.start(mIncomingConnectionHandler); mBtHandsfree.onBluetoothEnabled(); }

4: RFCOMM 连接的真正实现是在ConnectionThread 中,它分两步,第一步先通过SDPClient 查询 蓝牙设备时候支持Headset 和Handsfree profile,第二步才是去真正建立 RFCOMM 连接。 5:当RFCOMM连接成功建立后,BluetoothHeadsetDevice 会收到RFCOMM_CONNECTED消息,它 会调用BluetoothHandsfree 来建立SCO 连接,广播通知Headset 状态变化的Intent(PhoneApp 和 BluetoothSettings 会接收这个Intent)BluetoothHandsfree 会先做一些初始化工作,比如根据是 Headset 还是Handsfree 初始化不同的ATParser,并且启动一个接收线程从已建立的RFCOMM 上 接收蓝牙耳机过来的控制命令(也就是AT 命令),接着判断如果是在打电话过程中,才去建 立SCO 连接来打通数据通道。 6:当 SCO 连接成功建立后,BluetoothHandsfree 会收到SCO_CONNECTED 消息,它就会去调用 AudioManager setBluetoothScoOn 函数,从而通知音频系统有个蓝牙耳机可用了。到此, Android 完成了和蓝牙耳机的全部连接。

Bluetooth PAN Profile

功能介绍
The Bluetooth PAN feature offers IP support over Bluetooth(L2CAP) , comparable to Wireless LAN on a PC. Participants in a BlueZ PAN can take on the following roles: 1: PAN user (PANU): Client of a NAP or client-type member of a GN. 2: NAP: Network Access Point, Acts as proxy, router or bridge between an existing network infrastructure (typically LAN) and (up to 7 active) wireless clients (PANUs) 3:GN: Group ad-hoc Network controller, Forwarding node in a peer-to-peer style network (Bluetooth Piconet). Interconnects up to 7 (active) PANUs to a real peer-to-peer network

PAN的两种模型
PANU PANU PANU

LAN Infrastructure

GN

NAP

PANU

PANU

PANU

PANU

PANU



PANU

GN module

NAP module

NAP端的模型
device0 bnep0 bridging

device 1

bnep1

bridging

pan0
bridging

nating

eth0

LAN Infr astr uctu re

device 7

Device



bnep7



NAP server

Server端的设置和包安装(1)
Based on the Ubuntu system 1: Install the package list: bluez-compat bridge-utils dhcp3-server 2: Enable the Internet access on the master node, through eth0 device 3: on master (access point) side, edit /etc/sysconfig/network-scripts/ifcfg-bnep0 ~ ifcfg-bnepN, where N is the maximum number of slaves you would like to connect to this master node. DEVICE=bnepK BOOTPROTO=DHCP ONBOOT=no ps: K is corresponding to the file name, say ifcfg-bnepK 4: Modify the /etc/default/dhcp3-server: INTERFACE=“pan0” ; //set pan0 as the dhcp server network. 5:Modify the /etc/dhcp-server/dhcpd.conf # This is a very basic subnet declaration sample. subnet 192.168.0.0 netmask 255.255.0.0 { range 192.168.100.10 192.168.100.20; option domain-name "wrs.com"; option domain-name-servers 192.168.1.1; option broadcast-address 192.168.100.255; option routers 192.168.1.1; default-lease-time 600; max-lease-time 7200; }

Server端的设置和包安装(2)
6: On Server(access point) side: brctl addbr pan0 ifconfig pan0 192.168.100.1 //this is only example brctl setfd pan0 0 brctl stp pan0 disable 7: Start the dhcp server service dhcp-server start 8: When panu connect to NAP server successfully, we should add bridge on the benpX and pan0 brctl show all brctl addif pan0 bnepX brctl addif pan0 eth0 9: Enable ip_forward and iptables in linux on the access point side echo "1" > /proc/sys/net/ipv4/ip_forward Or sysctl net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE iptables -A FORWARD -i pan0 -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

PAN code分析-config
1: Add Bluetooth PAN into connectivity service config.xml //NetworkAttributes add Bluetooth, connection name is Bluetooth, connection type is 7 as Bluetooth type, radio type is 7 as Bluetooth type and the priority is 4, less than WIFI and mobile. <string-array translatable="false" name="networkAttributes"> <item>"wifi,1,1,1"</item> <item>"mobile,0,0,0"</item> <item>"mobile_mms,2,0,2"</item> <item>"mobile_supl,3,0,2"</item> <item>"mobile_hipri,5,0,3"</item> <item>"bluetooth,7,7,4"</item> </string-array> //Add Bluetooth into radioAttributes list, connection type is 7 as Bluetooth, simultaneous is 1 but this parameter is invaild <string-array translatable="false" name="radioAttributes"> <item>"1,1"</item> <item>"0,1"</item> <item>"7,1"</item> </string-array> //List of regexpressions describing the interface (if any) that represent tetherable bluetooth interfaces. If the device doesn't want to support tethering over bluetooth this should be empty for tethering <string-array translatable="false" name="config_tether_bluetooth_regexs" /> <item>“*****”</item> </string-array>

PAN code分析-connectivity

PAN code分析—流程图

PAN code分析--kernal

PAN code分析—dhcp client

PAN code分析—dhcp 状态
dhcpcd一共有7种状态: REBOOTING , INIT , SELECTING , REQUESTING , BOUND , REBINDING , RENEWING

Android HID Profile

概念
? HID(Human Interface Devices)规范运行在蓝牙的L2CAP协议上,并基于 GAP规范 ? HID 功能的实现是基于bluez里面的Input来实现的

HID在Android的实现
1:HID 开启蓝 Android_device 开启扫描

蓝牙设备 (HID)

2.Android_device 获取蓝牙设备信息,比如设备ID, name,UUID(设备具体类型,比如说FTP,蓝牙键盘, 蓝牙立体声耳机等) 3. .根据设备类型,使用不同的链接方式连接设备

Android_device

1,2 步骤我们以建立完毕,我们已经获取了设备的一些信息,通过UUID 参数确定设备为HID 设备, 然后连接设备 3 步骤,当识别设备为蓝牙输入设备(HID)之后(这里有一个UUID 信息的匹配,看蓝牙设备是否为 我们支持的设备类型,对于不支持的设备类型我们不提供连接),框架层会调用org.bluez.input 的 connect 函数进行连接,( 此处的input.so 是特意为蓝牙输入设备准备的库( 生成该库的源文件目录: external\bluetooth\bluez\input,蓝牙设备在此还有其他的库,比如立体声的A2DP.so 库等都有相应的 源文件目录)input.so 库留出的接口是connect 函数(参见external\bluetooth\bluez\doc\input‐api.txt 文 件,有具体的蓝牙input接口),传递好设备之后(打印出来之后发现传递的是ID),android_device 会建立与HID 设备的连接。

你可能感兴趣的:(BlueTooth)