Content uploaded by Alessandro Cingolani
Author content
All content in this area was uploaded by Alessandro Cingolani on Oct 30, 2020
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 Proles ............................................... 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 Sning 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 Rill ................................................ 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, scientic 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 ocial 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 dierent. 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 dierent 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
identied 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 splied 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
1hp://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 ”packed”4aributes is a compiler options that species that no padding optimization
should be performed on the specied structure. is is probably done, apart for saving space (useful in
embedded device), to avoid possible padding dierence between dierent 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?
Dierently 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 species 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 seing 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 conguration 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 specications 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 dierent in reality. e rst dierence is
that, unlike UDP, L2CAP enforce delivery order6. In addition to that, L2CAP can be congured 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 retransmied. 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 aects 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-eort 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-eort 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 retransmied, 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 prey 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 dierent protocols/layers.
Generally, two Bluetooth devices cannot have more than one ACL and SCO connection opened (the laer
one is to ensure QoS).
2.4 Proles
Bluetooth proles 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 dierent vendors.
Proles are placed on top of the Bluetooth stack (Application Level) because they dene options for each
lower-level protocol that are mandatory for the requested prole.
In addition to that, a prole can depend on another prole if it uses some part of it. For example, the
File Transfer Protocol (FTP) prole is dependent on Generic Object Exchange (GOEP), Serial Port (SPP) and
Generic Access Prole as shown in gure [2].
e ocial list7contains a lot of proles, some of which are:
•Advanced Audio Distribution Prole (A2DP): denes how multimedia audio can be streamed from
one device to another. Will be studied later at 5.4
•Audio/Video Remote Control Prole (AVRCP): provide a standard interface to control TVs, Hi-
equipment, etc. Commonly used in conjuncton with A2DP.
7Available at the ocial Bluetooth website
5
•Human Interface Device Prole (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 Prole (MESH): allows many-to-many communication over Bluetooth radio. Most suitable for
IoT devices.
Figure 2: FTP proles dependencies
Devices typically uses the Service discovery protocol (SDP) [2.3.3] to discover which proles 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 dened 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 specication. Essentially it denes the specica-
tion of Bluetooth transceiver devices that operates in the 2.4GHz ISM band.
Bluetooth devices are actually classied 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 transmied 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 conguration. 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 species if the master or the slave
initiated the connection., the subsequent 7 bits are used for the operation code that identies 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
verier 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 dierent 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 notications 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 dened ocial 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 denition of 5 ioctls. ese
function are very similar to system calls, but they are intrinsically more ”raw”. Generally ioctls are used
for device-specic 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-specic operation.
Another huge dierence from system calls resides in the syntax: while syscalls have well-dened 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-
specic 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 specic functionality, like the UART’s
ags. Linux provides some helper macros to create an unique ioctl identier 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
11e 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. Aer 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 dierent 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 denition of the hci uart proto structure which contains,
along with some aribute such as ”operational speed”, all the function pointer needed for the protocol. e
12More info on Line Disciple and y is available here
13e 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 dierent bluetooth chipset (e.g. Intel,
Nokia), however by dening such protocol structure it is possible to abstract hardware-specic dierences
and force the usage of well-dened 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 buer” and adds this buer to the HCI device ”socket kernel buer queue” (hdev-¿rx q)14.
Aer 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 aach 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
14ese structures will be further explained in the next chapter, for now they can be viewed, respectively, as a buer and as a
list of buers used for packets
15is 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 specication denes 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 dened in bluetooth doc-
umentation16 in order to create a well-dened interface between hardware developers and the operating
system. BlueZ denes 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): Species the general category of the command
2. Opcode Command Field(ocf): Species the actual command
3. Event parts: composed by an event code that species the actual command and some (optional) event
specic 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 specied 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 denition 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 oen than in
16Ocial 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 ecient 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, dierently 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 buers (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 laer 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.
21e 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 buers
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 armative case, the socket buer present on the head is removed (skb dequeue) and cloned in the
list of sent commands. en, aer 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 wrien on hci socks.c.
We le the discussion to Bluetooth socket to the next section.
4.1.1 Sning 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 identied 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 snied 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 eective 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 : 'BLUETOOTH−DEVICE−NAME '
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 congure 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 denes le’s aributes), and
sysfs ops (which denes the two available operation on the aributes: store and show). An in-
teresting thing inside the kobject structure is how the last variable is dened: the term ”:1” aer 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 ecient 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 dierent 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
23e sysfs virtual lesystem was introduced in 2.6, in previous version the same functionality was provided by procfs
24GCC ocial documentation regarding ”bitelds”
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 /
drwxr−xr −x 2 r o o t r o o t p ow er /
drwxr−xr −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 /
−rw−r−−r−− 1 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
−r−−r−−−−− 1 r o o t r o o t c l o s e d e l a y
−r−−r−−−−− 1 r o o t r o o t c l o s i n g w a i t
−r−−r−−−−− 1 r o o t r o o t c u s t o m d i v i s o r
−r−−r−−r−− 1 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 /
−r−−r−−−−− 1 r o o t r o o t f l a g s
drwxr−xr −x 4 r o o t r o o t h c i 0 /
−r−−r−−−−− 1 r o o t r o o t i o t y p e
−r−−r−−−−− 1 r o o t r o o t i o me m bas e
−r−−r−−−−− 1 r o o t r o o t i o m e m r e g s h i f t
−r−−r−−−−− 1 r o o t r o o t i r q
−r−−r−−−−− 1 r o o t r o o t l i n e
−r−−r−−−−− 1 r o o t r o o t p o r t
drwxr−xr −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 /
−r−−r−−−−− 1 root root typ e
−r−−r−−−−− 1 r o o t r o o t u a r t c l k
−rw−r−−r−− 1 r o o t r o o t u ev e n t
−r−−r−−−−− 1 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)
species the family of protocol that will be used for communication, the second one the species the
communication semantics (a stream based transport protocol as already said in 2.3.1) and the last one sets
the eective 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 denes 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 dened, 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 dierent protocols: the RF-
COMM sockaddr rc structure has an uint8 t led that species the connection’s channel, whereas
L2CAP sockaddr l2 structure uses an unsigned short l2 psm to represent the Protocol Service
Multiplexer at a dierent position with respect to the previous one, so a direct conversion is not possible.
In addition to that, since Bluetooth byte-ordering is lile-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 dened 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 congured/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 conguration from user-space with either copy to user or get user26 and perform the needed
conguration 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-eort 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 species the
maximum time to wait for a packet acknowledgment before moving to the next packet. e only draw-
backs of this conguration is that the ush timeout is only present at the low-level ACL connection, so
changing its value will aect 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 (identied with an hci dev structure) corresponding to the Bluetooth adapter
26e rst one is used to copy a block of data while the laer 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 prole 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 briey 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
dened by a struct net device item that, similarly to what happens with sockets, has a struct
net device ops that denes the available procedure to export, as shown in gure [].
Figure 14: net device available operations
e BNEP eectively 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 seing 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.c”and 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 conguration is done via les present in /etc/bluetooth.
e main.conf le is read by bluetoothd on start-up and contains general congurations. 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 specied 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).
28ese 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 identied by an object path (e.g. ”/hci0/dev XX XX)
and each of them implement one or several interfaces. is last element is identied 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/wrien; dierently ”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/notications
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 snis 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 us−send −−s ystem −− print−reply −−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 specication (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 ocial 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 IPC”32 in order to communicate
with the bluetooth stack.
5.3 Rfkill
Many computer systems contain radio transmiers, 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 transmiers in a computer system can be queried,
activated, and deactivated. When transmiers are deactivated, they can be placed in a state where so-
ware can reactive them (a so block) or where soware 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 notications that user applications can
interpret and ways for user applications to query transmier states. e RFKill interface is located at
/dev/rfkill, which contains the current state of all radio transmiers on the system. Each device has
29Located at bluez/client
30Now called Fluoride
31D-Bus Bluetooth API: hps://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 rill-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 rill devices via the simple
read/write system calls . For example, gure [] shows a portion
of code where the bluetoothd daemon opens the rill 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 rill le
is created and then a watchdog that handles rill events is aached 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 ”rill”, 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 species three audio proles, each of them further divided into two roles:
•A2DP (Advanced Audio Distribution Prole): 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 Prole): phone-quality audio playback and recording, appropriate for phone calls
–Audio Gateway role: the device that the headset is connected to. e HSP prole 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 Prole): 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 prole 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 Prole is the Bluetooth stereo prole which denes how high quality
stereo audio can be transmied from one device to another over a Bluetooth connection. Despite other
Bluetooth audio proles exists, they serves dierent purpose (e.g. only AD2P can provide stereo audio).
At low-level, A2DP uses ACL packets, whereas voice calls (Hands-free prole HFP) uses SCO packets and
thus cannot be to stream music. e AD2P prole is usually used in conjunction with the Audio/Video
Remote Control Prole (AVRCP) to support remote control functionalities like pause or volume changes,
which is implemented over L2CAP, whereas the Headset and HandsFree proles 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 denition 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 ocial Au-
dio/Video Bluetooth specications 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 conguration relative to A2DP proles (along with general audio
and HFP cong) inside the ”/etc/bluetooth/audio.conf”35 le. Here is it possible to enable/dis-
able support for specic services and congure proles 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 species the data needed to interact with
the Bluetooth D-Bus API, while in the Proles section two on them are available. e rst one is the A2DP
sink, which is used to output audio. e laer 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 prole (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 e−bluez5−d 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 −headphones−bluetooth”
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 :
headphone−o 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
headphone−i 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 prole 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 outpued by the previous command:
pactl set−card−p 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 conguration must be wrien 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 prole UUID and an audio codec
29
must be specied. 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 prole. 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 ”state”37 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);
...
;
36Dened at profiles/audio/a2dp-codecs.h
37A complete list of possible value is documented at audio-api.txt
38Dened 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 (identied by the number 31 in /etc/protocols) is registered in the
kernel. Immediately aer this (line 3-4) the HCI layer is initialized and, consequently, also the L2CAP and
SCO sockets are (line 5-6). Once the soware 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 e−w 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
39e output taken from a Raspberry Pi 3b running Ubuntu Core version
40e Raspberry Pi has the Bluetooth chipset connected through UART, on dierent devices the driver might change (e.g.
HCI-USB)
31