ESP-BLE-AUDIO
ESP-BLE-AUDIO sits directly on top of ESP-BLE-ISO and implements the Bluetooth LE Audio profiles and services. It is the layer an ESP-IDF Bluetooth LE Audio application actually programs against, through the esp_ble_audio_* API.
Component Layout
The component has two distinct kinds of code, and the distinction matters for this document:
Open source, covered here. The public API headers (
api/include/esp_ble_audio_*_api.h), the GATT service adapters underhost/adapter/bluedroid/profilesandhost/adapter/nimble/profiles, the Object Transfer Service underhost/services/ots, and the initialization orchestration inhost/common/init.c.Prebuilt, out of scope. The ESP-IDF Bluetooth LE Audio profile and controller logic -- the unicast and broadcast clients, the volume, microphone, media and call control, set coordination, and the top-level profiles -- ships as a prebuilt per-target library (
lib/lib/<target>/libble_audio.a, linked withadd_prebuilt_library). This document does not describe its internals; it describes the public contract around it and, where it matters, the task a registered callback runs on.
Layering
%%{init: {'flowchart': {'nodeSpacing': 40, 'rankSpacing': 40, 'subGraphTitleMargin': {'top': 6, 'bottom': 14}}}}%%
flowchart TB
APP["Application"]
API["ESP-BLE-AUDIO public API<br/>(esp_ble_audio_*)"]
subgraph AUDIO["ESP-BLE-AUDIO"]
direction LR
LIB["Prebuilt profile and<br/>controller library"]
SVC["GATT service adapters<br/>(per host)"]
OTS["Object Transfer Service"]
LIB ~~~ SVC
LIB ~~~ OTS
end
ISO["ESP-BLE-ISO transport<br/>(GATT, GAP, ISO, L2CAP, ISO task)"]
APP --> API --> AUDIO --> ISO
Services and Controllers
Bluetooth LE Audio functionality divides into two kinds of building block, and the component reflects the split:
GATT services are the attribute tables a peer reads, writes and subscribes to. They are implemented in the open per-host adapters (
host/adapter/*/profiles), one source file per service, on top of the ESP-BLE-ISO GATT-server layer. Grouped by their profile, as in the Bluetooth LE Audio specification, the set is PACS, ASCS and BASS (BAP), MCS (MCP), TBS (CCP), CSIS (CSIP), MICS (MICP), VCS (VCP), CAS (CAP), TMAS (TMAP) and HAS (HAP).Profile clients and controllers are the state machines that drive those services and orchestrate streams: the Basic Audio and Common Audio profiles, volume, microphone, media and call control, coordinated-set identification, and the top-level Telephony-and-Media, Gaming, and Public-Broadcast profiles. This logic lives in the prebuilt library; the application reaches it through the matching
esp_ble_audio_*_api.hheader.
The GATT services are detailed in GATT Services, and the clients and controllers in Clients and Controllers.
Where Profile Callbacks Run
A registered ESP-IDF Bluetooth LE Audio callback runs on whichever task delivered the underlying transport event, so the rules from Callback Execution Context carry over directly:
A callback driven by a notification -- for example an ASCS or volume-state change arriving as a GATT notification -- runs on the ISO task on both hosts.
A callback driven by a GATT client read or write completion -- for example reading a peer's PAC records -- runs on the ISO task on Bluedroid but on the NimBLE host task on NimBLE.
A callback driven by an inbound attribute write to a local service -- for example a client configuring an ASE -- runs on the ISO task on Bluedroid but on the NimBLE host task on NimBLE.
The consequence is the one that runs through the whole stack: on the ISO task a callback shares the 4 KB stack and must not block the event loop, while on the NimBLE host task it executes inside the host's attribute path. In every case the global ISO lock is held, so profile state stays consistent regardless of which task the callback runs on.
GATT Services
Bluetooth LE Audio exposes its capabilities and state through a fixed set of GATT services. These are the server side of the profiles -- the attribute tables a peer reads, writes and subscribes to -- and, as established in Services and Controllers, they are the open part of ESP-BLE-AUDIO: one source file per service under host/adapter/bluedroid/profiles and host/adapter/nimble/profiles. The state behind each service, and the command handling for its control points, lives in the prebuilt library; this section covers the services and their adapters, not that logic.
Service Adapter Pattern
Every service is realized the same way. The prebuilt library owns the canonical, host-agnostic definition of the service's attribute table (a bt_gatt_service); the open adapter registers that table with the active host's GATT server and then reconciles the handles the host assigns back onto the library's definition, so the library can address its own attributes when it notifies or indicates. The two hosts differ in how the registration is done:
The NimBLE adapter declares the service a second time in NimBLE's native form (a
ble_gatt_svc_def), registers it withble_gatts_add_svcs, checks that its characteristics match the library's definition, and maps the assigned handles back with a*_attr_handle_setstep. Registration is synchronous and single-phase.The Bluedroid adapter hands the library's
bt_gatt_serviceto a sharedbt_le_bluedroid_svc_inithelper that drives BTA GATTS. Because BTA registers a service in two asynchronous phases, every Bluedroid service adapter exposes a matching*_initand*_startpair and coordinates completion with the server semaphore from the GATT-server layer.
Once a service is registered, peer access to its attributes follows the per-host attribute-access path of Callback Execution Context: completed synchronously on the NimBLE host task, or posted to the ISO task on Bluedroid.
When a service is added (deferred registration)
Mechanism. Services are not all added to the GATT table during esp_ble_audio_common_init. The build defines BLE_AUDIO_SVC_DEFERRED_ADD by default, which holds a service back until the application registers the matching role through its esp_ble_audio_<profile>_register call -- the prebuilt library turns that call into the service's bt_le_<service>_init registration -- rather than adding it during init.
Reason. A firmware image usually has more Bluetooth LE Audio capabilities compiled in than any one application uses: enabling a service's Kconfig role option builds its code in, but the application may never take that role. If every compiled-in service were added at init, a connecting peer would discover and could access attributes for a service that has no backing state behind it yet -- the application has not registered it, so the prebuilt library cannot answer for it meaningfully.
Impact on the application. Deferring the add keeps an unused-but-compiled-in capability out of the GATT table until the application opts into it, so a peer only ever discovers services that are fully backed.
Service Reference
Service |
Full name |
Key characteristics |
Adapter |
Profile |
|---|---|---|---|---|
PACS |
Published Audio Capabilities Service |
Sink and Source PAC records, audio locations, available and supported audio contexts. |
|
BAP |
ASCS |
Audio Stream Control Service |
Sink and Source Audio Stream Endpoints (ASEs) and the ASE control point. |
|
BAP |
BASS |
Broadcast Audio Scan Service |
Broadcast Receive State and the broadcast audio scan control point. |
|
BAP |
MCS |
Media Control Service |
Media player name and track information, the media control point and related state. |
|
MCP |
TBS |
Telephone Bearer Service |
Bearer information, call states and the call control point. |
|
CCP |
CSIS |
Coordinated Set Identification Service |
Set Identity Resolving Key (SIRK), set size, set member lock and rank. |
|
CSIP |
MICS |
Microphone Control Service |
Microphone mute; includes AICS. |
|
MICP |
VCS |
Volume Control Service |
Volume state, the volume control point and volume flags; includes VOCS and AICS. |
|
VCP |
CAS |
Common Audio Service |
Identifies a Common Audio device; may include CSIS. |
|
CAP |
TMAS |
Telephony and Media Audio Service |
The device's TMAP role. |
|
TMAP |
HAS |
Hearing Access Service |
Hearing-aid features, the preset control point and the active preset index. |
|
HAP |
Each service is configured by the application through its profile's esp_ble_audio_*_api.h header (for example esp_ble_audio_vcp_api.h for VCS, esp_ble_audio_pacs_api.h for PACS); those APIs are part of the client-and-controller reference that follows.
Included Services and Control Points
Several services are not standalone but are included by another service:
CAS includes CSIS when the device is a member of a coordinated set, so a peer discovers set membership through the common audio device.
VCS includes zero or more VOCS (Volume Offset Control Service) and AICS (Audio Input Control Service) instances -- one VOCS per independently offset output, one AICS per audio input.
MICS includes zero or more AICS instances, one per audio input.
AICS and VOCS therefore have public API headers (esp_ble_audio_aics_api.h and esp_ble_audio_vocs_api.h) but no standalone adapter file; the including service registers them as part of its own attribute table.
Several services -- ASCS, BASS, MCS, TBS, CSIS, VCS and HAS -- expose a control point: a writable characteristic that carries a command and is answered by notifying the affected state characteristic. The command handling lives in the prebuilt library; the adapter only carries the write inward and the resulting notification outward, on the task described in Callback Execution Context.
Clients and Controllers
The profiles and their client and controller roles are the part of ESP-BLE-AUDIO that ships in the prebuilt library. This section describes them at the level this document can: their roles, the public API through which an application drives them, and the task their callbacks run on. The internal state machines are out of scope.
A client or controller role acts on a remote device over a connection -- for example a volume controller changing a renderer's volume -- while a renderer, device, member or server role responds locally and is backed by one of the GATT services in the previous section. A single application can hold several roles at once.
Profile Relationships
Bluetooth LE Audio profiles build on one another. The Basic Audio Profile (BAP) is the foundation: it establishes and carries the audio streams, both unicast (over Connected Isochronous Streams) and broadcast (over Broadcast Isochronous Streams). The control profiles -- volume, microphone, coordinated-set, media and call control -- manage features and are each backed by a GATT service. The Common Audio Profile (CAP) coordinates the others so an operation applies consistently across every member of a set. The top-level profiles -- Telephony and Media Audio (TMAP), Gaming Audio (GMAP), Public Broadcast (PBP) and Hearing Access (HAP) -- are defined combinations of the layers below.
flowchart TB
TOP["Top-level profiles — TMAP, GMAP, PBP, HAP"]
CAP["CAP — coordinated control across a set"]
CTRL["Control profiles — VCP, MICP, CSIP, MCP, CCP"]
BAP["BAP — unicast (CIS) and broadcast (BIS) streams"]
SVC["Bluetooth LE Audio GATT services"]
ISO["ESP-BLE-ISO transport"]
TOP --> CAP
CAP --> BAP
CAP --> CTRL
TOP --> CTRL
CTRL --> SVC
BAP --> ISO
Profile Reference
Profile |
Full name |
Roles |
API header |
|---|---|---|---|
BAP |
Basic Audio Profile |
Unicast client and server, broadcast source and sink, broadcast assistant, scan delegator. |
|
CAP |
Common Audio Profile |
Initiator, commander and handover across a coordinated set. |
|
VCP |
Volume Control Profile |
Volume controller (client) and volume renderer (server). |
|
MICP |
Microphone Control Profile |
Microphone controller (client) and microphone device (server). |
|
CSIP |
Coordinated Set Identification Profile |
Set coordinator (client) and set member (server). |
|
MCP |
Media Control Profile |
Media Control Client (client) and the media proxy (server). |
|
CCP |
Call Control Profile |
Call Control Client (the server side is the Telephone Bearer Service). |
|
TMAP |
Telephony and Media Audio Profile |
Role configuration combining CAP, BAP and the control profiles. |
|
GMAP |
Gaming Audio Profile |
Role configuration for low-latency gaming audio. |
|
PBP |
Public Broadcast Profile |
Public broadcast announcement helpers over BAP broadcast. |
|
API Shape and Roles
Each profile exposes a small, uniform API in its esp_ble_audio_<profile>_api.h header: the application registers a callback structure for the role it is taking and calls functions to start operations -- discover a peer, configure a stream, set a volume, place a call. Results and state changes then arrive asynchronously through that callback, on the task described in Callback Execution Context -- the ISO task in most cases, the NimBLE host task for GATT read and write completions and for inbound writes to a local service.
Because registration and dispatch are uniform across profiles, adding a role to an application always has the same shape: enable the role's Kconfig option, register its callback structure, and drive it through its functions. The role options also determine which GATT services are compiled in, as the initialization flow below shows.
Object Transfer (Draft)
Warning
Object Transfer is an early draft and is not yet officially supported. It builds on the draft L2CAP channel (L2CAP), so it runs only on NimBLE and not on Bluedroid, and its API and behavior are provisional and may change. Do not rely on it in production.
The Object Transfer Service (OTS) moves bulk objects -- larger than an ordinary GATT read can carry -- over the credit-based L2CAP channel from L2CAP. In Bluetooth LE Audio it is used by Media Control: a media player exposes objects such as the current track segmentation and group structure, and a client transfers them with OTS, reached through the media API (esp_ble_audio_mcs_get_ots and the Media Control Client).
Unlike the profiles, OTS is open source, under host/services/ots. Its parts are:
a server (
ots.c) and a client (ots_client.c);the Object Action Control Point (
ots_oacp.c), which carries the read, write, create and similar object operations;the Object List Control Point (
ots_olcp.c), which navigates the list of objects;an object manager (
ots_obj_manager.c) and a directory listing object (ots_dir_list.c);the L2CAP transport (
ots_l2cap.c) that carries object data over the credit-based channel.
Initialization Flow
An ESP-IDF Bluetooth LE Audio application brings the stack up with two calls, mirroring the transport: esp_ble_audio_common_init followed by esp_ble_audio_common_start.
esp_ble_audio_common_init runs bt_le_audio_init in init.c, which first establishes the boundary with the prebuilt library -- it checks that the shared-structure ABI matches and pushes the active Kconfig values into the library -- and then calls the host-specific bt_le_{host}_audio_init. The host initializer brings up the standard GAP and GATT services and then registers each enabled Bluetooth LE Audio service through its adapter, in a fixed order: PACS, ASCS, BASS, TMAS, GTBS, HAS, CSIS and CAS, then the media, volume and microphone services. Each service is compiled in only when its Kconfig role option is set, so a build contains exactly the services its roles need. That fixed order is the order the services register in; when most of them actually enter the GATT table is a separate question -- by default the add is deferred to the application's per-role esp_ble_audio_<profile>_register call rather than happening here at init (see deferred registration).
esp_ble_audio_common_start runs bt_le_audio_start and dispatches to the host-specific start, which first registers the coordinated-set services (CSIS and CAS) from start_info and then commits the GATT server. On Bluedroid the commit is the second phase that actually starts the BTA services registered during init -- the *_init and *_start pairing from The Service Adapter Pattern; on NimBLE it calls ble_gatts_start and then reconciles the assigned attribute handles back into the library.
%%{init: {'sequence': {'noteAlign': 'left'}}}%%
sequenceDiagram
participant APP as Application
participant CMN as ESP-BLE-AUDIO (init.c)
participant LIB as Prebuilt library
participant AD as Host adapter
APP->>CMN: esp_ble_audio_common_init (gap_cb, gatt_cb)
CMN->>LIB: check ABI, push configuration
CMN->>AD: bt_le_{host}_audio_init
Note over AD: bring up GAP/GATT, then register<br/>enabled services in fixed order
APP->>CMN: esp_ble_audio_common_start
CMN->>AD: bt_le_{host}_audio_start
Note over AD: register CSIS/CAS from start_info, then commit the GATT server<br/>Bluedroid: phase-2 start of the registered BTA services<br/>NimBLE: ble_gatts_start, then reconcile attr handles
ATT MTU
Bluetooth LE Audio depends on an ATT MTU large enough to carry its control PDUs.
Spec floor. The Basic Audio Profile (BAP) requires a minimum ATT MTU of only 64 octets (the public ESP_BLE_AUDIO_ATT_MTU_MIN).
Why 128. 64 octets is not enough to operate four ASEs at once, so ESP-IDF raises the default to 128 octets (BLE_AUDIO_ATT_MTU_MIN) to leave headroom for the ASCS and PACS control PDUs that Bluetooth LE Audio relies on. Both hosts set the device's preferred ATT MTU to this value during initialization (bt_le_{host}_audio_init), through BTA_GATT_SetLocalMTU on Bluedroid and ble_att_set_preferred_mtu on NimBLE.
Negotiation rule. This is the value the device offers as a client and accepts as a server, so the MTU that ends up in force is the smaller of the two peers' preferred values.
The exchange itself is the GATT procedure described in MTU Exchange: the client sends the request, the server responds, and one negotiation governs the whole connection. In the common Bluetooth LE Audio topology -- a phone as central and an ESP device as peripheral -- each device runs both a GATT client and a GATT server, since the GATT roles are independent of the GAP role. Yet a single MTU exchange covers the whole connection: the phone's client initiates it, the ESP's server responds, and the one negotiated value then governs all ATT traffic between them -- no matter which side is acting as client or server at a given moment:
sequenceDiagram
box transparent Phone (GAP central)
participant PS as GATT server
participant PC as GATT client
end
box transparent ESP (GAP peripheral)
participant ES as GATT server
participant EC as GATT client
end
PC->>ES: ATT Exchange MTU Request
ES-->>PC: ATT Exchange MTU Response
Note over ES: server responds, never initiates
Note over PS,EC: the one negotiated MTU (min of both sides)<br/>governs all ATT traffic, both directions
PC->>ES: service discovery
PC->>ES: subscribe (CCCD), then PACS / ASCS reads, writes
EC->>PS: service discovery (peripheral as client, reuses the same MTU)
The other two roles -- the phone's GATT server and the ESP's GATT client -- are present on the same connection: the ESP's client can run its own service discovery against the phone's server, but neither role runs a second MTU exchange; both reuse the value the phone's client already negotiated. Because the ESP peripheral only responds and never initiates the MTU exchange, that one negotiation is paced by the central, not by the peripheral's host stack.
End-to-End Flows
The four flows below tie the layers together for the two unicast roles and the two broadcast roles. They are deliberately high-level -- each arrow may stand for several exchanges -- and show which component owns each step.
Unicast Initiator
A unicast initiator connects to an acceptor, configures its audio stream endpoints, establishes a Connected Isochronous Stream and starts sending audio:
sequenceDiagram
participant APP as Application (initiator)
participant AUD as ESP-BLE-AUDIO
participant ISO as ESP-BLE-ISO
participant CTRL as Controller
APP->>ISO: scan and connect (GAP)
APP->>ISO: start GATT discovery
AUD->>ISO: discover PACS and ASCS, subscribe to ASEs
AUD->>ISO: configure ASEs (write the ASE control point)
AUD->>ISO: create CIG and connect CIS
ISO->>CTRL: LE Set CIG Parameters, Create CIS
CTRL->>ISO: CIS Established event
AUD->>ISO: set up the ISO data path (input)
APP->>CTRL: send ISO SDUs
CTRL->>ISO: ISO transmit complete
Note over APP,CTRL: subsequent SDUs repeat the send / transmit-complete cycle
The stream setup -- discovering PACS and ASCS, configuring the ASEs, creating the CIG, connecting the CIS and setting up the data path -- is driven by the ESP-BLE-AUDIO profile library on top of ESP-BLE-ISO's GATT and ISO layers, not by the application directly. The application drives only the high-level flow through the esp_ble_audio_* API -- connect, start discovery, start the stream and send audio -- and ESP-BLE-AUDIO carries out the underlying ESP-BLE-ISO operations on its behalf.
Unicast Acceptor
A unicast acceptor advertises, accepts a connection from an initiator and lets the initiator configure its audio stream endpoints before receiving audio:
sequenceDiagram
participant APP as Application (acceptor)
participant AUD as ESP-BLE-AUDIO
participant ISO as ESP-BLE-ISO
participant CTRL as Controller
APP->>ISO: advertise (GAP, audio announcement)
CTRL->>ISO: ACL connection established (peripheral)
CTRL->>ISO: remote initiator writes the ASE control point
ISO->>AUD: ASCS server applies config / QoS / enable
AUD->>APP: config / QoS / enable callbacks
APP->>AUD: response (accept / reject + QoS preferences)
AUD->>ISO: notify ASE state and control-point result
ISO->>CTRL: send to the remote initiator
CTRL->>ISO: CIS Established event
AUD->>ISO: set up the ISO data path (output)
CTRL->>ISO: ISO SDUs
ISO->>APP: recv callback on the ISO task
Note over APP,CTRL: subsequent ISO SDUs repeat the receive / recv-callback cycle
Unlike the initiator, the acceptor is passive. The remote initiator drives the ASCS state machine by writing the ASE control point, and the acceptor's ESP-BLE-AUDIO ASCS server surfaces each step -- config, QoS, enable -- to the application as callbacks. Each callback returns the application's response -- accept or reject, plus QoS preferences at codec configuration -- which the ASCS server notifies back to the initiator as the updated ASE state and control-point result. The Connected Isochronous Stream is established by the initiator (the acceptor is the peripheral); ESP-BLE-AUDIO sets up the ISO data path and delivers the received SDUs to the application through the recv callback on the ISO task. As on the initiator, the application never calls the ESP-BLE-ISO ISO API directly.
Broadcast Source
A broadcast source configures its audio, starts a periodic advertising train carrying the BASE and transmits audio into a Broadcast Isochronous Group without any connection:
sequenceDiagram
participant APP as Application (broadcast source)
participant AUD as ESP-BLE-AUDIO
participant ISO as ESP-BLE-ISO
participant CTRL as Controller
APP->>AUD: create broadcast source (codec, QoS, BASE)
APP->>ISO: start extended and periodic advertising (GAP, carries the BASE)
APP->>AUD: start the broadcast source
AUD->>ISO: create BIG
ISO->>CTRL: LE Create BIG
CTRL->>ISO: BIG Complete event
AUD->>ISO: set up the ISO data path (input)
AUD->>APP: stream started callback
APP->>CTRL: send ISO SDUs
CTRL->>ISO: ISO transmit complete
Note over APP,CTRL: subsequent SDUs repeat the send / transmit-complete cycle
The application drives the high-level flow through the esp_ble_audio_* API -- create the broadcast source, start advertising, start the source and send audio -- while ESP-BLE-AUDIO builds the BASE, creates the BIG on top of ESP-BLE-ISO's ISO subsystem and sets up the data path. As with the unicast initiator, the underlying ESP-BLE-ISO operations are carried out by ESP-BLE-AUDIO, not the application. A broadcast source has no connection and no GATT: it only advertises and transmits.
Broadcast Sink
A broadcast sink synchronizes to a broadcaster's periodic train, joins its Broadcast Isochronous Group and receives audio:
sequenceDiagram
participant APP as Application (broadcast sink)
participant AUD as ESP-BLE-AUDIO
participant ISO as ESP-BLE-ISO
participant CTRL as Controller
APP->>ISO: scan and synchronize to periodic advertising
CTRL->>ISO: BIGInfo report
AUD->>ISO: BIG sync (with broadcast code if encrypted)
ISO->>CTRL: LE BIG Create Sync
CTRL->>ISO: BIG Sync Established event
AUD->>ISO: set up the ISO data path (output)
CTRL->>ISO: ISO SDUs
ISO->>APP: recv callback on the ISO task
Note over APP,CTRL: subsequent ISO SDUs repeat the receive / recv-callback cycle
The application drives the high level -- periodic-advertising synchronization (through GAP) and the broadcast-sink start -- while the ESP-BLE-AUDIO broadcast-sink profile performs the BIG sync and the data path. Both rest on ESP-BLE-ISO: its scanning layer for PA sync and the BIGInfo report, its ISO subsystem for the BIG sync and data path. If the group is encrypted and the broadcast code is wrong, the controller still synchronizes but the stream fails its message-integrity check shortly afterward, so an application should treat an early post-sync failure as a likely bad code.
Public API
The application drives the ESP-IDF Bluetooth LE Audio implementation through the esp_ble_audio_* API. It has two surfaces: one common header, api/include/esp_ble_audio_common_api.h, for bring-up and the cross-cutting entry points, and one <profile>_api.h header per profile and service for the role-specific operations -- the bulk of the API, cataloged in Clients and Controllers.
Shape and Conventions
The common API sits on the ESP-BLE-ISO transport and the prebuilt profile library, and follows the same conventions as the transport's public API:
Two-call bring-up.
esp_ble_audio_common_inittakes anesp_ble_audio_init_info_t-- a GAP callback and a GATT callback, the single application sinks of Application Event Interface.esp_ble_audio_common_starttakes anesp_ble_audio_start_info_tcarrying the coordinated-set (CSIS) service instances to start. What the two calls do internally is the subject of Initialization Flow: a handshake with the prebuilt library -- the shared-structure ABI (Application Binary Interface) check and the Kconfig configuration push -- followed by the per-service registration.Opaque, transport-aliased types. The event types an application handles --
esp_ble_audio_gap_app_event_tandesp_ble_audio_gatt_app_event_t-- are typedefs of the transport'sbt_le_gap_app_event/bt_le_gatt_app_event, and theESP_BLE_AUDIO_GAP_EVENT_*/ESP_BLE_AUDIO_GATT_EVENT_*codes alias the transport's, so the audio and ISO layers present one event model.Error codes. Every function returns
esp_err_t.Per-role registration. A profile role follows the uniform shape from Clients and Controllers: enable the role's Kconfig option, register its callback structure through the role's
<profile>_api.h, and drive it through that header's functions. Registering a role is also what adds its GATT service to the table (see deferred registration).
Functional Groups
Group |
Representative functions |
Purpose |
|---|---|---|
Initialization |
|
Register the GAP and GATT callbacks and bring up the prebuilt library, GAP and GATT. |
Start |
|
Register the coordinated-set services (CSIS, CAS) from |
GATT discovery |
|
Start GATT discovery of a peer's services on a connection. |
Event forwarding |
|
Forward host GAP and GATT events into the engine (NimBLE only -- see below). |
LTV helpers |
|
Parse the length-type-value metadata Bluetooth LE Audio uses throughout. |
Per-profile roles |
the |
Take and drive a profile role -- the bulk of the API (see Clients and Controllers). |
Per-Host Integration Differences
As with ESP-BLE-ISO, the only host-divergent entry points are the event-forwarding functions, and they exist for the same reason -- letting the engine see the GAP and GATT events for a connection the application drives:
esp_ble_audio_gap_app_post_eventandesp_ble_audio_gatt_app_post_eventare needed only on NimBLE: the host delivers GAP and GATT events to the callbacks the application registered, and the application forwards them inward with these. On Bluedroid the adapter installs its own BTA/BTM callbacks and captures the events directly, so no forwarding is required --esp_ble_audio_gatt_app_post_eventis even hidden from Bluedroid builds, so calling it there is a compile-time error.