bluez tutorial BLE Link Layer States

 

 

bluez tutorial BLE Link Layer States
Chapter 8 Section 8.11 — Non-Connected States, Standby, Advertising & All Four Advertising Event Types
Non-Connected
4 states
Adv Events
4 types
Connected
1 state
Total States
5

Keywords:

BLE link layer states BLE standby state BLE advertising state BLE connectable undirected ADV_IND BLE connectable directed ADV_DIRECT_IND BLE non-connectable ADV_NONCONN_IND BLE scannable ADV_SCAN_IND BLE scatternet restrictions

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.

Scatternet Restrictions in BLE 4.0

Because BLE 4.0 does not support scatternet, the following rules apply to every BLE 4.0 device:

Rule 1

A device cannot be Master and Slave at the same time. It must be one or the other.

Rule 2

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.

Rule 3

A device cannot have more than one Slave connection at a time.

Rule 4

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.

The State Map — Non-Connected vs Connection
BLE Link Layer States — Full Map

NON-CONNECTED STATES
STANDBY
Default state
Radio off
ADVERTISING
(Advertiser)
Broadcasts PDUs
SCANNING
(Scanner)
Listens on adv ch
INITIATING
(Initiator)
Sends CONNECT_REQ

↓ Connection established (CONNECT_REQ accepted)

CONNECTION STATE
Master Role
Was Initiator
Slave Role
Was Advertiser

8.11.1.1 — Standby State

The Default Resting 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.
Standby as the Central Hub — State Transitions
Advertising
↑↓
Scanning
STANDBY
Initiating
To go from Scanning → Initiating: Scanning → Standby → Initiating

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

What the Advertising State Does

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:

Table 8.4 — Advertising Event Types and Acceptable Responses
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

Event Type 1 — Connectable Undirected (ADV_IND)

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.

Connectable Undirected Event — Sequence Diagrams

Scenario A — Scanner queries first
Advertising
ADV_IND
Scanning
Advertising
SCAN_REQ
Scanning
Advertising
SCAN_RSP
Scanning
Scanner may then decide to connect

Scenario B — Initiator connects directly
Advertising
ADV_IND
Initiating
Advertising
CONNECT_REQ
Initiating
Both transition to Connection state

🌡️ Real-world example — Smart Thermometer in a Building:

Thermometer advertises: “I am a thermometer”
Phone asks via SCAN_REQ: “Do you display temperature in Fahrenheit?”
Thermometer replies via SCAN_RSP: “Yes”
Phone sends CONNECT_REQ to establish a connection and get the actual temperature reading.
/* 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(&params, 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,
                        &params);
}

Event Type 2 — Connectable Directed (ADV_DIRECT_IND)

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.

Connectable Directed Event — Direct Connection to Named Device
Advertising
ADV_DIRECT_IND
(AdvA + InitA in payload)
Initiating
(named target)
Advertising
CONNECT_REQ
(only named device responds)
Initiating
Any other device that receives ADV_DIRECT_IND simply ignores it

👟 Real-world example — Pedometer in a Jogger’s Shoe:

Pedometer advertises: “I’m a pedometer. I want to send data to mobile phone A.” — the phone’s address is embedded in the ADV_DIRECT_IND payload.
Mobile phone A — and only phone A — receives the directed advertisement, sends CONNECT_REQ, connects, and retrieves the step data.
Any other phone nearby that also receives the ADV_DIRECT_IND will ignore it because the address in InitA field does not match their own.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *