Technical ReportPDF Available

Bluetooth Stack and how Linux OS handles it

Authors:

Abstract and Figures

This essay analyzes the whole Bluetooth stack and explains how Linux implements the corresponding protocols by providing code snippets and commands examples.
Content may be subject to copyright.
Bluetooth Stack and how Linux OS handles it
Alessandro Cingolani
A.Y. 2019/2020
Contents
1 Introduction 2
2 Bluetooth Working Mechanisms 2
2.1 Device Name ............................................ 2
2.2 Scanning for Devices ....................................... 3
2.3 Types of Protocols ......................................... 3
2.3.1 RFCOMM ......................................... 3
2.3.2 L2CAP ........................................... 3
2.3.3 SDP ............................................ 4
2.3.4 SCO ............................................ 4
2.3.5 ACL ............................................ 5
2.4 Proles ............................................... 5
3 Driver-level Working Mechanism 7
3.0.1 Radio Layer ........................................ 7
3.0.2 Link Layer ......................................... 7
3.0.3 Link Manager ....................................... 8
3.1 Host Controller Interface ..................................... 8
3.2 HCI Transport Layer ....................................... 9
4 Kernel Space Working Mechanism 12
4.1 Host Controller Interface ..................................... 12
4.1.1 Sning HCI Packets ................................... 16
4.2 Bluetooth and the Linux Device Driver Model ......................... 17
4.3 Bluetooth Sockets ......................................... 19
4.3.1 L2CAP ........................................... 19
4.3.2 SCO ............................................ 21
4.4 BNEP ................................................ 23
5 User Level Working Mechanism 24
5.1 Bluetooth Management API ................................... 24
5.2 e Bluetooth daemon ...................................... 24
5.2.1 D-Bus API ......................................... 24
5.3 Rill ................................................ 25
5.4 Bluetooth Audio .......................................... 27
6 Conclusion 31
1
1 Introduction
Bluetooth is a wireless technology standard used for exchanging data between xed and mobile devices
over short distances using short-wavelength UHF radio waves in the industrial, scientic and medical
radio bands, from 2.402 GHz to 2.480 GHz, and building personal area networks (PANs). Due to its wide
adoption, no modern Operating Systems can deny support to this interface.
e goal of this essay is to illustrate the internal organization of the Linux Bluetooth Stack, with a
special focus on the support of audio devices.
Nowadays the ocial Linux Bluetooth stack is implemented by BlueZ1. Since 2006, this package pro-
vides supports for all core layers and protocols implementing a complete Bluetooth stack. e whole
system consists of many separates modules that allows to customize and optimize kernel by inserting only
the strictly required functionality (For example, an embedded device will rarely need Bluetooth High-speed
features).
As already said, the kernel module is included in the Linux kernel since the 2.6 version2, however,
without the support of user-space packages these modules are quite useless since they only implement
interfaces to functionalities (in other words, kernel module are just API that user-level application should
use). e user-land package bluez provides all the tools and daemons needed by Bluetooth applications.
2 Bluetooth Working Mechanisms
Bluetooth stack shares many similarities with the classical TCP/IP stack, however, the underlying concepts
are completely dierent. In fact, Bluetooth just focuses on communication with physically proximate de-
vices whereas Internet protocols like TCP doesn’t really care if the destination device is within a 30 meters
range or on the other side of the planet. For that reason, the process of establishing a new connection
depends on whether the device wants to create an incoming or an outgoing connection. In few words, a
device that initiate an outgoing connection needs to choose a target device and transport protocol, estab-
lish a connection and transfer data. Similarly, in order to establish an incoming connection a device choose
a transport protocol, and then listen before accepting a connection and transferring data.
2.1 Device Name
e TCP/IP stack makes use of two dierent addresses to identify a device in a network: the rst one is
the MAC address and it is used in the second layer of the ISO/OSI stack, and the other one is the IP address,
that is used in every layer up to 3. In the same way, also the Bluetooth stack makes use of the hardware
MAC address but, instead, it does not need an higher layer address as across the entire stack a device is
identied only by its 48-bit address, referred as Device Address3.
e basic data structure used in BlueZ to represent such addresses is the bdaddr t structure.
Listing 1: Device address structure in bluetooth.h
/BD A d d r e s s /
t yp e de f s t r u c t {
u i n t 8 t b [ 6 ] ;
}a t t r i b u t e ( ( p a c ke d ) ) b da d dr t ;
Here the 48-bit address is splied into a byte array of six elements. e type uint8 t is used to
explicitly specify the size of a variable: in many architecture the the value of sizeof(int) could vary
1hp://www.bluez.org/
2Located into net/bluetooth
3Also Bluetooth Address
2
from 8 to 64 bit, so by using this type the compiler is forced to store the integer into 8 bit.
On the other hand, the ”packed4aributes is a compiler options that species that no padding optimization
should be performed on the specied structure. is is probably done, apart for saving space (useful in
embedded device), to avoid possible padding dierence between dierent compilers and to optimize data
transmission (in this case developers must take care of protocol’s endianess). is trick will be widely used
across all BlueZ code.
All Bluetooth addresses in BlueZ are stored and manipulated as bdaddr t structures and, for this reason,
there are two helper functions that converts this structure to a string and vice versa5.
int str2ba (const cha r s t r , b d a d d r t b a ) ;
int ba2str ( const b d a d d r t ba , c h ar s t r )
2.2 Scanning for Devices
How should a Bluetooth device advertize itself? Or how it can discover the presence of nearby devices?
Dierently from other radio protocols, a Bluetooth device will never ”announces” its presence by broad-
casting some packets. Instead, the only way for a device to discover the presence of another one is to
conduct a device discovery.
In fact, for both privacy and power concerns, all Bluetooth devices have two ags that species how they
should behave:
1. Inquiry Scan: determine if the device is detectable by other Bluetooth devices
2. Page Scan: determine if the device should accept incoming connections requests.
By seing these ags it is possible to specify the degree of interaction that a Bluetooth controller should
have. For example, due to security and privacy reasons, the default conguration on Android OS have the
rst ag turned o and the other one enabled: in this way an device scan will not reveal the smartphone,
but devices that already know the destination’s bluetooth address can initiate a connection.
2.3 Types of Protocols
Similarly to the TCP/IP stack, once an addressing mechanism is put in place, there is a need for a transport
protocol. e Bluetooth specications supports several types of protocols, however only few of them are
widely used in practice and worth to mention.
2.3.1 RFCOMM
e Radio Frequency Communications is a protocols used to create reliable and stream-based channels, being
compared for this reason to the TCP. Although they are quite similar in some aspects, the RFCOMM has a
smaller set of available ports (only 30) compared to TCP (65,535).
Every RFCOMM connection is actually incapsulated within a L2CAP connection.
2.3.2 L2CAP
e Logical Link Control and Adaption Protocol (L2CAP) is commonly considered ”the UDP of bluetooth
and, although they share some characteristics, they are quite dierent in reality. e rst dierence is
that, unlike UDP, L2CAP enforce delivery order6. In addition to that, L2CAP can be congured to achieve
4”packed” GCC reference
5Strings must be in the format ”XX:XX:XX:XX:XX:XX”
6In the UDP protocol, if two packets were sent sequentially, there is no guarantee that those packet will arrive in the same
sequential order
3
varying levels of reliability. is property is implemented via a transmit/acknowledgment scheme in which
unacknowledge packets may or may not be retransmied. ree possible retransmit policies are available:
Never Retransmit
Always retransmit until success or connection failure limit
Drop packet and move on to the queued data
e drawback of this customization, is that any changes in L2CAP policies inevitably aects the upper
RFCOMM protocol since it is encapsulated inside.
L2CAP supports far more port (called ”Protocol Service Multiplexer”) than RFCOMM, in particular it can
use all odd-numbered value between 1 and 32.767.
e L2CAP could also be converted into a best-eort protocol, as shown in [4.3.1].
2.3.3 SDP
Previous transport protocols make use of the concept of ports, which is also common to the TCP/IP stack.
However, the size of available port of Bluetooth protocols is quite low compared to the TCP/UDP counter-
part, so a scenario where two application tries to run on the same port becomes more common. To solve
this issue, Bluetooth introduced the Service Discovery Protocol (SDP): every Bluetooth device maintains an
SDP server listening on a well-known port number; applications that want to use a particular port must
register itself on the SDP server. en, when a remote client connects to a device, it searches for the SDP
server which will provide it all the available services.
Figure 1: Comparison between traditional network applications that uses hard-coded port number and
Bluetooth applications that employs SDP
2.3.4 SCO
e Synchronous Connection Oriented logical transport (SCO) is a best-eort packed based protocol that is
exclusively used to transmit voice-quality audio. e main characteristic is that audio quality is xed to
exactly 64 kb/s to guarantee the ”perfect” for processing human voices. Obviously such low transmission
rate excludes applications such as high-quality audio (even a mid-range MP3 has a bitrate of 128 kb/s), so
generally on devices such as Bluetooth headphones, audio transmission is managed by L2CAP whereas
phone call transit through SCO.
In fact, despite SCO packets are not reliable and never retransmied, the protocol provides a much more
important quality of service assumption: any SCO connection is always guaranteed to have a 64 kb/s
transmission rate and, if other application are contending for radio time, then SCO are prioritized.
4
2.3.5 ACL
e Asynchronous Connection-oriented Logical can be considered one of the lowest-level protocol present in
Bluetooth. It is prey similar to SCO, but ACL has a retransmission mechanism since it is used exclusively
to transport data. In fact, we can see from gure [] that ACL packets’ task is basically to encapsulates
all previous packets (from RFCOMM to HCI). In particular the image shows the process of fragmentation
between dierent protocols/layers.
Generally, two Bluetooth devices cannot have more than one ACL and SCO connection opened (the laer
one is to ensure QoS).
2.4 Proles
Bluetooth proles can be viewed as a set of rules that enable particular services. ey were developed in
order to describe how implementation of user functionalities should be accomplished, avoiding the risk of
interoperability problems between products of dierent vendors.
Proles are placed on top of the Bluetooth stack (Application Level) because they dene options for each
lower-level protocol that are mandatory for the requested prole.
In addition to that, a prole can depend on another prole if it uses some part of it. For example, the
File Transfer Protocol (FTP) prole is dependent on Generic Object Exchange (GOEP), Serial Port (SPP) and
Generic Access Prole as shown in gure [2].
e ocial list7contains a lot of proles, some of which are:
Advanced Audio Distribution Prole (A2DP): denes how multimedia audio can be streamed from
one device to another. Will be studied later at 5.4
Audio/Video Remote Control Prole (AVRCP): provide a standard interface to control TVs, Hi-
equipment, etc. Commonly used in conjuncton with A2DP.
7Available at the ocial Bluetooth website
5
Human Interface Device Prole (HID): provides support for devices such as mice and keyboards. It
is designed to provide a low latency link, with low power requirements.8
Mesh Prole (MESH): allows many-to-many communication over Bluetooth radio. Most suitable for
IoT devices.
Figure 2: FTP proles dependencies
Devices typically uses the Service discovery protocol (SDP) [2.3.3] to discover which proles are avail-
able and what parameters are needed to connect to another client.
8It is also a lightweight wrapper of the human interface device protocol dened for USB
6
3 Driver-level Working Mechanism
is section mainly focuses on the lowest level of the Bluetooth stack. Figure [3] made a comparison
between the classical ISO/OSI model and the actual Bluetooth stack. It is important to notice that the
separation between the Bluetooth-controller chipset and the BlueZ modules take place at Host Controller
Interface: in simple words, it can be considered as a bridge between the hardware and the OS that provides
a uniform method of accessing the Bluetooth baseband capabilities. e discussion of this layer can be
found later at [3.1].
Figure 3: Bluetooth Stack compared to the ISO/OSI model
3.0.1 Radio Layer
e Bluetooth Radio layer is the lowest of the Bluetooth specication. Essentially it denes the specica-
tion of Bluetooth transceiver devices that operates in the 2.4GHz ISM band.
Bluetooth devices are actually classied into 4 classes depending on the signal range and the maximum
output power:
Power Class 1: designed for long-range device, max. output power is 20 dBm (range of 100m)
Power Class 1.59: maximum output power is 10 dBm
Power Class 2: used in normal device, max. output power is 4 dBm (range of 10m)
Power Class 3: designed for short-range device, max. output power is 0 dBm (range of 10cm)
Devices can optionally change its transmied power in a link with LMP commands (see 3.0.3).
3.0.2 Link Layer
e link layer (also called ”link controller”) is mainly responsible for managing physical channels and links,
but it also deals with error correction and security.
is layer handles the two link-layer protocol already presented: the Synchronous Connection-Oriented
(SCO)[2.3.4] and the Asynchronous Connection-Less (ACL)[2.3.5].
9Available only in Bluetooth Low Energy radio controller (BLE)
7
3.0.3 Link Manager
e Link Manager layer is mainly responsible for link setup and conguration. Once it discovers an-
other device remote link manager, it communicates with the device through the Link Management Protocol
(LMP). is protocol is relatively simple, and essentially consists of a number of Protocol data units (PDU)
begin exchanged from one device to another determined by the AM ADDR eld in the packet header. By
looking at the header of a packet, the rst bit is called transaction ID and species if the master or the slave
initiated the connection., the subsequent 7 bits are used for the operation code that identies the type of
LMP message being sent and the rest of the packet is le for the payload.
Figure 4: LMP message sequence chart for ACL link setup
In order to establish an ACL links, the Link Controller layer must establish a link between devices
before LMP messages can be exchanged. Figure [4] shows all the message needed for the setup.
Apart from establishing links, this layer also deal with security: the authentication procedure is based
on a challenge-response scheme, with the assumption that both devices already share a secret key. e
verier sends an LMP au rand PDU which contains a random number (the challange), and the other
device calculates the response (that depends both on its BD ADDR and on the secret key).
Other interesting functionalities that LMP supports are pairing, role change (master/slave), QoS and
Power Control.
3.1 Host Controller Interface
e HCI provides a command interface to the baseband controller and link manager, and access to hardware
status and control registers. Essentially this interface provides a uniform method of accessing the Bluetooth
baseband capabilities. Later in this essay other HCI implementation will be discussued, and this is due to
the fact that HCI exists across 3 sections, each of them playing dierent role to in the HCI system:
HCI Firmware: located in the actual bluetooth hardware device (also called ”Host Controller”),
implements HCI commands by accessing hardware status registers, control registers, and event reg-
isters.
HCI Driver: located inside the Linux kernel, it receives asynchronous notications of HCI events
and parse them. is component is extensively discussed in [4.1].
8
HCI Transport layer: HCI Driver and Firmware communicate thought this level. In other terms,
this layer should provide the ability to transfer data without without worrying about its content.
3.2 HCI Transport Layer
As already said, this layer transports HCI commands, ACL and SCO data between the HCI Driver and the
Bluetooth chipset and vice versa.
e Bluetooth standard had dened ocial support three types of HCI transport layer: UART,RS232
and USB. e kernel code that implements all these functionality can be found in drivers/bluetooth
and, in this section, the HCI-UART layer is analyzed in detail, since it is most common on mobile and em-
bedded devices (PCs usually employs USB).
e code for that functionality, loosely speaking, is contained in hci uart.h,hci h4.c,hci ldisc.c
and h4 recv.h.
Figure 5: HCI-UART ioctls
e rst thing to notice in hci uart.h (presented in gure [5]) is the denition of 5 ioctls. ese
function are very similar to system calls, but they are intrinsically more ”raw”. Generally ioctls are used
for device-specic I/O or for other operation that cannot be expressed through a normal system call. e
classical example is the CD-ROM driver: although the open,read,write system calls suits very well
for managing data present on the disc, no existing syscall would allow user-level application to eject discs,
so an ioctl was used to perform such hardware-specic operation.
Another huge dierence from system calls resides in the syntax: while syscalls have well-dened param-
eters and names, in order to call a ioctl functionality developers must instead pass a le-descriptor of the
targeted device, a magic number10 that represent the requested functionality and all the other request-
specic parameters11.
Listing 2: ”Prototype of the function used to invoke an iotctl request”
#include <s ys / i o c t l . h>
int i o c t l ( int f d , int r e q u e s t , . . . )
In this context the ioctls calls are indeed used to control hardware specic functionality, like the UART’s
ags. Linux provides some helper macros to create an unique ioctl identier and add the required read-
/write features. ese are:
IO: an ioctl with no parameters
IOW : an ioctl with write parameters, used to write data to the driver
10Unique values with unexplained meaning that should be replaced with named constants; here there is a list of all Linux
kernel available request
11e dots are typically represented as char *argp, but they are used in the source code to prevent type checking during
compilation
9
IOR: an ioctl with read parameters, used for reading data from the driver
IOWR: an ioctl with both write and read parameters.
When the HCI-UART driver is initialized in hci uart init, the structure tty ldisc ops is
used to associate each protocol operation with a routine in the code: in fact by looking at the compact ioctl
eld it is clear that all these ioctl requests are simply then managed through a switch statement in
hci uart tty ioctl. Finally, once the previous structure is lled with the correct function pointers,
the driver is registered via tty register ldisc.
e term y in the previous function name can appear unusual, since it is commonly related to old,
ASCII-based teletype terminals. Despite these devices nowadays dissapeared, the TTY subsystem is cen-
tral to the design of Linux, and UNIX in general.
When a device is connected through a pair of wires to a UART port on a computer, the Linux UART driver
manages the physical transmission of bytes, including parity checks and ow control. Aer that, as shown
in gure [6a], an additional layer called ”Line Disciple”12 must be added in order to glue together the low
level device driver code with the high level generic interface routines (such as read,write and ioctl).
In addition to that, this layer is also responsible for implementing the semantics associated with the device.
e line policy is separated from the device driver so that the same serial hardware driver can be used by
devices that require dierent data handling.
In fact, as shown in gures [6b,6a], the terminal subsystem consists of three layers: the upper one, used to
provide the character device interface, the lower hardware driver, used to communicate with the hardware,
and the middle line discipline to implement behavior common to terminal devices.
(a) How Linux kernel treat UART devices
(b) e y subsystem components
In Linux is it possible to specify the line disciple of a serial line (via its associated device le) through the
ldattach command. When the line disciple ”HCI” is set on a line, the function hci uart tty open
is automatically invoked. In few words, this function allocate the hci uart structure of gure [7b] and
set the *tty eld to the tty device that correspond to the UART serial.
e serdev device structure refers to a new bus controller called ”Serial Device Bus” introduced
in Linux 4.2 to overcome some limitation13 of y character device.
In gure [7a] it is possible to see the denition of the hci uart proto structure which contains,
along with some aribute such as ”operational speed”, all the function pointer needed for the protocol. e
12More info on Line Disciple and y is available here
13e essay won’t examine in depth this structure; interested reader could nd a nice overview here
10
drivers/bluetooth directory contains several les related to dierent bluetooth chipset (e.g. Intel,
Nokia), however by dening such protocol structure it is possible to abstract hardware-specic dierences
and force the usage of well-dened procedures. For example, by looking at hci h4.c code (which im-
plement the Bluetooth-to-Serial H4 protocol) it is possible to see how the previous function pointers are
associated to the corresponding handler (e.g. open= h4 open). e technique of specifying only func-
tion pointer inside a protocol’s struct is widely used across the Linux kernel, as explained for sockets in
[4.3].
An important thing to notice is that from now, upper layers will only use the hci dev structure to
interact with lower layer. In fact, when the HCI-UART driver have to pass the received frame to the HCI-
Core, it employs hci recv frame function. is function, essentially, takes as input an HCI device and
a”socket kernel buer” and adds this buer to the HCI device ”socket kernel buer queue” (hdev-¿rx q)14.
Aer the new frame is added to the skb queue the function responsible for handling frame reception is
added to the device work-queue.15.
/R e c e i v e f ram e from HCI d r i v e r s /
int hci recv frame ( struct hci dev hde v , struct s k b u f f sk b )
{
...
T e s t i n g P a c k e t t y p e
...
s k b q u e u e t a i l ( &hd ev>rx q , sk b ) ;
queue w o r k ( h dev>wor kque ue , &h dev>r x w o r k ) ;
return 0 ;
}
Linux includes the command hciattach that, as the manpage says, is used to aach a serial UART to
the Bluetooth stack as HCI transport interface. In few words this tool acts as a middle-man between UART
and the HCI transport interface, the source code will not be analyzed since it is very similar to the one al-
ready discussed, but interested readers could nd it inside BlueZ user-level package at tools/hciattack.h.
(a) HCI-UART protocol structure
(b) HCI-UART structure
14ese structures will be further explained in the next chapter, for now they can be viewed, respectively, as a buer and as a
list of buers used for packets
15is functionality will be further explained in the next chapter at [4.1], for now think about it as sort of kernel thread
11
4 Kernel Space Working Mechanism
4.1 Host Controller Interface
As already seen in the Figure [16b], the communication between the Bluetooth controller (the integrated
circuit) and the host stack (the OS) happens through the Host Controller Interface (HCI).
A reason for this choice is due to the fact that controller deals with hard real-time requirements and
contact with the physical layer, so it is good to separate this part from the host. Host is mostly responsible
for more complex implementations but with less stringent in terms of timing.
e Bluetooth specication denes HCI as a set of commands and events for the host and the controller
to interact with each other, along with a data packet format and a set of rules for ow control. Nowadays,
most BLE chipset comes in a complete form that incorporates the complete controller, host and application
in a single packet. is kind of chipset is normally known as system-on-chip (SoC). SoC reduces cost and
size on the nal device, hence, it is preferable to runs all three layers concurrently on a single chip for any
BLE application.
All the available HCI events, commands and functionalities are extensively dened in bluetooth doc-
umentation16 in order to create a well-dened interface between hardware developers and the operating
system. BlueZ denes all these functionalities in bluetooth/hci lib.h and the related structures
in bluetooth/hci.h. A generic HCI request [8a] is characterized by
1. Opcode Group Filed (ogf): Species the general category of the command
2. Opcode Command Field(ocf): Species the actual command
3. Event parts: composed by an event code that species the actual command and some (optional) event
specic parameter.
(a) Genering HCI Request structure
(b) An HCI Command structure that contains its parameter
Developers that doesn’t want to dirty their hand into manually packing a structure could use these
two functions:
int h c i s e n d c m d ( int dd , u i n t 1 6 t o gf , u i n t 1 6 t o cf , u i n t 8 t p len , v o id par am ) ;
int h c i s e n d r e q ( int dd , struct h c i r e q u e s t req , int timeout ) ;
e rst one just send a single command to the Bluetooth controller, while the other one also waits for
a response (the timeout is specied in the parameters). All the other functions contained in hci lib.h
can be considered as wrappers of these two functions where, for example, some parameter are hard-coded.
We take a portion of code from hci code.h that it is interesting to discuss in order to present a
practical usage of most common Linux macros and data-structures.
By skipping the rst three line (for the moment), we came across the denition of two linked-list.
e rst list keeps track of all the available HCI devices and thus it is then locked with a read-write
spin-lock (hci dev list lock) since the code will access that list in read mode more oen than in
16Ocial Document; Vol 4 Part E
12
Figure 9: hci code.h
writing mode17. e second list, instead, employs a classical mutex since this list is used by two wrappers
(hci register cb and hci unregister cb) that basically are provided as an interface to upper-
layer protocols to store their callback functions, so a classical mutex is a good choice for such types of
interface when the behaviour is not completely predetermined.
e last line, on the other hand, is interesting because it shows the clever usage of Linux optimiza-
tions. In fact, the DEFINE IDA18 macro a is part of the IDR library that implements the IDR Allocator, a
particular structure that map IDs to pointers in an ecient way. e IDA variant, instead, allows to just
allocate any kind IDs19 in a safe way (automatically checks if that ID is already in use) and by using the
least possible bit (each ID occupies one bit) without any sort of mapping.
By coming back to the rst three lines, we see that BlueZ kernel implementation of HCI makes use
of workqueues to manage transmission/reception and command execution of the HCI layer. Basically
workqueues permit ”work” to be deferred outside the interrupt context into the kernel process context
and, dierently from its predecessor (Tasklets), the handler function responsible for the work can sleep.
is is due to the fact that workqueues executes as a normal process and not a interrupt, so it can hold
semaphores. Obviously this causes an higher latency compared to tasklets (which always runs in the in-
terrupt context), however their usage is preferable when speed is not a critical factor since they are more
recent20 and thus come with a richer set of API .
In its most basic form, the work queue subsystem is an interface for creating kernel threads to handle
work that is queued from elsewhere. All of these kernel threads are called worker threads. As shown
in gure (10a), the work queue are maintained by the work struct [] structure that is composed by
three eld: func is the function that will be scheduled by the workqueue,data represent all the
parameters passed to the handler and entry is just used to insert such structures into the higher-level
workqueue struct as shows in gure [10a].
Listing 3: work struct
struct work struct {
a t o m i c l o n g t d at a ;
struct l i s t h e a d en tr y ;
w o r k f u n c t fu n c ;
};
17Multiple reader can acquire the lock on the data structure simultaneously provided that no writer has taken the lock
18An article that explains the problem
19represented as an integer between 0 and INT MAX
20Introduced in 2.5, while Tasklet were added in 2.3
13
By looking at gure [9], we see how the HCI module associate to each HCI device (hci dev) several
work t structures that are statically initialized via INIT WORK. is macro basically associate to a work
its corresponding handler.
e Linux kernel provides special per-cpu threads that are called kworker that is used to schedule the
deferred functions of the workqueue. e following command can be used to display BlueZ’s kworkers.
ubunt u @ s e r v e r : # s y s t e md cgls k|g r e p k w o r k e r |g r e p h c i
1 7 3 [ k wo r k er / u 9 :0 h c i 0 ]
1 3 19 [ k wo r ke r / u 9 : 2 h c i 0 ]
e choice of workqueues for managing trasmission/reception of packets is probably done due to their
pausable” functionality.
(a) How Workqueue works
(b) Extract from hci alloc dev
Later in the code, we see the initialization of one of the fundamental Linux kernel data structures:
socket kernel buers (SKB)21. When the hardware receives a packet, the kernel usually place it inside
such type of structures. Later, at higher levels, applications can drain the SKB-queue through their corre-
sponding socket via a system calls to either recv or recv from.
Most SKBs are stored on a list, whose head is implemented by struct sk buff head, which is
relatively simple:
struct s k b u f f h e a d {
struct s k b u f f next ;
struct s k b u f f prev ;
u 3 2 q l e n ;
s p i n l o c k t l o ck ;
};
e rst two member implements a doubly linked list of SKB, the third one keeps track of how many
packet are in the list and the laer one is a simple spin-lock that regulates concurrent access. As performed
on [10b], this type of object must be initialized via skb queue head init. Inside the HCI layer of
Bluetooth, three SKB queues are initialized, two for incoming RX/TX and one for managing commands.
21e sk buff structure is too complex to describe it here, anyway it is extensively commented directly on the source code
14
By focusing on cmd q list, the work-handler hci cmd work [4.1] is analyzed to see how these buers
are managed at kernel-level.
First of all, the work handler retrieves the device’s hci dev structure by using the container of()
macro. Basically, this macro is used to cast a member of a structure out to the containing structure. is
technique becomes extremely useful inside the Linux kernel because some functions (such as callbacks or
work functions) have a xed set of arguments. So by considering the code below as example, the hci dev
structure has the cmd work member, which is used by the command handler to retrieve the higher-level
structure: the rst argument of the macro is a pointer to the contained struct, the second one is the type
of the container struct, and the last one represent the name of the member inside that higher struct.
en, the handler checks (through atomic read) if there is incoming queued commands to send.
In armative case, the socket buer present on the head is removed (skb dequeue) and cloned in the
list of sent commands. en, aer the pending command counter is decremented (always in atomic way)
the command is nally sent via the function hci send frame.
s t a t i c void h ci cmd w ork ( struct work struct work )
{
struct hci dev h de v = c o n t a i n e r o f ( w ork , struct h c i d e v , cmd w or k ) ;
struct s k b u f f s k b ;
...
/Sen d qu e u e d c ommands /
i f ( a t o m i c r e a d ( & hd ev>cmd cnt ) ) {
s k b = s k b d e q u e u e ( & h de v>cmd q ) ;
...
k f r e e s k b ( h de v>s e n t c m d ) ;
hdev>se nt c m d = s k b c l o n e ( s kb , G FP KERNEL ) ;
i f ( h dev>s e n t cmd ) {
i f ( h c i r e q s t a t u s p e n d ( hde v ) )
h c i d e v s e t f l a g ( hde v , HCI CMD PENDING ) ;
a t o m i c d e c ( & hd ev >c md c n t ) ;
h c i s e n d f r a m e ( h de v , s k b ) ;
i f ( t e s t b i t ( HCI RE SET , &hde v>f l a g s ) )
cancel delayed work(&hdev>cmd timer );
else
s c h e d u l e d e l a y e d w o r k ( & hd ev >cmd timer ,
HCI CMD TIMEOUT ) ;
}else {
s k b q u e u e h e a d ( & hd ev >cmd q , sk b ) ;
queue w o r k ( h dev>wor kque ue , &h dev>cmd work ) ;
}
}
}
To conclude the discussion, we refer to gure []. Here we can see
that the Host Controller Interface lies between the Bluetooth controller
and the BlueZ core. is consequently means that other protocols like
L2CAP and SCO sits over HCI. e kernel provides supports to such up-
per layer protocols via a socket interface, however it also allows to reach
a deeper lever of the stack (HCI) by providing a similar socket interface
called ”HCI socket” that enables apps to directly send arbitrary HCI pack-
ets transparently to the hardware and call the Bluetooth Management
15
API[5.1]. e code for this functionality is wrien on hci socks.c.
We le the discussion to Bluetooth socket to the next section.
4.1.1 Sning HCI Packets
BlueZ includes the tool hcidump that is able to sni bluetooth packets that pass through an HCI de-
vice. First of all, the HCI device must be identied via hciconfig, which returns a lot of interesting
information about the device like ACL and SCO MTUs along with other ags (UP, RUNNING, etc…).
u bu nt u@ serve r : h c i c o n f i g
h c i 0 : Ty pe : P r i m ar y B us : UART
BD A d d r es s : XX : XX : XX : XX : XX : XX ACL MTU : 1 0 2 1 : 8
SCO MTU : 6 4 : 1
UP RUNNING PSCAN
RX b y t es : 1 2 9 51 a c l : 3 4 s co : 0 e v e n ts : 2 6 9 e r r o r s : 0
TX b y t es : 4 0 9 5 a c l : 3 4 s c o : 0 command s : 1 6 6 e r r o r s : 0
e subsequent output shows all the snied HCI packet generated by an user-level application that
had called the hci inquiry API in order to perform a device scan. Initially, the HCI inquiry command
is sent by the kernel to the Bluetooth controller that will consequently generates three events in order to
notify that the inquiry scan is started, completed and the eective scan results. 22 .
ubunt u @ s e r v e r : su d o hcid ump i h c i 0
HCI s n i f f e r B l u e t o o t h p a c k e t a n a l y z e r v e r 5 . 5 3
d e v i c e : h c i 0 s n ap l e n : 1500 f i l t e r : 0 x f f f f f f f f f f f f f f f f
<HCI Command : I n q u i r y ( 0 x 01 |0 x 0 0 01 ) p l e n 5
l a p 0 x 9 e 8b 3 3 l e n 8 num 2 5 5
>HCI E ve nt : Command S t a t u s ( 0 x 0 f ) p l en 4
I n q u i r y ( 0 x 01 |0 x0 00 1 ) s t a t u s 0 x 00 ncmd 1
>HCI E v en t : E x t en d e d I n q u i r y R e s u l t ( 0 x 2 f ) p l e n 2 5 5
b d ad d r XX : XX : XX : XX : XX : XX m ode 1 c l k o f f s e t 0 x 0 f a 9 c l a s s 0 x 5 a 0 20 c r s s i 42
Complete l o c a l name : 'BLUETOOTHDEVICENAME '
Complete s e r v i c e c l a s s e s : 0 x 11 05 . . .
Unknown typ e 0 x 05 w it h 0 b y t e s d at a
Unknown typ e 0 x 07 w it h 1 2 8 b y t e s da t a
>HCI E v en t : I n q u i r y C o mp lete ( 0 x 01 ) p l e n 1
s t a t u s 0 x 00
22Real BD address and device name are substituted respectively with ’XX:XX:XX:XX:XX:XX’ and ’BLUETOOTH-DEVICE-
NAME’
16
4.2 Bluetooth and the Linux Device Driver Model
e last thing worth to mention in gure [10b] is the initialization of a sysfs interface by the HCI module
via hci init sysfs. Sysfs is a pseudo-le system provided by the Linux kernel that is usually used to
export info and congure parameters of various kernel subsystem, hardware device and device drivers to
user-space level.23 e /sys directory is organized in a hierarchical way according to the ”Linux device
driver model”.
e kobject is the core elemenent of the device driver model: the eld *name indicates the object’s
name that will be shown in the sysfs’s directories, whereas *parent refers the object’s parent in the
hierarchical structure. e kobj type eld is used to connect kernel object with the user-space le
operations on the sysfs le, in particular through default attrs (which denes le’s aributes), and
sysfs ops (which denes the two available operation on the aributes: store and show). An in-
teresting thing inside the kobject structure is how the last variable is dened: the term ”:1” aer the
variable’s name indicated the compiler that the variable is one-bit size. is types of variable are called ”bit-
elds”24 and are extremely useful in embedded device due to memory constraint. In general, this technique
is used for storing Boolean ags in the most ecient way, exactly like in this structure.
Figure [11] shows how the kobject structure is the basic structure of the Linux Device Model, in
fact structures in the higher levels of the model are bus type,device and device driver.
struct k o b j e c t {
const cha r name ;
struct l i s t h e a d en tr y ;
struct k o b j e c t parent ;
struct kset kset ;
struct k o b j t y p e kt ype ;
struct sysfs dirent s d ;
struct k r e f k r e f ;
...
u ns ig ne d i n t state initialized :1;
u ns ig ne d i n t s t a t e i n s y s f s : 1 ;
u ns ig ne d i n t state add uevent sent :1;
u ns ig ne d i n t s t a t e r e m o v e u e v e n t s e n t : 1 ;
u ns ig ne d i n t uevent suppress : 1;
};
Buses are used to implement a communication channel between the processor and IO devices. Each
device is connected to the CPU via such buses and it appears at /sys/bus directory. In Linux, a bus is
represented through a bus type structure which include as its member a struct device: in fact
any device in the system has a struct device structure associated with it. Devices are discovered
by dierent kernel methods (hotplug, device drivers, system initialization) and are registered in the sys-
tem: in fact, each device present in the kernel has an entry in /sys/devices. Inside hci sysfs.c,
the Bluetooth device is rstly initialized through device initialize() and then registered via
device add()25, which internally adds the device to the kobject hierarchy via kobject add(),
adds it to the global for the device and then adds it to the other relevant subsystems of the driver model..
As shown in gure [11], drivers for the device (represented by a device driver structure) must
be linked to a device via a bus. is operation is performed by the bus that will try to bind the device
23e sysfs virtual lesystem was introduced in 2.6, in previous version the same functionality was provided by procfs
24GCC ocial documentation regarding ”bitelds”
25Respectively inside hci init sysfs and hci conn add sysfs
17
Figure 11: Basic components of Linux Device Model
connected to in with every drivers that have been registered.
All low-level structure that manages drivers employs this model, in fact also the hci dev structure used
at driver level has a struct device eld.
To conclude the discussion, the bt sysfs init creates a sysfs class (via class create) called
bluetooth”. Classes are a kernel abstraction that contains all the devices with similar functionalities and,
in fact, Bluetooth information is exposed at /sys/class/bluetooth.
u bu n tu @ ser ve r : / s y s / c l a s s / b l u e t o o t h / h c i 0 # : l l
l rw xr w xr wx 1 r o o t r o o t d e v i c e >. . / . . / ttyAMA0 /
drwxrxr x 2 r o o t r o o t p ow er /
drwxrxr x 3 r o o t r o o t r f k i l l 1 /
l rw xr w xr wx 1 r o o t r o o t s ub s y s te m >. . / . . / c l a s s / b l u e t o o t h /
rwrr1 r o o t r o o t u ev e n t
u bu n tu @ ser ve r : / s y s / c l a s s / b l u e t o o t h / h c i 0 / d e v i c e # l l
rr1 r o o t r o o t c l o s e d e l a y
rr1 r o o t r o o t c l o s i n g w a i t
rr1 r o o t r o o t c u s t o m d i v i s o r
rrr1 r o o t r o o t de v
l rw xr w xr wx 1 r o o t r o o t d e v i c e >. . / . . / . . / 3 f 2 0 1 0 0 0 . s e r i a l /
rr1 r o o t r o o t f l a g s
drwxrxr x 4 r o o t r o o t h c i 0 /
rr1 r o o t r o o t i o t y p e
rr1 r o o t r o o t i o me m bas e
rr1 r o o t r o o t i o m e m r e g s h i f t
rr1 r o o t r o o t i r q
rr1 r o o t r o o t l i n e
rr1 r o o t r o o t p o r t
drwxrxr x 2 r o o t r o o t p ow er /
l rw xr w xr wx 1 r o o t r o o t s ub s y s te m >. . / . . / . . / . . / . . / . . / c l a s s / t t y /
rr1 root root typ e
rr1 r o o t r o o t u a r t c l k
rwrr1 r o o t r o o t u ev e n t
rr1 r o o t r o o t x m i t f i f o s i z e
18
Figure 12: Extract from l2cap socks.c
4.3 Bluetooth Sockets
As already said in the previous section, the BlueZ framework employs sockets to pass data between user-
level and the kernel. Everything works similarly to TCP/UDP socket programming, with the only exception
of the ags passed to the socket() system call.
s = s o c k e t ( AF BLUETOOTH , SOCK STREAM , BTPROTO RFCOMM ) ;
Here the code refers to the opening of a RFCOMM socket, the rst parameter (AF BLUETOOTH)
species the family of protocol that will be used for communication, the second one the species the
communication semantics (a stream based transport protocol as already said in 2.3.1) and the last one sets
the eective protocol to use.
In the next section we are going to analyze two of the main protocol related to audio transmission.
4.3.1 L2CAP
In order to implement a customized socket in the kernel, developers have to ll two structure: proto ops,
to register a new protocol, and net proto family, that denes the new protocol family. en, to -
nallt register the new socket a call to sock register must be issued.
From gure [12] it is possible to see how the interface is dened, mapping each socket API to the corre-
sponding L2CAP handler.
Below we have a simple application that employs L2CAP sockets in order to create a Bluetooth server.
By default, L2CAP connections provide reliable datagram-oriented connections with packets delivered in
order, so the socket type is SOCK SEQPACKET, and the protocol is BTPROTO L2CAP.
An important thing to note, is that the addressing structure changes between dierent protocols: the RF-
COMM sockaddr rc structure has an uint8 t led that species the connection’s channel, whereas
L2CAP sockaddr l2 structure uses an unsigned short l2 psm to represent the Protocol Service
Multiplexer at a dierent position with respect to the previous one, so a direct conversion is not possible.
In addition to that, since Bluetooth byte-ordering is lile-endian, a set of function equivalent to the TCP/IP
htons is provided by BlueZ:
u ns ig ne d s h or t i n t h t o b s ( u n si gn ed s h o r t i n t num ) ;
u ns ig ne d s h or t i n t b t o h s ( u n si gn ed s h o r t i n t num ) ;
19
u ns ig ne d i n t h t o b l ( u ns i gn ed i n t num ) ;
u ns ig ne d i n t b t o h l ( u ns i gn ed i n t num ) ;
e term BDADDR ANY is dened as a Bluetooth address lled with zeroes, and means that the socket
must be opened on the rst available Bluetooth controller.
#include <s t d i o . h>
#include <s t r i n g . h>
#include <s y s / s o c k e t . h>
#include <bluetooth / bluetooth . h>
#include <b l u e t o o t h / l 2 c a p . h>
int main ( int argc , c har ∗ ∗ ar g v )
{
struct s o c k a d d r l 2 l o c a d d r = {0}, rem addr = {0};
cha r b u f [ 1 0 2 4 ] = {0};
int s , c l i e n t , b y t e s r e a d ;
s o c k l e n t o pt = sizeof ( r em a d dr ) ;
/ / a l l o c a t e s o c k e t
s = s o c k e t ( AF BLUETOOTH , SOCK SEQPACKET , BTPROTO L2 CAP ) ;
/ / b in d s o c k e t t o p o r t 0 x 1 0 01 o f t h e f i r s t a v a i l a b l e B l u e t o o t h ad a p te r
l o c a d d r . l 2 f a m i l y = AF BLUETOOTH ;
l o c a d d r . l 2 b d a d d r = BDADDR ANY ;
l o c a d d r . l 2 p s m = h t o bs ( 0 x 10 01 ) ;
bi n d ( s , ( struct sockaddr ) & l o c a d d r , sizeof ( l o c a d d r ) ) ;
/ / pu t s o c k e t i n t o l i s t e n i n g mode
l i s t e n ( s , 1 ) ;
/ / a c c e p t o n e c o n n e c t i o n
c l i e n t = a c ce pt ( s , ( struct sockaddr ) & re m addr , &o p t ) ;
b a 2 s t r ( &r e m a d dr . l 2 b d a d d r , bu f ) ;
f p r i n t f ( s t d e r r , a c c e p t e d c o n n e c t i o n f ro m % s \n ” , b u f ) ;
me mset ( b u f , 0 , sizeof ( b uf ) ) ;
/ / re a d d ata f ro m t he c l i e n t
b y t e s r e a d = r e a d ( c l i e n t , b uf , sizeof ( b u f ) ) ;
i f ( b y t e s r e a d >0 ) {
p r i n t f ( r e c e i v e d [ % s ] \n ” , b u f ) ;
}
c l o s e ( c l i e n t ) ;
c l o s e ( s ) ;
}
L2CAP connection options can be congured/viewed through the classical getsockopt and setsockopt,
20
which accepts an l2cap options as input. At kernel level the procedure for changing such options is
managed by l2cap sock setsockopt, that essentially locks the socket (via lock sock), copy the
new conguration from user-space with either copy to user or get user26 and perform the needed
conguration before unlocking the socket.
struct l 2 c a p o p t i o n s {
u i n t 1 6 t om tu ;
u i n t 1 6 t i mtu ;
u i n t 1 6 t f l u s h t o ;
u i n t 8 t mode ;
};
Advanced developers could also customize the semantics of L2CAP connection, switching from a reli-
able to a best-eort protocol. is operation is not supported through sockets, so the only way to instruct
the Bluetooth controller is via HCI commands that adjust the ush timeout. is parameter species the
maximum time to wait for a packet acknowledgment before moving to the next packet. e only draw-
backs of this conguration is that the ush timeout is only present at the low-level ACL connection, so
changing its value will aect all upper layer protocol27.
An useful user-level tool for testing L2CAP connection is l2ping. It basically sends echo packets to
another Bluetooth device and waits for a response, giving timing information and regarding how long it
takes to send/receive packets of a certain size.
# l 2 p i n g c 5 XX:XX:XX:XX:XX:XX
P i ng : XX : XX : XX : XX : XX : XX fro m YY : YY : Y Y : YY : YY : Y Y ( d a t a s i z e 4 4 ) . . .
4 4 b y t e s f rom XX : XX : XX : XX : XX : XX i d 0 t i m e 1 0 2 2 . 7 1 ms
4 4 b y t e s f rom XX : XX : XX : XX : XX : XX i d 1 t i m e 4 9 . 7 1 ms
4 4 b y t e s f rom XX : XX : XX : XX : XX : XX i d 2 t i m e 3 2 . 2 4 ms
4 4 b y t e s f rom XX : XX : XX : XX : XX : XX i d 3 t i m e 5 7 . 2 7 ms
4 4 b y t e s f rom XX : XX : XX : XX : XX : XX i d 4 t i m e 4 3 . 4 8 ms
4.3.2 SCO
Similarly to L2CAP and RFCOMM, the SCO protocol can be used through sockets. e socket type and the
protocol is respectively SOCK SEQPACKET and BTPROTO SCO, and this time the sockaddr sco
addressing structure has not eld related to port or channel. e semantics of SCO sockets are nearly the
same of all other protocol, but with two major exception regarding audio format and MTU. In fact, before
establishing a SCO connection, the application should check and set the audio format used for future SCO
connections via the following API:
int h c i r e a d v o i c e s e t t i n g s ( int dd , u i n t 1 6 t vs , int to ) ;
int h c i w r i t e v o i c e s e t t i n g s ( int dd , u i n t 1 6 t v s , int t o ) ;
To conclude the discussion, the main function employed to send an SCO frame is analyzed. Just as
L2CAP sockets, SCO sockets must be registered by populating the struct proto ops sco sock ops
and struct net proto family sco sock family ops . e next code refers to the routine
called when the connect system call is called on a SCO socket.
Initially, the HCI device (identied with an hci dev structure) corresponding to the Bluetooth adapter
26e rst one is used to copy a block of data while the laer simply fetch a variable from user space
27Also considering that between two device only a single ACL connection is allowed
21
is retrieved via hci get route and then locked with hci dev lock. en, some of the macro de-
ned at hci core.h is used to manage LMP commands [3.0.3]. In particular the routine checks via
lmp esco capable if the Bluetooth controller supports the Enhanced SCO (eSCO), an improved pro-
tocol that even supports packet retransmissions to achieve reliability, and set the link type accordingly.
At this point, an HCI connection is created through hci connect sco (which basically perform all
low-level commands and procedures to setup the link) and then converted to an sco conn structure
via sco conn add. Finally, the SCO connection is applied to the socket through sco chan add and,
eventually, the socket’s timer is cleared when the device is fully connected.
At this point becomes clear how Bluetooth sockets are just a wrapper interface that implements under the
hood all the necessary HCI and LMP commands necessary to setup a connection.
s t a t i c i n t s c o c o n n e c t ( struct s o c k s k )
{
struct s c o c o n n conn ;
struct hci conn hcon ;
struct hci dev hd ev ;
int e r r , t y p e ;
hde v = h c i g e t r o u t e (& s c o p i ( s k)>ds t , & s c o p i ( s k)>s r c , BDADDR BREDR ) ;
...
h c i d e v l o c k ( h de v ) ;
i f ( l m p e s c o c a p a b l e ( h dev ) && ! d i s a b l e e s c o )
t y p e = E SCO LI NK ;
else
t y p e = S CO LI NK ;
....
hco n = h c i c o n n e c t s c o ( h de v , type , & s c o p i ( sk)>ds t ,
s c o p i ( sk)>s e t t i n g ) ;
...
c on n = s c o c o n n a d d ( h co n ) ;
...
/U pd a te s o u r c e a d dr of t h e s o c k e t /
b ac py (& s c o p i ( s k)>s r c , &h c on>s r c ) ;
s c o c h a n a d d ( co nn , s k , NULL ) ;
...
i f ( h con>s t a t e == BT CONNECTED) {
s c o s o c k c l e a r t i m e r ( s k ) ;
sk>s k s t a t e = BT CONNECTED ;
}else {
sk>s k s t a t e = BT CONNECT ;
s c o s o c k s e t t i m e r ( sk , s k>sk sndtimeo );
}
don e :
22
h c i d e v u n l o c k ( hde v ) ;
h c i d e v p u t ( h de v ) ;
return e r r ;
}
4.4 BNEP
e Bluetooth Network Encapsulation Protocol (BNEP) encapsulates packets from various networking pro-
tocols, which are transported directly over the Bluetooth Logical Link Control and Adaptation Layer Pro-
tocol (L2CAP) protocol. In other words, L2CAP provides a data link layer for Bluetooth. e Bluetooth
Personal Area networking prole describes how BNEP shall be used to provide networking capabilities for
Bluetooth devices.
(a) Overview of the BNEP stack
(b) How Ethernet packet is encapsulated in BNEP
By using BNEP, Bluetooth devices can supports network capabilities and thus employ most of the
TCP/IP stack as shown in gure [13a]. Ethernet packets are transparently encapsulated into an L2CAP
packet where, as explained in gure [13b], the Ethernet header is converted into a BNEP header.
Kernel code for this functionality can be found at net/bluetooth/bnep, and for now the content
of netdev.c is briey studied. In order to transparently implement Ethernet over Bluetooth, the BNEP
code allocated a new network device called bnepX via bnep add connection which internally is-
sue a call to alloc netdev and register netdev.
ese two function are used within the Linux kernel to create a new network interface: each interface is
dened by a struct net device item that, similarly to what happens with sockets, has a struct
net device ops that denes the available procedure to export, as shown in gure [].
Figure 14: net device available operations
e BNEP eectively creates an Ethernet
interface via ether setup inside the func-
tion bnep net setup.
Whenever an Ethernet packet is received, the
BNEP layer essentially puts it into an SKB list
that will be later drained by the L2CAP layer
(in bnep net xmit).
23
5 User Level Working Mechanism
5.1 Bluetooth Management API
Apart from passing through the Bluetooth daemon28, user-level application can communicate with the ker-
nel via the so-called ”Bluetooth Management socket”. ese sockets can be created by seing the hci channel
member of struct sockaddr hci to HCI CHANNEL CONTROL when creating a raw HCI socket.
ese API are even used by the Bluetooth daemon at mgmt.cand gure [15] shows the creation of
the HCI socket used to communicate with the kernel, as explained in section 4.1. e API documentation
can be found at mgmt-api.txt, however the BlueZ package provides a command-line utilty called
btmgmt that easily associate commands with the corresponding API.
By running hcidump while executing btmgmt commands becomes clear how a single mgmt request
relates to many HCI commands and events at kernel level.
Figure 15: Extract from mgmt.c
5.2 e Bluetooth daemon
e bluetoothd daemon manages all the Bluetooth devices. bluetoothd itself does not accept many
command-line options, as most of its conguration is done via les present in /etc/bluetooth.
e main.conf le is read by bluetoothd on start-up and contains general congurations. e
daemon can also provide a number of services via the D-Bus message bus system, and the security policies
for that subsystem can be specied inside the le bluetooth.conf.
5.2.1 D-Bus API
e Bluetooth daemon exposes a lot of API to user-space application through its D-Bus interface. e
complete list of available functionalities can be found on the BlueZ code inside the doc directory.
D-Bus is a system for interprocess communication (IPC) which consists, architecturally, of two funda-
mental part: the libdbus library that allows two application to connect to each other and exchange
messages, and the D-Bus Daemon, which acts as a router where all application connect to, that is re-
sponsible of routing messages. Normally two instances of this daemon are present, the heavily secured
machine-global bus (system) and the one generated for each user login session (session).
28ese sockets are completely independent from the daemon, since they communicate directly with the kernel
24
Essentially, each D-Bus application has its own service name (”org.bluez” in this case) that uses to
expose its objects. Similarly, objects are uniquely identied by an object path (e.g. ”/hci0/dev XX XX)
and each of them implement one or several interfaces. is last element is identied by an unique names
that uses dots (e.g. ”org.bluez.Device1”) and contains properties,methods and signals.
”Properties” are direct accessible typed elds that can be read/wrien; dierently ”methods” consists in a
remote procedure call from one process to another (in this case from the client bluetooth application to
the bluetooth daemon) that can return valeus/objects. ”Signals”, instead, are sort of message/notications
that are sent to every client that is listening for them.
Linux provides several utilities to manage the D-Bus subsystem, two of which are dbus-monitor,
that snis all exchanged messages on a bus, and dbus-send, that allows to invoke methods or get/set
object properties. e command below instruct the bluetooth daemon to start a discovery on the hci0
adapter. Adapter’s documentation gives all the necessary parameter to communicate with the daemon,
like the interface org.bluez.Adapter1 and the object path. e ag ”system” indicates that the
BlueZ daemon works at system bus rather than on a session bus.
ubunt u @ s e r v e r : d b ussend s ystem printreply t ype=method call
d e s t = o r g . b l u e z / o r g / b l u e z / h c i 0 o r g . b l u e z . A d ap t e r 1 . S t a r t D i s c o v e r y
By analyzing the bluetoothd code, it becomes clear that the daemon basically open the D-Bus bus
and, once a message is received, it parse it by following the API specication (interface, object etc..) and
execute the corresponding functionality through the use of Bluetooth sockets (as shown in gure [16b].
e same comparison can be made with the popular bluetoothctl tool29: essentially is parses com-
mands and instruct the Bluetooth daemon via the D-Bus corresponding API(s).
Android Bluetooth Stack comparison e Android operating system (that is based on Linux) also
used BlueZ till 2012, when it switched to the Brodacom developed BlueDroid30 . Despite the ocial reason
for this change is still unknown, probably it was due to the fact that BlueZ uses the D-Bus IPC system in
order to implement its API31, while the Android OS does support it. In fact we can see from picture [16a]
that the Android stack makes use of its own IPC system called ”Binder IPC32 in order to communicate
with the bluetooth stack.
5.3 Rfkill
Many computer systems contain radio transmiers, including Wi-Fi, Bluetooth, and 3G devices. ese
devices consume power, which is wasted when the device is not in use. RFKill is a subsystem in the Linux
kernel that provides an interface through which radio transmiers in a computer system can be queried,
activated, and deactivated. When transmiers are deactivated, they can be placed in a state where so-
ware can reactive them (a so block) or where soware cannot reactive them (a hard block). e RFKill
core provides the application programming interface (API) for the subsystem. Kernel drivers that have
been designed to support RFkill use this API to register with the kernel, and include methods for enabling
and disabling the device. Additionally, the RFKill core provides notications that user applications can
interpret and ways for user applications to query transmier states. e RFKill interface is located at
/dev/rfkill, which contains the current state of all radio transmiers on the system. Each device has
29Located at bluez/client
30Now called Fluoride
31D-Bus Bluetooth API: hps://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc
32Documentation
25
(a) Fluoride Android architecture (b) Bluez stack taken from Intel Edison docs
its current RFKill state registered in sysfs.rfkill is a command-line tool with which can be queried
to obtain and/or change the status of rill-enabled devices on the system.
Figure 17: bluetoothd uses
rfkill to discover available
controller
At user-space level, the reccomended way to interface with rfkill
subsystem is through the /dev/rfkill character device, which
allows to obtain and set the state of rill devices via the simple
read/write system calls . For example, gure [] shows a portion
of code where the bluetoothd daemon opens the rill device in or-
der to grab information about devices present on the system. Later on,
the corresponding le descriptor is wrapped around a GLib IO Chan-
nel33 , a data structure used to provide a portable method for using le
descriptors, pipes and sockets. In the code a new channel to the rill le
is created and then a watchdog that handles rill events is aached to
monitor each changes of such le (similarly to poll() system call).
When the rfkill event watchdog is called, it reads a
rfkill event structure from the character device and consult the
/sys/class/rfkill/” directory to grab information on the de-
vice. en, it calls btd adapter restore powered which, at
low level, perform a mgmt[5.1] request to change device’s power op-
tions.
In fact, by running btmon34 when an device is deactivated via ”rill”, the output shows that rst an
HCI ”Intel SW RF Kill” command is issued and then the mgmt event ”Class Of Device Changed” is received
(indicating that the device where powered o).
struct rfkill event {
u i n t 3 2 t i d x ;
u i n t 8 t t y pe ;
u i n t 8 t op ;
u i n t 8 t s o f t ;
u i n t 8 t h ard ;
};
33Although designed for powerful and complex GNOME applications, Glib is actually a separate library from GNOME and
readily usable from any C application
34A tool similar to hcidump that also supports mgmt commands
26
5.4 Bluetooth Audio
e Bluetooth standard species three audio proles, each of them further divided into two roles:
A2DP (Advanced Audio Distribution Prole): high-quality audio playback, appropriate for listening
to music.
Source role: the device that sends audio.
Sink role: the device that receives audio
HSP (HeadSet Prole): phone-quality audio playback and recording, appropriate for phone calls
Audio Gateway role: the device that the headset is connected to. e HSP prole is typically
used in phone calls, and this is the device that is connected to the cellular network
Headset role: the headset, obviously. is is where the speakers and microphone are.
HFP (Hands-Free Prole): same as HSP, but with additional functionality for managing phone calls.
Audio Gateway role: the device that the hands-free device is connected to. e HFP prole is
typically used for cellular phone calls, and this is the device that is connected to the cellular
network.
Hands-Free Unit role: the device with the speakers and microphone.
e Advanced Audio Distribution Prole is the Bluetooth stereo prole which denes how high quality
stereo audio can be transmied from one device to another over a Bluetooth connection. Despite other
Bluetooth audio proles exists, they serves dierent purpose (e.g. only AD2P can provide stereo audio).
At low-level, A2DP uses ACL packets, whereas voice calls (Hands-free prole HFP) uses SCO packets and
thus cannot be to stream music. e AD2P prole is usually used in conjunction with the Audio/Video
Remote Control Prole (AVRCP) to support remote control functionalities like pause or volume changes,
which is implemented over L2CAP, whereas the Headset and HandsFree proles employs RFCOMM for
control channel.
Linux implements Bluetooth audio by combining BlueZ with the
PulseAudio package: this one acts as a sound server, which essen-
tially is a background process accepting sound input from one or more
sources (processes, capture devices, etc.) and that later redirects these
sound sources to one or more sinks (sound cards or other processes).
In the case of Bluetooth, PulseAudio communicates with the Bluetooth
daemon [5.2] provided by BlueZ and create a new virtual sound card.
By looking at the source code of Pulse Audio, it is possible to
see the denition of the BlueZ’s D-Bus classes and interfaces inside
bluez5-util.c [5.2.1]. In fact, the Pulse Audio daemon interacts
with Bluetooth daemon through D-Bus messages via the Media inter-
face.
On the BlueZ side, the part of the code responsible for implement-
ing A2DP can be found inside profiles/audio. e ocial Au-
dio/Video Bluetooth specications introduces three main protocol for
managing media:
1. A2DP: used to manage audio, implemented at a2dp.c
2. AVDTP: used to distribute media, implemented at avdtp.c
3. AVRCP: used for remote control, implemented at avrcp.c
27
e Bluetooth daemon contains the conguration relative to A2DP proles (along with general audio
and HFP cong) inside the ”/etc/bluetooth/audio.conf35 le. Here is it possible to enable/dis-
able support for specic services and congure proles options (like the audio coded used for A2DP).
Once a Bluetooth device that supports A2DP is connected, PulseAudio should automatically create a
virtual sound card like in the following output , which refers to a pair of wireless headphones, that shows
how the sound-server view the device. e properties sections species the data needed to interact with
the Bluetooth D-Bus API, while in the Proles section two on them are available. e rst one is the A2DP
sink, which is used to output audio. e laer one, instead, is the Headset Head Unit, a protocol based
on SCO which is used for calls. In fact, by viewing the device Ports section, the headset head unit
is present both in output and input prole (a call is a bi-directional communication) whereas A2DP only
appear in outputs.
ubunt u @ s e r v e r : # p a c t l l i s t c a rd s
Card # 0
Name : b l u e z c a r d . XX XX XX XX XX XX
D r i v e r : m od ul ebluez5d e v i c e . c
Owner Modu le : 2 3
P r o p e r t i e s :
d e v i c e . d e s c r i p t i o n = B l u e t o o t h W i r e l e s s H ea dp h on es
d e v i c e . s t r i n g = ” XX : XX : XX : XX : XX : XX”
d e v i c e . a p i = b l u e z
d e v i c e . c l a s s = s ou n d ”
d e v i c e . b us = b l u e t o o t h
d e v i c e . f o r m f a c t o r = ” h ead p ho ne
b l u e z . p at h = / o r g / b l u e z / h c i 0 / d ev X X X X X X X X XX X X ”
b l u e z . c l a s s = ” 0 x 2 4 0 41 8
b l u e z . a l i a s = B l u e t o o t h W i r e l e s s H ea d ph on es ”
d e v i c e . i c o n n a me = a ud i o headphonesbluetooth
Profiles :
h e a d s e t h e a d u n i t : H e ad se t He ad U n it ( HSP / HFP ) ( . . . )
a 2 d p s i n k : H i gh F i d e l i t y P l a y b a c k ( A2DP S i n k ) ( . . . )
o f f : O ff ( . . . )
A c t iv e P r o f i l e : h e a d s e t h e a d u n i t
P o r t s :
headphoneo u t p u t : H ea dp h on e ( . . . )
P a r t o f p r o f i l e ( s ) : h e a d s e t h e a d u n i t , a 2 d p s i n k
headphonei n p u t : B l u e t o o t h I n p u t ( . . . )
P a r t o f p r o f i l e ( s ) : h e a d s e t h e a d u n i t
At this point, the card prole should be set from the available options (in this case headset head unit
or a2dp sink) by using the following command, where CARD ID is the ID of the Bluetooth device
sound card outpued by the previous command:
pactl setcardp r o f i l e CA RD ID a 2 d p s i n k
35In BlueZ-5 this le is no longer present, and all the needed conguration must be wrien directly into the
/etc/bluetooth/main.conf le
28
Below there is a scratch of the D-Bus interaction between the Bluetooth controller, BlueZ and an
application that wants to use A2DP for sending/receiving audio.
When an user-level app starts, it has to tell BlueZ that it needs to handle A2DP sinks or sources. is is
done by calling the Media method RegisterEndpoint, where both a prole UUID and an audio codec
29
must be specied. Currently BlueZ implements four types of codecs 36 , and usually SBC (Low-complexity
subband codec) is the most popular option due to the fact that it is the default codec and its implementation
is mandatory for devices supporting the A2DP prole. Anyway, vendors are free to add their own codecs
to match their needs (as shown in the last line of [5.4]).
# d ef i ne A2DP CODEC SBC 0 x 00
# d ef i ne A2DP CODEC MPEG12 0 x 01
# d ef i ne A2DP CODEC MPEG24 0 x 02
# d ef i ne A2DP CODEC ATRAC 0 x 04
# d ef i ne A2DP CODEC VENDOR 0 xF F
At this point the app waits until a Bluetooth A2DP device connects to the adapter. When this happens,
BlueZ will automatically notify the app again by using the MediaEndpoint.SelectConfiguration
event, which contains the device’s available codecs and other parameters. e user-space application will
then have to chose the right parameters according to its need (obviously trying to provide the best-audio
quality). If everything succeded, BlueZ will issue an event MediaEndpoint.SetConfiguration
that should contain exactly the same codec parameters that the app chose in the previous step. Apart from
this check, the event contains a parameter ”transport path” which will be needed later.
Once the remote device opens an audio streams, BlueZ will trigger an AudioSource.PropertyChanged
event: user-space applications must listen for such events and keep track of its ”state37 property (which
in this case switches from ”connected” to ”playing”).
At this point the application should call MediaTransport.Acquire method passing the previously
fetched ”transport path” parameter. BlueZ will then answer with a le descriptor where the app can read
from along with some other parameters such as the read MTU value.
Internally, BlueZ handles these transmission through a media transport structure which contains all
data necessary to act as a middleman between the remote device and the appliation, such as a btd device38
member that is used to communicate with the remote device, the le descriptor fd that is returned to the
user-space application and the input/output MTU value.
struct mediatransport –
char *path; /* Transport object path */
struct btddevice *device; /* Transport device */
const char *remoteendpoint; /* Transport remote SEP */
struct mediaendpoint *endpoint; /* Transport endpoint*/
struct mediaowner *owner; /* Transport owner */
int size; /* Transport configuration size*/
int fd; /* Transport file descriptor */
uint16t imtu; /* Transport input mtu */
uint16t omtu; /* Transport output mtu */
transportstatet state;
...
guint (*resume) (struct mediatransport *transport,
struct mediaowner *owner);
guint (*suspend) (struct mediatransport *transport,
struct mediaowner *owner);
void (*cancel) (struct mediatransport *transport, guint id);
...
;
36Dened at profiles/audio/a2dp-codecs.h
37A complete list of possible value is documented at audio-api.txt
38Dened inside src/device.c
30
6 Conclusion
To conclude the discussion, the output of dmesg is presented in order to show the order in which Blue-
tooth stack components are initialized by the kernel39.
On line 2 the Bluetooth protocol (identied by the number 31 in /etc/protocols) is registered in the
kernel. Immediately aer this (line 3-4) the HCI layer is initialized and, consequently, also the L2CAP and
SCO sockets are (line 5-6). Once the soware layer of the Bluetooth stack are ready, the OS loads the HCI
UART driver [3.2] needed to communicate with the Bluetooth chipset installed on the device40 (line 7-17).
Consequently, all the higher layer protocol like BNEP and RFCOMM are initialized (line 18-23) and then,
at user-level, the Bluetoot daemon is started.
[ 1 ] B l u e t o o t h : C or e v e r 2 . 2 2
[ 2 ] NET : R e g i s t e r e d p r o t o c o l f am i l y 3 1
[ 3 ] B l u e t o o t h : HCI d e v i c e a nd c o n n e c t i o n m an a ge r i n i t i a l i z e d
[ 4 ] B l u e t o o t h : HC I s o c k e t l a y e r i n i t i a l i z e d
[ 5 ] B l u e t o o t h : L2C AP s o c k e t l a y e r i n i t i a l i z e d
[ 6 ] B l u e t o o t h : SCO s o c k e t l a y e r i n i t i a l i z e d
[ 7 ] B l u e t o o t h : HC I UART d r i v e r v e r 2 . 3
[ 8 ] B l u e t o o t h : HC I UART p r o t o c o l H4 r e g i s t e r e d
[ 9 ] B l u e t o o t h : HC I UART p r o t o c o l B CSP r e g i s t e r e d
[ 1 0 ] B l u e t o o t h : HC I UART p r o t o c o l LL r e g i s t e r e d
[ 1 ] B l u e t o o t h : HC I UART p r o t o c o l ATH3K r e g i s t e r e d
[ 1 2 ] B l u e t o o t h : HC I UART p r o t o c o l T h re ew ir e ( H5 ) r e g i s t e r e d
[ 1 3 ] B l u e t o o t h : HC I UART p r o t o c o l I n t e l r e g i s t e r e d
[ 1 4 ] B l u e t o o t h : HC I UART p r o t o c o l B ro ad co m r e g i s t e r e d
[ 1 5 ] B l u e t o o t h : HC I UART p r o t o c o l QCA r e g i s t e r e d
[ 1 6 ] B l u e t o o t h : HC I UART p r o t o c o l AG6XX r e g i s t e r e d
[ 1 7 ] B l u e t o o t h : HC I UART p r o t o c o l M a r ve l l r e g i s t e r e d
[ 1 8 ] B l u e t o o t h : BNEP ( E t h e r n e t E m u l a t io n ) v e r 1 . 3
[ 1 9 ] B l u e t o o t h : BNEP f i l t e r s : p r o t o c o l m u l t i c a s t
[ 2 0 ] B l u e t o o t h : BNEP s o c k e t l a y e r i n i t i a l i z e d
[ 2 1 ] B l u e t o o t h : RFCOMM TTY l a y e r i n i t i a l i z e d
[ 2 2 ] B l u e t o o t h : RFCOMM s o c k e t l a y e r i n i t i a l i z e d
[ 2 3 ] B l u e t o o t h : RFCOMM v e r 1 . 1 1
39e output taken from a Raspberry Pi 3b running Ubuntu Core version
40e Raspberry Pi has the Bluetooth chipset connected through UART, on dierent devices the driver might change (e.g.
HCI-USB)
31
ResearchGate has not been able to resolve any citations for this publication.
ResearchGate has not been able to resolve any references for this publication.