BLE audio course – BLE ISO Channels Generic Audio Framework

BLE audio course – BLE ISO Channels Generic Audio Framework
A complete breakdown of the layered stack — ISO Channels, the Generic Audio Framework, LC3, and how BlueZ implements it on Linux
Core 5.2
ISO Channels added
23+
New specs in GAF
LC3
Mandatory codec
BlueZ 5.66+
Linux BLE Audio support

What Is Bluetooth LE Audio?

Hello students welcome to BLE audio course – BLE ISO Channels Generic Audio Framework, If you have worked with Bluetooth audio before — A2DP, HFP, HSP — those profiles run on Bluetooth Classic (BR/EDR). Bluetooth LE Audio is a completely different architecture, built ground-up on Bluetooth Low Energy. It is not a firmware patch to A2DP. It is a brand new audio stack.

The Bluetooth SIG evaluated whether existing Classic Audio profiles could be extended to meet new market requirements — hearing aids needing <40ms latency, multi-user broadcast, left/right earbud synchronisation within 25µs. The conclusion was that extending A2DP/HFP would require too many compromises. A clean-sheet design was started on top of BLE Core 4.1.

This post covers the full layered architecture — what was added to the Bluetooth Core, what the Generic Audio Framework (GAF) is, where LC3 fits in, and how BlueZ exposes all of this on Linux.

Classic Audio vs LE Audio — Key Differences

Feature Classic Audio (A2DP / HFP) Bluetooth LE Audio
Radio Layer Bluetooth Classic (BR/EDR) Bluetooth Low Energy (LE)
Audio Transport SCO / eSCO channels ISO Channels (CIS / BIS)
Mandatory Codec SBC LC3
Broadcast Audio Not supported Native (BIS / BIG)
Multi-device Sync Limited, profile-specific Built-in (CSIP / CAP)
Control Plane Embedded inside A2DP / HFP Separate from audio data path

The Layered Architecture

Like every Bluetooth specification, BLE Audio follows a layered model. The fundamental split is between the Controller (chipset + firmware, handles radio and Link Layer) and the Host (software stack, handles profiles and application logic). The HCI is the boundary between them. Both are often on a single chip today, but the split still exists logically.

Bluetooth LE Audio — Complete Stack

TOP LEVEL PROFILES (Host)
HAP / HAS TMAP PBP
Hearing Aids | Telephony & Media | Public Broadcast

GENERIC AUDIO FRAMEWORK (GAF) — Host Audio Middleware
BAP PACS ASCS BASS VCP VCS VOCS AICS MCP/MCS CCP/TBS CSIP/CSIS CAP/CAS MICP/MICS

HOST FUNCTIONALITY (existing BLE layers)
GATT ATT / EATT ★ L2CAP GAP ISOAL ★
★ = new additions for LE Audio

── HCI  (Host ↔ Controller boundary) ──

CONTROLLER — Core 5.1 and 5.2 additions
Isochronous Channels (5.2) Extended Advertising (5.1) Periodic Advertising (5.1) PAST (5.1) Enhanced AFH

LC3 Codec — Audio Data Path — can reside in Host or Controller (implementation choice)

Core Layer — What’s New

Isochronous Channels — The Heart of BLE Audio (Core 5.2)

Standard BLE uses ACL (Asynchronous Connection-oriented Logical) channels for data. ACL works on a request/response pattern — great for GATT reads and writes, but ACL gives no timing guarantee. If the radio is busy, data waits. For audio, that means glitches.

Core 5.2 introduced ISO (Isochronous) Channels. ISO channels deliver data on a fixed time schedule — every interval, a slot is reserved on the radio for that channel. Audio data either goes out in that slot or it is retransmitted in the next. This gives guaranteed delivery timing.

There are two types of ISO channel. Both can carry LC3-encoded audio:

CIS (Unicast) vs BIS (Broadcast)

CIS — Connected Isochronous Stream
Phone / Source
⇅ bidirectional
ACK / NACK supported
Earbud / Sink
• Point-to-point (unicast)
• Multiple CIS bundled in a CIG
• Left + Right earbuds = 2 CIS inside 1 CIG
• Retransmission via ACK/NACK
• ACL link always present alongside CIS

BIS — Broadcast Isochronous Stream
TV / Broadcast Source
↓ one-to-many
No ACK — source retransmits unconditionally
Hearing Aid L
Hearing Aid R
Earbud
• One source, unlimited receivers
• Multiple BIS bundled in a BIG
• No connection needed to receive audio
• Encryption supported (broadcast code)
• Stereo = 2 BIS (left + right) inside 1 BIG
CIS = unicast stream BIS = broadcast stream CIG = group of CIS BIG = group of BIS ISO PDU interval = 7.5ms or 10ms

Extended Advertising, Periodic Advertising, and PAST (Core 5.1)

A standard BLE advertisement carries about 31 bytes. A broadcast audio stream needs to advertise its codec, timing, channel assignments, and hopping sequence — far more than 31 bytes. Core 5.1 solved this with three related features:

Feature What It Does Why It Matters
Extended Advertising (EA) Uses general data channels for large advertising payloads Broadcast source can advertise all ISO stream parameters
Periodic Advertising (PA) Receiver synchronises to a periodic packet train without connecting Hearing aid can lock onto a TV broadcast without a BLE connection
PAST Connected device hands off PA sync info to another device over ACL Phone finds broadcast, tells hearing aid where to sync — hearing aid saves scan power
Practical example: In a cinema, the screen broadcasts audio as a BIG. Your phone scans, finds the PA train, and uses PAST to tell your hearing aids exactly where to synchronise. The hearing aids skip scanning entirely, preserving battery life.

EATT and ISOAL (Core 5.2)

Two Core 5.2 additions that are less visible but technically critical:

EATT — Enhanced Attribute Protocol

Standard ATT is a blocking protocol. If a GATT client sends a Read Request, it must wait for the response before sending another request. This is fine for simple sensors, but BLE Audio devices run many profiles at once — volume control, media control, telephony, stream management, coordination. All of them talk via ATT.

EATT allows multiple ATT instances to run concurrently over L2CAP Enhanced Credit-Based connections. Each profile can have its own ATT bearer, so they do not block each other.

ISOAL — Isochronous Adaptation Layer

LC3 encodes audio in 10ms frames (7.5ms also supported). But some LE connections — particularly those also talking to older BLE devices — operate at a 7.5ms interval. These two timings do not divide evenly.

ISOAL sits between the Host and the Link Layer. It segments SDUs (Service Data Units — 10ms LC3 frames) into PDUs (Protocol Data Units — Link Layer packets) of a different size, and reassembles them at the receiver. It handles the mismatch transparently.

The Generic Audio Framework (GAF)

The GAF is the audio middleware that lives inside the Host, above GATT. Every profile and service in the GAF uses the standard BLE GATT model: a Service holds state (implemented on the device where the state lives), and a Profile defines how to read, write, and be notified of that state (implemented on the device that controls it).

The 23 GAF specifications fall into four functional groups:

Group Specs Responsibility
Stream Control BAP, PACS, ASCS, BASS Set up and manage the ISO channels that carry audio
Rendering & Capture VCP, VCS, VOCS, AICS, MICP, MICS Volume control and microphone gain on the sink device
Content Control MCP, MCS, CCP, TBS Play/pause/seek for media; answer/hold/end for calls
Transition & Coordination CSIP, CSIS, CAP, CAS Synchronise control across a paired set of devices (L + R earbuds)
Minimum viable BLE Audio product: BAP + ASCS + PACS is enough for unicast streaming. BAP alone is enough for broadcast transmit. This matters because two BLE Audio devices with completely different top-level profiles can still exchange audio using just BAPS — removing the multi-profile incompatibility problem that exists in Bluetooth Classic.

LC3 — The Mandatory Codec

Why LC3 Instead of SBC?

A2DP mandates SBC (Sub-Band Coding). SBC was designed for reliable, high-bandwidth Bluetooth Classic links. For BLE Audio, the requirements were different: latency under 40ms (for hearing aid users mixing ambient and Bluetooth audio), low power draw on zinc-air batteries, and good quality at lower bitrates for BLE’s tighter link budget.

LC3 Property Value
Frame duration 10ms (default) or 7.5ms
Channel encoding Mono per instance. Stereo = 2 separate LC3 streams
Bitrate range 16 kbps (NB speech) to ~320 kbps (high-quality stereo)
Implementation location Host or Controller (implementer’s choice)
Mandatory for Every BLE Audio device — guarantees interoperability
LC3 on a hearing aid: The codec can run in the Controller (chipset), keeping the host processor asleep. This is important for zinc-air batteries, which degrade under sustained high-current draw. The battery constraints from hearing aid requirements actually shaped the packet structure of Isochronous Channels — maximum transmission time is bounded to avoid current spikes.

BLE Audio in BlueZ

Where BlueZ Sits in This Stack

BlueZ is the Host stack for Linux. It implements everything above the HCI — L2CAP, ATT/GATT, GAP, SMP, and all the GAF profiles. The chipset (Controller) communicates with BlueZ via HCI over USB, UART, or SDIO. For BLE Audio, the key pieces are:

  • bluetoothd — the main daemon. Implements GAF profiles and exposes them over D-Bus to applications.
  • btmon — HCI packet monitor. Shows all HCI commands and events including ISO data packets and LE Set CIG Parameters.
  • bluetoothctl — interactive CLI for scanning, connecting, and basic audio endpoint management.
  • Linux kernel — exposes ISO sockets (AF_BLUETOOTH / BTPROTO_ISO) from kernel 6.0 onwards. This is the data path for CIS and BIS.

Observe ISO channel setup with btmon:

# Run btmon before connecting the BLE Audio device
$ sudo btmon

# Controller assigns CIG parameters (unicast setup)
< HCI Command: LE Set CIG Parameters (0x08|0x0062) plen 15
        CIG ID: 0x00
        SDU interval C->P:   10000 us   (LC3 10ms frame)
        SDU interval P->C:   10000 us
        Max SDU C->P:        100        (bytes per frame)
        Max SDU P->C:        100
        RTN C->P:            2          (max retransmissions)
        Max transport latency C->P: 20 ms
        CIS count: 2                   (left + right = 2 CIS in 1 CIG)

# Once streaming, you will see ISO data
< HCI ISO Data: handle 0x0001 flags 0x02 dlen 104
        Time stamp: 12345678 us
        Packet sequence: 42
        Data length: 100 octets        (LC3 encoded audio)

Check BLE Audio endpoint via bluetoothctl:

# Scan and connect to a BLE Audio device
$ bluetoothctl
[bluetooth]# scan on
[NEW] Device AA:BB:CC:DD:EE:FF BLE Headset

[bluetooth]# connect AA:BB:CC:DD:EE:FF

# Show discovered media endpoints (BAP PACS)
[bluetooth]# menu media
[bluetooth]# list endpoints AA:BB:CC:DD:EE:FF

EndPoint /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF/pac_0
        UUID: 00001850-0000-1000-8000-00805f9b34fb  (BAP Sink)
        Codec: 0x06  (LC3)
        Capabilities: [sampling rates, frame durations, octets/frame]
Version requirements: Full BLE Audio on Linux requires kernel 6.0+ (ISO socket support) and BlueZ 5.66+. Ubuntu 22.04 ships kernel 5.15 and BlueZ 5.64 — both too old for full BLE Audio. On Ubuntu 22.04, you need a mainline kernel upgrade and a BlueZ build from source. Ubuntu 24.04 ships kernel 6.8 and BlueZ 5.72, which works correctly.

Summary

Layer Key Additions for BLE Audio BlueZ / Linux Equivalent
Controller (Core) ISO channels, Extended Advertising, PA, PAST Chipset firmware + kernel ISO socket (BTPROTO_ISO)
HCI LE Set CIG Params, LE Create CIS, ISO Data packets btmon for visibility, hciconfig/hcitool
Host (GATT/ATT) EATT (concurrent ATT), ISOAL (SDU/PDU mapping) bluetoothd core (L2CAP ECBM for EATT)
GAF Middleware BAP, PACS, ASCS, VCP, MCP, CCP, CSIP, CAP … bluetoothd profiles + D-Bus API (org.bluez.Media1)
Top Level Profiles HAP, TMAP, PBP (application-specific requirements) Your application code using BlueZ D-Bus API

Next Up: GAF Deep Dive

In the next post we go inside the Generic Audio Framework — how the ASCS state machine drives audio stream setup step by step, how BAP handles both unicast and broadcast modes, how volume and microphone control work, and how CSIP/CSIS keep your left and right earbuds in lock-step. this is all about BLE ISO Channels, the Generic Audio Framework

Leave a Reply

Your email address will not be published. Required fields are marked *