← Back to list

Core Bluetooth and the BLE stack

An introduction to BLE (Bluetooth Low Energy), and how it powers the Core Bluetooth Framework.

Thomas Asheim Smedmann · 2024-02-09 18:17 · 102 claps · 17.4 min read
#ios #corebluetooth #ble #bluetooth #l2cap
Open on Medium ↗

Core Bluetooth and the BLE stack

An introduction to BLE (Bluetooth Low Energy), and how it powers the Core Bluetooth Framework.

The different layers of abstractions the Bluetooth Low Energy stack is made up of, and how Apple’s Core Bluetooth Framework fits on top of it all.

The different layers of abstractions the Bluetooth Low Energy stack is made up of, and how Apple’s Core Bluetooth Framework fits on top of it all.

In this article we’ll explore BLE (Bluetooth Low Energy), and how the technology powers Apple’s Core Bluetooth Framework. We’ll have look at the different layers of abstraction the BLE stack is made up of, and how Core Bluetooth fits on top of it. Starting at the bottom — with the physical properties of BLE — we’ll work our way to the top.

Although this article is aimed towards iOS developers, it tries to give an overview of the BLE stack as a whole. Regardless of platform.

If you just want to get your hands dirty with some example code right away, check out https://github.com/thomsmed/ble-chat-ios. It features a simple local chat application, utilising everything Core Bluetooth has to offer.

[embed]GitHub - thomsmed/ble-chat-ios: A BLE (Bluetooth Low Energy) and Core Bluetooth showcasing app. A BLE (Bluetooth Low Energy) and Core Bluetooth showcasing app. - GitHub - thomsmed/ble-chat-ios: A BLE (Bluetooth Low…github.com

TL;DR

Starting at the bottom, the BLE Stack consist of the following layers of abstraction:

  • Physical Layer: Bluetooth radio and control circuitry. Often abbreviated PHY. Operates in the unlicensed 2.4 GHz ISM band. Communication typically range below 100 meters, with transfer rates up to 2 Mbit/s.
  • Link Layer: Combination of logic circuitry and firmware running on the BLE chip. Packs a lot of responsibility, including support for advertising, scanning and creating/maintaining connections.
  • Isochronous Adaptation layer: Logic circuitry and firmware primarily concerning multiplexing of isochronous data (e.g Audio data). Only really cared about in specific situations, e.g if building BLE Audio devices and applications. Not really touched upon in this article.
  • HCI (Host Controller Interface): The interface between the BLE chip and the outside world. Typically one of the following technologies: UART, USB, Secure Digital (SD) or three-wire UART.
  • L2CAP (Logical Link Control and Adaptation Protocol): Multiplexing and control software. Sends data and control signals to the BLE chip through the HCI. Uses the concept of channels to separate sequences of data packets associated with a higher level protocol (like ATT).
  • SMP (Security Manager Protocol): Primarily a software component concerning device pairing, bonding and key distribution. Act as a security toolbox for higher layers (primarily GAP).
  • ATT (Attribute Protocol): Software component defining a simple client-server model, where each BLE device manages a table of data items called attributes. ATT defines 6 categories of packets that are sent and received over L2CAP; Commands, Requests, Responses, Notifications, Indications and Confirmations. The Bluetooth SIG defines several officially adopted ATT attributes.
  • GATT (Generic Attribute Profile): Builds upon ATT and defines a hierarchy of ATT attribute types; Services, Characteristics and Descriptors. Also defines procedures on how these can be discovered and more. The Bluetooth SIG define several officially adopted GATT Services, Characteristics and Descriptors.
  • GAP (Generic Access Profile): In contrast to GATT, this software component concerns more about how BLE devices can discover and connect to each other. And defines four higher level roles; Broadcaster, Observer, Peripheral and Central.

The BLE stack

The different layers of abstractions the Bluetooth Low Energy stack is made up of.

The different layers of abstractions the Bluetooth Low Energy stack is made up of.

BLE (Bluetooth Low Energy) is a short range wireless communication technology. The key features of BLE are robustness, low power consumption, and low cost. The Bluetooth technology started with what we today call Bluetooth BR/EDR (Basic Rate / Enhanced Data Rate — often just called Bluetooth Classic). That version of Bluetooth is mostly intended for one-to-one communication between two devices. With BLE, Bluetooth now also supports broadcasting of data to multiple devices simultaneously (which is also the foundation for Bluetooth Mesh Networking). BLE first materialised in version 4.0 of the Bluetooth Core Specification, were it sits alongside its predecessor (Bluetooth BR/EDR, aka Bluetooth Classic) as an alternative with capabilities and qualities ready to meet a new generation of requirements.

The Bluetooth technology is govern by a group of people and companies calling themselves The Bluetooth Special Interest Group (Bluetooth SIG for short). You can read more about them and the Bluetooth technology at their website https://www.bluetooth.com/.

The BLE stack is split into two major architectural blocks known as the Host layers and the Controller layers. Application developers typically resides in a layer above the Host layers, in what we call the Application layer(s). This is where Apple’s Core Bluetooth Framework operate, as well as any applications that builds on top of Core Bluetooth (or any other Bluetooth Library for that matter).

Controller layers

The controller (with its controller layers) is part of the physical BLE chip, and is a combination of hardware logic and firmware controlling the Bluetooth radio hardware. A BLE chip might be part of a larger embedded system (like an iPhone or a Raspberry Pi), or located on a USB dongle connected to a computer.

Raspberry Pi 4, with its RF shielded CYW43455 WiFi/Bluetooth chip highlighted with a red square.

Raspberry Pi 4, with its RF shielded CYW43455 WiFi/Bluetooth chip highlighted with a red square.

Physical Layer

At the bottom of the BLE stack, there is the BLE radio and control circuitry (Physical Layer). This layer is often abbreviated PHY (for Physical, as in Physical Layer or Channel).

BLE lies in the 2.4 GHz ISM band, in the SHF (Super High Frequency) Radio Spectrum. Image taken from NASA.

BLE lies in the 2.4 GHz ISM band, in the SHF (Super High Frequency) Radio Spectrum. Image taken from NASA.

The BLE radio operates in the unlicensed 2.4 GHz ISM band, and uses a binary shaped FM (Frequency Modulation) — called Gaussian Frequency Shift Keying (GFSK) — to carry bits over radio waves. BLE uses 40 RF (Radio Frequency) channels with centre frequencies at a 2 MHz spacing from 2402 MHz to 2480 MHz.

Example of binary FM (Frequency Modulation). Image taken from Wikipedia.

Example of binary FM (Frequency Modulation). Image taken from Wikipedia.

The communication range is typically below 100 meters (but can theoretically go beyond several hundred meters), with data transfer rates up to 2 Mbit/s (1.37 Mbit/s with package/protocol overhead). Both stats depend on the hardware used. BLE hardware might support multiple variants in how radio waves are sent (affecting both range and data transfer rate), where each variant is often referred to as a PHY (as in a Physical Layer or Channel).

RSSI is often used as a measure of a received BLE signal’s strength, where -20 to -30 dBm typically indicate that the device is in close range (within a couple of meters).

Link Layer

The Link Layer is a combination of logic circuitry and firmware running on the BLE (Bluetooth Low Energy) chip. It is responsible for advertising, scanning, and creating/maintaining connections. It groups the 40 RF (Radio Frequency) channels provided by the Physical Layer (the PHY) into two groups of Link Layer channels: advertising channels and general/data channels. 3 RF channels for advertising, and 37 RF channels for general/data purposes. To combat interference, something called Frequency hopping is used to cycle through the 37 general/data RF channels while connected to devices.

The Link Layer is effectively a state machine, cycling through different states (and roles). Most of these states (and roles) is controlled by a higher layer in the BLE stack. E.g. an application might signal through the stack to the Link Layer that it wants the BLE chip to scan for advertisement packages, putting the BLE chip in the scanning state. An instance of this state machine can only be in one state at the time, but a Link Layer implementation might have support for multiple instances of a state machine concurrently.

BLE chips in the connection state can assume one of two roles. A device which initiates a connection and transitions its BLE chip from the initiating state to the connection state, assumes the Central role. A device which accepts a connection request, transitioning its BLE chip from the advertising state to the connection state, assumes the Peripheral role.

A BLE chip can be in one of 7 different states at the time, including the ones mentioned above. While in the connection state, the BLE chip also assumes one of two roles; the Central role or the Peripheral role. Check out The Bluetooth Low Energy Primer and The Bluetooth Core Specification for more details about Link Layer states and roles.

Each BLE chip has a 48-bit unique identifier used to address it (sometimes called a Bluetooth MAC address). This identifier can be a public known address (obtained from the IEEE Registration Authority), or a random address. Random addresses can either be a static random address — generated each time the BLE chip powers up — or a private random address generated periodically. This private random address can be made resolvable by using a pre-shared key (referred to as Identity Resolving Key — or IRK for short). This key is shared securely during the device bonding procedure, and is one of BLE’s key Privacy measures.

Privacy is an important topic of Bluetooth Low Energy, which you can read more about at www.bluetooth.com.

If two BLE devices want to establish a secure connection between them, they need to go through a pairing procedure. Pairing is the process of connecting to and establishing a secure connection to another device. This involves the exchange of a temporary key (typically generated as part of the pairing process), which is then used to generate a Short Term Key (STK). The STK is then used to encrypt all further data communication between the devices. Once the BLE devices disconnect from each other, the STK is lost, and the devices will need to go through the pairing process again.

Bonding, on the other hand, allows a secure connection between two devices to be persisted across connections. The devices will need to go through an initial pairing process, but will also generate and store a Long Term Key (LTK). The LTK is then used to encrypt all further data communication between the devices, and can be used with consecutive connections.

The data packages transferred over the air (over the RF channels) by the Link Layer range from 10 to 268 bytes, depending on the information carried and the coding of the data package. 4 of these bytes is called the Access Address, and is a randomly generated address representing a connection between two BLE devices (not to be confused with the device identifier/address), or fixed to the value 0x8E89BED6 if its an advertising packet. 2 to 258 of the bytes is called the PDU (Protocol Data Unit), and is the primary content of a BLE Link Layer data package.

A simplified view of a Link Layer Data Package, with the Access Address and PDU.

A simplified view of a Link Layer Data Package, with the Access Address and PDU.

The PDU has 2 or 4 bytes of header information and a payload consisting of the remaining bytes. The header contain information about the payload and PDU type. The Link Layer defines several types of PDUs used for all the different states/roles defined by the Link Layer. E.g. if the BLE Link Layer data package is an advertising package, the PDU will be an Advertisement PDU and the payload will contain the advertising device’s 48 bit identifier/address and any advertising data. The PDU payload may also be encrypted, in which case the PDU includes a Message Authentication Code (called Message Integrity Check (MIC) in the context of Bluetooth). This also protects against the PDU being tampered with.

If you want to know more about all the nits and grits of the link layer, I advise you to check out The Bluetooth Low Energy Primer and/or The Bluetooth Core Specification. The link layer has a lot of responsibility, and there is too much going on there to cover it in this article.

ISOAL (Isochronous Adaptation Layer)

This layer is primarily cared about when building Bluetooth LE (Low Energy) Audio devices and applications, so we’ll not go into any details about what this layer does. It is mostly concerning multiplexing isochronous data (e.g Audio data) received from an upper layer (typically through the Host Controller Interface) into Link Layer PDUs (Protocol Data Units) transmitted or received over the Link Layer.

Bluetooth LE Audio is a fairly new addition to the BLE spec, and a massive topic on its own. The Bluetooth SIG has some great documentation and articles to get you started if you want to learn more about Bluetooth LE Audio.

HCI (Host Controller Interface)

Communication between the BLE chip (with its controller layers) and the Host (with its host layers — typically defined in software), is done over a logical interface called HCI (Host Controller Interface). This interface is typically one of the following technologies: UART, USB, Secure Digital (SD) or three-wire UART.

How the host layers communicate with the controller layers depends on where the host software is running. If the host is part of a sophisticated system running an Operating System — e.g. Linux — this communication is typically done using UART or USB driver software (depending on what technology the HCI uses). If the host is part of a simple system — e.g an Arduino board — this communication might be handeled by the host software itself. In the case of an Arduino board, this will be handled by the software running on the Arduino (typically using the ArduinoBLE library).

The HCI is acting as a bridge between the BLE chip (the controller layers) and host software (the host layers). Host software sends commands and data (e.g the command to start scanning for other BLE devices) through the HCI to the BLE chip, and the BLE chip notifies host software about events (e.g. notify about incoming data from a remote BLE device) through the HCI.

Host layers

The host layers are software layers, communicating with the Bluetooth hardware and radio through the HCI (Host Controller Interface). On a sophisticated system (like an iPhone), the software associated with these layers is typically part of the OS (operating system). And are exposed to application developers through a user space library — like Apple’s Core Bluetooth.

L2CAP (Logical Link Control and Adaptation Protocol)

The L2CAP (Logical Link Control and Adaptation Protocol) layer controls and adapt data sent to and from the BLE hardware (via the Host Controller Interface), and is responsible for multiplexing data packets to/from protocols higher up in the host layers. These data packets are called Service Data Units (SDUs for short), and are converted to/from L2CAP data packages called L2CAP Protocol Data Units (or just PDUs for short). The L2CAP PDUs is converted to Link Layer PDUs, which the Link Layer then sends/receives over the BLE radio hardware. The L2CAP layer is also responsible for making sure data packets sent to remote BLE devices does not exceed any limitations on package size and/or processing speed on the remote receiving BLE device.

A simplified view of an L2CAP Channel, and how packages from different layers are multiplexed.

A simplified view of an L2CAP Channel, and how packages from different layers are multiplexed.

L2CAP uses the concept of channels to separate sequences of data packets associated with a higher level protocol. Channels can either be fixed or dynamically allocated, and can be connection-oriented or connectionless. The Bluetooth SIG define several fixed L2CAP channels, like the fixed channels for ATT (Attribute Protocol) and SMP (Security Manager Protocol). Both of which are mentioned later in this article. A dynamically allocated channel is associated with a given higher level protocol using a Protocol Service Multiplexer (PSM) value. The PSM value can be dynamically allocated, or a fixed Bluetooth SIG adopted value. E.g. 0x001F is the PSM value for ATT (depending on the setup, L2CAP can choose to use the fixed ATT channel or a dynamically allocated ATT channel).

Protocols with fixed PSM values (like ATT) is defined in the Bluetooth SIG Assigned Numbers specification.

SMP (Security Manager Protocol)

The SMP (Security Manager Protocol, sometimes just abbreviated SM) is the module responsible for device pairing, bonding and key distribution. This software component is acting as security toolbox for higher layers (primarily the GAP layer) with methods necessary to initiate and cary out secure data transfer and authentication between devices.

Security is an important topic within BLE, and involves concerns like authentication, integrity, confidentiality and privacy. The Bluetooth LE Security Study Guide is a great starting point if you want to learn more about security in BLE.

ATT (Attribute Protocol)

The ATT (Attribute Protocol) builds around a simple client-server model, where each BLE device manages a table of data items called attributes. Each attribute is associated with a 16 bit handle, a 16 or 128 bit UUID, a value (byte array) and a set of permissions. The 16 bit handle act as an index, and is used to reference the attribute during data transfer between two devices. The UUID uniquely identify the type of the attribute, and is 16 bit for types officially adopted by the Bluetooth SIG. Custom and proprietary types use 128 bit UUIDs.

A list of officially adopted attributes can be found in the Bluetooth SIG Assigned Numbers specification.

The permission flags controls whether an attribute can be read or written, or if it must be sent over a secure and encrypted link. Permissions are not exposed to connected devices, and are not discoverable using ATT. But are rather baked into higher level specifications that builds on top of ATT (like GATT), where the attribute type and value might indicate if an attribute can be written to etc.

ATT defines several distinct data packets that are sent and received over L2CAP. These data packets all have the same format, and can be grouped into 6 types; Commands, Requests, Responses, Notifications, Indications and Confirmations. GATT (discussed in the next section) heavily utilise all these types.

GATT (Generic Attribute Profile)

GATT (Generic Attribute Profile) builds upon ATT (Attribute Protocol), and defines a hierarchy of ATT attribute types. These attribute types are used to build GATT Services, Characteristics and Descriptors. GATT also define procedures on how to define and interact with these attributes. This include procedures on how Services, Characteristics and Descriptors can be discovered, how devices can read and write to Characteristics and Descriptors, how changes to a Characteristic’s value can be notified or indicated and more.

GATT Services are a grouping mechanism, used to group GATT Characteristics together and to provide a context for those Characteristics. For example, a BLE temperature sensor might expose a GATT Service with one Characteristic representing the current temperature and another Characteristic representing current operation mode (or something else configurable for the sensor).

GATT Characteristics represent state and/or data, and have a type, a value and a set of properties associated with it. The properties indicate how the data and/or state may be used by connected devices. For example, a Characteristic may have properties that allows a connected device to read its data value, but not write to it. The same Characteristic type can be used for several GATT Services, but the usage of the Characteristic might vary depending on the context of the Service.

GATT Descriptors are metadata associated with a Characteristic. This might be readable information and/or writeable information. A Descriptor could for example be read in order to get more information about an associated Characteristic. Or it could be written to in order to control the behaviour of that same Characteristic. Examples of such Descriptors are the Characteristic User Description Descriptor, which holds an UTF-8 string with a user friendly description of the Characteristic, and the Client Characteristic Configuration Descriptor, which holds a set of per-client bit flags that can be written to in order to control the behaviour of the associated Characteristic (as seen by a specific client). E.g bit 0 controls if the device — hosting this Characteristic — should send out an ATT Notification to a specific client if the Characteristic’s value changes.

The Bluetooth SIG define several officially adopted GATT Services, Characteristics and Descriptors. All of which can be found in the Bluetooth SIG Assigned Numbers specification and Bluetooth Core specification.

GAP (Generic Access Profile)

While GATT mostly concerns about how two devices can exchange data (and the format of that data) and explore each other Services, Characteristics and Descriptors, GAP (Generic Access Profile) is more about how BLE devices can discover and connect to each other.

GAP defines protocols and procedures concerned with device discovery and establishing connections between BLE devices, and is responsible for sending out advertising packets and scanning for remote devices. This includes authentication and ensuring secure data transfer between devices. GAP uses the lower layers of the stack to achieve this (like SMP and L2CAP), and act as the top most control layer in the BLE stack. GAP also defines four higher level roles (built on top the states and roles defined in the Link layer); Broadcaster, Observer, Peripheral and Central.

Application layers

The application layer(s) is all the software above the actual BLE (Bluetooth Low Energy) stack. It usually contains at least one layer of abstraction before any user-facing applications (like an iOS app). And this abstraction is meant to provide a more developer friendly API for application developers to use. Apple’s Core Bluetooth is one such abstraction layer, and shields the application developer from a lot of details when communicating with the BLE stack. Core Bluetooth comes with an easy to use API, which makes it easy to configure your BLE supporting Apple device to act as a Peripheral and/or Central (as defined by the roles in GAP). It also makes it easy to both advertise and discover GATT services, and you are also able to open up and stream data over custom L2CAP channels directly.

Core Bluetooth

The different layers of abstractions the Bluetooth Low Energy stack is made up of, and how Apple’s Core Bluetooth Framework fits on top of it all.

The different layers of abstractions the Bluetooth Low Energy stack is made up of, and how Apple’s Core Bluetooth Framework fits on top of it all.

Apple’s Core Bluetooth provides a developer friendly API for application developers to work with when building BLE applications for Apple devices. The two main components provided by Core Bluetooth is the CBCentralManager and CBPeripheralManager.

CBCentralManager

If your app wants to act as an Observer and/or Central (as defined by GAP), you instantiate an instance of CBCentralManager. The methods on this class lets your app scan for — and optionally connect to — BLE devices acting as a Broadcaster and/or Peripheral (as defined by GAP). The methods of CBCentralManagerDelegate will notify you of any discovered BLE devices and advertisements, as well as any connection events.

Once connected to a BLE device, you can start to discover its GATT Services, Characteristics and Descriptors. This can be achieved by calling methods on an instance of CBPeripheral (representing the remote BLE device) and handling callbacks from CBPeripheralDelegate.

If the connected BLE device allows for it, Core Bluetooth also makes it possible to open a custom L2CAP channel to the remote BLE device. This channel is represented by an instance of CBL2CAPChannel, and makes it possible to stream data directly to and from a connected BLE device. Perfect if you wan to implement your own protocol on top of BLE.

CBPeripheralManager

If your app wants to act as a Broadcaster and/or Peripheral (as defined by GAP), you instantiate an instance of CBPeripheralManager. The methods on this class let your app publish (to the GATT database managed by Core Bluetooth) and advertise GATT Services, and optionally accept incoming connection requests from BLE devices acting as an Observer and/or Central (as defined by GAP). The methods of CBPeripheralManagerDelegate will notify you about any connection events.

Once an incoming connection request has been accepted, CBPeripheralManagerDelegate will notify you about any requested reads and writes to published Characteristics. CBPeripheralManagerDelegate will also notify you when a connected device enables or disables Notifications or Indications (as defined by ATT) on a published Characteristic’s value. Core Bluetooth abstract away the details about this and just calls it subscribing and unsubscribing.

Core Bluetooth also makes it possible to open a custom L2CAP channel to a connected BLE device. This channel is represented by an instance of CBL2CAPChannel, and makes it possible to stream data directly to and from a connected BLE device. Perfect if you wan to implement your own protocol on top of BLE.

Bluetooth Profiles, Services and Assigned Numbers

At the highest level we often just talk about BLE Profiles and Services when we talk about Bluetooth Low Energy. Services are just the GATT Services mentioned earlier in this article, and is a construct to group one or more Characteristics with their Descriptors. In the context of the Service they help define one aspect of a device’s behaviour.

A Profile is collection of one or more Services, and a description on how two devices can discover and communicate with each other. A Profile is typically associated with a specific device’s application — like a heart rate monitor, or an audio headset. One or more of a Profile’s services are initially advertised (using GAP advertising packages). And additional Services (and Characteristics with their Descriptors) are typically discovered after two devices has connected.

There is a lot of profiles predefined by the Bluetooth SIG, but there is nothing stopping you from defining your own custom/proprietary profile. Since a profile is basically just a collection of Services, it's just a matter of defining which GATT Services devices needs to implement in order to comply with your custom/proprietary profile.

BLE makes use of unique identifiers (UUIDs) all over the place. All GATT Services, Characteristics and Descriptors have a UUID which identifies it and its type.

Identifiers (UUIDs) allocated by the Bluetooth SIG are known as assigned numbers and a full list of these identifiers can be obtained from the Bluetooth SIG’s website: Assigned Numbers.

Custom Profiles and Services need to define their own identifiers (128 bit UUIDs) if none of the predefined Services, Characteristics or Descriptors is suitable. All predefined identifiers share the same base UUID (only 16 bits varies), and it is important to make sure custom identifiers do not collide with these.

Final words

I hope this article has proven useful and provided some insight into BLE and the different abstractions that make up the BLE stack, and how Apple’s Core Bluetooth Framework fits on top of it all.

For a complete example application utilising everything Apple’s Core Bluetooth Framework has to offer, check out this repository on GitHub: https://github.com/thomsmed/ble-chat-ios.

[embed]GitHub - thomsmed/ble-chat-ios: A BLE (Bluetooth Low Energy) and Core Bluetooth showcasing app. A BLE (Bluetooth Low Energy) and Core Bluetooth showcasing app. - GitHub - thomsmed/ble-chat-ios: A BLE (Bluetooth Low…github.com

For more information about Bluetooth Low Energy, and how to get started developing BLE applications for Apple devices using Core Bluetooth, I encourage to check out these awesome resources:

Happy coding! 😄


메타데이터
post_id
95ddc29c8671
slug
core-bluetooth-and-the-ble-stack-95ddc29c8671
url
https://medium.com/@thomsmed/core-bluetooth-and-the-ble-stack-95ddc29c8671
canonical_url
https://medium.com/@thomsmed/core-bluetooth-and-the-ble-stack-95ddc29c8671
author_url
https://medium.com/@thomsmed
status
ok
fetched_at
2026-06-28 04:42:08