蓝牙部分
蓝牙协议栈 1.1 1.2 2.0 2.1 3.0
异步数据和语音传输 采用的协议:
逻辑链路控制和适配协议(L2CAP) 、服务发现协议(SDP) 、串口模拟协议(RFCOMM)
主要控制接口由主机控制接口层体现,他是蓝牙协议里软硬件之间的接口
在HCI之上的是蓝牙的上层应用框架,每个应用模式为一个profile ,如无线立体声耳机A2DP
(Advanced Audio Distribution Profile)等
蓝牙的基本架构
自上而下包括以下内容:
Linux 内核的蓝牙驱动程序
Linux 内核的蓝牙协议层
Bluez 蓝牙在用户空间的库
Bluez 适配层
Android.bluetooth包中的各个类(蓝牙在框架层的内容)
蓝牙相关的应用程序
蓝牙部分的结构图:
蓝牙的用户空间库 bluez
空间库bluez 是linux平台上的一套完整的蓝牙协议栈,通过D-BUS IPC机制来提供应用层接口
它的底层协议实现在kernel 代码中
D-BUS是一套应用广泛的进程间通信(IPC)机制,是相对比较底层的(类似socket) 它更加复杂
代码位于kernl目录下的net/bluetooth下
底层协议方面;
HCI: 主机控制协议, 完成与蓝牙硬件的交互
SDP: 服务发现协议, 访问其他服务的基础协议
RFCOMM: 类似于串口的通信协议 为上层服务的实现提供传输接口
L2CAP: 逻辑链路和控制协议,是RFCOMM.SDP等协议的基础
SCO: 同步数据交换协议
上图中左侧部分为HCI具体功能实现;
Adapter 一个adapter对应一个蓝牙设备,管理设备相关信息
Manager 管理主机上的蓝牙设备
Service 服务
Security 安全相关功能模块
Database 管理组织服务列表
右侧是各种服务
Audio 语音 A2DP 普通语音同步
Input 输入服务
Transfer 文件交换服务
Network 网络服务
各种协议之间的关系
在android系统中,bluez的源码在以下的目录中: \external\bluetooth\bluez
会生成若干个动态库和可执行程序
动态库
Libbluetooth: 公共库被各部分应用使用,
Libhcid: 主机接口的实现
Audio: 音频服务
Input : 输入服务
Liba2dp: 蓝牙立体声服务
可执行程序
Hcid: 直接封装libhcid 主机接口的实现 守护进程,提供对外的D-BUS接口
Hciconfig hcitool hciattach 主机接口辅助工具
Dund 提供dun服务
Pand 提供pan服务
Sdptool 提供sdp服务相关接口
Rfcomm rfcomm配置工具
Bluez的适配层
代码路径为:\system\bluetoot
封装了蓝牙的开关功能和射频开关
蓝牙的JNI部分和java部分
JNI部分的代码路径为: \frameworks\base\core\jni
最终生成libandroid_runtime.so
Jvav部分代码路径
蓝牙的服务部分代码路径 \frameworks\base\core\java\android\server
支持耳机(headset) 免提(handsfree) 立体声(a2dp)
核心组成 android.bluetooth包中以IBluetoothDevice.aidl为接口的IBinder服务端BluetoothDeviceService
客户端 BluetoothDevice以及android.service包中的BluetothEventLoop
bluetoothdeviceService 主要是用于蓝牙的开启和关闭,设备的发现和配对,服务的发现和邦定
开关功能是直接调用底层的bluezr接口来实现
Java部分和底层的关系
客户端bluetoothDevice.getRemoteServiceChannel调用服务端的bluetoothDeviceService.getRemoteServiceChannel然后调用JNI的getRemoteServiceChannelNative
Android_bluetooth_common.h的部分代码如下;
dbus_bool_t dbus_func_args_async(JNIEnv *env,
DBusConnection *conn,
int timeout_ms,
void (*reply)(DBusMessage *, void *, void *),
void *user,
void *nat,
const char *path,
const char *ifc,
const char *func,
int first_arg_type,
...);
最后调用;dbus_func_args_async_valist
static dbus_bool_t dbus_func_args_async_valist(JNIEnv *env,
DBusConnection *conn,
int timeout_ms,
void (*user_cb)(DBusMessage *,
void *,
void*),
void *user,
void *nat,
const char *path,
const char *ifc,
const char *func,
int first_arg_type,
va_list args) {
DBusMessage *msg = NULL;
const char *name;
dbus_async_call_t *pending;
dbus_bool_t reply = FALSE;
/* Compose the command */
//组成命令 (创建一个消息结构)
msg = dbus_message_new_method_call(BLUEZ_DBUS_BASE_IFC, path, ifc, func);
if (msg == NULL) {
LOGE("Could not allocate D-Bus message object!");
goto done;
}
/* append arguments */
//附加参数
if (!dbus_message_append_args_valist(msg, first_arg_type, args)) {
LOGE("Could not append argument to method call!");
goto done;
}
/* Make the call. */
//通过D-BUS调用接口
pending = (dbus_async_call_t *)malloc(sizeof(dbus_async_call_t));
if (pending) {
DBusPendingCall *call;
pending->env = env; //设置参数中的内容
pending->user_cb = user_cb;
pending->user = user;
pending->nat = nat;
//pending->method = msg;
// 发送命令返回信息
reply = dbus_connection_send_with_reply(conn, msg,
&call,
timeout_ms);
if (reply == TRUE) {
dbus_pending_call_set_notify(call,
dbus_func_args_async_callback,
pending,
NULL);
}
}
done:
if (msg) dbus_message_unref(msg);
return reply;
}
//本机的首个蓝牙设备
#define BLUEZ_ADAPTER_OBJECT_NAME BLUEZ_DBUS_BASE_PATH "/hci0"
Ifc 为DBUS_CLASS_NAME 指向org.bluez.adapter 直接访问HCI部分的adapter
在android 2.3之后有采用level11 ,支持了测试蓝牙链接状态的函数
//链接spp类的设备
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice bd = adapter.getRemoteDevice(addr);
Method m = bd.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
BluetoothSocket bs = (BluetoothSocket) m.invoke(bd, Integer.valueOf(1));