4 states
4 types
1 state
5
Keywords:
8.11 — The Five Link Layer States
The BLE link layer operates as a state machine with five possible states. At any given moment, the link layer is in exactly one state, and the state determines what radio activity is happening. The five states split into two broad categories: Non-Connected States (where no connection exists yet) and Connection State (where an active connection has been established).
Before looking at each state, it is important to understand a key restriction: BLE 4.0 does not support scatternet. A scatternet is when a device participates in more than one piconet simultaneously — acting as a Slave in two piconets or as a Master in one and Slave in another. BLE 4.0 forbids this to keep the link layer simple and low-power.
Because BLE 4.0 does not support scatternet, the following rules apply to every BLE 4.0 device:
A device cannot be Master and Slave at the same time. It must be one or the other.
A device already in Slave role cannot enter Initiating state. Initiating would create a new Master connection, which combined with the existing Slave role would form a scatternet.
A device cannot have more than one Slave connection at a time.
If a device is already in Connection or Initiating state, it cannot advertise with an event type that would lead to a Slave connection (like ADV_IND or ADV_DIRECT_IND).
Note: BLE 4.1 relaxed rule 3 and allowed multi-piconet participation. But the 4.0 restrictions are what the current section covers.
Radio off
Broadcasts PDUs
Listens on adv ch
Sends CONNECT_REQ
8.11.1.1 — Standby State
Standby is where the link layer lives when it is not actively doing anything. No packets are sent and no packets are received. The radio is effectively idle. This is the lowest-power non-sleeping state for the link layer.
Two important rules about Standby:
- From Standby, you can go to: Advertising, Scanning, or Initiating — but not directly to Connection. To get to Connection you must go through Advertising (to be connected to as Slave) or Initiating (to connect as Master).
- Any state can return to Standby. This makes Standby a universal hub in the state machine — to change between any two non-Standby states (e.g. Scanning to Initiating), the link layer passes through Standby as an intermediate step.
This design choice — routing all transitions through Standby — keeps the state machine simple. Without Standby as a hub, you would need direct transitions between every pair of states, which creates many more combinations to implement and test.
8.11.1.2 — Advertising State
In the Advertising state, the link layer broadcasts advertising PDUs on the advertising channels. The device in this state is called an Advertiser. The host tells the link layer which channels to use — it can use all three (37, 38, 39) or just a subset.
There are four types of advertising events, each suited to a different scenario. The table below shows which PDU each type uses and what responses it accepts from remote devices:
| Advertising Event Type | PDU Used | Scanner SCAN_REQ? |
Initiator CONNECT_REQ? |
|---|---|---|---|
| Connectable Undirected | ADV_IND | Yes | Yes (any Initiator) |
| Connectable Directed | ADV_DIRECT_IND | No | Yes (addressed only) |
| Non-Connectable Undirected | ADV_NONCONN_IND | No | No |
| Scannable Undirected | ADV_SCAN_IND | Yes | No |
This is the most general advertising type. The device broadcasts to everyone within range and is willing to accept a connection from any device that responds. Two things a remote device can do after receiving ADV_IND:
- If it is in Scanning state — it may send a SCAN_REQ to ask for more data, and then decide whether to connect.
- If it is in Initiating state — it may send a CONNECT_REQ to start a connection right away.
It can also do the first step and then the second — query for more information first, then decide to connect. Or just receive the ADV_IND and ignore it without any response.
Payload fields:
AdvA (6 octets)
The Advertiser’s Bluetooth address (public or random). The TxAdd header bit tells the receiver which type it is.
AdvData (0–31 octets)
The advertising data from the host — device name, service UUIDs, TX power, manufacturer data, etc.
🌡️ Real-world example — Smart Thermometer in a Building:
/* Setting up connectable undirected advertising (ADV_IND) with BlueZ */
/* This is the default mode for most sensors */
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
int start_connectable_advertising(int sock)
{
le_set_advertising_parameters_cp params;
memset(¶ms, 0, sizeof(params));
params.min_interval = htobs(0x00A0); /* 100 ms */
params.max_interval = htobs(0x00A0);
params.advtype = 0x00; /* ADV_IND = connectable undirected */
params.own_bdaddr_type = 0x00; /* use public address */
params.chan_map = 0x07; /* use channels 37, 38, and 39 */
params.filter_policy = 0x00; /* accept all scan/connect requests */
return hci_send_cmd(sock, OGF_LE_CTL,
OCF_LE_SET_ADVERTISING_PARAMETERS,
LE_SET_ADVERTISING_PARAMETERS_CP_SIZE,
¶ms);
}
This type is used when the Advertiser wants to reconnect to one specific known device. Unlike ADV_IND where any device in range can connect, ADV_DIRECT_IND names a specific target. Only that one named device is allowed to respond with a CONNECT_REQ.
The key difference from connectable undirected: no SCAN_REQ is permitted. The session goes straight to connection, no back-and-forth querying. This makes the reconnection process very fast.
Payload fields:
AdvA (6 octets)
The Advertiser’s address. TxAdd indicates if it is public or random.
InitA (6 octets)
The target Initiator’s address. Only this device may respond. RxAdd indicates if it is public or random.
(AdvA + InitA in payload)
(named target)
(only named device responds)
👟 Real-world example — Pedometer in a Jogger’s Shoe:
Next: Non-Connectable & Scannable Events, Then Scanning State
You now understand Standby, Advertising, and the first two event types. The next file covers ADV_NONCONN_IND, ADV_SCAN_IND, and the full Scanning state with passive and active scanning.
