蓝牙技术中,蓝牙地址(BD_ADDR) 和UUID ( Universally Unique Identifier **)**是两个最核心的标识符。地址用于唯一标识蓝牙设备,UUID用于标识蓝牙服务和特征。理解这两类标识符的定义、生成、绑定和使用,是深入掌握 BlueZ 协议栈的关键。
目录
[二、BLE 随机地址深度解析](#二、BLE 随机地址深度解析)
[三、蓝牙地址在 BlueZ 中的绑定与使用](#三、蓝牙地址在 BlueZ 中的绑定与使用)
[四、UUID 体系:从基础定义到协议规范](#四、UUID 体系:从基础定义到协议规范)
[五、UUID 核心操作函数源码解析](#五、UUID 核心操作函数源码解析)
[六、UUID 在服务发现与匹配中的应用](#六、UUID 在服务发现与匹配中的应用)
[七、地址与 UUID 在连接流程中的协同作用](#七、地址与 UUID 在连接流程中的协同作用)
本文基于 BlueZ 5.x 完整源码,深度剖析蓝牙地址与 UUID 的核心机制,涵盖:
-
蓝牙公有/私有地址、随机地址类型原理
-
BlueZ 地址结构体、地址校验、地址生成、地址绑定实现
-
基础 UUID、自定义 UUID、服务特征 UUID 规范定义
-
UUID 解析、匹配、注册、设备服务标识绑定核心函数
-
设备扫描、连接配对、服务发现场景下的地址与 UUID 应用
一、蓝牙地址体系:从物理标识到逻辑抽象
1.1 地址类型分类
蓝牙规范定义了三种地址类型,在 BlueZ 中通过宏定义明确区分:
cpp
// lib/bluetooth.h - 地址类型定义
#define BDADDR_BREDR 0x00 /* 经典蓝牙地址 */
#define BDADDR_LE_PUBLIC 0x01 /* BLE 公共地址 */
#define BDADDR_LE_RANDOM 0x02 /* BLE 随机地址 */
|--------------------|---------|--------------------------------|
| 类型 | 定义值 | 描述 |
| BDADDR_BREDR | 0x00 | BR/EDR 设备地址,基于 IEEE 802-24 MAC |
| BDADDR_LE_PUBLIC | 0x01 | BLE 公共地址,与 BR/EDR 地址相同 |
| BDADDR_LE_RANDOM | 0x02 | BLE 随机地址,可动态变化 |
1.2 地址结构体定义
cpp
// lib/bluetooth.h - BD Address 结构体
typedef struct {
uint8_t b[6];
} __attribute__((packed)) bdaddr_t;
关键特性:
-
6 字节(48 位)固定长度
-
紧凑存储(
__attribute__((packed))) -
可直接用于网络传输
1.3 特殊地址常量
cpp
// lib/bluetooth.h - 预定义地址
#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}}) /* 任意地址 */
#define BDADDR_ALL (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}) /* 广播地址 */
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}}) /* 本地地址 */
1.4 地址操作 内联函数
cpp
// lib/bluetooth.h - 地址比较与拷贝
static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
{
return memcmp(ba1, ba2, sizeof(bdaddr_t));
}
static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
{
memcpy(dst, src, sizeof(bdaddr_t));
}
二、 BLE 随机地址深度解析
2.1 随机地址类型
BLE 随机地址分为四类,通过地址最高 2 位区分:
|----------|------------|------------------|-----------|
| 类型 | 最高 2 位 | 特性 | 生命周期 |
| 静态随机地址 | 0xC0 | 上电随机生成,断电不变 | 设备生命周期内不变 |
| 私有可解析地址 | 0x40 | 基于 IRK 生成,可被对端解析 | 周期性更新 |
| 私有不可解析地址 | 0x00 | 完全随机,不可解析 | 每次连接更新 |
| 固定地址 | 0x80 | 保留 | - |
2.2 BlueZ 地址生成 逻辑
cpp
// src/adapter.c - 静态随机地址生成
static bool generate_static_address(struct btd_adapter *adapter)
{
// ...
bdaddr_t addr;
// 从存储中获取可用地址列表
addrs = g_key_file_get_string_list(file, "Static", mfg, &len, NULL);
if (addrs) {
for (i = 0; i < len; i++) {
str2ba(addrs[i], &addr);
if (adapter_find(&addr))
continue;
/* 找到可用地址 */
bacpy(&adapter->bdaddr, &addr);
adapter->bdaddr_type = BDADDR_LE_RANDOM; /* 标记为随机地址 */
ret = true;
goto done;
}
}
// 生成新地址
crypto = bt_crypto_new();
bt_crypto_random_bytes(crypto, &adapter->bdaddr, sizeof(adapter->bdaddr));
// 设置静态地址标志(最高 2 位置 1)
adapter->bdaddr.b[5] |= 0xc0; /* 设置 0xC0 标识 */
adapter->bdaddr_type = BDADDR_LE_RANDOM;
// ...
}
源码 解读:
-
首先从持久化存储中查找可用地址
-
如果没有可用地址,使用随机数生成器生成新地址
-
将地址最高 2 位置为
0xC0,标识为静态随机地址 -
最终将地址类型设为
BDADDR_LE_RANDOM
2.3 隐私地址( RPA )与 IRK
BLE 隐私功能使用**身份解析密钥(IRK)**生成可解析的私有地址:
cpp
// src/adapter.c - 设置隐私功能
static int set_privacy(struct btd_adapter *adapter, uint8_t privacy)
{
struct mgmt_cp_set_privacy cp;
memset(&cp, 0, sizeof(cp));
if (privacy) {
uint8_t irk[16];
// 加载 IRK
if (load_irk(adapter, irk) == 0) {
cp.privacy = privacy;
memcpy(cp.irk, irk, 16); /* 传递 IRK 给内核 */
}
}
// ...
}
关键机制:
-
IRK(Identity Resolving Key):用于生成和解析私有地址
-
设备周期性使用 IRK 生成新的私有地址
-
对端设备使用相同的 IRK 可以解析这些地址
2.4 地址类型配置
cpp
// src/adapter.c - 读取地址类型配置
static uint8_t get_default_address_type(void)
{
// 从配置文件读取 AddressType
type = g_key_file_get_string(keyfile, "General", "AddressType", NULL);
if (!type)
return BDADDR_LE_PUBLIC; /* 默认为公共地址 */
if (g_str_equal(type, "public"))
addr_type = BDADDR_LE_PUBLIC;
else if (g_str_equal(type, "static"))
addr_type = BDADDR_LE_RANDOM;
return addr_type;
}
配置示例(/etc/bluetooth/main.conf):
cpp
[General]
AddressType = public # 使用公共地址
# 或
AddressType = static # 使用静态随机地址
三、蓝牙地址在 BlueZ 中的绑定与使用
3.1 设备创建时的地址绑定
cpp
// src/device.c - 设备创建
struct btd_device *device_create(struct btd_adapter *adapter,
const bdaddr_t *address, uint8_t bdaddr_type)
{
struct btd_device *device;
device = g_new0(struct btd_device, 1);
device->adapter = adapter;
// 绑定地址信息
bacpy(&device->bdaddr, address);
device->bdaddr_type = bdaddr_type; /* 记录地址类型 */
// 根据地址类型设置支持的协议
if (bdaddr_type == BDADDR_BREDR)
device->bredr = TRUE; /* 标记支持 BR/EDR */
else
device->le = TRUE; /* 标记支持 LE */
return device;
}
3.2 地址类型在连接流程中的判断
cpp
// src/adapter.c - 连接建立时的地址类型处理
if (dst_type == BDADDR_BREDR) {
// BR/EDR 连接:使用经典蓝牙地址
bt_io_connect(io, connect_cb, data, NULL,
BT_IO_OPT_SOURCE_TYPE, BDADDR_BREDR,
BT_IO_OPT_DEST_TYPE, BDADDR_BREDR,
BT_IO_OPT_DEST_BDADDR, &dst,
BT_IO_OPT_INVALID);
} else {
// BLE 连接:根据地址类型设置
uint8_t addr_type = BDADDR_BREDR;
// 根据实际地址类型选择参数
if (data->dst_type == BDADDR_LE_PUBLIC)
addr_type = BDADDR_LE_PUBLIC;
else if (data->dst_type == BDADDR_LE_RANDOM)
addr_type = BDADDR_LE_RANDOM;
bt_io_connect(io, connect_cb, data, NULL,
BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC,
BT_IO_OPT_DEST_TYPE, addr_type,
BT_IO_OPT_DEST_BDADDR, &dst,
BT_IO_OPT_INVALID);
}
3.3 双模式设备的地址管理
cpp
// src/device.h - 设备状态结构
struct btd_device {
// ...
bdaddr_t bdaddr;
uint8_t bdaddr_type;
// 双模式标记
bool bredr; /* 支持 BR/EDR */
bool le; /* 支持 LE */
// 独立状态管理
struct bearer_state bredr_state; /* BR/EDR 连接状态 */
struct bearer_state le_state; /* LE 连接状态 */
// ...
};
// src/device.c - 获取指定类型的状态
static struct bearer_state *get_state(struct btd_device *dev, uint8_t bdaddr_type)
{
if (bdaddr_type == BDADDR_BREDR)
return &dev->bredr_state;
else
return &dev->le_state;
}
四、UUID 体系:从基础定义到协议规范
4.1 UUID 类型定义
BlueZ 支持三种 UUID 长度,通过 bt_uuid_t 结构体统一抽象:
cpp
// lib/uuid.h - UUID 类型定义
typedef struct {
enum {
BT_UUID_UNSPEC = 0, /* 未指定 */
BT_UUID16 = 16, /* 16-bit UUID */
BT_UUID32 = 32, /* 32-bit UUID */
BT_UUID128 = 128, /* 128-bit UUID */
} type;
union {
uint16_t u16; /* 16-bit 值 */
uint32_t u32; /* 32-bit 值 */
uint128_t u128; /* 128-bit 值 */
} value;
} bt_uuid_t;
UUID 类型对比:
|--------------|---------|-------------|----------------------------------------|
| 类型 | 长度 | 用途 | 示例 |
| BT_UUID16 | 16-bit | GATT 服务/特征值 | 0x2800 (Primary Service) |
| BT_UUID32 | 32-bit | 扩展 UUID | 较少使用 |
| BT_UUID128 | 128-bit | SDP 服务 UUID | 0000110d-0000-1000-8000-00805f9b34fb |
4.2 蓝牙基础 UUID
所有蓝牙 UUID 都基于一个基础 UUID:
cpp
// lib/uuid.c - 蓝牙基础 UUID
static uint128_t bluetooth_base_uuid = {
.data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
};
基础 UUID 格式:`00000000-0000-1000-8000-00805F9B34FB`
所有 16-bit 和 32-bit UUID 都嵌入到这个基础 UUID 中形成 128-bit 格式。
4.3 常用 UUID 常量定义
cpp
// lib/uuid.h - 经典蓝牙服务 UUID
#define HSP_HS_UUID "00001108-0000-1000-8000-00805f9b34fb" /* 耳机服务 */
#define HFP_HS_UUID "0000111e-0000-1000-8000-00805f9b34fb" /* 免提服务 */
#define ADVANCED_AUDIO_UUID "0000110d-0000-1000-8000-00805f9b34fb" /* 高级音频服务 */
#define HID_UUID "00001124-0000-1000-8000-00805f9b34fb" /* 人机接口设备 */
// BLE GATT 服务 UUID
#define GATT_UUID "00001801-0000-1000-8000-00805f9b34fb" /* GATT 服务 */
#define BATTERY_UUID "0000180f-0000-1000-8000-00805f9b34fb" /* 电池服务 */
#define HEART_RATE_UUID "0000180d-0000-1000-8000-00805f9b34fb" /* 心率服务 */
// GATT 16-bit 特征值 UUID
#define GATT_CHARAC_DEVICE_NAME 0x2A00 /* 设备名称 */
#define GATT_CHARAC_APPEARANCE 0x2A01 /* 外观 */
#define GATT_CHARAC_BATTERY_LEVEL 0x2A19 /* 电池电量 */
#define GATT_CHARAC_FIRMWARE_REVISION_STRING 0x2A26 /* 固件版本 */
#define GATT_CHARAC_SOFTWARE_REVISION_STRING 0x2A28 /* 软件版本 */
五、UUID 核心操作函数源码解析
5.1 UUID 创建函数
cpp
// lib/uuid.c - 创建不同类型的 UUID
int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
{
memset(btuuid, 0, sizeof(bt_uuid_t));
btuuid->type = BT_UUID16;
btuuid->value.u16 = value;
return 0;
}
int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
{
memset(btuuid, 0, sizeof(bt_uuid_t));
btuuid->type = BT_UUID32;
btuuid->value.u32 = value;
return 0;
}
int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
{
memset(btuuid, 0, sizeof(bt_uuid_t));
btuuid->type = BT_UUID128;
btuuid->value.u128 = value;
return 0;
}
5.2 UUID 转换为 128-bit
为了统一比较,所有 UUID 都需要转换为 128-bit 格式:
cpp
// lib/uuid.c - UUID 转 128-bit
#define BASE_UUID16_OFFSET 2 /* 16-bit UUID 在 128-bit 中的偏移 */
#define BASE_UUID32_OFFSET 0 /* 32-bit UUID 在 128-bit 中的偏移 */
static void bt_uuid16_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
uint16_t be16;
// 填充基础 UUID
dst->value.u128 = bluetooth_base_uuid;
dst->type = BT_UUID128;
// 将 16-bit UUID 转换为大端序并插入正确位置
be16 = htons(src->value.u16);
memcpy(&dst->value.u128.data[BASE_UUID16_OFFSET], &be16, sizeof(be16));
}
static void bt_uuid32_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
uint32_t be32;
dst->value.u128 = bluetooth_base_uuid;
dst->type = BT_UUID128;
be32 = htonl(src->value.u32);
memcpy(&dst->value.u128.data[BASE_UUID32_OFFSET], &be32, sizeof(be32));
}
// 统一入口
void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
switch (src->type) {
case BT_UUID128:
*dst = *src;
break;
case BT_UUID32:
bt_uuid32_to_uuid128(src, dst);
break;
case BT_UUID16:
bt_uuid16_to_uuid128(src, dst);
break;
}
}
转换示意图:
cpp
16-bit UUID: 0x2A19 (电池电量)
↓ 转换为
128-bit UUID: 00002A19-0000-1000-8000-00805F9B34FB
^^^^^^
嵌入位置(偏移 2 字节)
5.3 UUID 比较函数
cpp
// lib/uuid.c - UUID 比较
int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
{
bt_uuid_t u1, u2;
// 先都转换为 128-bit 再比较
bt_uuid_to_uuid128(uuid1, &u1);
bt_uuid_to_uuid128(uuid2, &u2);
return bt_uuid128_cmp(&u1, &u2); /* memcmp 比较 */
}
static int bt_uuid128_cmp(const bt_uuid_t *u1, const bt_uuid_t *u2)
{
return memcmp(&u1->value.u128, &u2->value.u128, sizeof(uint128_t));
}
设计亮点:统一转换为 128-bit 后再比较,支持不同类型 UUID 之间的相等判断。
5.4 字符串与 UUID 互转
cpp
// lib/uuid.c - 字符串转 UUID
int bt_string_to_uuid(bt_uuid_t *uuid, const char *string)
{
if (!string)
return -EINVAL;
// 智能识别 UUID 格式
if (is_base_uuid128(string))
return bt_string_to_uuid16(uuid, string + 4); // 基础UUID格式,提取16-bit部分
else if (is_uuid128(string))
return bt_string_to_uuid128(uuid, string); // 完整 128-bit
else if (is_uuid32(string))
return bt_string_to_uuid32(uuid, string); // 32-bit
else if (is_uuid16(string))
return bt_string_to_uuid16(uuid, string); // 16-bit
return -EINVAL;
}
// lib/uuid.c - UUID 转字符串
int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n)
{
bt_uuid_t tmp;
// 先转 128-bit
bt_uuid_to_uuid128(uuid, &tmp);
// 按标准格式输出
snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
data0, data1, data2, data3, data4, data5);
return 0;
}
六、UUID 在服务发现与匹配中的应用
6.1 SDP 服务搜索中的 UUID 匹配
cpp
// src/sdpd-request.c - SDP UUID 匹配
static int sdp_match_uuid(sdp_list_t *search, sdp_list_t *pattern)
{
int patlen = sdp_list_len(pattern);
if (patlen < sdp_list_len(search))
return -1;
// 遍历搜索 UUID,检查是否都存在于模式列表中
for (; search; search = search->next) {
uuid_t *uuid128;
void *data = search->data;
// 转换为 128-bit
uuid128 = sdp_uuid_to_uuid128((uuid_t *)data);
// 在模式列表中查找
list = sdp_list_find(pattern, uuid128, sdp_uuid128_cmp);
bt_free(uuid128);
if (!list)
return 0; // 未找到匹配
}
return 1; // 所有 UUID 都匹配
}
6.2 设备 UUID 列表管理
cpp
// src/device.c - 添加 UUID 到设备
void btd_device_add_uuid(struct btd_device *device, const char *uuid)
{
GSList *uuid_list;
char *new_uuid;
// 检查 UUID 是否已存在(使用字符串比较)
if (g_slist_find_custom(device->uuids, uuid, bt_uuid_strcmp))
return; // 已存在,直接返回
new_uuid = g_strdup(uuid);
uuid_list = g_slist_append(NULL, new_uuid);
// 触发 Profile 探测
device_probe_profiles(device, uuid_list);
g_free(new_uuid);
g_slist_free(uuid_list);
// 保存到持久化存储
store_device_info(device);
// 通知 DBus 属性变更
g_dbus_emit_property_changed(dbus_conn, device->path,
DEVICE_INTERFACE, "UUIDs");
}
6.3 Profile 匹配核心逻辑
cpp
// src/device.c - Profile 匹配
static bool device_match_profile(struct btd_device *device,
struct btd_profile *profile,
GSList *uuids)
{
if (profile->remote_uuid == NULL)
return false;
// 使用 UUID 字符串比较进行匹配
if (g_slist_find_custom(uuids, profile->remote_uuid,
bt_uuid_strcmp) == NULL)
return false;
return true; // 匹配成功
}
// 探测服务
static struct btd_service *probe_service(struct btd_device *device,
struct btd_profile *profile,
GSList *uuids)
{
struct btd_service *service;
if (profile->device_probe == NULL)
return NULL;
// 首先检查 UUID 是否匹配
if (!device_match_profile(device, profile, uuids))
return NULL;
// 创建服务实例
service = service_create(device, profile);
// 执行服务探测
if (service_probe(service)) {
btd_service_unref(service);
return NULL;
}
return service;
}
6.4 GATT 服务 UUID 处理
cpp
// src/device.c - GATT 服务 UUID 提取
static void add_gatt_service(struct gatt_db_attribute *attr, void *user_data)
{
struct btd_device *device = user_data;
bt_uuid_t uuid;
char uuid_str[MAX_LEN_UUID_STR];
// 获取服务 UUID
gatt_db_attribute_get_service_uuid(attr, &uuid);
bt_uuid_to_string(&uuid, uuid_str, sizeof(uuid_str));
// 检查是否已处理
if (find_service_with_uuid(device->services, uuid_str))
return;
// 添加 UUID 并触发服务探测
btd_device_add_uuid(device, uuid_str);
}
七、地址与 UUID 在连接流程中的协同作用
7.1 设备扫描阶段
cpp
// src/adapter.c - 扫描发现设备时
static void device_found(struct btd_adapter *adapter,
const bdaddr_t *bdaddr, uint8_t bdaddr_type)
{
struct btd_device *device;
// 1. 通过地址查找或创建设备
device = btd_adapter_find_device(adapter, bdaddr, bdaddr_type);
if (!device) {
device = device_create(adapter, bdaddr, bdaddr_type);
btd_adapter_add_device(adapter, device);
}
// 2. 根据地址类型标记支持的协议
if (bdaddr_type == BDADDR_BREDR)
device_set_bredr_support(device);
else
device_set_le_support(device, bdaddr_type);
// 3. 发送 DBus 信号通知新设备
g_dbus_emit_signal(dbus_conn, adapter->path,
ADAPTER_INTERFACE, "DeviceFound",
DBUS_TYPE_OBJECT_PATH, &device->path,
DBUS_TYPE_INVALID);
}
7.2 服务发现阶段
cpp
// src/device.c - 连接后服务发现
static void resolve_services(struct btd_device *dev, DBusMessage *msg)
{
uint8_t bdaddr_type = btd_device_get_bdaddr_type(dev);
int err;
// 根据地址类型选择不同的服务发现方式
if (bdaddr_type == BDADDR_BREDR)
err = device_browse_sdp(dev, msg); /* BR/EDR: SDP */
else
err = device_browse_gatt(dev, msg); /* LE: GATT */
if (err < 0) {
return btd_error_failed(msg, bdaddr_type == BDADDR_BREDR ?
ERR_BREDR_CONN_SDP_SEARCH : ERR_LE_CONN_GATT_BROWSE);
}
}
7.3 Profile 自动匹配
cpp
// src/adapter.c - 设备探测 Profile
static void probe_devices(void *user_data)
{
struct btd_device *device = user_data;
// 使用设备的 UUID 列表进行 Profile 匹配
device_probe_profiles(device, btd_device_get_uuids(device));
device_resolved_drivers(device_get_adapter(device), device);
}
流程总结:

八、开发实战与踩坑经验
8.1 地址相关问题
|-------------|----------|----------------------------------------------|
| 问题 | 原因 | 解决方案 |
| 无法识别 BLE 设备 | 地址类型错误 | 确保使用 BDADDR_LE_PUBLIC 或 BDADDR_LE_RANDOM |
| 随机地址连接失败 | 地址已过期 | 使用 IRK 解析真实身份 |
| 双模式设备无法连接 | 地址类型判断错误 | 检查 bdaddr_type 参数 |
8.2 UUID 相关问题
|----------------------|------------|------------------------------|
| 问题 | 原因 | 解决方案 |
| 服务无法识别 | UUID 格式不一致 | 使用 bt_uuid_cmp() 统一比较 |
| Profile 不匹配 | UUID 列表为空 | 确保服务发现完成后再匹配 |
| 16-bit 与 128-bit 不匹配 | 类型转换问题 | 使用 bt_uuid_to_uuid128() 转换 |
8.3 调试技巧
cpp
# 查看设备详细信息(包括地址和 UUID)
bluetoothctl info AA:BB:CC:DD:EE:FF
# 查看设备支持的 UUID 列表
bluetoothctl uuids AA:BB:CC:DD:EE:FF
# 使用 btmgmt 查看地址设置
btmgmt info
# 启用 BlueZ 调试日志
bluetoothd -d
8.4 代码示例
cpp
// 创建设备连接代码示例
int connect_to_device(const char *address, uint8_t addr_type)
{
bdaddr_t bdaddr;
struct btd_device *device;
// 1. 解析地址字符串
if (str2ba(address, &bdaddr) < 0) {
fprintf(stderr, "Invalid address format\n");
return -1;
}
// 2. 创建设备对象
device = device_create(adapter, &bdaddr, addr_type);
if (!device) {
fprintf(stderr, "Failed to create device\n");
return -1;
}
// 3. 添加到适配器
btd_adapter_add_device(adapter, device);
// 4. 执行连接
return device_connect(device);
}
// UUID 比较代码示例
bool check_service_match(const char *uuid_str, bt_uuid_t *service_uuid)
{
bt_uuid_t target_uuid;
// 字符串转 UUID
if (bt_string_to_uuid(&target_uuid, uuid_str) < 0) {
return false;
}
// 比较 UUID
return bt_uuid_cmp(&target_uuid, service_uuid) == 0;
}
九、核心函数索引
9.1 地址相关函数
|-----------------------------|-----------------|----------|
| 函数 | 文件 | 功能 |
| bacmp() | lib/bluetooth.h | 比较两个蓝牙地址 |
| bacpy() | lib/bluetooth.h | 拷贝蓝牙地址 |
| str2ba() | lib/bluetooth.h | 字符串转地址 |
| ba2str() | lib/bluetooth.h | 地址转字符串 |
| generate_static_address() | src/adapter.c | 生成静态随机地址 |
| set_privacy() | src/adapter.c | 设置隐私功能 |
9.2 UUID 相关函数
|--------------------------|--------------|-----------------|
| 函数 | 文件 | 功能 |
| bt_uuid16_create() | lib/uuid.c | 创建 16-bit UUID |
| bt_uuid32_create() | lib/uuid.c | 创建 32-bit UUID |
| bt_uuid128_create() | lib/uuid.c | 创建 128-bit UUID |
| bt_uuid_to_uuid128() | lib/uuid.c | UUID 转 128-bit |
| bt_uuid_cmp() | lib/uuid.c | UUID 比较 |
| bt_uuid_to_string() | lib/uuid.c | UUID 转字符串 |
| bt_string_to_uuid() | lib/uuid.c | 字符串转 UUID |
| btd_device_add_uuid() | src/device.c | 设备添加 UUID |
| device_match_profile() | src/device.c | Profile UUID 匹配 |
十、总结
蓝牙地址和 UUID 是 BlueZ 协议栈中最基础的两个核心标识体系:
- 地址体系:
-
三种类型:
BDADDR_BREDR、BDADDR_LE_PUBLIC、BDADDR_LE_RANDOM -
支持静态随机地址和隐私地址(RPA)
-
通过
bdaddr_t结构体统一抽象
- UUID 体系:
-
三种长度:16-bit、32-bit、128-bit
-
基于统一基础 UUID 进行转换
-
通过
bt_uuid_t结构体统一抽象
- 协同工作:
-
地址用于设备识别和连接
-
UUID 用于服务识别和功能匹配
-
两者配合实现完整的蓝牙设备管理
深入理解这两个标识体系,不仅有助于掌握 BlueZ 源码架构,更能有效解决实际开发中的设备识别、服务发现和功能适配问题。