Bluetooth - ATT and GATT

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

6/7/2019 Bluetooth: ATT and GATT

Bluetooth: ATT and GATT

BLUETOOTH 4.0, WHICH INCLUDES THE LOW ENERGY SPECIFICATION, BRINGS TWO NEW CORE PROTOCOLS:

ATT (Attribute Protocol) and GATT (Generic Attribute Profile). They are mainly
targeted for Low Energy, and every LE profile is expected to use them. But they
can also be used over "vanilla" Bluetooth (BR/EDR).

Overview

ATT is a wire application protocol, while GATT dictates how ATT is employed in
service composition. Every Low Energy profile must be based on GATT. So,
ultimately, every LE service uses ATT as the application protocol.

Locking profiles into these protocols brings several advantages:

Development and implementation of new LE profiles is much easier, since there is


no wire protocol to do from scratch;

ATT is optimized to run on Low Energy devices: it uses as few bytes as possible,
and implementation may use fixed-size structures in memory to make data
packets (PDUs).

ATT/GATT simplicity means that firmware may offer some degree of ATT/GATT
assistance, sparing the microcontroller software from the trouble.

For software-based stacks, ATT/GATT may be implemented only once in stack


itself, sparing the applications from the trouble.

Fewer ATT/GATT implementations out there means less problems with suboptimal
implementations and the accompanying interoperability issues (bad software
stacks plague Bluetooth Classic to this day).

There may be profiles for which ATT/GATT is not ideal as the application protocol.
But there can always be a second L2CAP connection in parallel with ATT channel,
which in turn implements a profile-specific protocol.

Now, let's take a deeper look into each protocol.


https://epxx.co/artigos/bluetooth_gatt.html 1/11
6/7/2019 Bluetooth: ATT and GATT

ATT: Attribute Protocol

The sole building block of ATT is the attribute. An attribute is composed by three
elements:

a 16-bit handle;

a UUID which defines the attribute type;

a value of a certaing length.

From the point of view of ATT, value is amorphous, it is an array of bytes of any
size. The actual meaning of the value depends entirely on UUID, and ATT does not
check if the value length is consistent with a given UUID etc.

The handle is just a number that uniquely identifies an attribute (since there may
be many attributes with the same UUID within a device).

ATT itself does not define any UUID. This is left to GATT and higher-level profiles.

An ATT server stores attributes. An ATT client stores nothing; it uses the ATT wire
protocol to read and write values on server attributes.

There may be security permissions associated with each attribute. They are stored
somewhere inside the value, and are defined by higher-level profiles. ATT itself
does not "know" them, and does not try to interpret attribute values to test
permissions. This is GATT's (and higher profile's) problem.

ATT wire protocol has some nice features, like searching attributes by UUID,
getting all attributes given a handle range and so on, so the client does not need
to know handle numbers beforehand, nor the higher-level profiles have to
hardcode them.

But handle numbers are expected to be stable for each given device. This allows
clients to cache information, using less packets (and less energy) to retrieve
attribute values after a first discovery. Higher-level profiles specify how to "hint"
a client that a server has changed attribute layout (e.g. after a firmware upgrade).

https://epxx.co/artigos/bluetooth_gatt.html 2/11
6/7/2019 Bluetooth: ATT and GATT

Most of the ATT protocol is pure client-server: client takes the initiative, server
answers. But ATT has notification and indication capabilities, in which the server
takes the initiative of notifying a client that an attribute value has changed, saving
the client from having to poll the attribute.

The wire protocol never sends value length; it is always implied from PDU size,
and client is expected to "know" the exact value layout for the UUID types it
understands.

Not sending value length explicitly saves bytes, which is particularly important in
Low Energy, since MTU (maximum transmission unit) in LE is just 23 bytes.

The small LE MTU is a problem for large attribute values. For those, ATT has "read
long" and "write long" operations, which transfer big attributes in chunks.

ATT adapts to link MTU; it does not limit packet size to lowest-common
denominator. For example, a 40-byte attribute demands using the "read long"
operation over LE, but can be read atomically over BR/EDR transport since the
minimum MTU for the latter is 48 bytes.

ATT is very, very generic, and would leave too much for higher-level profiles to
define. Apart from the excess of freedom, there are some open issues, like: what if
a device offers multiple services? There is just one ATT handle space for each
device, and multiple services must share the space in a cooperative way.

Fortunately, we have GATT, which shapes and delimits usage of attributes.

GATT: Generic Attribute Profile

GATT is a base profile for all top-level LE profiles. It defines how a bunch of ATT
attributes are grouped together into meaningful services.

GATT services

The cornerstone of a GATT service is the attribute with UUID equal to 0x2800. All
attributes following this belong to that service, until another attribute 0x2800 is
found.

https://epxx.co/artigos/bluetooth_gatt.html 3/11
6/7/2019 Bluetooth: ATT and GATT

For example, a device with three services might have the following attribute
layout:

Handle UUID Description

0x0100 0x2800 Service A definition

... ... Service details

0x0150 0x2800 Service B definition

... ... Service details

0x0300 0x2800 Service C definition

... ... Service details

Each attribute does not "know" by itself to which service it belongs. GATT needs to
figure it out based on handle ranges, and ranges are discovered solely on basis of
UUID 0x2800 "cornerstones".

Suddenly, the handle value becomes significant. In the example, for an attribute to
belong to service B, it must lie between 0x0151 and 0x02ff.

The UUID 0x2800 defines primary services. There are secondary services, too
(UUID 0x2801), which are meant to be included by primary services.

Ok, how do I know if a given service is a thermometer, of keyfob, or GPS? By


reading its value. The service attribute value contains a UUID, the service UUID.

So, each service definition attribute has actually two UUIDs in its body: 0x2800 or
0x2801 as attribute UUID, and another one stored in value, which specifies the
service.

For example, suppose an hypothetical LE thermometer service has UUID 0x1816.


The complete service attribute becomes:

Handle UUID Description Value

0x0100 0x2800 Thermometer service definition UUID 0x1816

https://epxx.co/artigos/bluetooth_gatt.html 4/11
6/7/2019 Bluetooth: ATT and GATT

Handle UUID Description Value

... ... Service details ...

0x0150 0x2800 Service B definition 0x18xx

... ... Service details ...

0x0300 0x2800 Service C definition 0x18xx

... ... Service details ...

This sounds a bit confusing at first; two UUIDs to define a single service? It is a
result of layered GATT/ATT approach. The UUID 0x2800, which is well-known by
GATT, is used to search for service boundaries. Once they are found, the attributes
are read and the second UUID (stored as value) specifies the service. So a client
may find all GATT services without knowing the specifics of e.g. a thermometer
service.

Important note: the thermometer UUID 0x1816 is not real. An official profile
for an LE thermometer did not exist at the time this article was written. If
you want the true UUIDs, grab the official spec.

GATT service characteristics

Each GATT service has a number of characteristics. The characteristics store useful
values for the services, as well as their permissions.

For example, a thermometer would likely have a "temperature" characteristic,


which is read-only, and possibly a date/time for timestamping, which is
read/write.

Handle UUID Description Value

0x0100 0x2800 Thermometer service definition UUID 0x1816

UUID 0x2A2B
0x0101 0x2803 Characteristic: temperature
Value handle: 0x0102

0x0102 0x2A2B Temperature value 20 degrees

https://epxx.co/artigos/bluetooth_gatt.html 5/11
6/7/2019 Bluetooth: ATT and GATT

Handle UUID Description Value

UUID 0x2A08
0x0110 0x2803 Characteristic: date/time
Value handle: 0x0111

0x0111 0x2A08 Date/Time 1/1/1980 12:00

First off, there may be several characteristics per service, and each handle ranges
for each characteristic are discovered by GATT the same way it does for services:
by finding the "cornerstone" attributes.

The main characteristic attribute has UUID = 0x2803. As happens with services,
this attribute has "double UUIDs": the generic one (0x2803) which allows for easy
discovering, and the specific one (in example: 0x2A2B for temperature) which
tells exactly which information the characteristic contains.

Each characteristic has at least two attributes: the main attribute (0x2803) and a
value attribute that actually contains the value. The main attribute "knows" the
value attribute's handle and UUID. This allows for a certain degree of cross-
checking.

The actual value format is entirely defined by its UUID. So, if the client knows how
to interpret the value UUID 0x2A08, it is capable of reading date and time from
any service that contains such a characteristic. In the other hand, if the client does
not know how to interpret a certain value UUID, it may safely ignore it.

Important note: the thermometer service layout shown in table is completely


fictitious. It was put together just to explain the concept of characteristics. If
you are going to implement a true thermometer, please grab and read the
official spec.

Characteristic descriptors

Apart from value, we can hang more attributes on every characteristic, if we need
them. In GATT lingo, those extra attributes are called descriptors.

For example, we may need to identify the temperature unit of our thermometer,
and this may be carried out by a descriptor:

https://epxx.co/artigos/bluetooth_gatt.html 6/11
6/7/2019 Bluetooth: ATT and GATT

Handle UUID Description Value

0x0100 0x2800 Thermometer service definition UUID 0x1816

UUID 0x2A2B
0x0101 0x2803 Characteristic: temperature
Value handle: 0x0102

0x0102 0x2A2B Temperature value 20 degrees

0x0104 0x2A1F Descriptor: unit Celsius

UUID 0x2A08
0x0110 0x2803 Characteristic: date/time
Value handle: 0x0111

0x0111 0x2A08 Date/Time 1/1/1980 12:00

GATT "knows" that handle 0x0104 is a descriptor that belongs to characteristic


0x0101 because

a) it is not the value attribute, since the value attribute is known to be 0x0102;
and

b) it falls into the range 0x0103..0x010F, which falls between one characteristic
and the next.

The descriptor value is interpreted accordingly to attribute UUID. In the example,


descriptor's UUID was 0x2A1F. A client may safely ignore a descriptor whose UUID
is unknown. This allows for easy extension of a service, without breaking old
clients.

Each service may define its own descriptors, but GATT defines a set of standard
descriptors that cover most cases, for example:

Numeric format and presentation;

Human-readable description;

Valid range;

Extended properties;

and so on. One particularly important descriptor is the client characteristic


configuration.

https://epxx.co/artigos/bluetooth_gatt.html 7/11
6/7/2019 Bluetooth: ATT and GATT

Client Characteristic Configuration descriptor

This descriptor, whose UUID is 0x2902, has a read/write 16-bit value, which is
meant to be a bitmap.

It is not some kind of client-side descriptor. It is server-side as any other


attribute. But the server is required to store and present a separate instance of the
value for each bonded client, and each client can only see its own copy. Hence the
name.

First two bits of CCC are already taken by GATT specification. They configure
characteristic notification and indication. The other bits might be used for other
functions, but they are currently reserved.

Remember that ATT has notification capabilities, so the client does not need to
poll for updates? By setting CCC, the client tells to server that it wants to be
notified when the characteristic changes. It makes all sense for e.g. a
thermometer. Let's see the thermometer service layout with CCC included:

Handle UUID Description Value

0x0100 0x2800 Thermometer service definition UUID 0x1816

UUID 0x2A2B
0x0101 0x2803 Characteristic: temperature
Value handle: 0x0102

0x0102 0x2A2B Temperature value 20 degrees

0x0104 0x2A1F Descriptor: unit Celsius

0x0105 0x2902 Client characteristic configuration descriptor 0x0000

UUID 0x2A08
0x0110 0x2803 Characteristic: date/time
Value handle: 0x0111

0x0111 0x2A08 Date/Time 1/1/1980 12:00

As usual, GATT knows that CCC belongs to temperature chraracteristic because the
handle falls into the range (0x0102..0x010F). And it knows it is CCC because of
the distinctive UUID (0x2902).
https://epxx.co/artigos/bluetooth_gatt.html 8/11
6/7/2019 Bluetooth: ATT and GATT

Service discovery in Low Energy

Since GATT puts all service details on ATT, there is no need for a separate service
discovery protocol (SDP), like we have in BR/EDR. The ATT protocol is used for
everything: disconvering services, finding services' characteristics, reading/writing
values, and so on.

GATT and vanilla Bluetooth

GATT works over BR/EDR, but specification mandates that service discovery must
still happen via SDP, even if the service (or the profile) uses GATT for actual data
exchange.

The idea is to segregate LE-only services from dual-mode ones, without having to
flag them. If a service can only be found via GATT, it is LE-only. If it can be found
via GATT and via SDP, it is dual-mode.

If a given profile uses GATT for data exchange and is meant to be dual-mode, it
must publish a SDP record, which contains the ATT handle range for the service.
So, the service itself is discovered via SDP, and from that moment on GATT is
employed to find the characteristics.

Currently, there is no profile that is dual-mode. "Old" profiles are BR/EDR-only


and have not been adapted to GATT; and LE profiles in current development are
LE-only.

If one wants to test GATT and does not possess LE hardware, he will need to patch
the Bluetooth stack in so GATT discovery is carried out over BR/EDR. This violates
the spec but it is very useful for developers.

Notifications versus connections

Notifications and indications are mechanisms that allow the server to send a
message to the client. Thanks to them, the client does not have to poll the server
for new data.

https://epxx.co/artigos/bluetooth_gatt.html 9/11
6/7/2019 Bluetooth: ATT and GATT

In the other hand, the typical GATT server is a "small", peripheral device, like a
sensor, that must conserve energy. Because of this, peripheral LE devices cannot
take the initiative of a Bluetooth connection. But then, how the notification can be
sent at all?

In BLE, when a server has data to send, it goes into Advertising mode, which sends
some radio signal. Each profile specifies the time span and frequency that a device
should advertise, balancing energy consumption against the probability of being
found, given the use cases.

The device in central role (cell phone, computer, anything with energy to spare)
has its radio turned on all the time in "listening mode". Let's say it's a phone.
When the phone listens an advertisement, and the advertised device is "known" (it
was paired or whitelisted with this phone), the phone should connect with the
peripheral device.

Once the connection is up, GATT communication can flow and the notification can
be delivered. So the typical sequence is: 1) server advertises; 2) client connects;
3) server notifies.

At this point, either side can establish a timeout for disconnection if no more
notifications are received. The "best" timeout depends on the use case; a service
with infrequent notifications and no real-time pretensions may just disconnect
immediately to save energy.

Since BLE advertisement/reconnection mechanism is very fast — a major


improvement from classic Bluetooth — I expect most profiles to use a very short
timeout or none at all.

The typical GATT server is a peripheral device, but this is not mandatory; we could
have a peripheral client and a central server, or two central devices
communicating with each other. It is opportune to mention that, in this (rather
uncommon) case, the client would have to enter Advertising mode when it wants
to query the server e.g. read or write a characteristic.

https://epxx.co/artigos/bluetooth_gatt.html 10/11
6/7/2019 Bluetooth: ATT and GATT

1 Comment Sort by Newest

Add a comment...

Jwngsar Basumatary
One of the best explanations of GATT/ATT
Like · Reply · 1w

Facebook Comments Plugin

This is the personal site of // Este é o site pessoal de


→ Elvis Pfützenreuter – PU5EPX   

https://epxx.co/artigos/bluetooth_gatt.html 11/11

You might also like