summaryrefslogtreecommitdiffstats
path: root/bluez-le-howto.tex
blob: 0ce9ca57e91ecc10d34ce6ea0b427875112d9955 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
\documentclass[11pt]{article}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{graphicx}
\usepackage{fancyhdr}

\pagestyle{fancy}
\lhead{}
\chead{}
\rhead{}
\fancyfoot[C] {This document is confidential}
\fancyfoot[R] {\thepage}
\fancyhead[C] {BlueZ BTLE How-To}
\fancyhead[R] {\thepage}

\setlength{\parskip}{10pt}

\title{BlueZ BTLE How-To}
\author{Claudio Takahasi \\ claudio.takahasi@openbossa.org \and
        João Paulo Rechi Vita \\ jprvita@openbossa.org \and
        Paulo Alcantara \\ paulo.alcantara@openbossa.org}

\begin{document}


\maketitle
\newpage


\tableofcontents
\newpage


\section{Introduction}

This document describes how to test and use Bluetooth Low-Energy on Linux
systems, using the most recent implementation available at the moment of this
writing. The instructions are based on an
Ubuntu\footnote{http://www.ubuntu.com/download/ubuntu/download} Linux 11.10,
since its the most widely deployed Linux distribution nowadays. Nonetheless,
the process for other distributions should be very similar.


\section{Dependencies}

Bellow are listed the libraries and tools needed to compile BlueZ for BTLE
development. The list uses the packages name on Ubuntu 11.10.

\begin{itemize}
 \item git
 \item automake
 \item byacc
 \item flex
 \item libtool
 \item libdbus-1-dev
 \item libglib2.0-dev
 \item libcap-ng-dev
 \item libusb-dev
 \item libudev-dev
 \item libreadline-dev
\end{itemize}

To install packages on Ubuntu, use \verb|apt-get|, like shown bellow.

\begin{verbatim}
$ sudo apt-get install <package>
\end{verbatim}

Make sure you have {\em libreadline-dev} installed, otherwise \verb|gatttool| is not
built.


\section{Getting the source code}


\subsection{Linux kernel}

BTLE development is focused on the new Management API, which requires a very
recent kernel tree. The most up-to-date kernel tree with several LE-specific
fixes can be found on the {\em integration} branch of the following tree on
github. Eventually this branch will be integrated on the official kernel trees.
Don't bother trying to compile other branches, since they have experimental
changes. To access this code, clone the tree and checkout the branch:

\begin{verbatim}
$ git clone -b integration git://github.com/aguedes/linux.git
\end{verbatim}

Additionally, one should take special care when doing changes on top of this
branch, since it's going to be constantly rebased on top of the {\em
bluetooth-next} kernel tree.

To update the local branch with the latest version of the remote {\em
integration} branch (make sure you're on the {\em linux} directory and {\em
integration} branch):

\begin{verbatim}
$ git fetch origin
$ git reset --hard origin/integration
\end{verbatim}

Note that all local changes to tracked files will be lost.


\subsection{Userspace}

The upstream BlueZ tree has all the code necessary for testing and do further
BTLE development on Linux.

\begin{verbatim}
$ git clone -b integration \
        git://git.infradead.org/users/cktakahasi/bluez.git
\end{verbatim}


\section{Building and running}


\subsection{Linux kernel}

Now, copy the Linux kernel configuration file from Ubuntu as \verb|.config| to
the Linux kernel sources directory, and generate a new configuration based on
the Ubuntu configuration file. Just press {\em Enter} for each question until
\verb|make oldconfig| returns.

\begin{verbatim}
$ cd linux
$ cp /boot/config-`uname -r` .config
$ make oldconfig
\end{verbatim}

Ubuntu doesn't enable {\em dynamic debug} on its stock kernel, so it should be
manually enabled to make possible to obtain debug information from the kernel
later. Edit the \verb|.config| file with your favorite editor, find the line
that says \verb|# CONFIG_DYNAMIC_DEBUG is not set| and substitute the whole
line with \verb|CONFIG_DYNAMIC_DEBUG=y|.

Now you're ready to compile your kernel. To build and generate a Debian package
that can be installed on Ubuntu the packages {\em fakeroot} and {\em dpkg-dev}
are needed.  Make sure they're installed and run:

\begin{verbatim}
$ make deb-pkg
\end{verbatim}

Then install the new kernel packages with {\em dpkg}:

\begin{verbatim}
$ cd ..
$ sudo dpkg -i linux-image* linux-headers*
\end{verbatim}

After the installation is complete, reboot to use the new kernel. To enable LE
discovery a parameter should be passed to the {\em bluetooth} kernel module. After
unloading all bluetooth adapters ({\em hci0} to {\em hciN}) and bluetooth
kernel modules, the {\em bluetooth} module should be reloaded with {\em
enable\_le=1} (make sure you substitute {\em hciX} with the name of the
adapter, for all bluetooth adapters on the system).

\begin{verbatim}
$ sudo service bluetooth stop
$ sudo hciconfig hciX down
$ sudo rmmod bnep rfcomm btusb bluetooth
$ sudo modprobe bluetooth enable_le=1
$ sudo modprobe btusb
\end{verbatim}

To check if the {\em bluetooth} module has been loaded with correct parameters,
refer to Section \ref{sec:test-mgmt}.


\subsection{Userspace}

BlueZ has a script that does the {\em bootstrap} and {\em configure} phases
with the recommended options for developers. Using it will ease the test and
development processes and is highly recommended. After downloading the source
code, run this script to prepare for compilation.

\begin{verbatim}
$ cd bluez
$ ./bootstrap-configure
\end{verbatim}

Due to a bug in Debian (thus Ubuntu) packaging, if you have the {\em check}
package installed you have to pass the link flag for the correct version of
{\em libcheck}. {\em Libcheck} is an optional dependency.

\begin{verbatim}
CHECK_LIBS="-lcheck_pic" ./bootstrap-configure
\end{verbatim}

And then build the binaries with {\em make}.

\begin{verbatim}
$ make
\end{verbatim}

Now you're ready to run the Bluetooth daemon you've just compiled. First stop
the one that came with you distribution:

\begin{verbatim}
$ sudo service bluetooth stop
\end{verbatim}

And then manually start it from the source tree, without forking into a daemon
(n) and with debug enabled (d).

\begin{verbatim}
$ sudo src/bluetoothd -nd
\end{verbatim}


% \subsection{Reporting errors}
% FIXME: Add here instructions to report errors: hcidump logs, kernel logs,
% bluetoothd traces, valgrind


\section{Testing management interface} \label{sec:test-mgmt}

The Bluetooth Management Interface is a new kernel-userspace API, which
replaces the traditional HCI interface. It aims to move some core host features
inside the kernel, hiding from the userspace some hardware or controller
specific features. It doesn't aim to expose every HCI command, but to group
them in meaningful commands.

Management interface usage is transparent to the userspace. BlueZ supports an
abstraction to hide the active interface from the user, through a plugin called
{\em adapter\_ops}. There is one plugin implementation that uses the management
interface, with higher priority, and another one that uses the HCI. If the MGMT
interface is not enabled in the kernel, the plugin system will fallback to HCI
plugin.

To check if the MGMT interface and LE discovery are enabled in the kernel, the
following command should return a \verb|Y|.

\begin{verbatim}
$ cat /sys/module/bluetooth/parameters/enable_le
Y
\end{verbatim}


% \subsection{btmgmt}
% describe here how to pair and start discovery using btmgmt


\section{Enabling debug}


\subsection{Enabling kernel debug}

Is possible to collect Bluetooth debug information from the kernel through {\em
debugfs}. It is a virtual file system that allows debug to be enabled on a
per-file base.

First check if dynamic debug and debugfs are enabled in the kernel settings
(.config file). If not, recompile you kernel with that features enabled.

\begin{verbatim}
CONFIG_DEBUG_FS=y
CONFIG_DYNAMIC_DEBUG=y
\end{verbatim}

Dynamic debugging is controlled via the {\em dynamic\_debug/control} file.
Bluetooth files that you wanna track should be added to that file, with {\em
root} privileges.

\begin{verbatim}
$ sudo su -
# FILES="net/bluetooth/hci_sock.c \
> net/bluetooth/hci_conn.c \
> net/bluetooth/hci_event.c \
> net/bluetooth/l2cap_core.c \
> net/bluetooth/l2cap.c \
> net/bluetooth/smp.c \
> net/bluetooth/hci_core.c \
> net/bluetooth/mgmt.c"

# for f in $FILES
> do
> echo "file $f +pf" >> /sys/kernel/debug/dynamic_debug/control
> done
# exit
\end{verbatim}

And finally, to see the messages through \verb|dmesg|, the level of messages
printed to console should be set to {\em debug}:

\begin{verbatim}
$ sudo dmesg -n debug
\end{verbatim}


\section{Testing using Python scripts}

BlueZ (bluetoothd) exposes a D-Bus \footnote{http://dbus.freedesktop.org/} API
to allow the applications to configure Bluetooth adapters, manage discovery,
pair with devices and interact with services.

D-Bus is widely used in Linux distributions as interprocess communication
mechanism. Python offers language bindings for D-Bus, exposing a simple syntax
to create {\em proxy objects} to interact with remote applications.

On the BlueZ API, there is a D-Bus object to represent each paired remote
Bluetooth device.  {\em CreateDevice} or {\em CreatePairedDevice} are the
starting point to access remote device's services. Bluetooth Low Energy support
in BlueZ aligns with BR/EDR, device discovery and pairing operations share the
same API.

There are a bunch of python scripts available under the \verb|test| directory
which use the D-Bus API and are good examples of its usage.


\subsection{Discovering devices}

Device discovery can be executed through management interface or the
standard HCI interface. The difference is where the code is implemented:
for Management, the discovery is in the kernel instead of userspace
plugin (HCI {\em adapter\_ops} plugin).

When using the MGMT interface, if LE discovery has been enabled through the
{\em enable\_le} module parameter, interleaved (LE + BR/EDR) discovery will be
performed. Otherwise only BR/EDR inquiry will be executed.

Start Discovery command in MGMT interface has a bit-wise parameter to inform
which remote address type is expected. At the moment, interleaved discovery is
the default method hard-coded in bluetoothd LE is enabled and the adapter used
is dual-mode.  The \verb|btmgmt| tool can be used to test discovery instead,
filtering per address type. The following values are allowed:

\begin{verbatim}
1   BR/EDR
6   LE (public & random)
7   BR/EDR/LE (interleaved discovery)
\end{verbatim}

Testing discovery using the D-Bus API:

\begin{verbatim}
$ ./test-discovery
\end{verbatim}

Testing discovery directly through MGMT socket, finding LE devices, both public
and random addresses:

\begin{verbatim}
$ sudo ./btmgmt find -l
\end{verbatim}

Finding BR/EDR devices through the MGMT socket:

\begin{verbatim}
$ sudo ./btmgmt find -b
\end{verbatim}

Without any parameter \verb|btmgmt find| will perform interleaved discovery:
5.12s of LE scanning followed by 5.12s of inquiry.


\subsection{Managing devices}


\subsubsection{Pairing}

The \verb|simple-agent| is a script that acts as an UI agent for Bluetooth
adapters, handling \verb|bluetoothd| requests for UI actions, like presenting a
PIN prompt and similar operations.

To start pairing with a specific device ({\em hciX} should be changed with the
correct adapter name):

\begin{verbatim}
$ simple-agent hciX <device address>
\end{verbatim}

The \verb|--capability| (short form \verb|-c|) option can be used to change how
the host will present itself to the remote device, regarding the capabilities
it have to present or request input of PIN codes during the pairing process.

The default value is {\em KeyboardDisplay}, and other possible values are {\em
DisplayOnly}, {\em DisplayYesNo}, {\em KeyboardOnly}, and {\em
NoInputNoOutput}.

It's also possible to register an agent to handle UI operations of incoming
pairing requests:

\begin{verbatim}
$ simple-agent hciX
\end{verbatim}

If it all works, the message {\em Agent registered} will be printed on the
console. Note that the agent doesn't set the adapter as {\em Discoverable} or
{\em Connectable}, this should be done via the MGMT interface.

Pairing can now be started on the remote device and \verb|simple-agent| will
ask for the PIN code, if needed. After entering it followed by Enter, if no
error occurs, the device will be paired with the adapter it is handling.


\subsubsection{Managing paired devices}

After pairing with a new device, the \verb|test-device| script can be used to
interact with the remote device. The possible actions are listed bellow:

\begin{enumerate}

\item List all known Bluetooth devices.

\begin{verbatim}
$ test-device list
\end{verbatim}

\item List GATT services from a given device.

\begin{verbatim}
$ test-device services <device address>
\end{verbatim}

\item Create a remote device from a given Bluetooth address. Triggers the SDP
or discover all primary services.

\begin{verbatim}
$ test-device create <device address>
\end{verbatim}

\item Remove all the information related to a device on the local storage. This
information includes settings, SDP information, cached attributes and
characteristics, and linkkeys. The argument can be either the device address or
D-Bus object path.

\begin{verbatim}
$ test-device remove <device address or object path>
\end{verbatim}

\item Disconnect a remote device.

\begin{verbatim}
$ test-device disconnect <device address>
\end{verbatim}

\item Discover a device from a given Bluetooth address and also an optional
pattern string. If this option argument is the string {\em yes}, for example,
then the {\em DiscoverDevices} method of the {\em org.bluez.Device} interface
will be called and find presumably the device that matches this pattern. Method
used to update the service list using SDP or discover all primary services.

\begin{verbatim}
$ test-device discover <device address> [pattern]
\end{verbatim}

\item Return the device class (retrieved using {\em
org.bluez.Device.GetProperties} method which returns all the properties of the
attached Bluetooth adapter) from a given Bluetooth address.

\begin{verbatim}
$ test-device class <device address>
\end{verbatim}

\item Return the device name (retrieved using {\em
org.bluez.Device.GetProperties} method which returns all the properties of the
attached Bluetooth adapter) from a given Bluetooth address.

\begin{verbatim}
$ test-device name <device address>
\end{verbatim}

\item Return the alias name (retrieved using {\em
org.bluez.Device.GetProperties} method which returns all the properties of the
attached Bluetooth adapter) from a given Bluetooth address.

\begin{verbatim}
$ test-device alias <device address> [alias]
\end{verbatim}

\item Set the value of the property named {\em Trusted} by passing as third
argument with either the values {\em yes} or {\em no}. Marking a device as
trusted for the adapter means that no authorization will be asked for the user
(through the user-agent) on an incoming connection from that device. This
applies to BR/EDR devices only.

\begin{verbatim}
$ test-device trusted <device addres> [yes/no]
\end{verbatim}

\item Set the value of the property named {\em Blocked} by passing as third
argument either the values {\em yes} or {\em no} (this command also requires an
address to be passed as second argument).

\begin{verbatim}
$ test-device blocked <device address> [yes/no]
\end{verbatim}

\end{enumerate}


\subsection{Generic Attribute API}

Generic Attribute API documentation is available at {\em
doc/attribute-api.txt}.  It's still an experimental API. GATT based services
have different requirements regarding (re)connection behaviour, making
abstractions difficult. The idea behind this API is to provide a generic method
so external GATT client applications can handle characteristics directly.

Applications can use the Generic Attribute API or use profile specific APIs.
Currently available profile APIs are {\em Proximity}, {\em Find Me}, and {\em
Thermometer}.

The \verb|test-attrib| is a script which tests the Generic Attribute D-Bus API.
Before using \verb|test-attrib| the remote device needs to be paired using
\verb|test-device|, \verb|simple-agent| or any other client.

Usage example:

\begin{enumerate}

\item For each Bluetooth LE device, return its address, as well for each
service of such Bluetooth LE device, and then return the service object path,
UUID, and all characteristics of it, respectively.

\begin{verbatim}
$ test-attrib list
\end{verbatim}

\item Return all GATT services supported by the device.

\begin{verbatim}
$ test-attrib services <Bluetooth address>
\end{verbatim}

\item Return all discovered characteristics that belongs to a given service
object path (primary service).

\begin{verbatim}
$ test-attrib discover <Service object path>
\end{verbatim}

\item Return all properties that belongs to a given GATT characteristic.

\begin{verbatim}
$ test-attrib chars <Service object path>
\end{verbatim}

\end{enumerate}


\subsection{Managing local Bluetooth adapter}

The \verb|test-adapter| script will make use of the Adapter D-Bus API to handle
Bluetooth adapters.

\begin{enumerate}

\item Retrieve Bluetooth adapter's address.

\begin{verbatim}
$ test-adapter address
\end{verbatim}

\item List all available Bluetooth adapters, as well as their object path, and
pair of key and value for all their properties.

\begin{verbatim}
$ test-adapter list
\end{verbatim}

\item Retrieve Bluetooth adapter's name (if no argument specified), otherwise
set the property named {\em Name} to the value passed as argument. Once it's
got its new name set, all other Bluetooth devices will see this new name when
looking for Bluetooth devices to pair with.

\begin{verbatim}
$ test-adapter name [name]
\end{verbatim}

\item Set the property named {\em Powered} to the value passed as argument (if
any), otherwise return the value that was previously set in it.

\begin{verbatim}
$ test-adapter powered [on/off]
\end{verbatim}

\item Set the property named {\em Pairable} to the value passed as argument (if
any), otherwise return the value that was previously set in it.

\begin{verbatim}
$ test-adapter pairable [on/off]
\end{verbatim}

\item Set the property named {\em PairableTimeout} to the value passed as
argument (if any), otherwise return the value that was previously set in it.
Note also that the value passed as argument must be an unsigned integer.

\begin{verbatim}
$ test-adapter pairabletimeout [timeout]
\end{verbatim}

\item Set the property named {\em Discoverable} to the value passed as argument
(if any), otherwise return the value that was previously set in it.

\begin{verbatim}
$ test-adapter discoverable [on/off]
\end{verbatim}

\item Set the property named {\em DiscoverableTimeout} to the value passed as
argument (if any), otherwise return the value that was previously set in it.
Note also that the value passed as argument must be an unsigned integer.

\begin{verbatim}
$ test-adapter discoverabletimeout [timeout]
\end{verbatim}

\item Return the current value of the property named {\em Discovering}.

\begin{verbatim}
$ test-adapter discovering
\end{verbatim}

\end{enumerate}


\subsection{Proximity API}

The Proximity API is available at {\em doc/proximity-api.txt}. The
\verb|test-proximity| Python script uses the Proximity Monitor D-Bus API. It
can be used to set values for LinkLossAlertLevel and ImmediateAlertLevel. The
values permitted are "none", "mild" and "high".

First, pair with remote device using \verb|simple-agent| or any other BlueZ
pairing tool. After this, \verb|test-proximity| can be used.

\begin{enumerate}

\item The LinkLossAlertLevel operation only takes effect when link is lost, at which
point the device will alert at the specified intensity level. For example, to
set LinkLossAlertLevel to "mild":

\begin{verbatim}
$ ./test-proximity -b <device address> LinkLossAlertLevel mild
Proximity SetProperty('LinkLossAlertLevel', 'mild')
PropertyChanged('LinkLossAlertLevel', 'mild')
\end{verbatim}

\item Using the ImmediateAlertLevel for any value other than "none" will make the
remote device alert as soon as possible at the specified intensity level. For
example, to set ImmediateAlertLevel to "high":

\begin{verbatim}
$ ./test-proximity -b <device address> ImmediateAlertLevel  high
Proximity SetProperty('ImmediateAlertLevel', 'high')
PropertyChanged('ImmediateAlertLevel', 'high')
\end{verbatim}

\end{enumerate}

\subsection{Thermometer API}

After connected with a {\em Thermometer}, the daemon of BlueZ will export a new
interface \verb|org.bluez.Thermometer| under \verb|org.bluez| service in D-Bus.
Each {\em Thermometer} device will appear with object path as \\
\verb|[prefix]/{hciX}/dev_XX_XX_XX_XX_XX_XX|.
The device path can be found using \verb|FindDevice| method under adapter path.

With device path, we just need to register a {\em Watcher} to listen measures
updates. For this, we create a {\em Watcher} object that implements \\
\verb|MeasurementReceived| method.

\begin{enumerate}

\item For testing purposes, there is a Python named \verb|test-thermometer| in BlueZ.
To get temperature information, run:

\begin{verbatim}
$ ./test-thermometer -b <device address>
Final  measurement received
Exponent:  -1
Mantissa:  372
Unit:  Celsius
Time:  943934599
Type:  Mouth
\end{verbatim}

\item To get {\em Intermediate Temperature} characteristic, we need to enable
in test script:

\begin{verbatim}
$ ./test-thermometer EnableIntermediateMeasurement -b <device address>
Intermediate  measurement received
Exponent:  -1
Mantissa:  372
Unit:  Celsius
Time:  943934590
Type:  Mouth
Final  measurement received
Exponent:  -1
Mantissa:  372
Unit:  Celsius
Time:  943934599
Type:  Mouth
\end{verbatim}

\end{enumerate}

%\section{Low Level GATT client API}

\section{Low Level GATT server API}

BlueZ doesn't allow external applications to register new GATT services.
The developer needs to write new service plugins following the GNU General
Public License premises.

GATT server functions declarations to manage services and characteristics
can be found in the following 'c' header files:

\begin{enumerate}
\item{\em attrib/gatt-service.h}: abstraction functions to add new service
	based on low level attrib server functions
\item{\em src/attrib-server.h}: functions to manage attributes directly in
	in the attribute server
\end{enumerate}

Current Time service is one simple example of how to use the internal GATT
server API.

% \section{Supporting tools}
% 
%
% \subsection{L2CAP testing}
% 
% The l2test is a tool which is part of the BlueZ package.
% 
% \begin{verbatim}
% $ TODO: example goes here
% \end{verbatim}
% 
%
% \subsection{GATT testing}
% 
% The gatttool is a tool which is part of the BlueZ package.
% 
% \begin{verbatim}
% $ TODO: example goes here
% \end{verbatim}
% 
%
% \subsection{Dump raw HCI data}
% 
% The hcidump is a tool which is part of the BlueZ package. It's the
% BlueZ project Bluetooth HCI data dumper which lets you view raw HCI
% data to and from a Bluetooth device in a human readable way.
% 
% Start hcidump like this and create a Bluetooth connection to your
% device:
% \begin{verbatim}
% $ hcidump -V -x
% \end{verbatim}
% 
% You will see a lot of verbose messages of the data and state of the connection.
% 
% explain here l2test, gatttool, hcidump

\end{document}