Prerequisites

GLib

zlib

zlib is a compression library and a prerequisite for building GLib.

Download, cross compile and install the zlib compression libraries. Configure doesn't accept the --host parameter (reports unknown option), so you need to hack the makefile.

wget http://zlib.net/zlib-1.2.8.tar.gz
tar -xzf zlib-1.2.8.tar.gz
cd zlib-1.2.8/
./configure --prefix=/usr/arm-linux-gnueabi 

Edit the makefile and prefix the build tools with arm-linux-gnueabi-.

CC=arm-linux-gnueabi-gcc
LDSHARED=arm-linux-gnueabi-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map
CPP=arm-linux-gnueabi-gcc -E
AR=arm-linux-gnueabi-ar
RANLIB=arm-linux-gnueabi-ranlib

Make and install:

make
make install

libffi

libffi is the Portable Foreign Function Interface Library and is a prerequisite for building GLib. It is an interface that allows code written in one language to call code written in another language.

Download, build and install:

wget ftp://sourceware.org/pub/libffi/libffi-3.0.13.tar.gz
tar -xzf libffi-3.0.13.tar.gz
cd libffi-3.0.13/
./configure --host=arm-linux-gnueabi --prefix=/usr/arm-linux-gnueabi  
make
make install

GLib

GLib is part of the GTK+ Project

GLib requires zlib, libffi and glibc >= 2.18 to successfully build. If you are building on ubuntu 14.04, the arm-linux-gnueabi should come installed with glibc 2.19 hence we don't rebuild it.

GLib requires the glib-genmarshal tool installed on your build system otherwise the following error is likey to result:

checking for glib-genmarshal... no
configure: error: Could not find a glib-genmarshal in your PATH

An easy way to resolve this is to install libglib2.0-dev:

sudo apt-get install libglib2.0-dev

To build Glib, download, build and install:

wget http://ftp.gnome.org/pub/gnome/sources/glib/2.40/glib-2.40.0.tar.xz
tar -xJf glib-2.40.0.tar.xz
cd glib-2.40.0
./configure --host=arm-linux-gnueabi --prefix=/usr/arm-linux-gnueabi PKG_CONFIG_PATH=/usr/arm-linux-gnueabi/lib/pkgconfig  glib_cv_stack_grows=no glib_cv_uscore=yes ac_cv_func_posix_getpwuid_r=yes ac_cv_func_posix_getgrgid_r=yes 
make
make install

D-Bus

The Expat XML Parser

Expat is an XML parser library written in C and is the only required dependency for the D-Bus daemon.

Download, build and install:

wget http://sourceforge.net/projects/expat/files/expat/2.1.0/expat-2.1.0.tar.gz
tar -xzf expat-2.1.0.tar.gz 
cd expat-2.1.0/
./configure --host=arm-linux-gnueabi --prefix=/usr/arm-linux-gnueabi
make
make install

D-Bus

D-Bus is a message bus system. It requires the expat library to successfully build otherwise the following error may result:

checking for XML_ParserCreate_MM in -lexpat... no
configure: error: Explicitly requested expat but expat not found

Download, build and install:

wget http://dbus.freedesktop.org/releases/dbus/dbus-1.8.0.tar.gz
tar -xzf dbus-1.8.0.tar.gz
cd dbus-1.8.0/
./configure --host=arm-linux-gnueabi --prefix=/usr/arm-linux-gnueabi
make
make install
make install DESTDIR=/home/export/rootfs

libical

libical provides a library for the iCal standard. It is a prerequisite of BlueZ.

libical requires cmake and g++ cross compilers to be installed:

sudo apt-get install cmake
sudo apt-get install g++-arm-linux-gnueabi

Download, build and install the library:

wget http://downloads.sourceforge.net/freeassociation/libical-1.0.tar.gz
tar -xzf libical-1.0.tar.gz
cd libical-1.0/
export CC=arm-linux-gnueabi-gcc
export CXX=arm-linux-gnueabi-g++
cmake -DCMAKE_INSTALL_PREFIX=/usr/arm-linux-gnueabi
make
make install

Readline

Readline references functions in ncurses. If ncurses is not linked, the following errors are likely to result when building BlueZ:

/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `PC'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `tgetflag'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `tgetent'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `UP'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `tputs'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `tgoto'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `tgetnum'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `BC'
/usr/arm-linux-gnueabi/lib/libreadline.so: undefined reference to `tgetstr'

First we must build ncurses and then link it to Readline using SHLIB_LIBS=-lncurses.

ncurses

Download, build and install the ncurses library:

wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz
tar -xzf ncurses-5.9.tar.gz
cd ncurses-5.9
./configure --host=arm-linux-gnueabi --prefix=/usr/arm-linux-gnueabi CXX="arm-linux-gnueabi-g++"
make
make install

Readline

Download, build and install the readline library:

wget ftp://ftp.cwru.edu/pub/bash/readline-6.3.tar.gz
tar -xzf readline-6.3.tar.gz
cd readline-6.3/
./configure --host=arm-linux-gnueabi --prefix=/usr/arm-linux-gnueabi bash_cv_wcwidth_broken=yes
make SHLIB_LIBS=-lncurses
make install

The bash_cv_wcwidth_broken=yes parameter avoids the following error when cross-compiling:

checking for wcwidth broken with unicode combining characters... 
configure: error: in `/.../readline-6.3':
configure: error: cannot run test program while cross compiling

Building BlueZ

BlueZ is the official Bluetooth protocol stack for Linux and include tools such as hciattach, hciconfig, hcitool and rfcomm.

BlueZ 5.18 requires GLib >= 2.28, D-Bus >= 1.6 and libudev >= 143. When these prerequisites are meet, you can download, build and install BlueZ using:

wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.18.tar.xz
tar -xJf bluez-5.18.tar.xz
cd bluez-5.18
./configure --host=arm-linux-gnueabi --prefix= PKG_CONFIG_PATH=/usr/arm-linux-gnueabi/lib/pkgconfig --disable-systemd --disable-udev --disable-cups --disable-obex --enable-library 
make
make install DESTDIR=/usr/arm-linux-gnueabi
make install DESTDIR=/home/export/rootfs

Installing

Some of the BlueZ tools (e.g. sdptool requires libglib, bluetoothd requires libdbus-1, dbus-daemon requires libexpat, bluetoothctl requires libreadline) will require the following shared libraries installed:

cp /usr/arm-linux-gnueabi/lib/libglib-2.0.so.0.4000.0 /home/export/rootfs/lib
cp /usr/arm-linux-gnueabi/lib/libdbus-1.so.3.8.3 /home/export/rootfs/lib
cp /usr/arm-linux-gnueabi/lib/libexpat.so.1.6.0 /home/export/rootfs/lib
cp /usr/arm-linux-gnueabi/lib/libreadline.so.6.3 /home/export/rootfs/lib

The Bluetooth Daemon requires the D-Bus Daemon to be running, otherwise the following error will result:

D-Bus setup failed: Failed to connect to socket /usr/arm-linux-gnueabi/var/run/dbus/system_bus_socket: No such file or directory

Copy the default bluetooth.conf over to dbus-1/systemd.d on the target:

cp bluez-5.18/src/bluetooth.conf /home/export/rootfs/etc/dbus-1/system.d/

The D-Bus Daemon wants to spawn from the user/group messagebus/messagebus. Failure to create a user and group results with:

Failed to start message bus: Could not get UID and GID for username "messagebus"

Create the appropriate group and user account:

addgroup -S messagebus
adduser -S messagebus -G messagebus

Now start the D-Bus Daemon:

dbus-daemon --system

Finally, start the Bluetooth Daemon:

/libexec/bluetooth/bluetoothd

Testing

The hciconfig (BlueTooth Host Controller Interface Configuration utility) will show any BlueTooth host controllers present:

# hciconfig
hci0:   Type: BR/EDR  Bus: USB
        BD Address: 00:19:0E:15:5A:EF  ACL MTU: 1021:8  SCO MTU: 64:1
        DOWN
        RX bytes:0 acl:0 sco:0 events:0 errors:0
        TX bytes:0 acl:0 sco:0 commands:0 errors:0

You can bring up the interface by issuing:

# hciconfig hci0 up

Now you can scan for BlueTooth devices:

# hcitool -i hci0 scan
Scanning ...
        7C:6D:62:9A:86:9A       n/a
        C8:19:F7:EF:D7:03       GT-P5100
        B4:62:93:CF:82:F5       GT-I9300

Ping a BlueTooth Device:

# l2ping C8:19:F7:EF:D7:03
Ping: C8:19:F7:EF:D7:03 from 00:19:0E:15:5A:EF (data size 44) ...
44 bytes from C8:19:F7:EF:D7:03 id 0 time 6.00ms
44 bytes from C8:19:F7:EF:D7:03 id 1 time 5.86ms
44 bytes from C8:19:F7:EF:D7:03 id 2 time 4.82ms
44 bytes from C8:19:F7:EF:D7:03 id 3 time 34.82ms
44 bytes from C8:19:F7:EF:D7:03 id 4 time 6.04ms
44 bytes from C8:19:F7:EF:D7:03 id 5 time 7.35ms
44 bytes from C8:19:F7:EF:D7:03 id 6 time 8.54ms
44 bytes from C8:19:F7:EF:D7:03 id 7 time 6.06ms
44 bytes from C8:19:F7:EF:D7:03 id 8 time 23.45ms

Interrogate SDP (Service Discovery Protocol) Descriptors:

 # sdptool -i hci0 browse B4:62:93:CF:82:F5
Browsing B4:62:93:CF:82:F5 ...
Service RecHandle: 0x10000
Service Class ID List:
  "Generic Attribute" (0x1801)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 31
  "ATT" (0x0007)
    uint16: 0x0001
    uint16: 0x0005

Service RecHandle: 0x10001
Service Class ID List:
  "Generic Access" (0x1800)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 31
  "ATT" (0x0007)
    uint16: 0x0014
    uint16: 0x001e

Service Name: Headset Gateway
Service RecHandle: 0x10002
Service Class ID List:
  "Headset Audio Gateway" (0x1112)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 2
Profile Descriptor List:
  "Headset" (0x1108)
    Version: 0x0102

Service Name: Handsfree Gateway
Service RecHandle: 0x10003
Service Class ID List:
  "Handsfree Audio Gateway" (0x111f)
  "Generic Audio" (0x1203)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 3
Profile Descriptor List:
  "Handsfree" (0x111e)
    Version: 0x0106

Service Name: Sim Access Server
Service RecHandle: 0x10004
Service Class ID List:
  "SIM Access" (0x112d)
  "Generic Telephony" (0x1204)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 4
Profile Descriptor List:
  "SIM Access" (0x112d)
    Version: 0x0102

Service Name: AV Remote Control Target
Service RecHandle: 0x10005
Service Class ID List:
  "AV Remote Target" (0x110c)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 23
  "AVCTP" (0x0017)
    uint16: 0x0102
Profile Descriptor List:
  "AV Remote" (0x110e)
    Version: 0x0103

Service Name: Advanced Audio
Service RecHandle: 0x10006
Service Class ID List:
  "Audio Source" (0x110a)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 25
  "AVDTP" (0x0019)
    uint16: 0x0102
Profile Descriptor List:
  "Advanced Audio" (0x110d)
    Version: 0x0102

Service Name: Android Network Access Point
Service Description: NAP
Service RecHandle: 0x10007
Service Class ID List:
  "Network Access Point" (0x1116)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 15
  "BNEP" (0x000f)
    Version: 0x0100
    SEQ8: 0 6
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Network Access Point" (0x1116)
    Version: 0x0100

Service Name: Android Network User
Service Description: PANU
Service RecHandle: 0x10008
Service Class ID List:
  "PAN User" (0x1115)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 15
  "BNEP" (0x000f)
    Version: 0x0100
    SEQ8: 0 6
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "PAN User" (0x1115)
    Version: 0x0100

Service Name: OBEX Phonebook Access Server
Service RecHandle: 0x1000a
Service Class ID List:
  "Phonebook Access - PSE" (0x112f)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 19
  "OBEX" (0x0008)
Profile Descriptor List:
  "Phonebook Access" (0x1130)
    Version: 0x0101

Service Name: OBEX Object Push
Service RecHandle: 0x1000b
Service Class ID List:
  "OBEX Object Push" (0x1105)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 12
  "OBEX" (0x0008)
Profile Descriptor List:
  "OBEX Object Push" (0x1105)
    Version: 0x0100

Service Name: SMS
Service RecHandle: 0x1000c
Service Class ID List:
  "Message Access - MAS" (0x1132)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 5
  "OBEX" (0x0008)
Profile Descriptor List:
  "Message Access" (0x1134)
    Version: 0x0100