Overview
Hello students welcome to embeddedpathashalas free course on bluetooth development in bluez, in this article i will teach you why L2CAP is needed in bluetooth This section covers the remaining L2CAP features — error retransmission policy via flush timeouts, streaming channels for real-time audio, Quality of Service for isochronous data, and L2CAP Signaling that orchestrates channel setup and teardown. It then introduces the Service Discovery Protocol (SDP) that lets Bluetooth devices dynamically advertise and find services on each other.
Key Concepts
4.2.3.4 Error Control – Flush Timeout Options
L2CAP uses a Transmit/Acknowledge mechanism. Every transmitted packet must be acknowledged by the remote device. If no acknowledgement arrives, L2CAP decides whether to retransmit or drop the packet based on the Flush Timeout setting for that channel. There are three possible behaviours:
No Retransmissions
The baseband performs zero retransmissions. Packets that fail are discarded immediately. Suitable for very latency-sensitive streams.
Timed Retransmissions
A specified flush timeout is set. Retransmissions continue until that timeout expires, then the packet is flushed. Balances reliability and latency.
Infinite Retransmissions
The baseband retransmits indefinitely until the physical link itself is lost. Used for critical data transfers where delivery must be guaranteed.
4.2.3.5 Streaming Channels
Streaming channels are designed for continuous real-time data such as audio, where a fixed data rate must be maintained. The channel is configured with a target data rate, and a flush timeout ensures that stale packets are dropped rather than causing a backlog that would disrupt playback.
PKT 1
✔ delivered
PKT 2
✘ flushed
PKT 3
✔ delivered
PKT 1
✔ delivered
PKT 2
↩ retry
PKT 2
✔ delivered
PKT 3
✔ delivered
4.2.3.6 Quality of Service (QoS)
L2CAP supports both isochronous (guaranteed bandwidth) and asynchronous (best-effort) data flows over the same ACL logical link simultaneously. The distinction is made via the Packet_Boundary_Flag in HCI ACL data packets.
- Time-bound data — expires if delayed
- Marked as auto-flushable in HCI flag
- Controller auto-flushes if not sent within flush timeout window
- Guaranteed bandwidth allocation
- No strict timing requirement
- Marked as non-flushable in HCI flag
- Packets queued until successfully transmitted
- Best-effort delivery
4.3.3 L2CAP Signaling
Signaling commands are exchanged between peer L2CAP entities to set up, configure, and tear down channels. Fixed signaling channels are available immediately after the ACL-U logical link is established — no separate connection setup is needed for them.
Signaling commands are wrapped in C-Frames (Control Frames). The Code field identifies the command type and the Identifier field matches each response back to its originating request.
Figure 4.3 – C-Frame Structure (L2CAP Signaling PDU)
Outer L2CAP Length
Channel ID (fixed)
Command Code
Identifier (match req↔rsp)
Command Data Length
Payload Data
Figure 4.4 – L2CAP Signaling Flow when RFCOMM uses L2CAP
PSM=RFCOMM, SrcCID=0x0040
DstCID assigned
MTU, Flush Timeout, QoS
Slave’s own params
on Signaling CID 0x0001
All signaling on CID 0x0001 · RFCOMM data on CID 0x0040 · Configure exchanged in both directions independently
Table 4.3 – L2CAP Signaling Packets
| Code | Command | Purpose | Applies To |
|---|---|---|---|
0x00 |
Reserved | — | — |
0x01 |
Command Reject | Sent when an unknown command is received or responding is not appropriate | BR/EDR & LE |
0x02 |
Connection Request | Initiates creation of an L2CAP channel between two devices | BR/EDR |
0x03 |
Connection Response | Reply to a Connection Request | BR/EDR |
0x04 |
Configure Request | Negotiates channel parameters: MTU, Flush Timeout, QoS, etc. | BR/EDR |
0x05 |
Configure Response | Reply to a Configure Request | BR/EDR |
0x06 |
Disconnection Request | Terminates an established L2CAP channel | BR/EDR |
0x07 |
Disconnection Response | Reply to a Disconnection Request | BR/EDR |
0x08 |
Echo Request | Requests a response from the remote L2CAP entity; used to check link status | BR/EDR |
0x09 |
Echo Response | Reply to an Echo Request | BR/EDR |
0x0A |
Information Request | Requests implementation-specific info from the remote L2CAP entity | BR/EDR |
0x0B |
Information Response | Reply to an Information Request | BR/EDR |
0x0C |
Create Channel Request | Creates an L2CAP channel over a specific controller (BT 3.0 + HS) | BR/EDR (AMP) |
0x0D |
Create Channel Response | Reply to a Create Channel Request | BR/EDR (AMP) |
0x0E |
Move Channel Request | Moves an existing channel from one controller to another (BT 3.0 + HS) | BR/EDR (AMP) |
0x0F |
Move Channel Response | Reply to a Move Channel Request | BR/EDR (AMP) |
0x10 |
Move Channel Confirmation | Confirms the channel move | BR/EDR (AMP) |
0x11 |
Move Channel Confirmation Response | Reply to Move Channel Confirmation | BR/EDR (AMP) |
0x12 |
Connection Parameter Update Request | LE Slave requests updated connection parameters from LE Master | LE only |
0x13 |
Connection Parameter Update Response | Reply to Connection Parameter Update Request | LE only |
BlueZ – Sending an L2CAP Connection Request (Example)
/* BlueZ: manually construct and send an L2CAP Connection Request C-Frame */
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/l2cap.h>
/* L2CAP signaling header */
struct l2cap_cmd_hdr {
uint8_t code; /* Command code e.g. 0x02 = Connection Request */
uint8_t ident; /* Identifier to match response */
uint16_t len; /* Length of data that follows */
} __attribute__((packed));
/* Connection Request payload */
struct l2cap_conn_req {
uint16_t psm; /* Protocol/Service Multiplexer e.g. 0x0003 = RFCOMM */
uint16_t scid; /* Source Channel ID chosen by initiator e.g. 0x0040 */
} __attribute__((packed));
4.4 Service Discovery Protocol (SDP)
Bluetooth is designed for ad hoc connections — devices can appear and disappear dynamically. Before two devices decide to connect for a specific purpose, one device may need to discover what services the other offers and what their characteristics are. SDP provides this mechanism.
SDP Discovery Workflow – Laptop Finding Bluetooth Speaker
→ServiceSearchRequest
ServiceSearchResponse←
Continue Learning
Explore SDP in depth — service records, attribute IDs, UUID matching — and then move on to RFCOMM and audio profiles. so i HOPE you have learnt why L2CAP is needed in bluetooth.
