Linux DevCenter    
 Published on Linux DevCenter (http://www.linuxdevcenter.com/)
 See this if you're having trouble printing code examples


Rediscovering Bluetooth

by Guylhem Aznar
09/21/2006

Presenting Bluetooth in 2006 is hard. By all accounts, it should have emerged much sooner to be omnipresent by now. Yet it did not succeed as planned and therefore carries a bad reputation. Bluetooth is popular, but not as popular as WiFi. However, you can do a lot more with Bluetooth, especially with casual hacking.

Do you know Bluetooth? You may already be familiar with it, and even use it, perhaps with your cellphone and wireless headset. If so, you may wonder what more Bluetooth can do for you, especially if you have read only technical literature about its theoretical aspects--full of overused buzzwords such as "piconets" or "scatternets," but devoid of any real-world application or implementation.

Do not worry. This article shows you how to play with Bluetooth, not buzzwords. If you are not familiar with Bluetooth, I hope to introduce you to such a nifty technology, and guide you through my wonderful world of Bluetooth, with wireless gizmos everywhere!

This article demonstrates how to make your Bluetooth module work, scan for other Bluetooth devices and see which services they can offer, and connect to them. I provide a service named PAN, which can perform wireless IP networking with Bluetooth.

A future article will cover other services: file transfer, serial port export, wireless HID peripherals such as keyboards and mice, audio streaming, and music streaming. Then you can perform and understand fun hacks, such as adding Bluetooth to non-Bluetooth devices, using Bluetooth to automatically start/stop a screensaver, and using existing Bluetooth attacks.

What's the goal? You should be able to synchronize your devices wirelessly, export a serial port for faxing or dialup networking, exchange files with other Bluetooth-enabled hardware, replace your wired HID peripherals with Bluetooth peripherals, and more.

Definitions

What exactly is Bluetooth? There are many definitions, but my favorite is that it is a generalization of WiFi with lesser power requirements.

With Bluetooth, you do not only have computers talking to other computers. You have wireless headsets streaming audio to cellphones, which you can synchronize with handhelds or computers, which can use peripherals such as mice or keyboards.

Because Bluetooth requires far less power than WiFi, and because it hides the networking complexity from the interface layer, Bluetooth has a lot of creative and interesting uses--more than WiFi.

Speaking of interfaces, you need Bluetooth hardware and software to use Bluetooth features. Some hardware hacks embed the software part directly into the hardware (for example, serial- or printer-cable replacement dongles). However, this removes some flexibility that a software stack provides. It also costs much more, yet introduces even greater complexity.

For the scope of this article, I prefer a light Bluetooth hardware and a large separate software stack.

The Linux kernel can use various software stacks. The best known are bluez and affix. My preference here is bluez, because it is now part of the Linux kernel.

Installation Time!

To deploy a working Bluetooth software stack on your Linux computer, you need Bluetooth hardware!

Hardware

There are three basic interfaces to Bluetooth hardware: USB, serial, and PCMCIA. Maybe your PC already has integrated Bluetooth? You may then find instructions online to enable that feature under Linux. There are far too many PCs with integrated Bluetooth to present them all within this article.

PCMCIA cards are usually only a PCMCIA-to-serial interface hooked to a Bluetooth chip, while being more expensive. Therefore, if you have a PC without integrated Bluetooth, you need a Bluetooth dongle, either serial or USB.

I recommend you purchase a D-Link DBT-120, as it includes handy special features which I will explain later, especially if you are considering a Bluetooth keyboard. If you cannot find that specific dongle, any cheap USB dongle will be fine. Serial RS-232 dongles are usually much more expensive and slower.

If you have something that's not really a general-purpose PC, and lacks any solution to easily plug in a Bluetooth solution, that's where it gets interesting. However, if you are using a standard USB module, you do not have to worry about all this and may go directly to the software section.

Unusual Hardware

Remember--you need only a serial port to add Bluetooth to your device. Because most devices (such as handhelds) have unused serial ports on their motherboards, adding Bluetooth is very easy. It can be as "easy" as soldering four pins total to the motherboard. This is the bare minimum, requiring two for the serial port (Receive, Send) and two to bring power (Ground, Power) to the Bluetooth chip. Six pins are better (with four pins for the serial port), as this enables flow control.

Many websites present solutions to add Bluetooth to various handhelds, such as the Siemens Simpad, the Sharp Zaurus, or the Psion MX. You can also do that on PCs or laptops with an unused serial port on the motherboard, if you feel like experimenting with Bluetooth. Here are some references:

Of course, you also need to connect these four or six wires to the Bluetooth chip some way or another. The easiest way is to pick up an "all-in-one" module: it features the Bluetooth chip and the antenna on a tiny board, along with the voltage converter you need (TTL 5V/CMOS 3.3V).

If you feel like saving some money, you can purchase cheap USB dongles and convert them into serial port dongles. If you prefer saving some time, you can purchase serial dongles online. Here are some references:

If you are purchasing serial dongles, and have a serial port with four pins (two additional pins for flow control), you do not have anything special to do.

Serial Protocols for Unusual Hardware

If you only have a serial port with two pins (receive/send), you must configure your dongle to use the BCSP protocol instead of H4. Basically, H4 is an industry standard that requires flow control, while BCSP is a CSR proprietary protocol that works just as well without flow control. Because the bluez stack supports both, you can use either.

However, odds are that your chip will be preset to some protocol. To use the other one, you must change its configuration. For this, use the pskey utility as documented in the pskey README or the Opensimpad introduction to Pskey.

Please proceed carefully. It is quite easy to kill a module with a single pskey mistake.

Software Installation

Depending on the Linux kernel configuration and your distribution's installed software, your system may work out of the box.

If you are using a distribution with automated package installation, such as Debian or Red Hat, you can get a precompiled version of bluez without any dependency problem. Go directly to the "Starting bluez" section.

However, I recommend that at least you recompile your kernel to patch it with the latest bluez patch (see also www.holtmann.org/linux/kernel).

Recompiling a kernel is clearly outside the scope of this article, but may be necessary for some special features that the bluez project has added after the release of the kernel version you use. This is especially true for my next article, which will introduce advanced features such as Bluetooth keyboard support.

I now assume that you either have a working kernel with bluez statically compiled or modules with auto-load support.

Software Compilation

If you wish to install everything yourself, you must use a specific version of bluez to avoid any dependency on DBus. Many parts of the Gnome desktop depend on DBus. It may not be a good idea to break it.

I recommend downloading bluez-libs-2.10, bluez-utils-2.10, bluez-hcidump-1.12, and bluez-hciemu-1.0, with the commands:

$ wget http://bluez.sf.net/download/bluez-libs-2.10.tar.gz
$ wget http://bluez.sf.net/download/bluez-utils-2.10.tar.gz
$ wget http://bluez.sf.net/download/bluez-hcidump-1.12.tar.gz
$ wget http://bluez.sf.net/download/bluez-hciemu-1.0.tar.gz

If you are not using i386-compatible hardware (for example, on handhelds with ARM or MIPS CPUs), please do a cross-compilation with the toolchain your architecture requires. Instructions to do that, along with this specific toolchain, may be available online on websites explaining how to hack your hardware (for example, Zaurus toolchain).

Compilation works the standard GNU way. I like to put everything into /opt/bluetooth so as not to conflict with your default install.

First, install the libraries, which everything else will use:

$ tar zxvf bluez-libs-2.10.tar.gz
$ cd bluez-libs-2.10
$ ./configure --prefix=/opt/bluetooth
$ make ; make install
$ echo "/opt/bluetooth/lib" >> /etc/ld.so.conf
$ ldconfig

Then, install the utilities:

$ tar zxvf bluez-utils-2.10.tar.gz
$ cd bluez-utils-2.10
$ ./configure --disable-debug --disable-dbus --disable-cups --disable-pcmcia \
    --disable-initscripts  --disable-bluepin --enable-hid2hci --enable-bcm203x \
    --prefix=/opt/bluetooth
$ make ; make install

Finally, install the debug application:

$ tar zxvf bluez-hcidump-1.12.tar.gz
$ cd bluez-hcidump-1.12
$ ./configure --prefix=/opt/bluetooth
$ make ; make install

To use the newly installed binaries, type:

export PATH=$PATH:/opt/bluetooth/bin:/opt/bluetooth/sbin

or add it to your .bashrc or similar file. You are now ready to go!

Attaching a Serial Dongle

The first thing to do with a serial dongle is to attach it. The syntax is simple: specify the serial port name, the protocol, the initial speed, flow control, and a sustainable speed for normal use.

For example, if you have a serial dongle on the first serial port using BCSP, with a firmware configuration of 115200 baud, but you want to set it to work at 230400 baud, use:

$ hciattach /dev/ttyS0 bcsp 115200 noflow 230400

If you have a serial dongle, odds are you either have added it yourself, and therefore know the parameters because you set them manually with pskey, or that you have internal Bluetooth in your laptop, in which case you will find all the parameters on the same website where you found explanations to enable Bluetooth.

I strongly advise you against changing the initial speed with pskey. Keep that value to a safe default and let hciattach do the magic of switching to higher speeds. You can then try to go as high as 921600 if you want to, without taking any risks: a simple reset of the chip will take you back to 115200. On the other hand, setting the Bluetooth module to a default speed you can't reach will render it useless.

Starting Bluetooth and Talking to Another Device

Whether your device is serial or USB, you can start it with:

$ hciconfig hci0 up
        hci0:   Type: USB
        BD Address: 00:80:C8:45:31:F8 ACL MTU: 192:8  SCO MTU: 64:8
        UP RUNNING PSCAN ISCAN AUTH ENCRYPT
        RX bytes:2882377 acl:151624 sco:0 events:212 errors:0
        TX bytes:2591 acl:184 sco:0 commands:20 errors:0

This means you have a USB device with an address of 00:80:C8:45:31:F8, running with the various options.

The address is unique and similar to a MAC address for an Ethernet card. It is unspoofable, unless you manage to get a development Bluetooth module that still has the "change address" feature enabled. In that case, you are one pskey command away from changing it. Therefore, I strongly advise you against using any Bluetooth address as a security token.

Now try to find neighboring Bluetooth devices:

$ hcitool scan
    Scanning ...
       00:A0:96:0A:D1:80       zaurus.guylhem.net

It found something!

The scan shows the other device's address and the device name. The owner has set the latter; it can be anything at all. However, I recommend you use a fully qualified domain name if you have your own domain--it makes it easier to find identify the device's owner with a simple whois.

Before you can go any further, start the hcid daemon and set up a PIN to protect the connection. Edit the hcid.conf file in /opt/bluetooth/etc/bluetooth to look like this:

options {
        # automatically put new hciN devices up
        autoinit yes;

        # security mode
        #  none : security disabled
        #  auto : use local pin for incoming connections
        #  user : always ask a pin to the user
        security auto;
        pairing multi;
        pin_helper /opt/bluetooth/bin/bluepin;
}

device {
        # whatever you want
        name "MyDevice.MyDomain.us";

        # 0x100 is fine for a PC, 0x120112 is better for a PDA
        class 0x100;

        # enable inquiry scan
        iscan enable;

        # enable page scan
        pscan enable;

        # default link mode
        #  none : no policy
        #  accept : always accept incoming connections
        #  master : becomes the master on incoming connections
        #           and deny role switch on outgoing connections
        lm accept;

        # default link policy
        #  none : no policy
        #  rswitch : allow role switch
        #  hold : allow hold mode
        #  sniff : allow sniff mode
        #  park : allow park mode
        lp rswitch,hold,sniff,park;

        # enable authentication
        auth enable;

        # enable encryption
        encrypt enable;
}

What Is All of This?

Bluetooth devices automatically organize themselves into piconets, with a master and slaves. There can only be one master per piconet. However, the master can be a slave in another piconet. The two piconets are, collectively, a scatternet.

What does it all mean? To avoid problems, enable role switch and let the devices manage themselves instead of forcing a master policy.

Another important option is page and inquiry scan. By default, Bluetooth devices are in standby mode and periodically try to listen for messages. With page scan, the device expects other devices to contact it by way of its code name. The remote device must know that name. Inquiry scan is the opposite; any device can call even if it does not know the proper code name. The class allows you to search for any type of device, when there are too many Bluetooth devices around you. If you want to hide your devices from other people, disable scans--either in hcid.conf, or manually after you have connected your devices:

$ hciconfig hci0 iscan disable

The most important option is certainly the security option.

To create a connection between two Bluetooth devices, they must both know the same PIN code. It can be as small as eight bits and as large as 128 bits, but ask you may have to type it on a cellphone keyboard, it usually is only four digits--"1234" by default in many embedded Bluetooth devices such as wireless headsets.

It works as a challenge, where one device creates a challenge by deriving a key from the PIN and sending it along with a random number. If the challenge is successful, a link key is created to secure this connection. This is why you should enable authentication and encryption as well: to prevent radio eavesdropping.

Regarding security, use auto and create an application that will give a PIN. Here's a simple one:

$ echo "
#!/bin/sh
echo -n PIN:
cat /opt/bluetooth/etc/pin
">/opt/bluetooth/bin/bluepin

$ echo "9874" > /opt/bluetooth/etc/pin

$ chmod +x /opt/bluetooth/bin/bluepin

This will display "PIN:9874" when it runs.

$ /opt/bluetooth/bin/bluepin PIN:9874

You can make it more complex, for example, by requesting the user to enter a specific password each time a new device attempts to connect. This is out of the scope of this article. Gnome and KDE already provide graphical bluepin applications. Feel free to improve them if you want.

Regarding modes, hold is when a master becomes silent, to save power or to do something else (perhaps to listen on another piconet, or to perform a scan). sniff is when a slave becomes deaf from time to time, to save power. park is when a slave leaves a piconet. You can still wake it up later by asking the master to unpark it.

Basically, you should enable all these modes if your hardware supports them all--and they now mostly do. You will save power and have more features. Ancient Bluetooth hardware like my old Socket CF+ Rev E (with a Nokia chipset, hci v 1.0b) may only support a subset of these options, and will fail to work if you still enable the unsupported options. (See a short introduction to the theoretical aspects behind a Bluetooth connection and hardware features.)

Now that you have set up a password and all the options, try a connection.

Start the hcid and sdpd daemons to allow communications (for example, giving a PIN or querying capabilities):

$ /opt/bluetooth/sbin/hcid -f /opt/bluetooth/etc/bluetooth/hcid.conf
$ /opt/bluetooth/sbin/sdpd

At the moment, there is no equivalent of /etc/hosts to map names to addresses, let alone a full-fledged DNS system. You must use the hardware address.

To test the connection:

$ l2ping 00:A0:96:0A:D1:80

You will know the device requires a password if you get:

Can't connect.: Connection timed out

Alternatively, if the device is off, you will get:

Can't connect.: Host is down

With some luck, everything will work fine:

# l2ping 00:A0:96:0A:D1:80
Ping: 00:A0:96:0A:D1:80 from 00:80:C8:45:31:F8 (data size 20) ...
20 bytes from 00:A0:96:0A:D1:80 id 200 time 64.76ms
20 bytes from 00:A0:96:0A:D1:80 id 201 time 45.80ms
20 bytes from 00:A0:96:0A:D1:80 id 202 time 38.89ms
20 bytes from 00:A0:96:0A:D1:80 id 203 time 95.60ms
20 bytes from 00:A0:96:0A:D1:80 id 204 time 43.26ms
20 bytes from 00:A0:96:0A:D1:80 id 205 time 53.72ms
20 bytes from 00:A0:96:0A:D1:80 id 206 time 39.92ms
20 bytes from 00:A0:96:0A:D1:80 id 207 time 28.68ms
8 sent, 8 received, 0% loss

Use Ctrl-C to stop this.

Now look at the syslog:

# tail /var/log/syslog
Aug  2 22:20:44 [hcid] link_key_request (sba=00:80:C8:45:31:F8,
dba=00:A0:96:0A:D1:80)_
Aug  2 22:20:44 [hcid] pin_code_request (sba=00:80:C8:45:31:F8,
dba=00:A0:96:0A:D1:80)_
Aug  2 22:20:44 [hcid] link_key_notify (sba=00:80:C8:45:31:F8)_
Aug  2 22:20:44 [hcid] Replacing link key 00:80:C8:45:31:F8 00:A0:96:0A:D1:80

Both devices shared the PIN to establish the connection.

Offering and Requesting Services

You have found a device. What can you do with it? Can you use it to go online, send or receive files, or stream audio? This is a job for SDP--a protocol to offer and request services. What does my Zaurus offer?

# sdptool browse 00:A0:96:0A:D1:80
Browsing 00:A0:96:0A:D1:80 ...
#

It looks like there is no service. I need to add some. How about NAP to offer networking, DUN to offer PPP networking, OPUSH to receive files, and SP to let another computer use the Zaurus serial port?

# sdptool add NAP
# sdptool add DUN
# sdptool add OPUSH
# sdptool add SP

Attention: I don't have space in this article to configure DUN, OPUSH, and SP. I'll just show how to fake support for this profile. Why not play pretend for once? An addition benefit is that this approach is useful as a honeypot to find in the syslog devices attempting to take advantage of DUN, OPUSH, and SP for Bluesnarfing or Bluejacking attacks.

Now what does the Zaurus offer?

# sdptool browse 00:A0:96:0A:D1:80
Browsing 00:A0:96:0A:D1:80 ...
Service Name: Network Access Point Service
Service RecHandle: 0x10000
Service Class ID List:
  "Network access point" (0x1116)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 15
  "BNEP" (0x000f)
    Version: 0x0100
    SEQ16: 10 20 30 40
Profile Descriptor List:
  "PAN access point" (0x1116)
    Version: 0x0100

Service Name: Dial-Up Networking
Service RecHandle: 0x10001
Service Class ID List:
  "Dialup Networking" (0x1103)
  "Generic Networking" (0x1201)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100

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

Service Name: Serial Port
Service Description: COM Port
Service RecHandle: 0x10003
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0100

Much better.

Now I want to try some networking. Imagine the Zaurus has a network connection to the internet, and you would like to share that connection with other devices. It's IP over Bluetooth!

On the Zaurus, start the network daemon in server mode:

# pand --listen --master --role NAP

On your PC, look for a NAP:

# sdptool search NAP
Inquiring ...
Searching for NAP on 00:A0:96:0A:D1:80 ...
Service Name: Network Access Point Service
Service RecHandle: 0x10000
Service Class ID List:
  "Network access point" (0x1116)
Protocol Descriptor List:
  "L2CAP" (0x0100)
    PSM: 15
  "BNEP" (0x000f)
    Version: 0x0100
    SEQ16: 10 20 30 40
Profile Descriptor List:
  "PAN access point" (0x1116)
    Version: 0x0100

It looks like the Zaurus correctly advertises its support for PAN. Now connect with pand in client mode:

# /usr/bin/pand --role PANU --service NAP --connect 00:A0:96:0A:D1:80

You can also let pand search in client mode to find a NAP to connect to and then do the connection:

# /usr/bin/pand --role PANU --service NAP --search

Each device will then have a bnep0 device that supports automatic configuration--perhaps with DHCP or with a static IP address.

pand calls a script named dev-up in /etc/bluetooth/pan/ whenever it creates a bnepx interface; this is the easiest way to configure bnep0. You can alternatively try to use hotplug.

On the Zaurus, type (and store in /etc/bluetooth/pan/dev-up for the next time):

ifconfig bnep0 192.168.1.1
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat  -A POSTROUTING -o eth0 -j MASQUERADE

On the PC, type (and store in /etc/bluetooth/pan/dev-up for the next time):

ifconfig bnep0 192.168.1.2
route add default gw 192.168.1.1

You can now ping the Zaurus and use it to connect to the internet.

pand is a network daemon--you can use it to do different things, including peer-to-peer networking, if you use GN instead of NAP. On the client run:

# pand --listen --role GN

This will look for peer-to-peer servers to connect to as you pass by. Along with a DHCP request to get an IP address on bnep0, it offers unique possibilities to share files with passersby who have configured their Bluetooth devices likewise. See The PAN HOWTO for more information.

Conclusion

So far, your Bluetooth device has only reached the feature set provided by WiFi--maybe with more nice options and possibilities for automation.

Even with just networking, there is much more than PAN in Bluetooth.

My next article will play with DUND and SP--respectively, PPP over Bluetooth and serial port export to handle traditional serial port issues. You can take advantage of these profiles to offer dial-on-demand services and wireless synchronization of a Palm pilot featuring Bluetooth.

I will also show how to exchange files with OBEX, and use that to back up a cellphone. I will explain Bluesnarfing and Bluejacking attacks to transform the cellphone backup into a "cellphone slurper," which will attempt to download the content of the phonebook, calendar, pictures, etc. of any passing Bluetooth phone that accepts the transfer.

Guylhem Aznar was the coordinator of The Linux Documentation Project from 1999 to 2006. He has a special interest in Linux embedded devices and health informatics, being a physician with a clinical experience but also a full traditional computer-science education.


Return to the Linux DevCenter.

Copyright © 2009 O'Reilly Media, Inc.