mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
docs(ble_audio): Adopt SIG product name and add LE Audio API guide entry
This commit is contained in:
@@ -229,6 +229,17 @@ ESP-NimBLE 仅支持低功耗蓝牙,不支持经典蓝牙。
|
||||
- :example:`应用示例 <bluetooth/blufi>`
|
||||
|
||||
|
||||
.. only:: SOC_BLE_AUDIO_SUPPORTED
|
||||
|
||||
ESP-BLE-AUDIO
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
蓝牙低功耗音频是蓝牙核心规范 5.2 引入的音频架构。ESP-BLE-AUDIO 在 ESP-BLE-ISO 传输层之上提供通用音频框架 (Generic Audio Framework) 的规范和服务。两者均可运行在 ESP-Bluedroid 或 ESP-NimBLE 主机协议栈上。
|
||||
|
||||
- :doc:`ESP-IDF 低功耗音频文档 <../esp-ble-audio/ble-audio-index>`:标准概述、架构、功能支持状态等。
|
||||
- :example:`应用示例 <bluetooth/esp_ble_audio>`
|
||||
|
||||
|
||||
应用
|
||||
----
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ ESP-BLE-ISO
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
ESP-BLE-ISO 提供了上层规范所需的每一个 BLE 传输原语:ACL 连接状态、广播与扫描、周期性广播同步、HCI 命令路径、ISO(CIS 和 BIS)、GATT、GAP 和 L2CAP,以及 :ref:`并发与线程安全 <arch-concurrency>` 中描述的 ISO 任务事件循环和全局锁。这些都不是音频专用的;ESP-IDF 蓝牙 LE Audio 只是目前位于其上的规范层。本章依次介绍整个组件:连接管理、广播与扫描、HCI 命令路径、ISO 子系统、GAP、GATT 和 L2CAP,以及公共 API。
|
||||
ESP-BLE-ISO 提供了上层规范所需的每一个低功耗蓝牙传输原语:ACL 连接状态、广播与扫描、周期性广播同步、HCI 命令路径、ISO(CIS 和 BIS)、GATT、GAP 和 L2CAP,以及 :ref:`并发与线程安全 <arch-concurrency>` 中描述的 ISO 任务事件循环和全局锁。这些都不是音频专用的;ESP-IDF 蓝牙低功耗音频只是目前位于其上的规范层。本章依次介绍整个组件:连接管理、广播与扫描、HCI 命令路径、ISO 子系统、GAP、GATT 和 L2CAP,以及公共 API。
|
||||
|
||||
整个组件中反复出现两个约定,值得在此一次性说明:
|
||||
|
||||
@@ -27,14 +27,14 @@ ESP-BLE-ISO 提供了上层规范所需的每一个 BLE 传输原语:ACL 连
|
||||
并发与线程安全
|
||||
------------------------
|
||||
|
||||
主机协议栈之上的所有 ESP-IDF 蓝牙 LE Audio 处理都运行在单个任务上 —— **ISO 任务**\ (``iso_task``)—— 并且对所有共享状态的访问都由一把全局递归互斥锁串行化,即 **ISO 锁**\ (``bt_le_host_lock``)。这两种机制共同保证了协议栈的线程安全;理解它们是厘清顺序与竞态问题的关键。
|
||||
主机协议栈之上的所有 ESP-IDF 蓝牙低功耗音频处理都运行在单个任务上 —— **ISO 任务**\ (``iso_task``)—— 并且对所有共享状态的访问都由一把全局递归互斥锁串行化,即 **ISO 锁**\ (``bt_le_host_lock``)。这两种机制共同保证了协议栈的线程安全;理解它们是厘清顺序与竞态问题的关键。
|
||||
|
||||
ISO 任务事件循环
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
ISO 任务(位于 ``host/common/task.c``)是一个永远循环的单个 FreeRTOS 任务,负责排空协议栈其余部分通过 ``bt_le_iso_task_post()`` 投递给它的工作。每一项携带一个事件类型标签,任务据此将其分发给对应类别的处理函数 —— 定时器、GAP、GATT、ISO HCI、ISO 发送完成或 ISO 接收数据。
|
||||
|
||||
投递的工作并非单一队列,而是\ **三个优先级层**\ ,每层是一条独立的 FreeRTOS 队列,合并到任务所阻塞等待的一个队列集(queue set)中。每次被唤醒时,任务都\ **严格按优先级**\ 处理各层 —— 先 critical、再 normal、最后 floodable —— 每轮循环处理一项,并在下一轮重新优先检查 critical 层:
|
||||
投递的工作并非单一队列,而是\ **三个优先级层**\ ,每层是一条独立的 FreeRTOS 队列,合并到任务所阻塞等待的一个队列集 (queue set) 中。每次被唤醒时,任务都\ **严格按优先级**\ 处理各层 —— 先 critical、再 normal、最后 floodable —— 每轮循环处理一项,并在下一轮重新优先检查 critical 层:
|
||||
|
||||
.. list-table:: ISO 任务优先级层
|
||||
:header-rows: 1
|
||||
@@ -131,7 +131,7 @@ ISO 任务(位于 ``host/common/task.c``)是一个永远循环的单个 Free
|
||||
- ISO 任务
|
||||
- **NimBLE 主机任务**
|
||||
|
||||
有两行将回调放在 NimBLE 主机任务上,而非 ISO 任务。GATT 客户端读写完成落在那里,是因为 NimBLE 通过其主机任务上的完成回调报告流程结果,适配器在 ISO 锁下原地(inline)调用应用回调,而不是重新投递它 —— 相比之下,Bluedroid 会把每个 BTA GATT 事件都投递到 ISO 任务。GATT 服务端属性访问那一行有更鲜明的原因:两种主机以相反的方式完成访问。在 Bluedroid 上,请求被投递到 ISO 任务,已注册的回调在那里运行,而响应随后\ **异步**\ 发送,如下图所示:
|
||||
有两行将回调放在 NimBLE 主机任务上,而非 ISO 任务。GATT 客户端读写完成落在那里,是因为 NimBLE 通过其主机任务上的完成回调报告流程结果,适配器在 ISO 锁下原地 (inline) 调用应用回调,而不是重新投递它 —— 相比之下,Bluedroid 会把每个 BTA GATT 事件都投递到 ISO 任务。GATT 服务端属性访问那一行有更鲜明的原因:两种主机以相反的方式完成访问。在 Bluedroid 上,请求被投递到 ISO 任务,已注册的回调在那里运行,而响应随后\ **异步**\ 发送,如下图所示:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -206,7 +206,7 @@ ISO 任务(位于 ``host/common/task.c``)是一个永远循环的单个 Free
|
||||
* - 文件
|
||||
- 作用
|
||||
* - ``host.c``
|
||||
- 初始化与反初始化编排;全局递归锁(``bt_le_host_lock`` / ``bt_le_host_unlock``)。
|
||||
- 初始化与反初始化编排;全局递归锁 (``bt_le_host_lock`` / ``bt_le_host_unlock``)。
|
||||
* - ``task.c``
|
||||
- ISO 任务事件循环、其三条优先级队列和队列集,以及 ``bt_le_iso_task_post()``。
|
||||
* - ``conn.c``
|
||||
@@ -251,12 +251,12 @@ ISO 状态机独立于通用层的其余部分,位于 ``host/iso/iso.c`` 中
|
||||
广播与扫描
|
||||
------------------------
|
||||
|
||||
``adv.c`` 被刻意保持得很小:它按句柄跟踪扩展广播集(``bt_le_ext_adv_find`` / ``bt_le_ext_adv_new_safe`` / ``bt_le_ext_adv_delete_safe``)。广播集是广播 ISO 组所附着的锚点,因此这张表是 ISO 子系统中 BIG 广播端流程的前提。
|
||||
``adv.c`` 被刻意保持得很小:它按句柄跟踪扩展广播集 (``bt_le_ext_adv_find`` / ``bt_le_ext_adv_new_safe`` / ``bt_le_ext_adv_delete_safe``)。广播集是广播 ISO 组所附着的锚点,因此这张表是 ISO 子系统中 BIG 广播端流程的前提。
|
||||
|
||||
``scan.c`` 覆盖三项相关职责:
|
||||
|
||||
- **扫描**。``bt_le_scan_cb`` 注册表;广播报告到达 ``bt_le_scan_recv_listener`` 并被递交给应用。
|
||||
- **周期性广播同步**。同步表(``bt_le_per_adv_sync_new`` / ``..._delete`` / ``..._lookup_addr``)及其监听器 —— ``..._establish_listener``、``..._lost_listener`` 和 ``..._report_recv_listener`` —— 跟踪对广播源周期性广播序列的同步。
|
||||
- **周期性广播同步**。同步表 (``bt_le_per_adv_sync_new`` / ``..._delete`` / ``..._lookup_addr``) 及其监听器 —— ``..._establish_listener``、``..._lost_listener`` 和 ``..._report_recv_listener`` —— 跟踪对广播源周期性广播序列的同步。
|
||||
- **BIGInfo 报告**。``hci_le_biginfo_adv_report`` 呈现搭载在周期性广播序列上的 BIGInfo。BIGInfo 携带接收端同步到广播等时组所需的参数,因此该处理函数是从扫描进入 BIG 接收端流程的桥梁。
|
||||
|
||||
因此,周期性广播同步是接收广播音频的入口点:扫描、同步到周期性广播序列、读取 BIGInfo,然后请求 ISO 子系统同步到该 BIG。
|
||||
@@ -277,7 +277,7 @@ ISO 引擎从不直接与主机协议栈对话。它用 ``bt_hci_cmd_create(opco
|
||||
- ``bt_le_bluedroid_iso_cmd_send_sync``
|
||||
- ``bt_le_nimble_iso_cmd_send_sync``
|
||||
* - 转换
|
||||
- 一个 opcode 分支;每个命令都通过一条私有的直连 HCI(direct-HCI)路径作为原始 HCI 命令转发。
|
||||
- 一个 opcode 分支;每个命令都通过一条私有的直连 HCI (direct-HCI) 路径作为原始 HCI 命令转发。
|
||||
- 一个 opcode 分支;每个命令都被拆解到 NimBLE 的类型化 ``ble_hs_hci_*`` ISO 辅助函数。
|
||||
* - 同步
|
||||
- ``adapter/bluedroid/hci.c`` 中的一个私有完成信号量;完成回调运行在 HCI 层任务上。
|
||||
@@ -310,9 +310,9 @@ Bluedroid 自带命令路径的原因是并发。Bluedroid 的 BTU 任务使用
|
||||
ISO 子系统
|
||||
------------------------
|
||||
|
||||
ISO 子系统分布在三处:引擎(``host/iso/iso.c``)、元事件与数据粘合层(``host/common/iso.c``),以及适配器(``host/adapter/*/iso.c``)。引擎拥有三个按配置确定大小的静态池 —— 一个用于 ISO 通道(``CONFIG_BT_ISO_MAX_CHAN``)、一个用于连接等时组(``CONFIG_BT_ISO_MAX_CIG``)、一个用于广播等时组(``CONFIG_BT_ISO_MAX_BIG``)。每个公共引擎操作都遵循本节开头的 ``_safe`` 约定。
|
||||
ISO 子系统分布在三处:引擎 (``host/iso/iso.c``)、元事件与数据粘合层 (``host/common/iso.c``),以及适配器 (``host/adapter/*/iso.c``)。引擎拥有三个按配置确定大小的静态池 —— 一个用于 ISO 通道 (``CONFIG_BT_ISO_MAX_CHAN``)、一个用于连接等时组 (``CONFIG_BT_ISO_MAX_CIG``)、一个用于广播等时组 (``CONFIG_BT_ISO_MAX_BIG``)。每个公共引擎操作都遵循本节开头的 ``_safe`` 约定。
|
||||
|
||||
入站 ISO 元事件在两种主机上形态相同:适配器注册一个主机原生的 ISO 事件回调,封装该事件,并向 ISO 任务投递一个 ``ISO_HCI_EVENT`` 项;随后 ``host/common/iso.c`` 解码 LE 子事件并将其分发给引擎。一处线格式(wire-format)差异在此被吸收:NimBLE 的元事件结构已经包含子事件码,而 Bluedroid 适配器会在前面补上它,因此 ``host/common/iso.c`` 中的解码器无论在哪种主机上都看到统一的布局。
|
||||
入站 ISO 元事件在两种主机上形态相同:适配器注册一个主机原生的 ISO 事件回调,封装该事件,并向 ISO 任务投递一个 ``ISO_HCI_EVENT`` 项;随后 ``host/common/iso.c`` 解码 LE 子事件并将其分发给引擎。一处线格式 (wire-format) 差异在此被吸收:NimBLE 的元事件结构已经包含子事件码,而 Bluedroid 适配器会在前面补上它,因此 ``host/common/iso.c`` 中的解码器无论在哪种主机上都看到统一的布局。
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -330,10 +330,10 @@ ISO 子系统分布在三处:引擎(``host/iso/iso.c``)、元事件与数
|
||||
T->>CORE: 在 common/iso.c 中处理,然后引擎处理函数
|
||||
CORE->>APP: 通道回调(在 ISO 锁下)
|
||||
|
||||
连接 ISO(CIS)
|
||||
连接 ISO (CIS)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
连接等时流(CIS)是点对点的,并依托一条 ACL 连接。两种角色通过不同的入口点驱动引擎:
|
||||
连接等时流 (CIS) 是点对点的,并依托一条 ACL 连接。两种角色通过不同的入口点驱动引擎:
|
||||
|
||||
.. list-table:: CIS 角色
|
||||
:header-rows: 1
|
||||
@@ -349,10 +349,10 @@ ISO 子系统分布在三处:引擎(``host/iso/iso.c``)、元事件与数
|
||||
- 注册一个服务端,由它决定是否接受入站的流;随后每个对端请求被接受或拒绝,若接受则予以确认。
|
||||
- ``bt_iso_server_register`` /\ |br|\ ``hci_le_cis_req`` / ``hci_le_cis_established``
|
||||
|
||||
广播 ISO(BIG)
|
||||
广播 ISO (BIG)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
广播等时组(BIG)是无连接的,并依托一条周期性广播序列,而非 ACL 连接:
|
||||
广播等时组 (BIG) 是无连接的,并依托一条周期性广播序列,而非 ACL 连接:
|
||||
|
||||
.. list-table:: BIG 角色
|
||||
:header-rows: 1
|
||||
@@ -416,14 +416,14 @@ GATT 横跨\ **客户端**\ 侧(本设备在对端进行发现、读、写和
|
||||
|
||||
客户端发现有两条不同的流程,运行在不同的任务上。这种拆分的存在是因为两种主机在是否维护属性缓存上有差异:Bluedroid 的 BTA GATTC 会发现对端的属性表并自动缓存,而 NimBLE 不会 —— 因此移植在 ``gatt.db.c`` 中补上了该缓存。
|
||||
|
||||
**遍历对端的属性表(构建缓存)。**\ 当上层调用 ``bt_gattc_disc_start`` 时,NimBLE 适配器(``bt_le_nimble_gattc_db_auto_disc``)用 NimBLE 的 ``ble_gattc_disc_*`` 流程对对端执行真正的 ATT 发现,把整张表完整遍历一次 —— 每个主服务、包含服务、特征和描述符,包括每个 CCCD。这些流程回调运行在 **NimBLE 主机任务**\ 上,并填充按连接缓存的数据库;只有在遍历完成后,上层才在 ISO 任务上被通知。在 Bluedroid 上,这一步是隐式的:``bt_le_bluedroid_gattc_disc_start`` 驱动 BTA GATTC,由它执行 ATT 流程并维护自己的缓存。
|
||||
**遍历对端的属性表(构建缓存)。**\ 当上层调用 ``bt_gattc_disc_start`` 时,NimBLE 适配器 (``bt_le_nimble_gattc_db_auto_disc``) 用 NimBLE 的 ``ble_gattc_disc_*`` 流程对对端执行真正的 ATT 发现,把整张表完整遍历一次 —— 每个主服务、包含服务、特征和描述符,包括每个 CCCD。这些流程回调运行在 **NimBLE 主机任务**\ 上,并填充按连接缓存的数据库;只有在遍历完成后,上层才在 ISO 任务上被通知。在 Bluedroid 上,这一步是隐式的:``bt_le_bluedroid_gattc_disc_start`` 驱动 BTA GATTC,由它执行 ATT 流程并维护自己的缓存。
|
||||
|
||||
**响应一项发现请求。**\ 当上层 —— 例如音频规范 —— 为特定属性调用 ``bt_gatt_discover`` 时,NimBLE 适配器把一个发现事件投递到 **ISO 任务**,在那里缓存的层次结构在本地回答该请求、无需进一步的 ATT 流量,并调用调用方的回调。在 Bluedroid 上,等价的结果作为 ISO 任务上的发现事件从 BTA 的缓存中呈现。
|
||||
|
||||
订阅生命周期
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
订阅以与主机无关的方式跟踪。``bt_gatt_subscribe`` 把每个 ``bt_gatt_subscribe_params`` 记录在一个按连接的列表(``gattc_sub``)上,并且,除非已存在等价的订阅,否则通过适配器写入 CCC。有两点行为值得注意:
|
||||
订阅以与主机无关的方式跟踪。``bt_gatt_subscribe`` 把每个 ``bt_gatt_subscribe_params`` 记录在一个按连接的列表 (``gattc_sub``) 上,并且,除非已存在等价的订阅,否则通过适配器写入 CCC。有两点行为值得注意:
|
||||
|
||||
- 订阅在 CCC 写完成之前就被追加到列表,因为有些对端在回复 CCC 写之前就发送了第一条通知。
|
||||
- ``subscribe`` 回调被\ **同步**\ 调用,在调用方的上下文中完成该流程,而不是在 CCC 写响应之后。在 NimBLE 上,这与缓存的数据库相配合:CCCD 句柄已经已知,因此无需发现往返,订阅路径也不会阻塞。
|
||||
@@ -448,7 +448,7 @@ GATT 横跨\ **客户端**\ 侧(本设备在对端进行发现、读、写和
|
||||
服务端
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``host/common/gatt.c`` 的服务端侧负责注册服务(``bt_gatt_service_register``),提供标准的属性读辅助函数(``bt_gatt_attr_read`` 以及服务、包含服务、特征和 CCC 的各变体)、CCC 写路径(``bt_gatt_attr_write_ccc``、``bt_gatts_sub_changed``),以及出站的通知与指示 API(``bt_gatt_notify_cb``、``bt_gatt_indicate``)。两种主机之间差异最大的行为是入站属性访问如何完成,这正是 :ref:`回调执行上下文 <arch-callback-context>` 中首次描述的那个例外:
|
||||
``host/common/gatt.c`` 的服务端侧负责注册服务 (``bt_gatt_service_register``),提供标准的属性读辅助函数(``bt_gatt_attr_read`` 以及服务、包含服务、特征和 CCC 的各变体)、CCC 写路径(``bt_gatt_attr_write_ccc``、``bt_gatts_sub_changed``),以及出站的通知与指示 API(``bt_gatt_notify_cb``、``bt_gatt_indicate``)。两种主机之间差异最大的行为是入站属性访问如何完成,这正是 :ref:`回调执行上下文 <arch-callback-context>` 中首次描述的那个例外:
|
||||
|
||||
- Bluedroid 把读或写投递到 ISO 任务;已注册的属性回调在那里运行,响应则通过 BTA 异步返回给对端,并由一个专用的服务端信号量协调。
|
||||
- NimBLE 在主机任务上原地运行属性回调,因为它的访问回调必须同步返回值。
|
||||
@@ -469,7 +469,7 @@ ATT MTU 交换让两个对端把 ATT MTU 从其 23 字节的默认值抬高,
|
||||
- 在 Bluedroid 上这是自动的:当一个 GATT 客户端连接打开时,GATTC 适配器发起该交换(``handle_gattc_open_event`` 调用 ``BTA_GATTC_ConfigureMTU``,在 ``BTA_GATTC_Enh_Open`` 路径内部)。实践中,这会为一个 **central**\ 触发;而对于一个 **peripheral**,GATT 客户端的打开发生在发现启动路径内部,而后者本身又被 MTU 更新事件所阻挡 —— 一个使其无法发起的循环依赖。
|
||||
- 在 NimBLE 上,组件不发起任何东西,因此由应用用 ``ble_gattc_exchange_mtu()`` 触发它 —— 通常在安全变更事件之后紧接着调用。在 Bluedroid 上,同一个调用对 MTU 而言是空操作,因为适配器已经交换过它了。
|
||||
|
||||
由于 GATT 服务端只会响应,一次交换 —— 由先充当客户端的那一侧发起 —— 就为整条连接确定了 MTU;同一条连接上同时也是客户端的对端会重用已协商的值,而不是再运行一次交换。设备所提供的首选值,以及某个规范为何会把它抬高到 ATT 默认值之上,由传输层之上的那一层设定:对于蓝牙 LE Audio,参见 :ref:`ATT MTU <arch-audio-mtu>`。
|
||||
由于 GATT 服务端只会响应,一次交换 —— 由先充当客户端的那一侧发起 —— 就为整条连接确定了 MTU;同一条连接上同时也是客户端的对端会重用已协商的值,而不是再运行一次交换。设备所提供的首选值,以及某个规范为何会把它抬高到 ATT 默认值之上,由传输层之上的那一层设定:对于蓝牙低功耗音频,参见 :ref:`ATT MTU <arch-audio-mtu>`。
|
||||
|
||||
.. _arch-l2cap:
|
||||
|
||||
@@ -478,9 +478,9 @@ L2CAP(草案)
|
||||
|
||||
.. warning::
|
||||
|
||||
L2CAP 面向连接的通道目前是\ **早期草案,尚未正式支持**。该实现尚不完整 —— 它只存在于 NimBLE 上(``host/adapter/nimble/l2cap.c``),且\ **没有 Bluedroid 支持** —— 其 API 和行为都是临时的,可能会改变。请勿在生产环境中依赖该层。
|
||||
L2CAP 面向连接的通道目前是\ **早期草案,尚未正式支持**。该实现尚不完整 —— 它只存在于 NimBLE 上 (``host/adapter/nimble/l2cap.c``),且\ **没有 Bluedroid 支持** —— 其 API 和行为都是临时的,可能会改变。请勿在生产环境中依赖该层。
|
||||
|
||||
``host/common/l2cap.c`` 提供基于信用(credit-based)的 L2CAP 面向连接的通道:一个服务端注册表(``bt_l2cap_server_register``)、出站通道操作(``bt_l2cap_chan_connect``、``bt_l2cap_chan_disconnect``、``bt_l2cap_chan_send``),以及主机在通道被接受、连接、断开或收到数据时调用的入站事件处理函数(``bt_le_l2cap_accept``、``bt_le_l2cap_connected``、``bt_le_l2cap_disconnected``、``bt_le_l2cap_received``)。协议栈中唯一的使用方是对象传输服务,它通过一条基于信用的通道搬运批量对象;不使用对象传输的规范从不打开通道。
|
||||
``host/common/l2cap.c`` 提供基于信用 (credit-based) 的 L2CAP 面向连接的通道:一个服务端注册表 (``bt_l2cap_server_register``)、出站通道操作(``bt_l2cap_chan_connect``、``bt_l2cap_chan_disconnect``、``bt_l2cap_chan_send``),以及主机在通道被接受、连接、断开或收到数据时调用的入站事件处理函数(``bt_le_l2cap_accept``、``bt_le_l2cap_connected``、``bt_le_l2cap_disconnected``、``bt_le_l2cap_received``)。协议栈中唯一的使用方是对象传输服务,它通过一条基于信用的通道搬运批量对象;不使用对象传输的规范从不打开通道。
|
||||
|
||||
.. _arch-app-event:
|
||||
|
||||
@@ -514,7 +514,7 @@ GAP 和 GATT 事件不会从适配器直达应用。它们会经过 ``host/commo
|
||||
|
||||
- **无论哪种主机都是同一个事件模型。**\ 适配器把每个原生事件 —— Bluedroid 上的 BTA/BTM 回调、NimBLE 上的 ``ble_gap_event`` —— 在它到达应用之前归一化成同一个有类型的 ``bt_le_gap_app_event`` / ``bt_le_gatt_app_event``。因此上层 —— 示例和音频规范 —— 处理一组完全相同的事件,从不针对主机协议栈做分支。这是该接口最重要的特性:在两种主机之间迁移一个应用,无需改动其事件处理。
|
||||
- **内部使用方也会收到该事件。**\ 有些事件不仅供应用使用:``host/iso/iso.c`` 中的 ISO 引擎和预构建的音频库也会消费它们 —— 一次周期性广播同步及其 BIGInfo 会驱动一次 BIG 同步,而连接、断开和安全变更会驱动各规范。因此接口保证一份副本到达 ISO 任务,内部工作在那里于 ISO 锁下运行。在 Bluedroid 上,BTU 任务的回调直接投递它;在 NimBLE 上,应用用 ``esp_ble_iso_gap_app_post_event`` 把它收到的事件转发进 ISO 任务(参见 :ref:`各主机集成差异 <arch-iso-host-diff>`)。
|
||||
- **与普通 BLE 应用共存。**\ 向 ISO 任务投递一份副本并不会消耗掉该事件。在 Bluedroid 上,同一个回调仍会把原生事件转发给 Bluedroid 的应用回调层(BTC),因此一个同时通过 ``esp_ble_gap_register_callback`` 注册的应用,会继续收到它用于自己的、非音频的 BLE 工作;在 NimBLE 上,应用已经在它的 ``ble_gap_event`` 回调内部,可以继续在那里处理它需要的其他任何事情。ESP-IDF 蓝牙 LE Audio 应用和一个传统 BLE 应用可以在一个设备上并行运行。
|
||||
- **与普通低功耗蓝牙应用共存。**\ 向 ISO 任务投递一份副本并不会消耗掉该事件。在 Bluedroid 上,同一个回调仍会把原生事件转发给 Bluedroid 的应用回调层 (BTC),因此一个同时通过 ``esp_ble_gap_register_callback`` 注册的应用,会继续收到它用于自己的、非音频的低功耗蓝牙工作;在 NimBLE 上,应用已经在它的 ``ble_gap_event`` 回调内部,可以继续在那里处理它需要的其他任何事情。ESP-IDF 蓝牙低功耗音频应用和一个传统低功耗蓝牙应用可以在一个设备上并行运行。
|
||||
|
||||
.. important::
|
||||
|
||||
@@ -525,7 +525,7 @@ GAP 和 GATT 事件不会从适配器直达应用。它们会经过 ``host/commo
|
||||
公共 API
|
||||
------------------------
|
||||
|
||||
到目前为止描述的一切都是内部实现。应用只看到一个公共头文件 ``api/include/esp_ble_iso_common_api.h``,它把传输层暴露为一个小巧的 ``esp_ble_iso_*`` API,用于纯 ISO 用例 —— 不带蓝牙 LE Audio 规范的 CIS 或 BIS。
|
||||
到目前为止描述的一切都是内部实现。应用只看到一个公共头文件 ``api/include/esp_ble_iso_common_api.h``,它把传输层暴露为一个小巧的 ``esp_ble_iso_*`` API,用于纯 ISO 用例 —— 不带蓝牙低功耗音频规范的 CIS 或 BIS。
|
||||
|
||||
形态与约定
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -570,7 +570,7 @@ GAP 和 GATT 事件不会从适配器直达应用。它们会经过 ``host/commo
|
||||
- 查询通道与发送定时信息。
|
||||
* - 辅助
|
||||
- ``esp_ble_iso_data_parse``
|
||||
- 解析长度-类型-值(LTV)编码的数据。
|
||||
- 解析长度-类型-值 (LTV) 编码的数据。
|
||||
|
||||
这些与 :ref:`ISO 子系统 <arch-iso>` 中的引擎操作一一对应;公共层只增加了锁、错误转换和不透明 typedef。
|
||||
|
||||
|
||||
@@ -11,15 +11,15 @@ ESP-BLE-AUDIO
|
||||
|
||||
.. contents:: 目录
|
||||
|
||||
ESP-BLE-AUDIO 直接位于 ESP-BLE-ISO 之上,实现蓝牙 LE Audio 的各项规范和服务。它是 ESP-IDF 蓝牙 LE Audio 应用实际编程所面向的那一层,通过 ``esp_ble_audio_*`` API 访问。
|
||||
ESP-BLE-AUDIO 直接位于 ESP-BLE-ISO 之上,实现蓝牙低功耗音频的各项规范和服务。它是 ESP-IDF 蓝牙低功耗音频应用实际编程所面向的那一层,通过 ``esp_ble_audio_*`` API 访问。
|
||||
|
||||
组件布局
|
||||
------------------------
|
||||
|
||||
该组件有两类截然不同的代码,而这一区分对本文档很重要:
|
||||
|
||||
- **开源、本文涵盖**。公共 API 头文件(``api/include/esp_ble_audio_*_api.h``)、``host/adapter/bluedroid/profiles`` 和 ``host/adapter/nimble/profiles`` 下的 GATT 服务适配器、``host/services/ots`` 下的对象传输服务,以及 ``host/common/init.c`` 中的初始化编排。
|
||||
- **预构建、不在范围内**。ESP-IDF 蓝牙 LE Audio 的规范与控制器逻辑 —— 单播与广播客户端,音量、麦克风、媒体和通话控制,集合协调,以及顶层规范 —— 以预构建的、按目标芯片的库形式提供(``lib/lib/<target>/libble_audio.a``,用 ``add_prebuilt_library`` 链接)。本文档不描述其内部实现;它描述围绕它的公共契约,以及在重要之处,一个已注册回调运行在哪个任务上。
|
||||
- **开源、本文涵盖**。公共 API 头文件 (``api/include/esp_ble_audio_*_api.h``)、``host/adapter/bluedroid/profiles`` 和 ``host/adapter/nimble/profiles`` 下的 GATT 服务适配器、``host/services/ots`` 下的对象传输服务,以及 ``host/common/init.c`` 中的初始化编排。
|
||||
- **预构建、不在范围内**。ESP-IDF 蓝牙低功耗音频的规范与控制器逻辑 —— 单播与广播客户端,音量、麦克风、媒体和通话控制,集合协调,以及顶层规范 —— 以预构建的、按目标芯片的库形式提供(``lib/lib/<target>/libble_audio.a``,用 ``add_prebuilt_library`` 链接)。本文档不描述其内部实现;它描述围绕它的公共契约,以及在重要之处,一个已注册回调运行在哪个任务上。
|
||||
|
||||
分层
|
||||
------------------------
|
||||
@@ -46,9 +46,9 @@ ESP-BLE-AUDIO 直接位于 ESP-BLE-ISO 之上,实现蓝牙 LE Audio 的各项
|
||||
服务与控制器
|
||||
------------------------
|
||||
|
||||
蓝牙 LE Audio 的功能分为两类构建块,组件也反映了这一划分:
|
||||
蓝牙低功耗音频的功能分为两类构建块,组件也反映了这一划分:
|
||||
|
||||
- **GATT 服务**\ 是对端进行读、写和订阅的属性表。它们在开源的各主机适配器(``host/adapter/*/profiles``)中实现,每个服务一个源文件,构建在 ESP-BLE-ISO 的 GATT 服务端层之上。按其所属规范分组(如蓝牙 LE Audio 规范中那样),这组服务是 PACS、ASCS 和 BASS(BAP),MCS(MCP),TBS(CCP),CSIS(CSIP),MICS(MICP),VCS(VCP),CAS(CAP),TMAS(TMAP)和 HAS(HAP)。
|
||||
- **GATT 服务**\ 是对端进行读、写和订阅的属性表。它们在开源的各主机适配器 (``host/adapter/*/profiles``) 中实现,每个服务一个源文件,构建在 ESP-BLE-ISO 的 GATT 服务端层之上。按其所属规范分组(如蓝牙低功耗音频规范中那样),这组服务是 PACS、ASCS 和 BASS (BAP),MCS (MCP),TBS (CCP),CSIS (CSIP),MICS (MICP),VCS (VCP),CAS (CAP),TMAS (TMAP) 和 HAS (HAP)。
|
||||
- **规范客户端与控制器**\ 是驱动这些服务并编排各条流的状态机:基本音频规范和通用音频规范,音量、麦克风、媒体和通话控制,协调集识别,以及顶层的电话与媒体、游戏、公共广播规范。这部分逻辑位于预构建库中;应用通过对应的 ``esp_ble_audio_*_api.h`` 头文件访问它。
|
||||
|
||||
GATT 服务在 :ref:`GATT 服务 <arch-audio-services>` 中详述,客户端与控制器在 :ref:`客户端与控制器 <arch-audio-profiles>` 中详述。
|
||||
@@ -56,7 +56,7 @@ GATT 服务在 :ref:`GATT 服务 <arch-audio-services>` 中详述,客户端与
|
||||
规范回调运行在何处
|
||||
------------------------
|
||||
|
||||
一个已注册的 ESP-IDF 蓝牙 LE Audio 回调运行在递交底层传输事件的那个任务上,因此 :ref:`回调执行上下文 <arch-callback-context>` 中的规则直接适用:
|
||||
一个已注册的 ESP-IDF 蓝牙低功耗音频回调运行在递交底层传输事件的那个任务上,因此 :ref:`回调执行上下文 <arch-callback-context>` 中的规则直接适用:
|
||||
|
||||
- 由\ **通知**\ 驱动的回调 —— 例如作为 GATT 通知到达的 ASCS 或音量状态变更 —— 在两种主机上都运行于 ISO 任务。
|
||||
- 由\ **GATT 客户端读或写完成**\ 驱动的回调 —— 例如读取对端的 PAC 记录 —— 在 Bluedroid 上运行于 ISO 任务,但在 NimBLE 上运行于\ **NimBLE 主机任务**。
|
||||
@@ -69,7 +69,7 @@ GATT 服务在 :ref:`GATT 服务 <arch-audio-services>` 中详述,客户端与
|
||||
GATT 服务
|
||||
------------------------
|
||||
|
||||
蓝牙 LE Audio 通过一组固定的 GATT 服务暴露其能力和状态。这些是各规范的服务端侧 —— 对端进行读、写和订阅的属性表 —— 并且,如 :ref:`服务与控制器 <arch-audio-svc-ctrl>` 中所确立的,它们是 ESP-BLE-AUDIO 的开源部分:``host/adapter/bluedroid/profiles`` 和 ``host/adapter/nimble/profiles`` 下每个服务一个源文件。每个服务背后的状态,以及其控制点的命令处理,位于预构建库中;本节涵盖这些服务及其适配器,而非那部分逻辑。
|
||||
蓝牙低功耗音频通过一组固定的 GATT 服务暴露其能力和状态。这些是各规范的服务端侧 —— 对端进行读、写和订阅的属性表 —— 并且,如 :ref:`服务与控制器 <arch-audio-svc-ctrl>` 中所确立的,它们是 ESP-BLE-AUDIO 的开源部分:``host/adapter/bluedroid/profiles`` 和 ``host/adapter/nimble/profiles`` 下每个服务一个源文件。每个服务背后的状态,以及其控制点的命令处理,位于预构建库中;本节涵盖这些服务及其适配器,而非那部分逻辑。
|
||||
|
||||
.. _arch-audio-adapter:
|
||||
|
||||
@@ -89,14 +89,14 @@ GATT 服务
|
||||
|
||||
**机制**:并非所有服务都在 ``esp_ble_audio_common_init`` 期间被添加到 GATT 表。构建默认定义了 ``BLE_AUDIO_SVC_DEFERRED_ADD``,它会把一个服务保留到应用通过其 ``esp_ble_audio_<profile>_register`` 调用注册对应角色为止 —— 预构建库把该调用转化为该服务的 ``bt_le_<service>_init`` 注册 —— 而不是在 init 期间添加它。
|
||||
|
||||
**原因**:一个固件镜像通常编译进了比任何单个应用所用更多的蓝牙 LE Audio 能力:启用一个服务的 Kconfig 角色选项会把它的代码编译进来,但应用可能永远不会担任那个角色。如果每个编译进来的服务都在 init 时被添加,一个连接上来的对端就会发现、并可能访问一个其背后尚无支撑状态的服务的属性 —— 应用还没注册它,因此预构建库无法对它做出有意义的应答。
|
||||
**原因**:一个固件镜像通常编译进了比任何单个应用所用更多的蓝牙低功耗音频能力:启用一个服务的 Kconfig 角色选项会把它的代码编译进来,但应用可能永远不会担任那个角色。如果每个编译进来的服务都在 init 时被添加,一个连接上来的对端就会发现、并可能访问一个其背后尚无支撑状态的服务的属性 —— 应用还没注册它,因此预构建库无法对它做出有意义的应答。
|
||||
|
||||
**对应用的影响**:延迟添加把一个未使用但已编译进来的能力挡在 GATT 表之外,直到应用主动选用它,因此对端永远只会发现那些被完整支撑的服务。
|
||||
|
||||
服务参考
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. list-table:: 蓝牙 LE Audio GATT 服务
|
||||
.. list-table:: 蓝牙低功耗音频 GATT 服务
|
||||
:header-rows: 1
|
||||
:widths: 10 24 38 11 17
|
||||
|
||||
@@ -106,57 +106,57 @@ GATT 服务
|
||||
- 适配器
|
||||
- 规范
|
||||
* - PACS
|
||||
- 已发布音频能力服务(Published Audio Capabilities Service)
|
||||
- 已发布音频能力服务 (Published Audio Capabilities Service)
|
||||
- Sink 和 Source PAC 记录、音频位置、可用与支持的音频上下文。
|
||||
- ``pacs.c``
|
||||
- BAP
|
||||
* - ASCS
|
||||
- 音频流控制服务(Audio Stream Control Service)
|
||||
- Sink 和 Source 音频流端点(ASE)以及 ASE 控制点。
|
||||
- 音频流控制服务 (Audio Stream Control Service)
|
||||
- Sink 和 Source 音频流端点 (ASE) 以及 ASE 控制点。
|
||||
- ``ascs.c``
|
||||
- BAP
|
||||
* - BASS
|
||||
- 广播音频扫描服务(Broadcast Audio Scan Service)
|
||||
- 广播音频扫描服务 (Broadcast Audio Scan Service)
|
||||
- 广播接收状态以及广播音频扫描控制点。
|
||||
- ``bass.c``
|
||||
- BAP
|
||||
* - MCS
|
||||
- 媒体控制服务(Media Control Service)
|
||||
- 媒体控制服务 (Media Control Service)
|
||||
- 媒体播放器名称与曲目信息、媒体控制点及相关状态。
|
||||
- ``mcs.c``
|
||||
- MCP
|
||||
* - TBS
|
||||
- 电话承载服务(Telephone Bearer Service)
|
||||
- 电话承载服务 (Telephone Bearer Service)
|
||||
- 承载信息、通话状态以及通话控制点。
|
||||
- ``tbs.c``
|
||||
- CCP
|
||||
* - CSIS
|
||||
- 协调集识别服务(Coordinated Set Identification Service)
|
||||
- 集合身份解析密钥(SIRK)、集合大小、集合成员锁和排名。
|
||||
- 协调集识别服务 (Coordinated Set Identification Service)
|
||||
- 集合身份解析密钥 (SIRK)、集合大小、集合成员锁和排名。
|
||||
- ``csis.c``
|
||||
- CSIP
|
||||
* - MICS
|
||||
- 麦克风控制服务(Microphone Control Service)
|
||||
- 麦克风控制服务 (Microphone Control Service)
|
||||
- 麦克风静音;包含 AICS。
|
||||
- ``mics.c``
|
||||
- MICP
|
||||
* - VCS
|
||||
- 音量控制服务(Volume Control Service)
|
||||
- 音量控制服务 (Volume Control Service)
|
||||
- 音量状态、音量控制点和音量标志;包含 VOCS 和 AICS。
|
||||
- ``vcs.c``
|
||||
- VCP
|
||||
* - CAS
|
||||
- 通用音频服务(Common Audio Service)
|
||||
- 通用音频服务 (Common Audio Service)
|
||||
- 标识一个通用音频设备;可包含 CSIS。
|
||||
- ``cas.c``
|
||||
- CAP
|
||||
* - TMAS
|
||||
- 电话与媒体音频服务(Telephony and Media Audio Service)
|
||||
- 电话与媒体音频服务 (Telephony and Media Audio Service)
|
||||
- 设备的 TMAP 角色。
|
||||
- ``tmas.c``
|
||||
- TMAP
|
||||
* - HAS
|
||||
- 助听器访问服务(Hearing Access Service)
|
||||
- 助听器访问服务 (Hearing Access Service)
|
||||
- 助听器特性、预设控制点和当前预设索引。
|
||||
- ``has.c``
|
||||
- HAP
|
||||
@@ -188,7 +188,7 @@ GATT 服务
|
||||
规范之间的关系
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
蓝牙 LE Audio 各规范彼此构建于其上。\ **基本音频规范(BAP)**\ 是基础:它建立并承载音频流,既包括单播(通过连接等时流)也包括广播(通过广播等时流)。\ **控制规范** —— 音量、麦克风、协调集、媒体和通话控制 —— 管理各项功能,每个都由一个 GATT 服务支撑。\ **通用音频规范(CAP)**\ 协调其他规范,使一个操作在一个集合的每个成员上一致地生效。\ **顶层规范** —— 电话与媒体音频(TMAP)、游戏音频(GMAP)、公共广播(PBP)和助听器访问(HAP)—— 是下层各层的既定组合。
|
||||
蓝牙低功耗音频各规范彼此构建于其上。\ **基本音频规范 (BAP)**\ 是基础:它建立并承载音频流,既包括单播(通过连接等时流)也包括广播(通过广播等时流)。\ **控制规范** —— 音量、麦克风、协调集、媒体和通话控制 —— 管理各项功能,每个都由一个 GATT 服务支撑。\ **通用音频规范 (CAP)**\ 协调其他规范,使一个操作在一个集合的每个成员上一致地生效。\ **顶层规范** —— 电话与媒体音频 (TMAP)、游戏音频 (GMAP)、公共广播 (PBP) 和助听器访问 (HAP)—— 是下层各层的既定组合。
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -197,7 +197,7 @@ GATT 服务
|
||||
CAP["CAP — 跨协调集的协同控制"]
|
||||
CTRL["控制规范 — VCP、MICP、CSIP、MCP、CCP"]
|
||||
BAP["BAP — 单播 (CIS) 与广播 (BIS) 流"]
|
||||
SVC["蓝牙 LE Audio GATT 服务"]
|
||||
SVC["蓝牙低功耗音频 GATT 服务"]
|
||||
ISO["ESP-BLE-ISO 传输层"]
|
||||
TOP --> CAP
|
||||
CAP --> BAP
|
||||
@@ -209,7 +209,7 @@ GATT 服务
|
||||
规范参考
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. list-table:: 蓝牙 LE Audio 规范
|
||||
.. list-table:: 蓝牙低功耗音频规范
|
||||
:header-rows: 1
|
||||
:widths: 10 27 45 18
|
||||
|
||||
@@ -218,43 +218,43 @@ GATT 服务
|
||||
- 角色
|
||||
- API 头文件
|
||||
* - BAP
|
||||
- 基本音频规范(Basic Audio Profile)
|
||||
- 基本音频规范 (Basic Audio Profile)
|
||||
- 单播客户端与服务端、广播源与广播接收端、广播助手、扫描委托设备。
|
||||
- ``bap_api.h``
|
||||
* - CAP
|
||||
- 通用音频规范(Common Audio Profile)
|
||||
- 通用音频规范 (Common Audio Profile)
|
||||
- 在一个协调集上的发起者、指挥者与切换。
|
||||
- ``cap_api.h``
|
||||
* - VCP
|
||||
- 音量控制规范(Volume Control Profile)
|
||||
- 音量控制规范 (Volume Control Profile)
|
||||
- 音量控制器(客户端)和音量渲染器(服务端)。
|
||||
- ``vcp_api.h``
|
||||
* - MICP
|
||||
- 麦克风控制规范(Microphone Control Profile)
|
||||
- 麦克风控制规范 (Microphone Control Profile)
|
||||
- 麦克风控制器(客户端)和麦克风设备(服务端)。
|
||||
- ``micp_api.h``
|
||||
* - CSIP
|
||||
- 协调集识别规范(Coordinated Set Identification Profile)
|
||||
- 协调集识别规范 (Coordinated Set Identification Profile)
|
||||
- 集合协调者(客户端)和集合成员(服务端)。
|
||||
- ``csip_api.h``
|
||||
* - MCP
|
||||
- 媒体控制规范(Media Control Profile)
|
||||
- 媒体控制规范 (Media Control Profile)
|
||||
- 媒体控制客户端(客户端)和媒体代理(服务端)。
|
||||
- ``mcc_api.h``、``media_proxy_api.h``
|
||||
* - CCP
|
||||
- 通话控制规范(Call Control Profile)
|
||||
- 通话控制规范 (Call Control Profile)
|
||||
- 通话控制客户端(服务端侧即电话承载服务)。
|
||||
- ``ccp_api.h``
|
||||
* - TMAP
|
||||
- 电话与媒体音频规范(Telephony and Media Audio Profile)
|
||||
- 电话与媒体音频规范 (Telephony and Media Audio Profile)
|
||||
- 组合 CAP、BAP 和各控制规范的角色配置。
|
||||
- ``tmap_api.h``
|
||||
* - GMAP
|
||||
- 游戏音频规范(Gaming Audio Profile)
|
||||
- 游戏音频规范 (Gaming Audio Profile)
|
||||
- 面向低延迟游戏音频的角色配置。
|
||||
- ``gmap_api.h``
|
||||
* - PBP
|
||||
- 公共广播规范(Public Broadcast Profile)
|
||||
- 公共广播规范 (Public Broadcast Profile)
|
||||
- 在 BAP 广播之上的公共广播通告辅助。
|
||||
- ``pbp_api.h``
|
||||
|
||||
@@ -270,26 +270,26 @@ API 形态与角色
|
||||
|
||||
.. warning::
|
||||
|
||||
对象传输目前是\ **早期草案,尚未正式支持**。它构建在草案 L2CAP 通道(:ref:`L2CAP <arch-l2cap>`)之上,因此只运行在 NimBLE 上,**不支持 Bluedroid**,其 API 和行为都是临时的,可能会改变。请勿在生产环境中依赖它。
|
||||
对象传输目前是\ **早期草案,尚未正式支持**。它构建在草案 L2CAP 通道 (:ref:`L2CAP <arch-l2cap>`) 之上,因此只运行在 NimBLE 上,**不支持 Bluedroid**,其 API 和行为都是临时的,可能会改变。请勿在生产环境中依赖它。
|
||||
|
||||
对象传输服务(OTS)通过 :ref:`L2CAP <arch-l2cap>` 中那条基于信用的 L2CAP 通道搬运批量对象 —— 比一次普通 GATT 读所能承载的更大。在蓝牙 LE Audio 中它被媒体控制使用:一个媒体播放器暴露诸如当前曲目分段和分组结构之类的对象,客户端用 OTS 传输它们,经由媒体 API(``esp_ble_audio_mcs_get_ots`` 和媒体控制客户端)访问。
|
||||
对象传输服务 (OTS) 通过 :ref:`L2CAP <arch-l2cap>` 中那条基于信用的 L2CAP 通道搬运批量对象 —— 比一次普通 GATT 读所能承载的更大。在蓝牙低功耗音频中它被媒体控制使用:一个媒体播放器暴露诸如当前曲目分段和分组结构之类的对象,客户端用 OTS 传输它们,经由媒体 API(``esp_ble_audio_mcs_get_ots`` 和媒体控制客户端)访问。
|
||||
|
||||
与各规范不同,OTS 是开源的,位于 ``host/services/ots`` 下。它的各个部分是:
|
||||
|
||||
- 一个\ **服务端**\ (``ots.c``)和一个\ **客户端**\ (``ots_client.c``);
|
||||
- **对象动作控制点**\ (``ots_oacp.c``),它承载读、写、创建等对象操作;
|
||||
- **对象列表控制点**\ (``ots_olcp.c``),它在对象列表中导航;
|
||||
- 一个\ **对象管理器**\ (``ots_obj_manager.c``)和一个\ **目录列表**\ 对象(``ots_dir_list.c``);
|
||||
- **L2CAP 传输**\ (``ots_l2cap.c``),它通过基于信用的通道承载对象数据。
|
||||
- 一个\ **服务端**\ (``ots.c``) 和一个\ **客户端**\ (``ots_client.c``);
|
||||
- **对象动作控制点**\ (``ots_oacp.c``),它承载读、写、创建等对象操作;
|
||||
- **对象列表控制点**\ (``ots_olcp.c``),它在对象列表中导航;
|
||||
- 一个\ **对象管理器**\ (``ots_obj_manager.c``) 和一个\ **目录列表**\ 对象 (``ots_dir_list.c``);
|
||||
- **L2CAP 传输**\ (``ots_l2cap.c``),它通过基于信用的通道承载对象数据。
|
||||
|
||||
.. _arch-init-flow:
|
||||
|
||||
初始化流程
|
||||
------------------------
|
||||
|
||||
一个 ESP-IDF 蓝牙 LE Audio 应用用两次调用启动协议栈,与传输层对应:先 ``esp_ble_audio_common_init``,后 ``esp_ble_audio_common_start``。
|
||||
一个 ESP-IDF 蓝牙低功耗音频应用用两次调用启动协议栈,与传输层对应:先 ``esp_ble_audio_common_init``,后 ``esp_ble_audio_common_start``。
|
||||
|
||||
``esp_ble_audio_common_init`` 运行 ``init.c`` 中的 ``bt_le_audio_init``,它首先与预构建库建立边界 —— 检查共享结构 ABI 是否匹配,并把当前激活的 Kconfig 值推送进库 —— 然后调用主机相关的 ``bt_le_{host}_audio_init``。该主机初始化函数启动标准的 GAP 和 GATT 服务,然后按固定顺序通过各自的适配器注册每个已启用的蓝牙 LE Audio 服务:PACS、ASCS、BASS、TMAS、GTBS、HAS、CSIS 和 CAS,然后是媒体、音量和麦克风服务。每个服务仅在其 Kconfig 角色选项被设置时才编译进来,因此一个构建恰好包含其角色所需的服务。那个固定顺序是这些服务注册的顺序;它们中大多数实际何时进入 GATT 表是另一个问题 —— 默认情况下,添加被延迟到应用按角色的 ``esp_ble_audio_<profile>_register`` 调用,而不是在 init 这里发生(参见 :ref:`延迟注册 <arch-audio-deferred-add>`)。
|
||||
``esp_ble_audio_common_init`` 运行 ``init.c`` 中的 ``bt_le_audio_init``,它首先与预构建库建立边界 —— 检查共享结构 ABI 是否匹配,并把当前激活的 Kconfig 值推送进库 —— 然后调用主机相关的 ``bt_le_{host}_audio_init``。该主机初始化函数启动标准的 GAP 和 GATT 服务,然后按固定顺序通过各自的适配器注册每个已启用的蓝牙低功耗音频服务:PACS、ASCS、BASS、TMAS、GTBS、HAS、CSIS 和 CAS,然后是媒体、音量和麦克风服务。每个服务仅在其 Kconfig 角色选项被设置时才编译进来,因此一个构建恰好包含其角色所需的服务。那个固定顺序是这些服务注册的顺序;它们中大多数实际何时进入 GATT 表是另一个问题 —— 默认情况下,添加被延迟到应用按角色的 ``esp_ble_audio_<profile>_register`` 调用,而不是在 init 这里发生(参见 :ref:`延迟注册 <arch-audio-deferred-add>`)。
|
||||
|
||||
``esp_ble_audio_common_start`` 运行 ``bt_le_audio_start`` 并分发到主机相关的 start,它首先从 ``start_info`` 注册协调集服务(CSIS 和 CAS),然后提交 GATT 服务端。在 Bluedroid 上,提交是第二个阶段,它真正启动 init 期间注册的 BTA 服务 —— 即 :ref:`服务适配器模式 <arch-audio-adapter>` 中的 ``*_init`` 与 ``*_start`` 配对;在 NimBLE 上,它调用 ``ble_gatts_start``,然后把分配的属性句柄回填到库中。
|
||||
|
||||
@@ -314,15 +314,15 @@ API 形态与角色
|
||||
ATT MTU
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
蓝牙 LE Audio 依赖一个足够大的 ATT MTU 来承载其控制 PDU。
|
||||
蓝牙低功耗音频依赖一个足够大的 ATT MTU 来承载其控制 PDU。
|
||||
|
||||
**规范下限**:基本音频规范(BAP)要求的最低 ATT MTU 仅为 64 字节(公共的 ``ESP_BLE_AUDIO_ATT_MTU_MIN``)。
|
||||
**规范下限**:基本音频规范 (BAP) 要求的最低 ATT MTU 仅为 64 字节(公共的 ``ESP_BLE_AUDIO_ATT_MTU_MIN``)。
|
||||
|
||||
**为何选 128**:64 字节不足以同时操作四个 ASE,因此 ESP-IDF 把默认值提高到 128 字节(``BLE_AUDIO_ATT_MTU_MIN``),为蓝牙 LE Audio 所依赖的 ASCS 和 PACS 控制 PDU 留出余量。两种主机都在初始化期间(``bt_le_{host}_audio_init``)把设备的首选 ATT MTU 设为该值,Bluedroid 通过 ``BTA_GATT_SetLocalMTU``、NimBLE 通过 ``ble_att_set_preferred_mtu``。
|
||||
**为何选 128**:64 字节不足以同时操作四个 ASE,因此 ESP-IDF 把默认值提高到 128 字节 (``BLE_AUDIO_ATT_MTU_MIN``),为蓝牙低功耗音频所依赖的 ASCS 和 PACS 控制 PDU 留出余量。两种主机都在初始化期间 (``bt_le_{host}_audio_init``) 把设备的首选 ATT MTU 设为该值,Bluedroid 通过 ``BTA_GATT_SetLocalMTU``、NimBLE 通过 ``ble_att_set_preferred_mtu``。
|
||||
|
||||
**协商规则**:该值是设备作为客户端时提供、作为服务端时接受的值,因此最终生效的 MTU 是两个对端首选值中较小的那个。
|
||||
|
||||
交换本身就是 :ref:`MTU 交换 <arch-iso-mtu>` 中描述的那个 GATT 流程:客户端发送请求,服务端响应,一次协商管辖整条连接。在通常的蓝牙 LE Audio 拓扑中 —— 手机作为 central、ESP 设备作为 peripheral —— 每个设备都\ **同时**\ 运行一个 GATT 客户端和一个 GATT 服务端,因为 GATT 角色独立于 GAP 角色。然而单次 MTU 交换覆盖整条连接:手机的客户端发起它,ESP 的服务端响应,随后那一个协商出的值便管辖它们之间所有的 ATT 流量 —— 无论某一时刻哪一侧充当客户端或服务端:
|
||||
交换本身就是 :ref:`MTU 交换 <arch-iso-mtu>` 中描述的那个 GATT 流程:客户端发送请求,服务端响应,一次协商管辖整条连接。在通常的蓝牙低功耗音频拓扑中 —— 手机作为 central、ESP 设备作为 peripheral —— 每个设备都\ **同时**\ 运行一个 GATT 客户端和一个 GATT 服务端,因为 GATT 角色独立于 GAP 角色。然而单次 MTU 交换覆盖整条连接:手机的客户端发起它,ESP 的服务端响应,随后那一个协商出的值便管辖它们之间所有的 ATT 流量 —— 无论某一时刻哪一侧充当客户端或服务端:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -350,10 +350,10 @@ ATT MTU
|
||||
|
||||
下面的四条流程把各层串联起来,对应两个单播角色和两个广播角色。它们刻意保持高层次 —— 每个箭头可能代表多次交换 —— 并展示每一步由哪个组件负责。
|
||||
|
||||
单播发起端(Unicast Initiator)
|
||||
单播发起端 (Unicast Initiator)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
单播发起端(Initiator)连接到一个接受端(Acceptor),配置其音频流端点,建立一条连接等时流,并开始发送音频:
|
||||
单播发起端 (Initiator) 连接到一个接受端 (Acceptor),配置其音频流端点,建立一条连接等时流,并开始发送音频:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -376,10 +376,10 @@ ATT MTU
|
||||
|
||||
流的建立 —— 发现 PACS 和 ASCS、配置各 ASE、创建 CIG、连接 CIS 和建立数据通路 —— 是由 ESP-BLE-AUDIO 规范库在 ESP-BLE-ISO 的 GATT 和 ISO 层之上驱动的,而非由应用直接驱动。应用只通过 ``esp_ble_audio_*`` API 驱动高层流程 —— 连接、启动发现、启动流和发送音频 —— 而 ESP-BLE-AUDIO 代为执行底层的 ESP-BLE-ISO 操作。
|
||||
|
||||
单播接受端(Unicast Acceptor)
|
||||
单播接受端 (Unicast Acceptor)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
单播接受端(Acceptor)进行广播,接受来自发起端的连接,并在接收音频之前让发起端配置其音频流端点:
|
||||
单播接受端 (Acceptor) 进行广播,接受来自发起端的连接,并在接收音频之前让发起端配置其音频流端点:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -404,10 +404,10 @@ ATT MTU
|
||||
|
||||
与发起端不同,接受端是被动的。远端发起端通过写 ASE 控制点驱动 ASCS 状态机,接受端的 ESP-BLE-AUDIO ASCS 服务端把每一步 —— config、QoS、enable —— 作为回调呈现给应用。每个回调返回应用的响应 —— 接受或拒绝,外加编解码器配置时的 QoS 偏好 —— ASCS 服务端把它作为更新后的 ASE 状态和控制点结果通知回发起端。连接等时流由发起端建立(接受端是 peripheral);ESP-BLE-AUDIO 建立 ISO 数据通路,并通过 ISO 任务上的接收回调把收到的 SDU 递交给应用。与发起端一样,应用从不直接调用 ESP-BLE-ISO 的 ISO API。
|
||||
|
||||
广播源(Broadcast Source)
|
||||
广播源 (Broadcast Source)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
广播源(Broadcast Source)配置其音频,启动一条承载 BASE 的周期性广播序列,并在没有任何连接的情况下把音频发送进一个广播等时组:
|
||||
广播源 (Broadcast Source) 配置其音频,启动一条承载 BASE 的周期性广播序列,并在没有任何连接的情况下把音频发送进一个广播等时组:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -430,10 +430,10 @@ ATT MTU
|
||||
|
||||
应用通过 ``esp_ble_audio_*`` API 驱动高层流程 —— 创建广播源、启动广播、启动广播源和发送音频 —— 而 ESP-BLE-AUDIO 构建 BASE、在 ESP-BLE-ISO 的 ISO 子系统之上创建 BIG,并建立数据通路。与单播发起端一样,底层的 ESP-BLE-ISO 操作由 ESP-BLE-AUDIO 执行,而非应用。广播源没有连接也没有 GATT:它只进行广播和发送。
|
||||
|
||||
广播接收端(Broadcast Sink)
|
||||
广播接收端 (Broadcast Sink)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
广播接收端(Broadcast Sink)同步到广播端的周期性序列,加入其广播等时组并接收音频:
|
||||
广播接收端 (Broadcast Sink) 同步到广播端的周期性序列,加入其广播等时组并接收音频:
|
||||
|
||||
.. mermaid::
|
||||
|
||||
@@ -459,14 +459,14 @@ ATT MTU
|
||||
公共 API
|
||||
------------------------
|
||||
|
||||
应用通过 ``esp_ble_audio_*`` API 驱动 ESP-IDF 蓝牙 LE Audio 实现。它有两个接口面:一个公共头文件 ``api/include/esp_ble_audio_common_api.h``,用于启动和横切的入口点;以及每个规范和服务一个 ``<profile>_api.h`` 头文件,用于角色相关的操作 —— 即 API 的主体,已在 :ref:`客户端与控制器 <arch-audio-profiles>` 中编目。
|
||||
应用通过 ``esp_ble_audio_*`` API 驱动 ESP-IDF 蓝牙低功耗音频实现。它有两个接口面:一个公共头文件 ``api/include/esp_ble_audio_common_api.h``,用于启动和横切的入口点;以及每个规范和服务一个 ``<profile>_api.h`` 头文件,用于角色相关的操作 —— 即 API 的主体,已在 :ref:`客户端与控制器 <arch-audio-profiles>` 中编目。
|
||||
|
||||
形态与约定
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
公共 API 位于 ESP-BLE-ISO :ref:`传输层 <arch-iso-transport>` 和预构建规范库之上,并遵循与传输层公共 API 相同的约定:
|
||||
|
||||
- **两次调用启动**。``esp_ble_audio_common_init`` 接收一个 ``esp_ble_audio_init_info_t`` —— 一个 GAP 回调和一个 GATT 回调,即 :ref:`应用事件接口 <arch-app-event>` 中那唯一的应用汇聚点。``esp_ble_audio_common_start`` 接收一个 ``esp_ble_audio_start_info_t``,携带要启动的协调集(CSIS)服务实例。这两次调用内部做了什么,是 :ref:`初始化流程 <arch-init-flow>` 的主题:与预构建库的一次握手 —— 共享结构 ABI(Application Binary Interface,应用二进制接口)检查和 Kconfig 配置推送 —— 随后是逐个服务的注册。
|
||||
- **两次调用启动**。``esp_ble_audio_common_init`` 接收一个 ``esp_ble_audio_init_info_t`` —— 一个 GAP 回调和一个 GATT 回调,即 :ref:`应用事件接口 <arch-app-event>` 中那唯一的应用汇聚点。``esp_ble_audio_common_start`` 接收一个 ``esp_ble_audio_start_info_t``,携带要启动的协调集 (CSIS) 服务实例。这两次调用内部做了什么,是 :ref:`初始化流程 <arch-init-flow>` 的主题:与预构建库的一次握手 —— 共享结构 ABI(Application Binary Interface,应用二进制接口)检查和 Kconfig 配置推送 —— 随后是逐个服务的注册。
|
||||
- **不透明、与传输层别名的类型**。应用所处理的事件类型 —— ``esp_ble_audio_gap_app_event_t`` 和 ``esp_ble_audio_gatt_app_event_t`` —— 是传输层 ``bt_le_gap_app_event`` / ``bt_le_gatt_app_event`` 的 typedef,而 ``ESP_BLE_AUDIO_GAP_EVENT_*`` / ``ESP_BLE_AUDIO_GATT_EVENT_*`` 代码是传输层代码的别名,因此音频层和 ISO 层呈现同一个事件模型。
|
||||
- **错误码**。每个函数返回 ``esp_err_t``。
|
||||
- **按角色注册**。一个规范角色遵循 :ref:`客户端与控制器 <arch-audio-profiles>` 中那个统一的形态:启用该角色的 Kconfig 选项,通过该角色的 ``<profile>_api.h`` 注册其回调结构体,并通过该头文件的函数驱动它。注册一个角色也正是把它的 GATT 服务添加到表中的操作(参见 :ref:`延迟注册 <arch-audio-deferred-add>`)。
|
||||
@@ -495,7 +495,7 @@ ATT MTU
|
||||
- 把主机的 GAP 和 GATT 事件转发进引擎(仅 NimBLE —— 见下文)。
|
||||
* - LTV 辅助
|
||||
- ``esp_ble_audio_data_parse``,\ |br|\ ``esp_ble_audio_data_get_val``
|
||||
- 解析蓝牙 LE Audio 通篇使用的长度-类型-值元数据。
|
||||
- 解析蓝牙低功耗音频通篇使用的长度-类型-值元数据。
|
||||
* - 按规范的角色
|
||||
- 各 ``<profile>_api.h`` 的注册与操作函数
|
||||
- 担任并驱动一个规范角色 —— 即 API 的主体(参见 :ref:`客户端与控制器 <arch-audio-profiles>`)。
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
.. _ble-audio-architecture:
|
||||
|
||||
ESP-IDF 蓝牙 LE Audio 架构
|
||||
ESP-IDF 蓝牙低功耗音频架构
|
||||
==============================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本文档描述 ESP-IDF 蓝牙 LE Audio 协议栈,以及它所基于的通用 BLE 传输层的内部架构,涉及两个蓝牙组件:
|
||||
本文档描述 ESP-IDF 蓝牙低功耗音频协议栈,以及它所基于的通用低功耗蓝牙传输层的内部架构,涉及两个蓝牙组件:
|
||||
|
||||
- **ESP-BLE-ISO** —— 通用的 BLE 传输层。它提供 GATT、GAP、ISO、L2CAP 和 HCI 原语,以及用于串行化所有主机事件的专用处理任务和锁模型。它\ **并非蓝牙 LE Audio 专用** —— 它是一个自包含的传输层,任何上层规范都可以构建于其上,也可以\ **独立运行**:它拥有自己的公共 API(``esp_ble_iso_*``)和自己的初始化流程,因此应用程序可以直接使用它,而无需 ESP-BLE-AUDIO 或其上的任何规范层。
|
||||
- **ESP-BLE-AUDIO** —— 上层规范层。它实现蓝牙 LE Audio 的各项规范和服务(PACS、ASCS、BASS、BAP、CAP、VCP、MICP、CSIP、MCP、CCP、TMAP 等),并通过公共 ``esp_ble_audio_*`` API 对外暴露。
|
||||
- **ESP-BLE-ISO** —— 通用的低功耗蓝牙传输层。它提供 GATT、GAP、ISO、L2CAP 和 HCI 原语,以及用于串行化所有主机事件的专用处理任务和锁模型。它\ **并非蓝牙低功耗音频专用** —— 它是一个自包含的传输层,任何上层规范都可以构建于其上,也可以\ **独立运行**:它拥有自己的公共 API (``esp_ble_iso_*``) 和自己的初始化流程,因此应用程序可以直接使用它,而无需 ESP-BLE-AUDIO 或其上的任何规范层。
|
||||
- **ESP-BLE-AUDIO** —— 上层规范层。它实现蓝牙低功耗音频的各项规范和服务(PACS、ASCS、BASS、BAP、CAP、VCP、MICP、CSIP、MCP、CCP、TMAP 等),并通过公共 ``esp_ble_audio_*`` API 对外暴露。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -16,9 +16,9 @@ ESP-IDF 蓝牙 LE Audio 架构
|
||||
|
||||
ESP-BLE-ISO 是一个独立组件:它可以单独构建和初始化,并通过其公共 ``esp_ble_iso_*`` API 驱动,用于纯 ISO 场景(CIS 或 BIS,不带任何规范层)—— 参见 :ref:`ESP-BLE-ISO 公共 API <arch-iso-api>`。
|
||||
|
||||
该传输层也与规范无关:其 GATT、GAP、ISO、L2CAP 和 HCI 原语都是通用的 BLE 构建块,其他规范 —— 例如未来的 HID-over-ISO —— 预期也会构建在同一组件之上。本文档中凡描述 ESP-BLE-ISO 之处,其行为均适用于任何使用方,而不仅限于蓝牙 LE Audio。
|
||||
该传输层也与规范无关:其 GATT、GAP、ISO、L2CAP 和 HCI 原语都是通用的低功耗蓝牙构建块,其他规范 —— 例如未来的 HID-over-ISO —— 预期也会构建在同一组件之上。本文档中凡描述 ESP-BLE-ISO 之处,其行为均适用于任何使用方,而不仅限于蓝牙低功耗音频。
|
||||
|
||||
这两个组件都可运行在 **Bluedroid** 或 **NimBLE** 两种 BLE 主机协议栈之一之上,并隐藏在一个公共接口之后。明确揭示两种主机之间的行为差异是本文档的首要目标之一,因为它们决定了回调运行所处的任务上下文、连接建立期间的操作顺序,以及事件的分发方式。
|
||||
这两个组件都可运行在 **Bluedroid** 或 **NimBLE** 两种低功耗蓝牙主机协议栈之一之上,并隐藏在一个公共接口之后。明确揭示两种主机之间的行为差异是本文档的首要目标之一,因为它们决定了回调运行所处的任务上下文、连接建立期间的操作顺序,以及事件的分发方式。
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -38,16 +38,16 @@ ESP-IDF 蓝牙 LE Audio 架构
|
||||
分层结构
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
ESP-IDF 蓝牙 LE Audio 被组织为一组相互协作的分层。每一层只与其正下方的一层通信,所有与主机相关的知识都被限制在每个组件内部的适配器子层中。
|
||||
ESP-IDF 蓝牙低功耗音频被组织为一组相互协作的分层。每一层只与其正下方的一层通信,所有与主机相关的知识都被限制在每个组件内部的适配器子层中。
|
||||
|
||||
.. mermaid::
|
||||
|
||||
flowchart TB
|
||||
APP["应用 / 示例(app 任务)"]
|
||||
AUDIO["ESP-BLE-AUDIO —<br/>蓝牙 LE Audio 规范与服务<br/>(esp_ble_audio_* API)"]
|
||||
AUDIO["ESP-BLE-AUDIO —<br/>蓝牙低功耗音频规范与服务<br/>(esp_ble_audio_* API)"]
|
||||
ISO["ESP-BLE-ISO — 传输原语:<br/>GATT、GAP、ISO、L2CAP、HCI<br/>全部由全局 ISO 锁串行化 —<br/>多数事件运行在 ISO 任务事件循环上"]
|
||||
HOST["BLE 主机协议栈<br/>(Bluedroid 或 NimBLE)"]
|
||||
CTRL["BLE 控制器"]
|
||||
HOST["低功耗蓝牙主机协议栈<br/>(Bluedroid 或 NimBLE)"]
|
||||
CTRL["低功耗蓝牙控制器"]
|
||||
APP <--> AUDIO
|
||||
AUDIO <--> ISO
|
||||
ISO <--> HOST
|
||||
@@ -83,9 +83,9 @@ ESP-IDF 蓝牙 LE Audio 被组织为一组相互协作的分层。每一层只
|
||||
- ``host/adapter/nimble``
|
||||
- ``api/include``
|
||||
* - ESP-BLE-AUDIO
|
||||
- - 蓝牙 LE Audio GATT 服务
|
||||
- - 蓝牙低功耗音频 GATT 服务
|
||||
- 规范客户端与控制器
|
||||
- 对象传输服务(OTS)
|
||||
- 对象传输服务 (OTS)
|
||||
- ``esp_ble_audio_*`` API
|
||||
- - ``host/common``
|
||||
- ``host/adapter/bluedroid/profiles``
|
||||
@@ -117,7 +117,7 @@ ESP-IDF 蓝牙 LE Audio 被组织为一组相互协作的分层。每一层只
|
||||
- ``*_cb_safe`` 包装函数先获取 ISO 锁;随后大多数事件被投递到 ISO 任务队列。
|
||||
* - 同步例外
|
||||
- GATT 服务端的属性访问以异步方式完成:请求被投递到 ISO 任务,响应稍后发送。
|
||||
- GATT 服务端的属性访问在主机任务上原地(inline)完成,因为 NimBLE 要求同步返回属性值。
|
||||
- GATT 服务端的属性访问在主机任务上原地 (inline) 完成,因为 NimBLE 要求同步返回属性值。
|
||||
* - ISO 任务所在 CPU 核
|
||||
- 绑定到所配置的 Bluedroid 核。
|
||||
- 绑定到所配置的 NimBLE 核。
|
||||
@@ -198,14 +198,14 @@ ESP-IDF 蓝牙 LE Audio 被组织为一组相互协作的分层。每一层只
|
||||
- 两阶段且异步(``*_init`` 然后 ``*_start``)
|
||||
- 单阶段 ``ble_gatts_add_svcs``
|
||||
* - L2CAP 面向连接的通道
|
||||
- 未实现(TODO)
|
||||
- 未实现 (TODO)
|
||||
- 已实现(草案)
|
||||
* - 对象传输服务(OTS)
|
||||
* - 对象传输服务 (OTS)
|
||||
- 未实现(构建在 L2CAP 之上)
|
||||
- 已实现(草案)
|
||||
* - 连接发起的事件路由
|
||||
- 共享引擎的 BTA GATTC 接口(``esp_ble_iso_bluedroid_get_gattc_if``)
|
||||
- 把 GAP 事件转发进引擎(``*_gap_app_post_event``)
|
||||
- 共享引擎的 BTA GATTC 接口 (``esp_ble_iso_bluedroid_get_gattc_if``)
|
||||
- 把 GAP 事件转发进引擎 (``*_gap_app_post_event``)
|
||||
|
||||
超出这些范围的任何差异都需要同样的论证,并记录在引入它的地方。
|
||||
|
||||
@@ -215,7 +215,7 @@ ESP-IDF 蓝牙 LE Audio 被组织为一组相互协作的分层。每一层只
|
||||
该架构依赖几条调用者和维护者都应尊重的边界:
|
||||
|
||||
- **公共 API 是唯一稳定的接口面**。``esp_ble_iso_*`` 和 ``esp_ble_audio_*`` API 之下的一切都是内部实现,可能在不同版本之间改变。
|
||||
- **两种 BLE 主机协议栈是被适配,而非被修改**。适配器层的存在正是为了让组件永不改动 Bluedroid 或 NimBLE 本身;主机行为被视为既定。
|
||||
- **两种低功耗蓝牙主机协议栈是被适配,而非被修改**。适配器层的存在正是为了让组件永不改动 Bluedroid 或 NimBLE 本身;主机行为被视为既定。
|
||||
- **规范与控制器逻辑是一个具有固定 ABI 的预构建库**。开源代码只通过在初始化时校验的共享函数表和配置表与它交互;它的内部实现不属于这个契约。
|
||||
|
||||
常见陷阱
|
||||
@@ -259,7 +259,7 @@ ESP-BLE-ISO
|
||||
* - ``host/iso``
|
||||
- ISO 引擎(CIS 和 BIG 状态机及通道 API)。
|
||||
* - ``host/adapter/bluedroid``,\ |br|\ ``host/adapter/nimble``
|
||||
- GAP、GATT、ISO、HCI 和(NimBLE)L2CAP 的各主机适配器。
|
||||
- GAP、GATT、ISO、HCI 和 (NimBLE) L2CAP 的各主机适配器。
|
||||
* - ``host/utils``
|
||||
- 地址、UUID、CRC、加密、定时器和缓冲区辅助函数。
|
||||
|
||||
@@ -275,7 +275,7 @@ ESP-BLE-AUDIO
|
||||
* - ``api/include``
|
||||
- 公共 ``esp_ble_audio_*_api.h`` 头文件,每个规范和服务一个。
|
||||
* - ``host/common``
|
||||
- 初始化编排(``init.c``)。
|
||||
- 初始化编排 (``init.c``)。
|
||||
* - ``host/adapter/bluedroid/profiles``,\ |br|\ ``host/adapter/nimble/profiles``
|
||||
- GATT 服务适配器(PACS、ASCS、BASS、CAS、CSIS、HAS、MCS、MICS、TBS、TMAS、VCS)。
|
||||
* - ``host/services/ots``
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本页跟踪 ESP-IDF 中蓝牙 LE Audio 功能的支持状态 —— ESP-BLE-AUDIO 提供的通用音频框架(GAF)规范和服务,以及 ESP-BLE-ISO 提供的等时传输。
|
||||
本页跟踪 ESP-IDF 中蓝牙低功耗音频功能的支持状态 —— ESP-BLE-AUDIO 提供的通用音频框架 (GAF) 规范和服务,以及 ESP-BLE-ISO 提供的等时传输。
|
||||
|
||||
.. note::
|
||||
|
||||
下表中标为支持的蓝牙 LE Audio 功能目前为\ **预览版**\ :其 API 和行为均为暂定,可能在未来版本中变化。
|
||||
下表中标为支持的蓝牙低功耗音频功能目前为\ **预览版**\ :其 API 和行为均为暂定,可能在未来版本中变化。
|
||||
|
||||
下表列出了 ESP-IDF 中当前支持的蓝牙 LE Audio 规范和服务。
|
||||
下表列出了 ESP-IDF 中当前支持的蓝牙低功耗音频规范和服务。
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
@@ -18,7 +18,7 @@
|
||||
* - 规范 / 服务
|
||||
- 支持状态
|
||||
- 说明
|
||||
* - LE 等时通道(CIS / BIS)
|
||||
* - LE 等时通道 (CIS / BIS)
|
||||
- 支持
|
||||
- 通过 :doc:`ESP-BLE-ISO <../../api-reference/bluetooth/esp-ble-iso>` 直接访问 ISO。
|
||||
* - BAP
|
||||
@@ -78,6 +78,6 @@
|
||||
|
||||
.. note::
|
||||
|
||||
规范和服务的定义参见 :doc:`蓝牙 LE Audio 标准 <ble-audio-introduction>`。
|
||||
规范和服务的定义参见 :doc:`蓝牙低功耗音频标准 <ble-audio-introduction>`。
|
||||
|
||||
通用蓝牙低功耗功能支持参见 :doc:`主要功能支持状态 <../ble/ble-feature-support-status>`。
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
ESP-IDF 蓝牙 LE Audio
|
||||
=====================
|
||||
蓝牙\ :sup:`™` 低功耗音频
|
||||
==========================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
蓝牙 LE Audio 是蓝牙核心规范 5.2 中引入的音频架构。阅读本系列文档前,应注意区分以下两个概念:
|
||||
蓝牙低功耗音频是蓝牙核心规范 5.2 中引入的音频架构。阅读本系列文档前,应注意区分以下两个概念:
|
||||
|
||||
- **标准**\ 指蓝牙技术联盟 (Bluetooth SIG) 定义的规范 (Profile)、服务 (Service) 与角色 (Role) 体系,其核心为构建在 LE 等时传输之上的通用音频框架 (GAF)。它与平台无关,详见 :doc:`蓝牙 LE Audio 标准 <ble-audio-introduction>`。
|
||||
- **实现**\ 是在特定平台上实现该标准的软件。ESP-IDF 的实现详见 :doc:`ESP-IDF 蓝牙 LE Audio 架构 <ble-audio-architecture-overview>`。
|
||||
- **标准**\ 指蓝牙技术联盟 (Bluetooth SIG) 定义的规范 (Profile)、服务 (Service) 与角色 (Role) 体系,其核心为构建在 LE 等时传输之上的通用音频框架 (GAF)。它与平台无关,详见 :doc:`蓝牙低功耗音频标准 <ble-audio-introduction>`。
|
||||
- **实现**\ 是在特定平台上实现该标准的软件。ESP-IDF 的实现详见 :doc:`ESP-IDF 蓝牙低功耗音频架构 <ble-audio-architecture-overview>`。
|
||||
|
||||
在 ESP-IDF 中,该实现由两个组件提供:
|
||||
|
||||
- **ESP-BLE-ISO** 提供等时传输 —— 承载音频的连接式和广播式等时流(CIS/BIS)。参见其 :doc:`API 参考 <../../api-reference/bluetooth/esp-ble-iso>`。
|
||||
- **ESP-BLE-AUDIO** 提供通用音频框架(GAF)规范和服务,构建在 ESP-BLE-ISO 之上。参见其 :doc:`API 参考 <../../api-reference/bluetooth/esp-ble-audio>`。
|
||||
- **ESP-BLE-ISO** 提供等时传输 —— 承载音频的连接式和广播式等时流 (CIS/BIS)。参见其 :doc:`API 参考 <../../api-reference/bluetooth/esp-ble-iso>`。
|
||||
- **ESP-BLE-AUDIO** 提供通用音频框架 (GAF) 规范和服务,构建在 ESP-BLE-ISO 之上。参见其 :doc:`API 参考 <../../api-reference/bluetooth/esp-ble-audio>`。
|
||||
|
||||
这两个组件均可运行于 ESP-IDF 的两个蓝牙主机协议栈 **Bluedroid** 或 **NimBLE** 之上。在可行范围内,两者的 API 与行为保持一致;当行为差异不可避免时,将在架构文档中说明,并解释原因。
|
||||
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
蓝牙 LE Audio 标准
|
||||
蓝牙低功耗音频标准
|
||||
==================
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
本文介绍蓝牙 LE Audio 标准:各规范(Profile)、服务(Service)的定义、它们所包含的角色,以及彼此之间的依赖关系。在使用 :doc:`ESP-BLE-AUDIO API 参考 <../../api-reference/bluetooth/esp-ble-audio>` 进行开发之前,建议先阅读本文,以便选择适合应用场景的规范组合。
|
||||
本文介绍蓝牙低功耗音频标准:各规范 (Profile)、服务 (Service) 的定义、它们所包含的角色,以及彼此之间的依赖关系。在使用 :doc:`ESP-BLE-AUDIO API 参考 <../../api-reference/bluetooth/esp-ble-audio>` 进行开发之前,建议先阅读本文,以便选择适合应用场景的规范组合。
|
||||
|
||||
.. note::
|
||||
|
||||
本文聚焦 LE Audio **标准** 本身。关于 **ESP-IDF 的实现架构**\ (ESP-BLE-ISO 与 ESP-BLE-AUDIO 组件、任务与锁模型、各主机适配器),参见 :doc:`ESP-IDF 蓝牙 LE Audio 架构 <ble-audio-architecture-overview>`。
|
||||
本文聚焦蓝牙低功耗音频 **标准** 本身。关于 **ESP-IDF 的实现架构**\ (ESP-BLE-ISO 与 ESP-BLE-AUDIO 组件、任务与锁模型、各主机适配器),参见 :doc:`ESP-IDF 蓝牙低功耗音频架构 <ble-audio-architecture-overview>`。
|
||||
|
||||
|
||||
概述
|
||||
----
|
||||
|
||||
蓝牙 LE Audio 由蓝牙核心规范 5.2 引入,支持在低功耗蓝牙上传输高质量音频,具备以下核心特性:
|
||||
蓝牙低功耗音频由蓝牙核心规范 5.2 引入,支持在低功耗蓝牙上传输高质量音频,具备以下核心特性:
|
||||
|
||||
- **LE 等时通道(ISO)** — 控制器层的新传输机制,提供时间同步、低延迟的数据流,支持已连接(CIS)和无连接(BIS)两种模式。
|
||||
- **LC3 编解码器** — 低复杂度通信编解码器(Low Complexity Communication Codec),与 SBC 相比,在更低比特率下提供更好的音频质量。
|
||||
- **通用音频框架(GAF)** — 一套分层的规范和服务,标准化了音频流建立、音量控制、媒体控制、通话控制和设备协调等功能。
|
||||
- **LE 等时通道 (ISO)** — 控制器层的新传输机制,提供时间同步、低延迟的数据流,支持已连接 (CIS) 和无连接 (BIS) 两种模式。
|
||||
- **LC3 编解码器** — 低复杂度通信编解码器 (Low Complexity Communication Codec),与 SBC 相比,在更低比特率下提供更好的音频质量。
|
||||
- **通用音频框架 (GAF)** — 一套分层的规范和服务,标准化了音频流建立、音量控制、媒体控制、通话控制和设备协调等功能。
|
||||
|
||||
蓝牙 LE Audio 支持两种基本音频场景:
|
||||
蓝牙低功耗音频支持两种基本音频场景:
|
||||
|
||||
- **单播音频(Unicast Audio)** — 通过连接等时流(CIS)在两个已连接设备之间进行双向或单向音频传输。典型应用:TWS 耳机、助听器、耳麦、电话通信。
|
||||
- **广播音频(Broadcast Audio,Auracast™)** — 通过广播等时流(BIS),由一个广播源向任意数量的接收端进行单向音频传输。典型应用:公共场所音频、无障碍辅助收听、群组电视收听。
|
||||
- **单播音频 (Unicast Audio)** — 通过连接等时流 (CIS) 在两个已连接设备之间进行双向或单向音频传输。典型应用:TWS 耳机、助听器、耳麦、电话通信。
|
||||
- **广播音频(Broadcast Audio,Auracast™)** — 通过广播等时流 (BIS),由一个广播源向任意数量的接收端进行单向音频传输。典型应用:公共场所音频、无障碍辅助收听、群组电视收听。
|
||||
|
||||
|
||||
标准概览
|
||||
--------
|
||||
|
||||
蓝牙 LE Audio 标准分为三个层次:
|
||||
蓝牙低功耗音频标准分为三个层次:
|
||||
|
||||
1. **传输层** — LE Audio 底层的蓝牙传输:LE 等时通道(CIS/BIS)承载音频数据,ACL 连接承载 GATT/ATT 规范控制,周期性广播承载广播通告。其中只有等时通道为 LE Audio 新增(详见下文)。
|
||||
2. **通用音频框架(GAF)** — 核心规范套件,分为四个功能层:流控制、内容控制、渲染/采集控制和过渡/协调控制。
|
||||
1. **传输层** — 低功耗音频底层的蓝牙传输:LE 等时通道 (CIS/BIS) 承载音频数据,ACL 连接承载 GATT/ATT 规范控制,周期性广播承载广播通告。其中只有等时通道为低功耗音频新增(详见下文)。
|
||||
2. **通用音频框架 (GAF)** — 核心规范套件,分为四个功能层:流控制、内容控制、渲染/采集控制和过渡/协调控制。
|
||||
3. **特定用例规范** — 更高层的规范(HAP、TMAP、GMAP、PBP),针对特定使用场景选择并配置相应的 GAF 组件。
|
||||
|
||||
.. figure:: ../../../_static/ble/ble-audio-gaf-zh.png
|
||||
:align: center
|
||||
:width: 90%
|
||||
:alt: 蓝牙 LE Audio 标准分层图
|
||||
:alt: 蓝牙低功耗音频标准分层图
|
||||
|
||||
蓝牙 LE Audio 协议栈:特定用例规范构建于通用音频框架(GAF)之上。规范的控制经由 GATT/ATT 走 ACL 连接,音频数据走 LE 等时通道(CIS/BIS),广播通告走周期性广播。
|
||||
蓝牙低功耗音频协议栈:特定用例规范构建于通用音频框架 (GAF) 之上。规范的控制经由 GATT/ATT 走 ACL 连接,音频数据走 LE 等时通道 (CIS/BIS),广播通告走周期性广播。
|
||||
|
||||
GAF 各层仅依赖其下方的层。特定用例规范选择 GAF 层的子集,并在其之上添加角色特定的约束。以下各节将详细介绍每个组件。
|
||||
|
||||
@@ -47,7 +47,7 @@ GAF 各层仅依赖其下方的层。特定用例规范选择 GAF 层的子集
|
||||
LE 等时通道
|
||||
-----------
|
||||
|
||||
LE 等时通道是蓝牙核心规范中定义的控制器层特性,为蓝牙 LE Audio 提供时间同步、低延迟的数据传输。
|
||||
LE 等时通道是蓝牙核心规范中定义的控制器层特性,为蓝牙低功耗音频提供时间同步、低延迟的数据传输。
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
@@ -58,18 +58,18 @@ LE 等时通道是蓝牙核心规范中定义的控制器层特性,为蓝牙 L
|
||||
- 说明
|
||||
* - 连接等时流
|
||||
- CIS
|
||||
- 两个设备之间的双向等时链路,需要先建立 ACL 连接。多个 CIS 实例可组成一个连接等时组(CIG),用于同步播放(例如左右耳机)。
|
||||
- 两个设备之间的双向等时链路,需要先建立 ACL 连接。多个 CIS 实例可组成一个连接等时组 (CIG),用于同步播放(例如左右耳机)。
|
||||
* - 广播等时流
|
||||
- BIS
|
||||
- 从广播方向任意数量的同步接收方进行的单向等时流,无需事先建立连接。多个 BIS 实例属于一个广播等时组(BIG)。
|
||||
- 从广播方向任意数量的同步接收方进行的单向等时流,无需事先建立连接。多个 BIS 实例属于一个广播等时组 (BIG)。
|
||||
|
||||
ESP-IDF 通过 :doc:`ESP-BLE-ISO API <../../api-reference/bluetooth/esp-ble-iso>` 提供对 CIS 和 BIS 的直接访问。使用蓝牙 LE Audio 规范(BAP 及更高层)时,ISO 层由规范栈自动管理。
|
||||
ESP-IDF 通过 :doc:`ESP-BLE-ISO API <../../api-reference/bluetooth/esp-ble-iso>` 提供对 CIS 和 BIS 的直接访问。使用蓝牙低功耗音频规范(BAP 及更高层)时,ISO 层由规范栈自动管理。
|
||||
|
||||
|
||||
通用音频框架(GAF)
|
||||
通用音频框架 (GAF)
|
||||
-------------------
|
||||
|
||||
通用音频框架(GAF)是蓝牙 LE Audio 的核心,定义了四个功能层,下文从下至上依次介绍。
|
||||
通用音频框架 (GAF) 是蓝牙低功耗音频的核心,定义了四个功能层,下文从下至上依次介绍。
|
||||
|
||||
|
||||
流控制层
|
||||
@@ -77,16 +77,16 @@ ESP-IDF 通过 :doc:`ESP-BLE-ISO API <../../api-reference/bluetooth/esp-ble-iso>
|
||||
|
||||
流控制层负责发现音频能力、建立音频流(编解码器配置和 QoS)以及管理 CIS 和 BIS 连接的生命周期。
|
||||
|
||||
**基本音频规范(BAP)**
|
||||
**基本音频规范 (BAP)**
|
||||
|
||||
BAP 是所有蓝牙 LE Audio 流传输的基础规范,定义了以下角色:
|
||||
BAP 是所有蓝牙低功耗音频流传输的基础规范,定义了以下角色:
|
||||
|
||||
- **单播客户端(Unicast Client)** — 发现远端单播服务器上的 ASE,发起编解码器配置、QoS 协商和流控制(使能、连接、开始、禁用、释放)。
|
||||
- **单播服务器(Unicast Server)** — 通过 ASCS 暴露音频端点(ASE),响应客户端发起的流控制流程。
|
||||
- **广播源(Broadcast Source)** — 创建 BIG,配置 BIS 流,发送音频数据。
|
||||
- **广播接收端(Broadcast Sink)** — 扫描并同步至广播源,接收 BIS 音频数据。
|
||||
- **广播助手(Broadcast Assistant)** — 代替低功耗的扫描委托设备扫描广播源,并将结果写入委托设备上的 BASS。
|
||||
- **扫描委托设备(Scan Delegator)** — 暴露 BASS,将 BIS 扫描委托给广播助手。
|
||||
- **单播客户端 (Unicast Client)** — 发现远端单播服务器上的 ASE,发起编解码器配置、QoS 协商和流控制(使能、连接、开始、禁用、释放)。
|
||||
- **单播服务器 (Unicast Server)** — 通过 ASCS 暴露音频端点 (ASE),响应客户端发起的流控制流程。
|
||||
- **广播源 (Broadcast Source)** — 创建 BIG,配置 BIS 流,发送音频数据。
|
||||
- **广播接收端 (Broadcast Sink)** — 扫描并同步至广播源,接收 BIS 音频数据。
|
||||
- **广播助手 (Broadcast Assistant)** — 代替低功耗的扫描委托设备扫描广播源,并将结果写入委托设备上的 BASS。
|
||||
- **扫描委托设备 (Scan Delegator)** — 暴露 BASS,将 BIS 扫描委托给广播助手。
|
||||
|
||||
BAP 依赖三个 GATT 服务:
|
||||
|
||||
@@ -96,11 +96,11 @@ BAP 依赖三个 GATT 服务:
|
||||
|
||||
* - 服务
|
||||
- 说明
|
||||
* - 已发布音频能力服务(PACS)
|
||||
* - 已发布音频能力服务 (PACS)
|
||||
- 暴露设备支持的编解码器、编解码器配置和可用音频上下文。存在于单播服务器和广播接收端。
|
||||
* - 音频流控制服务(ASCS)
|
||||
- 暴露一个或多个音频流端点(ASE),每个 ASE 代表一个接收或发送数据路径。仅存在于单播服务器。
|
||||
* - 广播音频扫描服务(BASS)
|
||||
* - 音频流控制服务 (ASCS)
|
||||
- 暴露一个或多个音频流端点 (ASE),每个 ASE 代表一个接收或发送数据路径。仅存在于单播服务器。
|
||||
* - 广播音频扫描服务 (BASS)
|
||||
- 由扫描委托设备暴露,用于记录接收状态;由广播助手写入广播源信息。仅存在于扫描委托设备。
|
||||
|
||||
|
||||
@@ -109,25 +109,25 @@ BAP 依赖三个 GATT 服务:
|
||||
|
||||
内容控制层提供对音频流所传输的媒体内容和通话活动的标准化控制。
|
||||
|
||||
**媒体控制规范(MCP)与媒体控制服务(MCS)**
|
||||
**媒体控制规范 (MCP) 与媒体控制服务 (MCS)**
|
||||
|
||||
MCP 定义了 **媒体控制服务器**\ (通过 MCS 暴露媒体播放器)和 **媒体控制客户端**\ (发现并控制播放器)。MCS 暴露媒体状态(播放中/暂停/停止)、播放位置、曲目元数据以及控制点操作(播放、暂停、下一曲、跳转等)。
|
||||
|
||||
MCS 有两种形式:
|
||||
|
||||
- **MCS** — 针对拥有多个并发媒体播放器的设备,每个播放器一个实例。
|
||||
- **通用 MCS(GMCS)** — 单一必选实例,提供对当前活跃播放器的访问,适用于无需按播放器区分的客户端。
|
||||
- **通用 MCS (GMCS)** — 单一必选实例,提供对当前活跃播放器的访问,适用于无需按播放器区分的客户端。
|
||||
|
||||
当设备支持媒体对象传输时,MCP 可选依赖 **对象传输规范(OTP)** 和 **对象传输服务(OTS)**,用于传输媒体对象(曲目名称、图标、对象元数据等)。
|
||||
当设备支持媒体对象传输时,MCP 可选依赖 **对象传输规范 (OTP)** 和 **对象传输服务 (OTS)**,用于传输媒体对象(曲目名称、图标、对象元数据等)。
|
||||
|
||||
**通话控制规范(CCP)与电话承载服务(TBS)**
|
||||
**通话控制规范 (CCP) 与电话承载服务 (TBS)**
|
||||
|
||||
CCP 定义了 **通话控制服务器**\ (通过 TBS 暴露一个或多个电话承载)和 **通话控制客户端**\ (发现并控制通话)。TBS 暴露通话状态、通话 URI 方案、来电/去电控制、信号强度和运营商名称。
|
||||
|
||||
TBS 有两种形式:
|
||||
|
||||
- **TBS** — 针对拥有多个电话承载(例如多张 SIM 卡或 VoIP 应用)的设备,每个承载一个实例。
|
||||
- **通用 TBS(GTBS)** — 单一必选实例,提供所有承载的统一视图。
|
||||
- **通用 TBS (GTBS)** — 单一必选实例,提供所有承载的统一视图。
|
||||
|
||||
|
||||
渲染与采集控制层
|
||||
@@ -135,9 +135,9 @@ TBS 有两种形式:
|
||||
|
||||
渲染与采集控制层提供对设备音频输出音量和音频输入增益的标准化控制,独立于所播放的内容。
|
||||
|
||||
**音量控制规范(VCP)**
|
||||
**音量控制规范 (VCP)**
|
||||
|
||||
VCP 定义了 **音量渲染器(Volume Renderer)**\ (暴露音量状态,接受远程控制)和 **音量控制器(Volume Controller)**\ (发现并控制渲染器)。VCP 依赖以下 GATT 服务:
|
||||
VCP 定义了 **音量渲染器 (Volume Renderer)**\ (暴露音量状态,接受远程控制)和 **音量控制器 (Volume Controller)**\ (发现并控制渲染器)。VCP 依赖以下 GATT 服务:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
@@ -146,19 +146,19 @@ VCP 定义了 **音量渲染器(Volume Renderer)**\ (暴露音量状态,
|
||||
* - 服务
|
||||
- 是否必选
|
||||
- 说明
|
||||
* - 音量控制服务(VCS)
|
||||
* - 音量控制服务 (VCS)
|
||||
- 必选
|
||||
- 暴露音量设置(0–255)、静音状态以及绝对或相对音量控制点。
|
||||
* - 音量偏移控制服务(VOCS)
|
||||
* - 音量偏移控制服务 (VOCS)
|
||||
- 可选
|
||||
- 支持对每路输出进行音量偏移调整(例如左右声道输出分别设置偏移)。一个 VCS 可包含一个或多个 VOCS 实例。
|
||||
* - 音频输入控制服务(AICS)
|
||||
* - 音频输入控制服务 (AICS)
|
||||
- 可选
|
||||
- 支持对一路音频输入(例如麦克风)的增益和静音状态进行控制。一个 VCS 可包含一个或多个 AICS 实例。
|
||||
|
||||
**麦克风控制规范(MICP)**
|
||||
**麦克风控制规范 (MICP)**
|
||||
|
||||
MICP 定义了 **麦克风设备(Microphone Device)**\ (暴露麦克风状态)和 **麦克风控制器(Microphone Controller)**\ (发现并控制静音/取消静音)。MICP 依赖以下 GATT 服务:
|
||||
MICP 定义了 **麦克风设备 (Microphone Device)**\ (暴露麦克风状态)和 **麦克风控制器 (Microphone Controller)**\ (发现并控制静音/取消静音)。MICP 依赖以下 GATT 服务:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
@@ -167,10 +167,10 @@ MICP 定义了 **麦克风设备(Microphone Device)**\ (暴露麦克风状
|
||||
* - 服务
|
||||
- 是否必选
|
||||
- 说明
|
||||
* - 麦克风控制服务(MICS)
|
||||
* - 麦克风控制服务 (MICS)
|
||||
- 必选
|
||||
- 暴露麦克风静音状态和静音控制点,存在于麦克风设备端。
|
||||
* - 音频输入控制服务(AICS)
|
||||
* - 音频输入控制服务 (AICS)
|
||||
- 可选
|
||||
- 支持对特定输入的音频输入增益进行控制。一个 MICS 可包含一个或多个 AICS 实例。
|
||||
|
||||
@@ -184,27 +184,27 @@ MICP 定义了 **麦克风设备(Microphone Device)**\ (暴露麦克风状
|
||||
|
||||
过渡与协调控制层位于 GAF 的最顶层,负责协调作为一个群组运行的多台设备(例如一对 TWS 耳机或一个房间内的多个扬声器)的音频操作。
|
||||
|
||||
**通用音频规范(CAP)**
|
||||
**通用音频规范 (CAP)**
|
||||
|
||||
CAP 是最高层规范,定义了单个发起设备如何协调一台或多台目标设备执行音频操作(流建立、音量控制、麦克风控制)。它定义了三个角色:
|
||||
|
||||
- **CAP 接受端(CAP Acceptor)** — 接受来自 CAP 发起端或指挥端的音频流和音量/麦克风控制的设备。CAP 接受端须支持 BAP 单播服务器或 BAP 广播接收端(或两者兼具),以及 VCP 音量渲染器。MICP 麦克风设备为可选。
|
||||
- **CAP 发起端(CAP Initiator)** — 发现 CAP 接受端,并使用 BAP、VCP 和 MICP 同时对一个或多个接受端发起单播或广播音频流程的设备。
|
||||
- **CAP 指挥端(CAP Commander)** — 向一个或多个 CAP 接受端下发协调的音量和麦克风控制指令,但不直接管理音频流的设备。
|
||||
- **CAP 接受端 (CAP Acceptor)** — 接受来自 CAP 发起端或指挥端的音频流和音量/麦克风控制的设备。CAP 接受端须支持 BAP 单播服务器或 BAP 广播接收端(或两者兼具),以及 VCP 音量渲染器。MICP 麦克风设备为可选。
|
||||
- **CAP 发起端 (CAP Initiator)** — 发现 CAP 接受端,并使用 BAP、VCP 和 MICP 同时对一个或多个接受端发起单播或广播音频流程的设备。
|
||||
- **CAP 指挥端 (CAP Commander)** — 向一个或多个 CAP 接受端下发协调的音量和麦克风控制指令,但不直接管理音频流的设备。
|
||||
|
||||
CAP 依赖 **通用音频服务(CAS)**,这是每个 CAP 接受端上的必选 GATT 服务,用于协调集成员通告,为 CAP 发起端/指挥端提供稳定的发现锚点。
|
||||
CAP 依赖 **通用音频服务 (CAS)**,这是每个 CAP 接受端上的必选 GATT 服务,用于协调集成员通告,为 CAP 发起端/指挥端提供稳定的发现锚点。
|
||||
|
||||
CAP 还使用 **CSIP**\ (见下文)对协调集的成员进行识别和集体寻址。
|
||||
|
||||
**协调集标识规范(CSIP)**
|
||||
**协调集标识规范 (CSIP)**
|
||||
|
||||
CSIP 定义了如何发现并识别一组设备("协调集")属于同一整体。典型示例是左右耳机对:每个耳机是一个 **CSIP 集成员(Set Member)**,手机或音源设备是一个 **CSIP 集协调器(Set Coordinator)**。
|
||||
CSIP 定义了如何发现并识别一组设备("协调集")属于同一整体。典型示例是左右耳机对:每个耳机是一个 **CSIP 集成员 (Set Member)**,手机或音源设备是一个 **CSIP 集协调器 (Set Coordinator)**。
|
||||
|
||||
CSIP 依赖 **协调集标识服务(CSIS)**,该服务暴露:
|
||||
CSIP 依赖 **协调集标识服务 (CSIS)**,该服务暴露:
|
||||
|
||||
- **集身份解析密钥(SIRK)** — 用于集协调器匹配属于同一集的设备,即使在重新通告后也有效。
|
||||
- **集规模(Set Size)** — 集中的成员数量。
|
||||
- **成员排名(Member Rank)** — 该设备在集中的排名(用于有序操作)。
|
||||
- **集身份解析密钥 (SIRK)** — 用于集协调器匹配属于同一集的设备,即使在重新通告后也有效。
|
||||
- **集规模 (Set Size)** — 集中的成员数量。
|
||||
- **成员排名 (Member Rank)** — 该设备在集中的排名(用于有序操作)。
|
||||
|
||||
|
||||
特定用例规范
|
||||
@@ -212,16 +212,16 @@ CSIP 依赖 **协调集标识服务(CSIS)**,该服务暴露:
|
||||
|
||||
特定用例规范位于 GAF 之上,每个规范选择一部分 GAF 规范,定义针对特定角色的配置约束(例如编解码器参数、QoS 设置),并可添加自己的小型 GATT 服务用于角色通告。
|
||||
|
||||
**助听器访问规范(HAP)**
|
||||
**助听器访问规范 (HAP)**
|
||||
|
||||
HAP 面向助听器设备,增加了 **听力预设(Hearing Aid Preset)** 的概念:用户可命名的音频配置(例如"室外"、"餐厅"),可在不同场景间切换。HAP 定义了:
|
||||
HAP 面向助听器设备,增加了 **听力预设 (Hearing Aid Preset)** 的概念:用户可命名的音频配置(例如"室外"、"餐厅"),可在不同场景间切换。HAP 定义了:
|
||||
|
||||
- **助听器(Hearing Aid)** — 实现音频接收、音量控制以及(双耳助听器对)协调集成员所需的全部 GAF 角色。
|
||||
- **助听器单播客户端(Hearing Aid Unicast Client)** — 发现助听器、控制预设,并管理单播音频流。
|
||||
- **助听器 (Hearing Aid)** — 实现音频接收、音量控制以及(双耳助听器对)协调集成员所需的全部 GAF 角色。
|
||||
- **助听器单播客户端 (Hearing Aid Unicast Client)** — 发现助听器、控制预设,并管理单播音频流。
|
||||
|
||||
HAP 依赖 **助听器访问服务(HAS)** 进行预设读写操作,同时依赖 GAF 中的 BAP、PACS、VCP、MICP 和 CSIP。
|
||||
HAP 依赖 **助听器访问服务 (HAS)** 进行预设读写操作,同时依赖 GAF 中的 BAP、PACS、VCP、MICP 和 CSIP。
|
||||
|
||||
**电话和媒体音频规范(TMAP)**
|
||||
**电话和媒体音频规范 (TMAP)**
|
||||
|
||||
TMAP 为电话和媒体场景定义互操作配置,包含六个角色:
|
||||
|
||||
@@ -251,9 +251,9 @@ TMAP 为电话和媒体场景定义互操作配置,包含六个角色:
|
||||
- BMR
|
||||
- 通过 BIS 接收来自 BMS 的媒体音频,充当 BAP 广播接收端。
|
||||
|
||||
TMAP 通过 **电话和媒体音频服务(TMAS)** 通告其角色,该服务是一个包含单一 TMAP 角色特征的小型 GATT 服务,允许远端设备在建立连接前发现本地设备支持的 TMAP 角色。TMAP 本身不定义新的音频传输机制,完全委托给 BAP(流建立)、VCP(音量)、MCP/MCS(UMS/UMR 的媒体控制)和 CCP/TBS(CG/CT 的通话控制)。
|
||||
TMAP 通过 **电话和媒体音频服务 (TMAS)** 通告其角色,该服务是一个包含单一 TMAP 角色特征的小型 GATT 服务,允许远端设备在建立连接前发现本地设备支持的 TMAP 角色。TMAP 本身不定义新的音频传输机制,完全委托给 BAP(流建立)、VCP(音量)、MCP/MCS(UMS/UMR 的媒体控制)和 CCP/TBS(CG/CT 的通话控制)。
|
||||
|
||||
**游戏音频规范(GMAP)**
|
||||
**游戏音频规范 (GMAP)**
|
||||
|
||||
GMAP 面向游戏音频产品,采用针对更低传输延迟和更少重传优化的参数。它定义了四个角色:
|
||||
|
||||
@@ -277,14 +277,14 @@ GMAP 面向游戏音频产品,采用针对更低传输延迟和更少重传优
|
||||
- BGR
|
||||
- 通过 BIS 接收游戏音频,充当 BAP 广播接收端。
|
||||
|
||||
GMAP 通过 **游戏音频服务(GMAS)** 通告角色,依赖 BAP 进行流建立,依赖 VCP 进行音量控制。
|
||||
GMAP 通过 **游戏音频服务 (GMAS)** 通告角色,依赖 BAP 进行流建立,依赖 VCP 进行音量控制。
|
||||
|
||||
**公共广播规范(PBP)**
|
||||
**公共广播规范 (PBP)**
|
||||
|
||||
PBP 为公共广播源的元数据格式提供标准化定义,使任何兼容的接收方无需配对即可发现并同步该广播流。它定义了:
|
||||
|
||||
- **公共广播源(Public Broadcast Source)** — 通过标准化扩展通告数据(包含 Broadcast Audio Announcement 和 Public Broadcast Announcement)通告 Auracast™ 音频流,委托 BAP 广播源进行 BIS 建立。
|
||||
- **公共广播接收端(Public Broadcast Sink)** — 扫描 PBP 源,读取通告元数据以确定音频质量和内容,并同步至 BIG,委托 BAP 广播接收端实现。
|
||||
- **公共广播源 (Public Broadcast Source)** — 通过标准化扩展通告数据(包含 Broadcast Audio Announcement 和 Public Broadcast Announcement)通告 Auracast™ 音频流,委托 BAP 广播源进行 BIS 建立。
|
||||
- **公共广播接收端 (Public Broadcast Sink)** — 扫描 PBP 源,读取通告元数据以确定音频质量和内容,并同步至 BIG,委托 BAP 广播接收端实现。
|
||||
|
||||
PBP 完全依赖 BAP 提供底层广播传输,不定义新的 GATT 服务。
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ API 指南
|
||||
:SOC_BT_CLASSIC_SUPPORTED: classic-bt/index
|
||||
:SOC_BLE_SUPPORTED: ble/index
|
||||
:SOC_BLE_MESH_SUPPORTED: esp-ble-mesh/ble-mesh-index
|
||||
:SOC_BLE_AUDIO_SUPPORTED: esp-ble-audio/ble-audio-index
|
||||
bootloader
|
||||
build-system
|
||||
build-system-v2
|
||||
|
||||
Reference in New Issue
Block a user