The birth of GattLib - Solving BLE GATT access on Long Term supported Linux distributions by Olivier on 28/04/2016 14:03

Problematic

In one of our projects we had to communicate with BLE (Bluetooth Low Energy) devices. After some early investigations we highlighted two issues:

C GATT Library

We know GATT libraries exist in other languages (eg: pygattlib for python, bluepy) but impossible to find one in C!

GATT protocol did not seem to be supported by libbluetooth:

$ mkdir /tmp/libbluetooth-dev && cd /tmp/libbluetooth-dev
$ wget http://es.archive.ubuntu.com/ubuntu/pool/main/b/bluez/libbluetooth-dev_4.101-0ubuntu13_amd64.deb
$ sudo dpkg -x libbluetooth-dev_4.101-0ubuntu13_amd64.deb
$ grep -r gatt ./usr
$

Our project being mainly built in C we were not really considering to rewrite it into another language to only use an existing GATT library.

Bluez v4.x Support

The 'new' Bluez D-BUS API that enables any user space application to communicate with Bluetooth devices through D-BUS is only supported in the latest Bluez v5.x releases. The Bluez D-BUS API is still receiving many bug fixes - we recently contributed a fix for it.
Unfortunately, few LTS (Long Term Support) Linux distributions still use Bluez v4.x - including Ubuntu 14.04 LTS that only support Bluez v4.x. Ubuntu 14.04 LTS is still supported until 2019! Either we do not support a widely available Linux distribution (including my own development machine!) or we find the solution to our issue...

Funnily enough I discovered the day we started our investigation that the day after would have been released the new Ubuntu 16.04 LTS. So I could have potentially go to the beach for a day and upgrade my Ubuntu machine the day after with the new LTS and Bluez v5.x and its D-BUS API.
But looking at different discussion threads on Internet I realized that there was a real gap. We had the mission to fix it!

Investigation

During my initial investigation, I found that the only way to use Bluez GATT support was to manually pickup the files used by BlueZ gatttool and to call the GATT functions in the way gatttool is doing.
Obviously as many Open Source project no documentation - the documentation is the source code...
After losing few hairs while trying to understand the almost non commented source code and thinking few times I would lose my time with this new project. I decided to start slowly and see if I could isolate the source files and build gatttool into its own project directory.

  1. The initial step was to retrieve the latest stable version of Bluez v4.x (ie: v4.101 - actually the same version used by Ubuntu 14.04).

  2. From the Bluez Makefile.tools, I could already see the required files and libraries used by gatttool:

    attrib_gatttool_SOURCES = attrib/gatttool.c attrib/att.c attrib/gatt.c \
                                    attrib/gattrib.c btio/btio.c \
                                    attrib/gatttool.h attrib/interactive.c \
                                    attrib/utils.c src/log.c
    attrib_gatttool_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@ @READLINE_LIBS@
    

    I also wanted to see the Bluez build command lines to avoid missing any build arguments.

  3. Build gatttool
    The following dependencies are required: automake, libtool, libdbus-1-dev, libreadline-dev

    git clone git://git.kernel.org/pub/scm/bluetooth/bluez.git
    cd bluez
    git checkout 4.101
    ./bootstrap-configure
    make V=1 attrib/gatttool
    

    Finally, ensure the application runs ./attrib/gatttool

Create GattLib library

  1. Isolate gatttool in its own project and create a CMake file to build the new project.

    We should have this following tree:

    ├── bluez
    │   ├── attrib
    │   │   ├── att.c
    │   │   ├── att.h
    │   │   ├── gatt.c
    │   │   ├── gatt.h
    │   │   ├── gattrib.c
    │   │   ├── gattrib.h
    │   │   ├── gatttool.c
    │   │   ├── gatttool.h
    │   │   ├── interactive.c
    │   │   └── utils.c
    │   ├── btio
    │   │   ├── btio.c
    │   │   └── btio.h
    │   └── src
    │       ├── log.c
    │       └── log.h
    └── CMakeLists.txt
    
  2. If we build this project:

    mkdir build && cd build
    cmake .. && make
    

    We have some expected linking issues because gatttool depends on lib/libbluetooth-private.la:

    Linking C executable gatttool
    /usr/bin/cmake -E cmake_link_script CMakeFiles/gatttool.dir/link.txt --verbose=1
    /usr/bin/cc      CMakeFiles/gatttool.dir/bluez/attrib/att.c.o CMakeFiles/gatttool.dir/bluez/attrib/gatt.c.o CMakeFiles/gatttool.dir/bluez/attrib/gattrib.c.o CMakeFiles/gatttool.dir/bluez/attrib/gatttool.c.o CMakeFiles/gatttool.dir/bluez/attrib/interactive.c.o CMakeFiles/gatttool.dir/bluez/attrib/utils.c.o CMakeFiles/gatttool.dir/bluez/btio/btio.c.o CMakeFiles/gatttool.dir/bluez/src/log.c.o  -o gatttool -rdynamic -lglib-2.0 
    CMakeFiles/gatttool.dir/bluez/attrib/att.c.o: In function `att_get_uuid16':
    att.c:(.text+0x1e5): undefined reference to `bt_uuid16_create'
    CMakeFiles/gatttool.dir/bluez/attrib/att.c.o: In function `att_get_uuid128':
    att.c:(.text+0x263): undefined reference to `bt_uuid128_create'
    CMakeFiles/gatttool.dir/bluez/attrib/gatt.c.o: In function `sdp_get_service_classes':
    gatt.c:(.text+0x8d): undefined reference to `sdp_get_uuidseq_attr'
    CMakeFiles/gatttool.dir/bluez/attrib/gatt.c.o: In function `att_get_uuid16':
    gatt.c:(.text+0x140): undefined reference to `bt_uuid16_create'
    CMakeFiles/gatttool.dir/bluez/attrib/gatt.c.o: In function `att_get_uuid128':
    gatt.c:(.text+0x1be): undefined reference to `bt_uuid128_create'
    CMakeFiles/gatttool.dir/bluez/attrib/gatt.c.o: In function `encode_discover_primary':
    gatt.c:(.text+0x2bc): undefined reference to `bt_uuid16_create'
    CMakeFiles/gatttool.dir/bluez/attrib/gatt.c.o: In function `primary_all_cb':
    

    lib/libbluetooth-private.la uses lib/bluetooth.c, lib/hci.c, lib/sdp.c, lib/uuid.c (see Bluez Makefile.am). Let's add these files to the project.

    After adding this file, I managed to build gatttool. The next step was to separate gatttool from the GATT code to isolate what was gatttool specific and what could be used as the core of the GATT library.

    The gatttool specific files gatttool.c, gatttool.h, interactive.c and utils.c would live in their own directory examples/gatttool.

  3. Thanks to CMake, I quickly had my first GATT shared library and gatttool application binary.
    The next challenge was to provide a new API that would make the use of GattLib really easy.

    The main issue I had during this phase was to understand how gatttool was communicating with Bluez stack.

    I finally found all the interactions were made through GLib IO Channel. GLib IO Channel is a wrapper on top of files, pipes and sockets - Unix Domain Socket are used by Bluez. The IO Channel only works when a GLib Main Event Loop is running.
    As I did not want to force the GattLib users to have to add a GLib Main Event loop to their project I added a thread to GattLib where the GattLib specific GLib Main Loop would run from.

    Bluez GATT API is all about asynchronous callbacks. I wanted my GattLib API to keep this asynchronous feature but also to support synchronous functions.

    After spending a couple of days on this new library, I ended up with a satisfactory result that was good enough for my project.
    I wrote one of my project BLE use cases with my new GattLib library and the result was a code clear to read.

    I also wrote a couple of examples to help users to use this new library.

  4. After doing a bit of CMake and its magic CPack, I could quickly package a first release of GattLib as a Debian/Ubuntu/... DEB package, a RPM package and a ZIP package.

    • DEB Package:

      $ dpkg-deb -I gattlib-0.1.deb
       new debian package, version 2.0.
       size 81510 bytes: control archive=440 bytes.
           258 bytes,    10 lines      control
           175 bytes,     3 lines      md5sums
       Package: gattlib
       Version: 0.1
       Section: devel
       Priority: optional
       Architecture: amd64
       Depends: libglib2.0-0
       Installed-Size: 227
       Maintainer: Olivier Martin <olivier@labapart.com>
       Description: Library to access GATT information from Bluetooth Low Power devices
      
      $ dpkg-deb -c gattlib-0.1.deb
      drwxrwxr-x root/root         0 2016-04-28 13:05 ./usr/
      drwxrwxr-x root/root         0 2016-04-28 13:05 ./usr/lib/
      drwxrwxr-x root/root         0 2016-04-28 13:05 ./usr/lib/pkgconfig/
      -rw-r--r-- root/root       269 2016-04-28 13:04 ./usr/lib/pkgconfig/gattlib.pc
      -rw-r--r-- root/root    228334 2016-04-28 13:05 ./usr/lib/libgattlib.so
      drwxrwxr-x root/root         0 2016-04-28 13:05 ./usr/include/
      -rw-r--r-- root/root      3421 2016-04-28 00:47 ./usr/include/gattlib.h
      
    • RPM Package:

      $ rpm -qpl gattlib-0.1.rpm
      /usr/include/gattlib.h
      /usr/lib/libgattlib.so
      /usr/lib/pkgconfig
      /usr/lib/pkgconfig/gattlib.pc
      
    • ZIP Package:

      $ unzip -l gattlib-0.1.zip
      Archive:  gattlib-0.1.zip
        Length      Date    Time    Name
      ---------  ---------- -----   ----
            269  2016-04-28 13:04   gattlib-0.1/lib/pkgconfig/gattlib.pc
         228334  2016-04-28 13:05   gattlib-0.1/lib/libgattlib.so
           3421  2016-04-28 00:47   gattlib-0.1/include/gattlib.h
      ---------                     -------
         232024                     3 files
      
  5. And finally a couple of days after starting the project, I can make it alive on Github: https://github.com/labapart/gattlib!

Anonymous on 12/05/2022 03:31
canadian pharmacy cialis 20mg <a href="https://postcialis.org/">can i take 40mg of cialis</a> define cialis
Anonymous on 01/06/2022 08:55
Hello,
Really, Thanks a lot for this great job!!!

I want to share my problem that I encountered and maybe someone helps me :(. I am using this code in PC( operating system is Ubuntu 18.04). I believe that I adjusted the Bluetooth setting of the PC. And, gattlib is installed and used as linker during running source code sharing in https://github.com/labapart/gattlib!. then, I try to run examples of "nordic_uart". My BLE device is connected to my PC(when source code is running) via bluetooth but I took the error "Fail to discover characteristic." in my terminal. Thus, the connection is set up but code stucks in here:

// Look for handle for NUS_CHARACTERISTIC_TX_UUID
gattlib_characteristic_t* characteristics;
int characteristic_count;
ret = gattlib_discover_char(m_connection, &characteristics, &characteristic_count);
if (ret) {
GATTLIB_LOG(GATTLIB_ERROR, "Fail to discover characteristic.");
return 1;
}
May someone helps me? or any idea?
Anonymous on 03/06/2022 06:51
buy bimatoprost 0.03 online <a href="https://bimatoprostonlines.com/">eye drops bimatoprost</a> bimatoprost ophthalmic solution eyelashes
Anonymous on 03/06/2022 10:17
cenforce 200 sildenafil citrate <a href="https://edcenforce.org/">cenforce 150mg</a> sildenafil cenforce 100mg
Anonymous on 04/06/2022 15:48
zanaflex prescription <a href="https://zanaflextizanidineon.org/">tizanidine 4 mg tablet</a> tizanidine generic for zanaflex
Anonymous on 08/06/2022 07:07
augmentin clavulanic acid <a href="https://augmentinlife.net/">augmentinlife</a> augmentin danger
Anonymous on 15/07/2022 06:42
viagra near me <a href="https://viagrarest.com/">http://www.viagrarest.com/</a> home remedy viagra
Anonymous on 22/08/2022 10:58
casino online casino <a href="https://onlinecasinokosmo.org/">online online casino</a> euro casino online
Anonymous on 01/09/2022 02:35
help me with my college essay <a href="https://helpeessayfors.net/">professional essay writing help</a> online essay writing help
Anonymous on 17/10/2022 06:55
liquid cialis <a href="https://cialisarm.com/">order cialis online</a> how long does cialis stay in your system

Login to comment Comment as anonymous