Basic mode PDU
0xFFFF (infinite)
0x0005
6 in Table 10.4
Continuing Section 10.5.3 — Multiplexing Wrap-up
The previous file (PDF 1920) explained all three L2CAP features — Fixed CIDs, Fragmentation, and Channel Multiplexing. This file opens with the additional 4.1 CID space (mentioned at the end of 10.5.3), then covers the actual packet formats: the B-Frame data packet in Section 10.6, the L2CAP parameter values in Section 10.7, and the signaling channel with its commands in Section 10.8.
Starting from BLE 4.1, additional channel numbers were defined beyond the original three fixed CIDs. These support the new credit-based flow control mechanism introduced in 4.1:
CID 0x0020–0x003E
Assigned by the Bluetooth SIG as per the Assigned Numbers page — fixed assignments for specific protocols that need connection-oriented LE channels.
CID 0x0040–0x007F
Dynamically allocated when a credit-based connection is established using the LE Credit Based Connection Request signaling command. Released when the channel is closed.
10.6 — Data Packets
BR/EDR L2CAP supports five different operating modes, each designed for a different use case:
Simple send-and-forget, no built-in retransmission at L2CAP level
L2CAP-level flow control — not needed, Link Layer already does this
L2CAP-level retransmission — not needed, Link Layer already does this
More capable retransmission — not needed in LE
Isochronous audio streaming — not part of classic LE
The reason LE needs only Basic Mode is that the Link Layer already provides reliability (via SN/NESN retransmission) and flow control (via slave latency and HCI flow control). Adding L2CAP-level retransmission on top would be redundant complexity that wastes both code space and power. Removing these modes makes the LE L2CAP implementation much simpler.
In Basic Mode, every data PDU is called a B-Frame (Basic Frame). It has a simple three-field structure with no extra headers or sequence numbers beyond what the Link Layer already provides.
Size of the Information Payload in bytes. Up to 65535, but limited to the negotiated MTU. Used during reassembly when fragments arrive.
Identifies which higher-layer entity this packet belongs to. 0x0004 = ATT, 0x0006 = SMP. The CID is set by L2CAP based on which protocol sent this SDU.
The ATT or SMP data — the SDU that was handed to L2CAP. L2CAP does not interpret this content, just delivers it to the peer’s correct upper-layer entity.
The simplicity of the B-Frame is intentional. There are no sequence numbers, no acknowledgment bits, and no window size fields. All of that is handled at the Link Layer. The B-Frame is just “here is the data, it is for this CID, it is N bytes long.”
BLE 4.1 added LE credit-based flow control mode — this introduced a new PDU type for connection-oriented channels (the LE-frame or L-Frame). It uses a credit-based scheme where the receiver grants permission to send packets by giving credits. This mode is used by the IPSP (Internet Protocol Support Profile) to let BLE devices connect to the internet via IPv6 gateways. This will be covered later in Chapter 15.
10.7 — L2CAP Parameters
Both the ATT channel (CID 0x0004) and the SMP channel (CID 0x0006) use the same set of fixed L2CAP parameters. These do not need to be negotiated — they are defined by the specification and cannot be changed.
| Parameter | Value | What it means |
|---|---|---|
| MTU | 23 bytes | Default maximum SDU size. Can be increased via ATT Exchange MTU, but 23 is the guaranteed minimum every LE device must support. |
| Flush Timeout | 0xFFFF (Infinite) | The baseband keeps retransmitting indefinitely until the packet is acknowledged or the connection is dropped. There is no timeout that would cause the controller to give up on a packet and move to the next one. |
| Quality of Service | Best Effort | No bandwidth guarantee. The system tries to deliver data but makes no promises about delivery time or rate. BR/EDR also supports Guaranteed QoS but LE does not need it. |
| Mode | Basic Mode | Only Basic Mode (B-Frames) is used for these channels. The more complex BR/EDR modes are not present in LE. |
If a packet cannot be acknowledged — perhaps because the remote device moved out of range — the controller will keep retrying until the supervision timeout expires and the connection is declared lost. There is no “give up on this packet and skip to the next one” behaviour. Every packet either gets delivered or the connection closes.
LE applications are typically periodic data uploads (sensor readings) or event-driven notifications (button presses). Neither requires a guaranteed bandwidth reservation. Best Effort with reliable retransmission from the Link Layer is all that is needed for these use cases.
10.8 — L2CAP Signaling
L2CAP uses CID 0x0005 as its own control channel. This is where L2CAP sends commands to the peer L2CAP entity — things like requesting a connection parameter update, setting up a credit-based channel, or rejecting an unknown command.
The LE signaling channel is simpler than the BR/EDR equivalent in one important way: only one command can be sent per PDU. In BR/EDR, multiple commands can be packed into one PDU. The LE restriction means the parsing logic on the receiving side only ever needs to handle one command at a time — no loop needed, no risk of partial command parsing.
The PDUs that carry signaling messages are called C-Frames (Control Frames).
| Code | Command | Direction |
|---|---|---|
| 0x01 | Command Reject | Both directions |
| 0x12 | Connection Parameter Update Request | Slave → Master |
| 0x13 | Connection Parameter Update Response | Master → Slave |
| 0x14 | LE Credit Based Connection Request (4.1) | Both directions |
| 0x15 | LE Credit Based Connection Response (4.1) | Both directions |
| 0x16 | LE Flow Control Credit (4.1) | Both directions |
Notice how much shorter this list is compared to BR/EDR, which has over 20 signaling commands. LE L2CAP only needs 6 because it eliminated all the dynamic channel setup negotiation (CONNECT, CONFIGURE, DISCONNECT PDUs) and kept only what is genuinely needed.
10.8.1 — Command Reject
If a device receives a signaling command it does not understand (wrong Code value) or a command that has an incorrect length, it sends back a Command Reject (Code 0x01). The rejection PDU includes a reason field that explains why the command was rejected. There are three possible reasons:
The Code value in the received command does not correspond to any known command. The sender may have used a newer specification command that this device does not implement.
The received command was too large for the signaling channel’s MTU. The rejection response includes the actual signaling MTU value so the sender knows the limit.
The command referenced a CID that does not exist or is not valid in the current state. For example, a credit-based flow control command referencing a channel that was never set up.
10.8.2 — Connection Parameter Update Request
This is the most commonly used signaling command. A BLE Slave (Peripheral) sends this to the Master (Central) to request a change to the connection parameters. This is the L2CAP-level mechanism — remember that in BLE 4.0, the Slave cannot initiate a direct Link Layer connection update, so it uses this L2CAP signaling message instead.
The command travels over CID 0x0005 (the L2CAP signaling channel) and carries four parameters:
Interval Min
The minimum connection event interval the Slave would like. If the Master cannot accept this minimum, it rejects the request.
Interval Max
The maximum connection event interval the Slave will accept. The Master can pick any value between Min and Max.
Slave Latency
How many connection events the Slave would like to be allowed to skip. 0 = Slave must respond to every event. Higher = more battery savings.
Timeout Multiplier
Used to calculate the supervision timeout. Connection Supervision Timeout = Timeout Multiplier × 10 ms. If no packet is received for this long, the connection is declared lost.
Direction: This command goes only from Slave to Master. If the Master needs to change connection parameters, it can do so directly using the HCI_LE_Connection_Update HCI command — it does not need to ask the Slave via L2CAP. If the Master accepts the Slave’s request, it sends a Connection Parameter Update Response (Code 0x13) and then initiates the actual parameter change using the Link Layer procedure.
/* Sending Connection Parameter Update Request from Peripheral */
/* This is done automatically by BlueZ when a Peripheral calls */
/* the connection update function */
/* In BlueZ, Peripheral (Slave) requests new params via: */
/* The host can use HCI_LE_Remote_Connection_Parameter_Request */
/* or via L2CAP socket with setsockopt: */
struct bt_le_conn_param param = {
.min_interval = 80, /* 80 × 1.25ms = 100ms min interval */
.max_interval = 100, /* 100 × 1.25ms = 125ms max interval */
.latency = 0, /* no slave latency */
.supervision_timeout = 2000, /* 2000 × 10ms = 20s timeout */
};
/* BlueZ kernel sends L2CAP Connection Parameter Update Request */
/* automatically when the application requests it */
/* Monitor with btmon: look for */
/* "LE L2CAP Signaling: Connection Parameter Update Request" */
- Bridge between ATT/SMP and Link Layer
- HCI is optional (single-chip systems)
- SDU = upper-layer data, PDU = SDU + header
- 4 controller assumptions (sequence, reliability, flow)
- Min MTU = 23 bytes (LE)
- Fixed CIDs: 0x0004/0x0005/0x0006
- No CONNECT/CONFIGURE needed
- 4.1 adds CID 0x0020–0x007F
- Fragmentation/defragmentation
- MUX/DEMUX by CID
- B-Frame: Length + CID + Payload
- Basic Mode only (5 BR/EDR modes → 1)
- 4.1 credit-based mode (IPSP)
- MTU=23, Flush=infinite, QoS=best effort
- CID 0x0005, one command per PDU
- C-Frame: Code + ID + Length + Data
- 6 commands (vs 20+ in BR/EDR)
- Command Reject — 3 reasons
- Conn Param Update — Slave → Master
Chapter 10 Complete — On to Security Manager & ATT
L2CAP for BLE is fully covered. The next chapters focus on the Security Manager Protocol (Chapter 11) and the Attribute Protocol (Chapter 12), both of which use the L2CAP channels you just learned about.
