Bluetooth Low Energy (BLE) defines a framework for a wide variety of communication schemes. It allows devices to discover each other, broadcast data, establish connections and many other fundamental operations.
The primary objective is to focus on the procedures defined for the following elements of the BLE stack:
In order to present those procedures in a comprehensive way, a series of sequence diagrams will be used, focusing on the following items:
Besides, the sequence diagrams will use the terms of master and slave or server and client, depending on the context (GAP or GATT protocol).
This article does not expose the Bluetooth stack packet management nor it describes the host controller interface (HCI).
Note: Readers are welcome to make any suggestions on improvement that can be brought to that article.
We assume in this article that the necessary Bluetooth hardware is being used, that is, an EFR32 SoC or a BGM module.
For two devices A and B to establish a BLE connection, the following has to happen: one device, say A, has to advertise, and the other one, say B, has to scan for connectable devices. As a result, only the scanning device B can initiate the connection. The scanning device B is then the master and the advertising device A is the slave.
BLE implements a time division duplex scheme. This means that on a given frequency channel, duplex communication (i.e. sending and receiving data) is taking place on one physical link. This differs, for example, from a wired serial link, where TX and RX wires would be used respectively for transmission and reception.
As a result, a defined set of tunable timing parameters are available: advertising interval, scanning interval, scanning window. For more information, refer to the BLE core specification .
The advertiser periodically sends advertising packets to any listening device. The scanner starts listening and a "scan response" event is raised each time an advertising packets is received. The advertising packets convey some useful informations, such as the advertiser Bluetooth address for example. Those informations can eventually be used in order to establish a connection.
Two scanning methods are available: passive and active. In passive scanning, the scanner only receives advertising packets. In active scanning, the scanner sends "scan request" messages to the advertiser, containing the scanner Bluetooth address and its address type.
Note: This article does not cover the extended advertising.
Once the scanner has collected all necessary information from an advertiser, it can connect to it. The following sequence diagram illustrates the steps taking place in order to successfully establish a connection:
It is important to note that the scanner is the one that is initiating the connection.
A connection initiation failure can happen for two reasons: either the connection initiation is canceled or it times out. A device can cancel a pending connection immediately after creation. It is necessary for the slave to respond to the master within a given time interval. The BLE standard defines the fixed number of six connection interval as the limit within whichever host can remain silent (as in, not sending any packet). If one of the host (master or slave) remains silent for longer, the connection is then dropped.
In this example, six connection intervals passed without receiving any data channel PDU from the slave. As a result, the connection is dropped. Similarly, If the master would have failed to send data channel PDU to the slave for that same time interval, the connection would have dropped.
Note: This is different from the supervision timeout. It applies only for the connection initiation, in other words, there is at least one successful connection event where packets are exchanged between the master and slave.
Once a BLE connection has been established, some parameter adjustments might be requested. To do so, the "Connection parameter request" procedure can be triggered by whichever host, master or slave. The procedure can be triggered at link layer level (i.e. without the application requesting it) during connection initiation. The BGAPI implements the routine gecko_cmd_le_gap_set_conn_parameters() to preset the parameter values. When the connection is initiated, it is still possible, at any point in time, to update the connection parameters via a call to the routine gecko_cmd_le_connection_set_parameters() in the application layer:
Additionally, the sequence diagram above exhibit the "GATT MTU exchange" sub procedure.
The ATT protocol defines a Maximum Transmission Unit (MTU) of 23 bytes by default. In case the two devices connected can support a bigger ATT_MTU value, the "GATT MTU exchange" procedure is triggered to set the ATT protocol MTU. This procedure shall be initiated only once during a connection initiation.
Note that the security mode and the data channel PDU payload length may vary during the connection session. For more information on general BLE security features, please refer to KBA_BT_1101: Using Bluetooth security features in Silicon Labs Bluetooth SDK.
Note: During the "Connection parameter request" procedure, the master has always the priority over parameter decision. In other words, the master has always the "last word" for parameter negotiation.
GATT provides a framework for all profiles defined either by the Bluetooth SIG or by the user. Bluetooth profiles are implemented using a hierarchical structure:
GATT database *--> Services | --> Characteristics (always placed under a service) | --> Descriptors (always placed under a characteristic)
The BLE specification refers to all the attributes within a single service as the service definition.
A primary service is the standard type of GATT service that includes relevant, standard functionality exposed by the GATT server. In other words, a service is a collection of characteristics. As a result, when a connection is established, it is necessary for the GATT client to be able to discover the available services.
The procedure iterate through all available services of the GATT database, an evt_gatt_service event is generated for each primary service discovered. Once the end of the list is reached, an evt_gatt_end_procedure is raised by the stack.
Once a client has obtained the handle range for a service, a similar procedure exist in order to retrieve a full list of the characteristics under that service.
As mentioned earlier, characteristics are data containers. They consist in a declaration (a label) and a value.
There are multiple types of characteristic:
Moreover, on a given characteristic, different types of read/write operations can be performed. We will focus here the following procedures:
We won't depict here the following sub-procedures:
The BLE stack manages the read and write operations for these characteristics. In case of the read, upon reception of the "Read request", the server's stack sends back a "Read response" containing the characteristic value as depicted below:
The following sequence diagram describes the write operation:
The "Write Response" contains only an error code indicating whether the write was successful or not.
Note that if the maximum length of the payload is reached, the read/write long characteristic is automatically used by the BLE stack.
The "Read Characteristic Value" procedure is implemented via the gecko_cmd_gatt_read_characteristic_value() BGAPI command. In this procedure, the characteristic length must be less or equal to the maximum payload, that is (ATT_MTU-1) bytes. In other words, the length of the characteristic has to fit in one "Read Response".
The data are sent from the server to the client via the "Read Response". Then, the client application can retrieve the data via the "evt_gatt_characteristic_value" event.
If the characteristic does not fit in one "Read Response", then the "Read Long Characteristic Value" procedure implemented via the gecko_cmd_gatt_read_characteristic_value() routine can be used. If the payload is bigger than (ATT_MTU-1), the stack will automatically pack and send the data using gecko_cmd_gatt_read_characteristic_value_from_value(). It is not the responsibility of the application to call gecko_cmd_gatt_read_characteristic_value_from_value(), instead, the application will still use the gecko_cmd_gatt_read_characteristic_value() routine. The following sequence diagram describes the "Read Long Characteristic Value" mechanism using the offset routine.
The client reads the characteristic by chunks of (ATT_MTU-1) bytes. The client stack keeps and update the byte offset used for the read request.
For more extensive description on long characteristic operations, refer to KBA_BT_0916: Working with Long Characteristic Values
The "Write Characteristic Value" procedure is implemented via the gecko_cmd_gatt_write_characteristic_value() BGAPI command. In this procedure, the characteristic length must be less or equal to the maximum payload, that is (ATT_MTU-3) bytes. In a similar way to the "Read Characteristic", the length of the characteristic has to fit in one "Write Request".
For longer characteristics, the same command can be used to write a characteristic in a remote GATT database. If the payload does not fit in one request, the "write long" procedure is automatically used when gecko_cmd_gatt_write_characteristic_value() is called. The value is buffered on the server side until all data are sent over. Upon reception by the server of all data, the client can issue a "write request execute" to trigger the effective write in the remote GATT database.
If the operation is successful, an evt_gatt_procedure_completed is sent by the server.
For more extensive on long characteristic operations, refer to KBA_BT_0916: Working with Long Characteristic Values
Server initiated updates can be sent from the GATT server to the client without the client having to request it. This has the advantage to save both power and bandwidth. There are two types of server initiated updates: notifications and indications. In both cases, the procedure has to be enabled first on the remote GATT server using the gecko_cmd_gatt_set_characteristic_notification() beforehand.
Notifications includes the handle of the characteristic (i.e. its identifier) and the value. The client receives the notifications but does not send any acknowledgment back to the server.
The indications, on the other hand, have the same behaviour but require an explicit acknowledgment from the client in form of confirmation. In case the confirmation is not sent by the client, the server will not send further indications.
The indications uses the same attribute protocol feature than the notifications.
The Security Manager (SM) is both a protocol and a series of security algorithms designed to provide the Bluetooth protocol stack with the ability to generate and exchange security keys, which then allow the peers to communicate securely over an encrypted link, to trust the identity of the remote device, and finally, to hide the public Bluetooth Address if required to avoid malicious peers tracking a particular device.
The Silicon Labs BGAPI implements a series of routines for each feature needed by the security manager. The security mechanisms implemented in BLE such as pairing, bonding, key exchange are described more extensively in KBA_BT_1102: Pairing Processes.
The BLE stack is designed to manage and abstract away the hardware and packet management from the application. The BGAPI implements BLE procedures such as GATT service discovery, characteristic read/write and so on, via function calls. On the other hand, an event driven design implemented by the BLE state machine, allows the application to monitor the status of the BLE stack and control it.
Great work and efforts!!
Very Informative article.