From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH BlueZ v2 8/9] doc/btmon: Add A2DP/AVDTP protocol flow documentation
Date: Tue, 24 Mar 2026 15:49:44 -0400 [thread overview]
Message-ID: <20260324194946.109349-8-luiz.dentz@gmail.com> (raw)
In-Reply-To: <20260324194946.109349-1-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Add btmon-a2dp.rst documenting the A2DP protocol flow as seen in btmon
output, wrapped by btmon-classic-audio.rst parent file. Coverage
includes:
- AVDTP signaling: Discover, Get Capabilities, Set Configuration,
Open, Start, Suspend, Close
- Codec capability/configuration decoding for SBC, AAC, aptX, aptX HD,
aptX Low Latency, FastStream, LDAC, and Opus
- AVDTP media transport channel setup
- AVRCP control and browsing channel overview
- Delay Reporting
- Automation-friendly grep patterns
---
doc/btmon-a2dp.rst | 418 ++++++++++++++++++++++++++++++++++++
doc/btmon-classic-audio.rst | 12 ++
doc/btmon.rst | 2 +
3 files changed, 432 insertions(+)
create mode 100644 doc/btmon-a2dp.rst
create mode 100644 doc/btmon-classic-audio.rst
diff --git a/doc/btmon-a2dp.rst b/doc/btmon-a2dp.rst
new file mode 100644
index 000000000000..516410e4e283
--- /dev/null
+++ b/doc/btmon-a2dp.rst
@@ -0,0 +1,418 @@
+.. This file is included by btmon-classic-audio.rst.
+
+A2DP: Advanced Audio Distribution
+-----------------------------------
+
+A2DP uses AVDTP (Audio/Video Distribution Transport Protocol) over
+L2CAP to negotiate codec parameters and stream high-quality audio.
+btmon fully decodes AVDTP signaling, codec capabilities, and AVRCP
+remote control messages.
+
+AVDTP Signaling Channel
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+A2DP begins with an L2CAP connection on PSM 25 (0x0019). The first
+L2CAP connection on this PSM carries AVDTP signaling; a second
+connection on the same PSM carries media transport data::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 12
+ L2CAP: Connection Request (0x02) ident 1 len 4
+ PSM: 25 (0x0019)
+ Source CID: 64
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 16
+ L2CAP: Connection Response (0x03) ident 1 len 8
+ Destination CID: 64
+ Source CID: 64
+ Result: Connection successful (0x0000)
+ Status: No further information available (0x0000)
+
+After L2CAP configuration completes, AVDTP signaling begins on this
+channel.
+
+Stream Endpoint Discovery
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The initiator discovers available Stream Endpoints (SEPs) on the
+remote device::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 6
+ Channel: 64 len 2 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Discover (0x01) Command (0x00) type 0x00 label 0 nosp 0
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 10
+ Channel: 64 len 6 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Discover (0x01) Response Accept (0x02) type 0x00 label 0 nosp 0
+ ACP SEID: 1
+ Media Type: Audio (0x00)
+ SEP Type: SNK (0x01)
+ In use: No
+
+Each SEP has a SEID (Stream Endpoint Identifier), media type, and
+role (Source or Sink). ``In use: Yes`` means the endpoint is already
+streaming.
+
+Codec Capability Discovery
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After discovering SEIDs, the initiator queries each endpoint's
+capabilities::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 7
+ Channel: 64 len 3 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Get All Capabilities (0x0c) Command (0x00) type 0x00 label 1 nosp 0
+ ACP SEID: 1
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 30
+ Channel: 64 len 26 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Get All Capabilities (0x0c) Response Accept (0x02) type 0x00 label 1 nosp 0
+ Service Category: Media Transport (0x01)
+ Service Category: Media Codec (0x07)
+ Media Type: Audio (0x00)
+ Media Codec: SBC (0x00)
+ Frequency: 0xf0
+ 16000
+ 32000
+ 44100
+ 48000
+ Channel Mode: 0x0f
+ Mono
+ Dual Channel
+ Stereo
+ Joint Stereo
+ Block Length: 0xf0
+ 4
+ 8
+ 12
+ 16
+ Subbands: 0x0c
+ 4
+ 8
+ Allocation Method: 0x03
+ SNR
+ Loudness
+ Minimum Bitpool: 2
+ Maximum Bitpool: 53
+ Service Category: Content Protection (0x04)
+ Content Protection Type: SCMS-T (0x0002)
+ Service Category: Delay Reporting (0x08)
+
+Capability responses list all supported values as bitmasks. Key
+service categories:
+
+- **Media Transport** (0x01) -- Always present, indicates the endpoint
+ supports a media transport channel
+- **Media Codec** (0x07) -- Codec type and supported parameters
+- **Content Protection** (0x04) -- Copy protection (SCMS-T or DTCP)
+- **Delay Reporting** (0x08) -- Endpoint supports delay reporting
+
+Supported Codecs
+~~~~~~~~~~~~~~~~~
+
+btmon decodes several A2DP codecs. Each has a different parameter
+format.
+
+**SBC** (mandatory A2DP codec)::
+
+ Media Codec: SBC (0x00)
+ Frequency: 44100 (0x20)
+ Channel Mode: Joint Stereo (0x01)
+ Block Length: 16 (0x10)
+ Subbands: 8 (0x04)
+ Allocation Method: Loudness (0x01)
+ Minimum Bitpool: 2
+ Maximum Bitpool: 53
+
+**AAC** (MPEG-2,4)::
+
+ Media Codec: MPEG-2,4 AAC (0x02)
+ Object Type: MPEG-4 AAC LC (0x40)
+ Frequency: 44100 (0x0100)
+ Channels: 2 (0x04)
+ Bitrate: 256000bps
+ VBR: No
+
+**aptX** (Qualcomm, vendor-specific)::
+
+ Media Codec: Non-A2DP (0xff)
+ Vendor ID: Qualcomm Technologies International, Ltd. (APT) (0x0000004f)
+ Vendor Specific Codec ID: aptX (0x0001)
+ Frequency: 44100 (0x20)
+ Channel Mode: Stereo (0x02)
+
+**aptX HD** (Qualcomm, vendor-specific)::
+
+ Media Codec: Non-A2DP (0xff)
+ Vendor ID: Qualcomm Technologies, Inc. (0x000000d7)
+ Vendor Specific Codec ID: aptX HD (0x0024)
+ Frequency: 44100 (0x20)
+ Channel Mode: Stereo (0x02)
+
+**LDAC** (Sony, vendor-specific)::
+
+ Media Codec: Non-A2DP (0xff)
+ Vendor ID: Sony Corporation (0x0000012d)
+ Vendor Specific Codec ID: LDAC (0x00aa)
+
+Vendor codecs appear as ``Non-A2DP (0xff)`` with decoded Vendor ID
+and Codec ID. Capability responses list all supported values as
+bitmasks; configuration responses show the single selected value.
+
+Stream Configuration
+~~~~~~~~~~~~~~~~~~~~~
+
+After selecting a codec and parameters, the initiator sends Set
+Configuration::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 20
+ Channel: 64 len 16 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Set Configuration (0x03) Command (0x00) type 0x00 label 2 nosp 0
+ ACP SEID: 1
+ INT SEID: 1
+ Service Category: Media Transport (0x01)
+ Service Category: Media Codec (0x07)
+ Media Type: Audio (0x00)
+ Media Codec: SBC (0x00)
+ Frequency: 44100 (0x20)
+ Channel Mode: Joint Stereo (0x01)
+ Block Length: 16 (0x10)
+ Subbands: 8 (0x04)
+ Allocation Method: Loudness (0x01)
+ Minimum Bitpool: 2
+ Maximum Bitpool: 53
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 6
+ Channel: 64 len 2 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Set Configuration (0x03) Response Accept (0x02) type 0x00 label 2 nosp 0
+
+Configuration responses show single selected values instead of
+bitmask lists. ``ACP SEID`` is the remote endpoint, ``INT SEID`` is
+the local endpoint.
+
+If configuration is rejected::
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 8
+ Channel: 64 len 4 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Set Configuration (0x03) Response Reject (0x03) type 0x00 label 2 nosp 0
+ Service Category: Media Codec (0x07)
+ Error code: Unsupported Configuration (0x29)
+
+Common AVDTP error codes:
+
+.. list-table::
+ :header-rows: 1
+ :widths: 10 30 60
+
+ * - Code
+ - Name
+ - Meaning
+ * - 0x01
+ - Bad Header Format
+ - Malformed AVDTP header
+ * - 0x11
+ - Bad ACP SEID
+ - Unknown endpoint ID
+ * - 0x12
+ - SEP In Use
+ - Endpoint already streaming
+ * - 0x13
+ - SEP Not In Use
+ - Endpoint not configured
+ * - 0x29
+ - Unsupported Configuration
+ - Requested parameters not supported
+ * - 0x31
+ - Bad State
+ - Command not valid in current state
+
+Open and Start
+~~~~~~~~~~~~~~~
+
+After configuration, the stream is opened and then started::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 7
+ Channel: 64 len 3 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Open (0x06) Command (0x00) type 0x00 label 3 nosp 0
+ ACP SEID: 1
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 6
+ Channel: 64 len 2 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Open (0x06) Response Accept (0x02) type 0x00 label 3 nosp 0
+
+After Open succeeds, a **second L2CAP connection** on PSM 25 is
+established for the media transport channel. Then Start begins
+streaming::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 7
+ Channel: 64 len 3 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Start (0x07) Command (0x00) type 0x00 label 4 nosp 0
+ ACP SEID: 1
+
+ > ACL Data RX: Handle 1 flags 0x02 dlen 6
+ Channel: 64 len 2 [PSM 25 mode Basic (0x00)] {chan 0}
+ AVDTP: Start (0x07) Response Accept (0x02) type 0x00 label 4 nosp 0
+
+Media Data
+~~~~~~~~~~~
+
+After Start, encoded audio flows on the media transport channel
+(second L2CAP connection on PSM 25). btmon does **not** decode media
+packet contents by default -- media data is suppressed. Only the
+L2CAP channel header is visible when the ``--show-a2dp-stream``
+filter is enabled, with the payload shown as a raw hex dump.
+
+The AVDTP state machine visible in the trace:
+
+.. list-table::
+ :header-rows: 1
+ :widths: 20 30 50
+
+ * - State
+ - Triggered By
+ - Description
+ * - Idle
+ - Initial / Abort response
+ - No stream configured
+ * - Configured
+ - Set Configuration accept
+ - Codec and parameters selected
+ * - Open
+ - Open accept / Suspend accept
+ - Transport channel ready, not streaming
+ * - Streaming
+ - Start accept
+ - Audio data flowing
+ * - Closing
+ - Close command sent
+ - Tearing down stream
+ * - Aborting
+ - Abort command sent
+ - Forced teardown
+
+Suspend, Close, and Abort
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Suspend** pauses streaming without tearing down the transport::
+
+ AVDTP: Suspend (0x09) Command (0x00) type 0x00 label 5 nosp 0
+ ACP SEID: 1
+ AVDTP: Suspend (0x09) Response Accept (0x02) type 0x00 label 5 nosp 0
+
+**Close** tears down the stream (returns to Idle)::
+
+ AVDTP: Close (0x08) Command (0x00) type 0x00 label 6 nosp 0
+ ACP SEID: 1
+ AVDTP: Close (0x08) Response Accept (0x02) type 0x00 label 6 nosp 0
+
+**Abort** forces immediate teardown::
+
+ AVDTP: Abort (0x0a) Command (0x00) type 0x00 label 7 nosp 0
+ ACP SEID: 1
+ AVDTP: Abort (0x0a) Response Accept (0x02) type 0x00 label 7 nosp 0
+
+Delay Reporting
+~~~~~~~~~~~~~~~~
+
+When the sink supports delay reporting, it sends a Delay Report to
+inform the source of its rendering delay::
+
+ AVDTP: Delay Report (0x0d) Command (0x00) type 0x00 label 8 nosp 0
+ ACP SEID: 1
+ Delay: 15.0ms
+ AVDTP: Delay Report (0x0d) Response Accept (0x02) type 0x00 label 8 nosp 0
+
+AVRCP Remote Control
+~~~~~~~~~~~~~~~~~~~~~
+
+AVRCP (Audio/Video Remote Control Profile) uses L2CAP PSM 23
+(control) and PSM 27 (browsing). btmon decodes AVCTP framing and
+AVRCP PDUs.
+
+**Volume control**::
+
+ < ACL Data TX: Handle 1 flags 0x00 dlen 17
+ Channel: 66 len 13 [PSM 23 mode Basic (0x00)] {chan 2}
+ AVCTP Control: Response: type 0x00 label 0 PID 0x110e
+ AV/C: Accepted: address 0x48 opcode 0x00
+ Subunit: Panel
+ Opcode: Vendor Dependent
+ Company ID: 0x001958
+ AVRCP: SetAbsoluteVolume pt Single len 0x0001
+ Volume: 50.39% (64/127)
+
+**Playback status**::
+
+ AVRCP: GetPlayStatus pt Single len 0x0009
+ SongLength: 0x00038270 (230000 milliseconds)
+ SongPosition: 0x00000000 (0 milliseconds)
+ PlayStatus: 0x01 (PLAYING)
+
+**Track metadata** (GetElementAttributes response)::
+
+ AVRCP: GetElementAttributes pt Single len 0x0050
+ AttributeCount: 0x02
+ Attribute: 0x00000001 (Title)
+ CharsetID: 0x006a (UTF-8)
+ AttributeValueLength: 0x000c
+ AttributeValue: My Song Name
+ Attribute: 0x00000002 (Artist)
+ CharsetID: 0x006a (UTF-8)
+ AttributeValueLength: 0x000b
+ AttributeValue: The Artist
+
+**Passthrough commands** (play, pause, skip)::
+
+ AVCTP Control: Command: type 0x00 label 1 PID 0x110e
+ AV/C: Control: address 0x48 opcode 0x7c
+ Subunit: Panel
+ Opcode: Passthrough
+ Operation: 0x44 (PLAY Pressed)
+ Length: 0x00
+
+**Event notifications** (volume change, track change)::
+
+ AVRCP: RegisterNotification pt Single len 0x0005
+ EventID: 0x0d (EVENT_VOLUME_CHANGED)
+ Volume: 50.39% (64/127)
+
+Automating A2DP Analysis
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Identify A2DP activity**::
+
+ grep -n "AVDTP:\|Media Codec:" output.txt
+
+**Track AVDTP state transitions**::
+
+ grep -n "AVDTP:.*Command\|AVDTP:.*Response" output.txt
+
+**Check codec negotiation** (what was selected)::
+
+ grep -n "Set Configuration\|Media Codec:" output.txt
+
+**Verify stream is flowing** -- look for Start accept followed by
+media data::
+
+ grep -n "AVDTP: Start\|PSM 25.*chan 1" output.txt
+
+**Detect codec mismatch** -- look for Set Configuration reject::
+
+ grep -n "Response Reject\|Error code:" output.txt
+
+**Track AVRCP volume and playback**::
+
+ grep -n "SetAbsoluteVolume\|Volume:\|GetPlayStatus\|PlayStatus:" output.txt
+
+**Full A2DP diagnosis pattern**:
+
+1. Find L2CAP Connection Request for PSM 25 -- confirms AVDTP channel
+ setup
+2. Find Discover response -- shows available endpoints and whether any
+ are already in use
+3. Find Get All Capabilities response -- verify codec support overlap
+4. Find Set Configuration -- verify agreed codec and parameters
+5. Find Open and Start -- confirm stream setup succeeded
+6. Find second L2CAP connection on PSM 25 -- media transport channel
+7. On failure, check for Response Reject with error code
+8. If audio cuts out, look for Suspend or Close, or check for ACL
+ disconnection
diff --git a/doc/btmon-classic-audio.rst b/doc/btmon-classic-audio.rst
new file mode 100644
index 000000000000..11943c3a54bf
--- /dev/null
+++ b/doc/btmon-classic-audio.rst
@@ -0,0 +1,12 @@
+.. This file is included by btmon.rst.
+
+CLASSIC AUDIO PROTOCOL FLOW
+=============================
+
+Classic Bluetooth audio uses two main profiles: A2DP for high-quality
+stereo streaming and HFP for voice calls. Both run over BR/EDR ACL
+connections and use different transport mechanisms for audio data --
+A2DP uses L2CAP-based AVDTP media channels while HFP uses SCO/eSCO
+synchronous connections.
+
+.. include:: btmon-a2dp.rst
diff --git a/doc/btmon.rst b/doc/btmon.rst
index 6ecadf3f260d..8a02edce8e6a 100644
--- a/doc/btmon.rst
+++ b/doc/btmon.rst
@@ -767,6 +767,8 @@ PROTOCOL FLOWS
.. include:: btmon-le-audio.rst
+.. include:: btmon-classic-audio.rst
+
.. include:: btmon-advertising.rst
EXAMPLES
--
2.53.0
next prev parent reply other threads:[~2026-03-24 19:50 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-24 19:49 [PATCH BlueZ v2 1/9] doc/btmon: Split Advertising and Scanning into btmon-advertising.rst Luiz Augusto von Dentz
2026-03-24 19:49 ` [PATCH BlueZ v2 2/9] doc/btmon: Split LE Audio Protocol Flow into btmon-le-audio.rst Luiz Augusto von Dentz
2026-03-24 19:49 ` [PATCH BlueZ v2 3/9] doc/btmon: Split L2CAP Channel Tracking into btmon-l2cap.rst Luiz Augusto von Dentz
2026-03-24 19:49 ` [PATCH BlueZ v2 4/9] doc/btmon: Split SMP Pairing Flow into btmon-smp.rst Luiz Augusto von Dentz
2026-03-24 19:49 ` [PATCH BlueZ v2 5/9] doc/btmon: Split GATT Database Reconstruction into btmon-gatt.rst Luiz Augusto von Dentz
2026-03-24 19:49 ` [PATCH BlueZ v2 6/9] doc/btmon: Split Connection Tracking into btmon-connections.rst Luiz Augusto von Dentz
2026-03-24 19:49 ` [PATCH BlueZ v2 7/9] doc/btmon: Add HCI initialization sequence documentation Luiz Augusto von Dentz
2026-03-24 19:49 ` Luiz Augusto von Dentz [this message]
2026-03-24 19:49 ` [PATCH BlueZ v2 9/9] doc/btmon: Add HFP protocol flow documentation Luiz Augusto von Dentz
2026-03-26 11:28 ` Frédéric Danis
2026-03-24 20:44 ` [BlueZ,v2,1/9] doc/btmon: Split Advertising and Scanning into btmon-advertising.rst bluez.test.bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260324194946.109349-8-luiz.dentz@gmail.com \
--to=luiz.dentz@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox