bluetoothd: source file reading
程序入口
首先从 /src/main.c
的 main() 函数开始,对于本地定义的函数功能作出解读。
第一部分
init_defaults() 默认值的初始化操作,主要是给全局变量
btd_opts
设置默认值。其中有我们所关心的一些信息:BlueZ版本、临时设备(Temporary)被清理的定时时长、适配器配对属性(Pairable)和可发现属性(Discoverable)默认有效时长 等等。第二部分
解析bluetoothd支持的输入参数,
options
结构体变量预定义了一些参数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 省略...
// 创建一个上下文结构体指针变量context
context = g_option_context_new(NULL);
// 将options的条目增加到context
g_option_context_add_main_entries(context, options, NULL);
// 通过用户输入的参数argv与预定义的命令行参数对比解析
if (g_option_context_parse(context, &argc, &argv, &err) == FALSE) {
if (err != NULL) {
g_printerr("%s\n", err->message);
g_error_free(err);
} else
g_printerr("An unknown error occurred\n");
exit(1);
}
g_option_context_free(context);
// 省略...注意:上述几个函数都是 Glib库中的函数
1、g_option_context_new
2、g_option_context_add_main_entries
3、g_option_context_parse
4、g_option_context_free
第三部分
debug和log部分的初始化处理
第四部分
用户配置文件导入和解析,前提条件:用户运行bluetoothd时通过参数-f指定了配置文件,若用户没有指定配置文件,那么将使用main.conf。
第五部分
连接dbus daemon,然后向dbus上注册
org.bluez
服务。第六部分
adapter_init() 函数用于适配器初始化操作,查找本地蓝牙适配器数量,在适配器上注册所有的事件(event)通知回调函数,这里需要重点关注几个:
1
2device_found_callback()
discovering_callback()当底层的蓝牙适配器controller发现蓝牙设备通过 device_found_callback() 回调函数通知bluetoothd应用
当底层的蓝牙适配器controller启动/停止扫描通过 discovering_callback() 回调函数通知bluetoothd应用
Host和Controller之间通过HCI通信,Host创建socket接口,接着注册 can_read_data() 回调函数,可以读取Controller的Event,当然也可以通过send_request() 发送Command给Controller。
1
socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
第七部分
device、agent、profile、plugin的初始化
1
2
3btd_device_init();
btd_agent_init();
btd_profile_init();第八部分
注册信号,然后进入glib事件循环
1
mainloop_run_with_signal(signal_callback, NULL);
bluetoothd就启动完毕了。
对于bluetoothd源码的解读还有非常的多的疑问,互联网上对于bluez中bluetoothd资料更是凤毛麟角,只能是暂时自己对于bluetoothd源码的一个简单的认识。
MGMT
1 |
|
设备发现
当适配器开始扫描时,发现了附近的蓝牙设备,蓝牙设备被添加到适配器的过程是怎么样的?
当适配器执行扫描时,发现的蓝牙设备通过回调函数传递(bluetoothd在main函数中执行adapter_init函数就注册所有的事件回调函数),以下就是关于设备发现的回调函数。
1 | static void device_found_callback(uint16_t index, uint16_t length, |
接着关注这个函数 btd_adapter_device_found,由于这个函数太长,仅放出部分代码:
1 | void btd_adapter_device_found(struct btd_adapter *adapter, |
device_store_cached_name函数用于在cache目录下创建设备的持久化存储,接下来关注这个函数 adapter_create_device
1 | static struct btd_device *adapter_create_device(struct btd_adapter *adapter, |
重点来了,此时看到了函数 device_create
用于创建设备,具体看它的实现
1 | struct btd_device *device_create(struct btd_adapter *adapter, |
我们知道蓝牙设备被适配器添加后,会注册类似这种对象路径 /org/bluez/hci0/dev_50_64_2B_BF_46_36
,这部分内容就在这个函数 device_new()
1 | static const GDBusMethodTable device_methods[] = { |
这个函数 g_dbus_register_interface
为蓝牙设备注册了 org.bluez.Device1
服务
扫描注意事项:
参考来源:Core_amended_2024_06_11_v5.4.pdf
查询扫描类型(inquiry scan type)
Inquiry_Scan_Type 配置参数指示查询扫描是否使用非隔行扫描或隔行扫描进行。目前,定义了一种强制查询扫描类型和一种可选查询扫描类型。
查询扫描窗口(inquiry scan window):持续扫描查询的时间,必须小于或等于扫描间隔。取值范围:0x0011 ~ 0x1000,转化为时间单位范围:10.625 ms ~ 2560 ms,默认值:0x0012(11.25ms)
注意:一个扫描窗口并不会扫描所有的40个射频通道,完全取决于硬件底层实现。
查询扫描间隔(inquiry scan interval):从上一次扫描查询开始扫下一次扫描查询开始的时间间隔。取值范围:0x0012 ~ 0x1000,转化为时间单位范围:11.25 ms ~ 2560 ms,默认值:0x1000(2560ms)
Inquiry_Scan_Interval 配置参数定义连续查询扫描之间的时间量。这定义为从 BR/EDR 控制器开始其上一次查询扫描到开始下一次查询扫描的时间间隔
页扫描间隔(page scan interval):Page_Scan_Interval 配置参数定义连续页面扫描之间的时间量。此时间间隔定义为从控制器开始其上一次页面扫描到开始下一次页面扫描的时间。
页扫描窗口(page scan window):Page_Scan_Window 配置参数定义页面扫描的持续时间。Page_Scan_Window 只能小于或等于 Page_Scan_Interval。
扫描窗口和扫描间隔的关系:
其他学习参考BLE设备功耗太高?弄懂这几个参数,功耗想不降都难
扫描参数
在 main.conf 配置文件中涉及到bredr 和 le 的扫描参数。
1 | [BT] |
在src/main.c 中若用户没有指定配置文件(例如main.conf),那么就会给定一个默认值。
通过读取配置文件,覆盖默认扫描参数:
- LE扫描参数范围
1 | { "ScanIntervalDiscovery", |
- BREDR扫描参数范围
1 | { "InquiryScanType", |