Part 1 of 3 | Introduction, Roles & Architecture | HAP v1.0.1
What is the Bluetooth Hearing Access Profile (HAP)?
The Hearing Access Profile (HAP) is a Bluetooth SIG specification that defines a standardised way for hearing aids and companion devices to communicate over Bluetooth Low Energy. Version 1.0.1 was adopted in October 2024.
Before HAP, hearing aid manufacturers each used proprietary Bluetooth protocols. A Samsung phone paired fine with Brand A hearing aids but refused to work properly with Brand B. HAP solves this fragmentation by specifying exactly which roles, services, characteristics, and procedures every device in the hearing aid ecosystem must support.
HAP is built on the LE Audio framework — the new generation of BLE audio that uses Isochronous Channels (ISO) for guaranteed low-latency, high-quality audio. This is completely different from classic Bluetooth A2DP. LE Audio was designed from scratch for accessibility devices that require deterministic latency and synchronised left/right binaural audio.
HAP works as a thin orchestration layer. It delegates audio streaming to BAP, volume control to VCP, microphone control to MICP, binaural set coordination to CSIP, call control to CCP, and preset management to its own Hearing Access Service (HAS). HAP specifies who talks to whom and which rules must be followed.
Critical constraint: HAP operates over BLE transport only — no BR/EDR. Bluetooth Core 5.2 or later is required for the HA, HAUC, and HARC roles (because BT 5.2 introduced LE Isochronous Channels). The IAC role (simple alert devices) only needs BT 4.2+.
Key Terms You Will Learn in This Series
The Four HAP Profile Roles Explained
HAP defines four roles. A single physical device can implement multiple roles simultaneously — for example, a smartphone typically acts as HAUC + HARC + IAC all at once.
The HA role runs on the hearing aid hardware itself. It is the peripheral / GATT server side of all interactions. Every conforming hearing aid must implement: the HAS GATT Server, BAP Unicast Server (as Audio Sink), BAP Broadcast Sink, and VCP Volume Renderer. If the hearing aid can also transmit audio back to the phone (e.g., for a hands-free phone call), it additionally needs the MICP Microphone Device role.
Three physical forms of hearing aid are all covered under the single HA role:
Required core spec: Bluetooth 5.2+ | Transport: BLE LE only | PHY: LE 2M PHY mandatory
The HAUC is the audio source device — it streams audio to the hearing aid over BLE CIS (Connected Isochronous Streams). Common HAUC devices are smartphones, tablets, laptops, personal microphones, and voice-recognition gateways. The HAUC is the central / GATT client side — it initiates connections and manages audio stream setup using BAP Unicast Client procedures.
The HAUC must be able to establish two separate unicast audio streams simultaneously — one for the Front Left audio location and one for Front Right — to feed both ears in a binaural hearing aid set.
The HARC controls the hearing aid without necessarily streaming audio. Its primary functions are adjusting volume, muting/unmuting the microphone, and switching the active preset — for example, switching between “Quiet room,” “Noisy restaurant,” and “Music” hearing profiles. The HARC reads and writes GATT characteristics in the Hearing Access Service on the hearing aid.
If HARC is the only HAP role on a device, it does not need to support LE Isochronous Channels. This means a simple, low-cost remote control dongle can implement HARC with minimal hardware. On smartphones, HARC and HAUC roles typically coexist.
The IAC role is for non-audio devices that simply need to grab the hearing aid wearer’s attention. A smart doorbell, smoke detector, baby monitor, or kitchen appliance can implement IAC. It connects to the hearing aid and writes a “Mild Alert” or “High Alert” value to the Alert Level characteristic in the Immediate Alert Service (IAS). The hearing aid responds by playing an audio alert tone through its speaker.
IAC devices only need Bluetooth Core 4.2+ — making this compatible with very simple, cheap IoT hardware that does not support LE Audio at all.
HAP Ecosystem Architecture — Who Talks to Whom
The diagram below shows all four HAP roles and their connections to the hearing aid. The HA sits at the centre as the server. CIS streams carry actual audio; GATT operations carry control data; IAS carries alert signals.
|
CIS Audio (LE ISO)
⇄
GATT R/W
⇄
IAS Alert Write
→
|
Hearing Aid (HA)
✓ HAS GATT Server (preset management)
✓ BAP Unicast Server — Audio Sink (M)
✓ BAP Broadcast Sink (M)
✓ VCP Volume Renderer (M)
✓ CSIP Set Member (if binaural)
✓ IAS Server (alert tones)
○ MICP Device (if audio source)
○ BAS (if has battery)
LE 2M PHY mandatory | BT Core 5.2+
|
Binaural Hearing Aid Set — How Two Aids Work Together
When a user wears two hearing aids, they form a Binaural Hearing Aid Set. HAP handles this using CSIP (Coordinated Set Identification Profile). Both aids share a common SIRK (Set Identity Resolving Key), allowing the HAUC and HARC to discover and recognise them as a matched set. The HAUC then sends separate Left and Right audio channels as two independent CISes — one per aid.
Left vs right is distinguished by the Sink Audio Locations characteristic: the left aid has the Front Left bit set to 1, the right aid has Front Right bit set to 1. A Banded Hearing Aid (single device, both outputs) sets both bits to 1.
| Smartphone (HAUC) CSIP Set Coordinator BAP Unicast Client
Step 1: Scan & find SIRK Step 2: Connect both aids Step 3: Open CIS Left + Right |
CIS L
CIS R
|
|
HAP Profile Dependency Stack — Full Hierarchy
HAP is a thin orchestrator. It does not reinvent audio streaming, volume control, or microphone management — it relies on this stack of sub-profiles:
| HAP — Hearing Access Profile (Top Level Orchestrator) | |||
| ▼ requires ▼ | |||
| CAP — Common Audio Profile (governs connection setup & coordination) | |||
| ▼ CAP requires these ▼ | |||
| BAP Basic Audio Profile (CIS/BIS streaming) |
VCP Volume Control Profile (VCS + AICS + VOCS) |
MICP Microphone Control (MICS mute) |
CSIP Coordinated Set ID (binaural pairing) |
| CCP Call Control Profile (phone calls) |
HAS Hearing Access Service (preset management) |
IAS Immediate Alert Svc (attention alert) |
BAS Battery Service (battery level) |
| ▼ foundation ▼ | |||
| GATT | BLE Isochronous Channels (CIS + BIS) | LC3 Codec | Bluetooth Core Spec 5.2 | |||
HAP Role Conformance Matrix — Quick Reference
This table shows what is mandatory (M), optional (O), conditional (C), excluded (X), or unchanged (—) per HAP role. Study this before building any HAP implementation.
| LE Audio Profile Role | HA | HAUC | HARC |
|---|---|---|---|
| BAP Unicast Client | — | M | — |
| BAP Unicast Server | M | — | — |
| BAP Broadcast Sink | M | — | — |
| VCP Volume Controller | — | — | M |
| VCP Volume Renderer | M | — | — |
| MICP Microphone Controller | — | — | O |
| MICP Microphone Device | C.2 | — | — |
| CSIP Set Coordinator | — | M | M |
| CSIP Set Member | C.1 | — | — |
| HAS Client (GATT Client) | X | X | M |
| HAS Server (GATT Server) | M | X | X |
M=Mandatory | O=Optional | X=Excluded | —=No HAP change beyond CAP | C.1=Mandatory if HA is part of Binaural Set | C.2=Mandatory if HA supports BAP Audio Source role
BlueZ Prerequisites — Setting Up for HAP / LE Audio Development
HAP requires Bluetooth Core 5.2+ hardware and BlueZ 5.65 or later. Older BlueZ lacks the ISO socket API needed for CIS and BIS streams. Use the steps below to verify your Linux development machine.
Step 1 — Verify BlueZ Version
# Check installed BlueZ version (need 5.65+ for LE Audio)
bluetoothctl version
# Expected output: Version 5.65 or higher
bluetoothd --version
# Check via package manager on Debian/Ubuntu
dpkg -l bluez | grep bluez
# For latest LE Audio support, build from BlueZ source
# git clone https://git.kernel.org/pub/scm/bluetooth/bluez.git
Step 2 — Verify BT 5.2 Hardware Support
# List Bluetooth adapters
bluetoothctl list
# Show adapter details — look for LE features in output
bluetoothctl show
# Check HCI features at the kernel level
hciconfig hci0 features
# Query LE features via btmgmt (look for "LE ISO Channels" support)
btmgmt info
# Check kernel ISO socket support (needed for CIS/BIS)
cat /boot/config-$(uname -r) | grep -i "BT_LE_L2CAP_ECRED\|BT_HS"
Step 3 — Enable Adapter and Experimental LE Audio Features
# Start and enable bluetoothd service
sudo systemctl start bluetooth
sudo systemctl enable bluetooth
# Power on the adapter
bluetoothctl power on
# Confirm adapter is powered
bluetoothctl show | grep -E "Powered|Pairable|Discoverable"
# Enable experimental features (required for some LE Audio APIs)
# Add to /etc/bluetooth/main.conf under [General]:
sudo tee -a /etc/bluetooth/main.conf << EOF
[General]
Experimental = true
EOF
# Restart to apply
sudo systemctl restart bluetooth
Step 4 — Python D-Bus Setup for BlueZ GATT Scripting
# Install Python D-Bus bindings for BlueZ GATT API
sudo apt-get install -y python3-dbus python3-gi libdbus-1-dev
# Verify BlueZ is reachable over D-Bus
python3 <<EOF
import dbus
bus = dbus.SystemBus()
obj = bus.get_object('org.bluez', '/')
print("BlueZ D-Bus OK:", obj is not None)
EOF
# List all managed BlueZ objects (adapters + bonded devices)
python3 <<EOF
import dbus
bus = dbus.SystemBus()
mgr = dbus.Interface(
bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager'
)
objs = mgr.GetManagedObjects()
for path, ifaces in objs.items():
if 'org.bluez.Adapter1' in ifaces:
p = ifaces['org.bluez.Adapter1']
print(f"Adapter: {path} ({p.get('Address', '-')})")
if 'org.bluez.Device1' in ifaces:
p = ifaces['org.bluez.Device1']
print(f"Device: {path} ({p.get('Alias', '-')}) paired={p.get('Paired')}")
EOF
Step 5 — Scan for HAP Devices Using the HAS Service UUID
# Hearing Access Service UUID (Bluetooth Assigned Numbers)
# HAS short UUID: 0x1854
# HAS full UUID: 00001854-0000-1000-8000-00805f9b34fb
#
# Key HAS Characteristics:
# Hearing Aid Features: 0x2BDA
# Hearing Aid Preset Control Pt: 0x2BDB
# Active Preset Index: 0x2BDC
# Scan for BLE devices advertising HAS UUID (Python + D-Bus)
python3 <<EOF
import dbus, dbus.mainloop.glib, time
from gi.repository import GLib
HAS_UUID = "00001854-0000-1000-8000-00805f9b34fb"
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
adapter_props = dbus.Interface(
bus.get_object('org.bluez', '/org/bluez/hci0'),
'org.freedesktop.DBus.Properties'
)
adapter = dbus.Interface(
bus.get_object('org.bluez', '/org/bluez/hci0'),
'org.bluez.Adapter1'
)
# Filter: only discover devices advertising HAS UUID
adapter.SetDiscoveryFilter({
'UUIDs': dbus.Array([HAS_UUID], signature='s'),
'Transport': 'le'
})
adapter.StartDiscovery()
print("Scanning 10s for HAP / Hearing Aid devices...")
time.sleep(10)
adapter.StopDiscovery()
# Report found devices
mgr = dbus.Interface(
bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager'
)
found = False
for path, ifaces in mgr.GetManagedObjects().items():
if 'org.bluez.Device1' in ifaces:
p = ifaces['org.bluez.Device1']
uuids = list(p.get('UUIDs', []))
if HAS_UUID in uuids:
print(f" Found HA: {p.get('Alias','?')} {p.get('Address','?')} RSSI={p.get('RSSI','?')}")
found = True
if not found:
print(" No HAP devices found.")
EOF
Part 1 Summary
Next: Part 2 — HA Role Deep Dive
Part 2 covers the Hearing Aid (HA) role in full detail: LE 2M PHY, CIS/BIS transport parameters (ISOAL), HAS GATT server setup with characteristics, advertising rules, Volume Control Service with AICS/VOCS, MICP Device, and complete BlueZ Python code for a hearing aid GATT server.
Read Part 2: HA Role & GATT Server → Read Part 3: HAUC, HARC & Security →
