world leader in high performance signal processing
Trace: » bluetooth

Bluetooth

Bluetooth is low-cost, low-power, short-range wireless technology. It was designed as a replacement for cables and other short-range technologies like IrDA. Bluetooth operates in personal area range that typically extends up to 10 meters. More information about Bluetooth can be found at <http://www.bluetooth.com/>.

Linux Bluetooth subsystem consist of several layers:

  • Bluetooth Core (HCI device and connection manager, scheduler)
  • HCI Device drivers (Interface to the hardware)
  • SCO Module (SCO audio links)
  • L2CAP Module (Logical Link Control and Adaptation Protocol)
  • RFCOMM Module (RFCOMM Protocol)
  • BNEP Module (Bluetooth Network Encapsulation Protocol)
  • CMTP Module (CAPI Message Transport Protocol)
  • HIDP Module (Human Interface Device Protocol

Bluetooth HCI Drivers

Linux BlueZ Library and Utilities

Official Linux Bluetooth protocol stack

Bluetooth Usage Examples

Receive data from an GPS Bluetooth receiver

Make sure your interface is up and running

root:~> hciconfig
hci0:   Type: UART
        BD Address: 00:80:37:24:34:6A ACL MTU: 339:7 SCO MTU: 120:6
        UP RUNNING PSCAN ISCAN
        RX bytes:94 acl:0 sco:0 events:9 errors:0
        TX bytes:43 acl:0 sco:0 commands:9 errors:0

root:~>

Search for the GPS receivers bd-addres

root:~> hcitool scan
Scanning ...
        00:0D:B5:36:09:85       BT-GPS-360985
        00:16:41:9C:FD:53       MPAFFEN-L02
        00:10:C6:4E:DC:45       TLORENZ-L04

Browse Services and get RFCOMM channel

root:~> sdptool records 00:0D:B5:36:09:85
Service Name: BT-GPS COM Port
Service RecHandle: 0x10000
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
 

Alternatively search for a device featuring Serial Port Protocol (SP)

root:~> sdptool search SP
Inquiring ...
Searching for SP on 00:0D:B5:36:09:85 ...
Service Name: BT-GPS COM Port
Service RecHandle: 0x10000
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

Now bind /dev/rfcomm0 to the BT-GPS Channel 1

root:~> rfcomm --help
RFCOMM configuration utility ver 2.25
Usage:
        rfcomm [options] <command> <dev>

Options:
        -i [hciX|bdaddr]   Local HCI device or BD Address
        -h, --help         Display help
        -a                 Show all devices (default)

Commands:
        bind     <dev> <bdaddr> [channel]       Bind device
        release  <dev>                          Release device
        show     <dev>                          Show device
        connect  <dev> <bdaddr> [channel]       Connect device
        listen   <dev> [channel]                Listen
root:~> rfcomm bind /dev/rfcomm0 00:0D:B5:36:09:85 1

Output GPS raw data from /dev/rfcomm0

root:~> cat /dev/rfcomm0
0,00,,,M,0.0,M,,0000*51

$GPRMC,091658.501,V,,,,,,,280207,,*27

$GPGGA,091659.500,,,,,0,00,,,M,0.0,M,,0000*51

$GPRMC,091659.500,V,,,,,,,280207,,*27

$GPGGA,091700.510,,,,,0,00,,,M,0.0,M,,0000*5D

$GPRMC,091700.510,V,,,,,,,280207,,*2B

$GPGGA,091701.500,,,,,0,00,,,M,0.0,M,,0000*5D

$GPRMC,091701.500,V,,,,,,,280207,,*2B

Capture GPS data by GPS daemon from /dev/rfcomm0

root:/> gpsd /dev/rfcomm0 

root:/> gpspipe -r
netlib_connectsock() returns socket on fd 3
{"class":"VERSION","release":"2.95","rev":"2012-08-22T03:52:04","proto_major":3,"proto_minor":3}
{"class":"DEVICES","devices":[{"class":"DEVICE","path":"/dev/rfcomm0","activated":419758.06,"native":0,"bps":9600,"parity":"N","stopbi}
{"class":"WATCH","enable":true,"json":false,"nmea":true,"raw":0,"scaled":false,"timing":false}
{"class":"DEVICE","path":"/dev/rfcomm0","activated":419758.50,"driver":"Generic NMEA","native":0,"bps":9600,"parity":"N","stopbits":1,}
$GPGGA,003350.161,0000.0000,N,00000.0000,E,0,00,,0.0,M,0.0,M,,0000*40
$GPRMC,003350.161,V,0000.0000,N,00000.0000,E,,,060305,,,N*75
$GPVTG,,T,,M,,N,,K,N*2C
{"class":"DEVICE","path":"/dev/rfcomm0","activated":419759.58,"flags":1,"driver":"SiRF binary","native":1,"bps":9600,"parity":"N","sto}
$GPRMC,003349,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*31
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003350,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*39
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003351,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*38
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003352,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*3B
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003353,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*3A
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003354,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*3D
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003355,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*3C
$GPGSA,A,1,,,,,,,,,,,,,,,,*32
$GPRMC,003356,V,0000.0000,S,00000.0000,W,0.0000,0.000,210785,,*3F
$GPGSA,A,1,,,,,,,,,,,,,,,,*32

Enable console shell over Bluetooth

Following two small scripts allow a remote terminal connection to take place.

The getty command sets and manages terminal lines and ports.
This script is called from bt_shell.sh and ensures getty is restarted
when it terminates after an timeout waiting for an connection
on /dev/rfcomm0 or an established connection terminates.

run_getty.sh

#!/bin/sh
while [ 1 ];do /sbin/getty -n -l /bin/sh 115200 /dev/rfcomm0 vt100;done

bt_shell.sh

#!/bin/sh
/usr/sbin/hcid -n 2>&1 > /dev/null &
/usr/sbin/hciattach -n /dev/ttyBF1 bfin-unistone 2>&1 > /dev/null &
#hciattach -n -s 115200 /dev/ttyBF1 any &
/usr/sbin/sdpd -n 2>&1 > /dev/null &
/usr/sbin/hciconfig hci0 up 2>&1 > /dev/null
/bin/run_getty.sh &
/usr/bin/sdptool add SP 2>&1 > /dev/null
while [ 1 ];do /usr/bin/rfcomm -r listen 0 1 2>&1 > /dev/null;done

This script performs following functions in order

  1. Start hcid demon
  2. Attach UART HCI interface
  3. Start sdpd demon (sdpd allows Bluetooth devices connected to the host to advertise via SDP the Bluetooth services available)
  4. Bring up / configure the bluethooth device
  5. Stat the run_getty.sh script in background
  6. Add Serial Port Service (SP) to the local services
  7. Start and restart rfcomm listening for incoming connections

Connecting a terminal Program

From a Windows host:

  1. Enable Bluetooth
  2. Search for Devices
  3. Pair with device Blackfin(0) (This will provide a COMx port)
  4. Use a terminal program such as Hyperterm and select COMx and connect.

For more information see here: terminal_programs

From a Linux host

  • Use the graphical utilities

or

  • Use command line
# mhenner-D01:/home/michael # hcitool scan
Scanning ...
        00:0D:B5:36:09:85       BT-GPS-360985
        00:80:37:24:34:6A       Blackfin (0)
        00:10:C6:4E:DC:45       TLORENZ-L04
        00:16:41:9D:D1:A9       MHENNER-L02
mhenner-D01:/home/michael # sdptool records 00:80:37:24:34:6A
Service Name: Serial Port
Service Description: COM Port
Service RecHandle: 0x10000
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
mhenner-D01:/home/michael # rfcomm -r connect /dev/rfcomm0 00:80:37:24:34:6A 1
Connected /dev/rfcomm0 to 00:80:37:24:34:6A on channel 1
Press CTRL-C for hangup
  1. Open minicom and set Serial Device /dev/rfcomm0
  2. Connect

For more information see here: terminal_programs

Dial Up Networking and GPRS

Bluetooth Keyboards

Bluez4-compatible

First run bluetoothd deamon:

#/etc/init.d/S30dbus start & 
# bluetoothd

Then you need to get path to the default bluetooth adapter which should appear when you have bluetoothd running and bluetooth device is powered on. Do it like this:

# export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter 
| tail -1 | sed 's/^.*"\(.*\)".*$/\1/'`
#

Then scan bluetooth keyboard and start related daemon.

# hcitool scan
Scanning ...
        50:63:13:8E:00:29       Dell Wireless 365 Bluetooth Module
        00:22:68:EE:F5:FE       VLI-L02
        78:DD:08:AF:F4:AF       JJIANG-L01
        20:42:11:04:00:9D       Bluetooth Keyboard
# 
# agent 0000 &

Create device, you may need to input pincode the same as agent on the keyboard for pair:

# dbus-send --system --print-reply --dest=org.bluez $BTADAPTER org.bluez.Adapter.CreateDevice 
string:20:42:11:04:00:9D
#

Connect device:

# dbus-send --system --print-reply --dest=org.bluez
$BTADAPTER/dev_20_42_11_04_00_9D org.bluez.Input.Connect
# 
input: Bluetooth Keyboard as /devices/platform/ehci-omap.0/usb2/2-2/2-2.2/2-2.2:1.0/bluetooth/hci0/hci0:
7/input0
generic-bluetooth 0005:05AC:023C.0001: input,hidraw0: BLUETOOTH HID v0.01 Keyboard [Bluetooth Keyboard] 
on 00:15:83:15:A3:10
# 
# ls /dev/event0 -l
crw-rw----    1 root     root       13,  64 Jan  1 02:31 /dev/event0
#

Deprecated bluez-specific usage

# hcitool scan
Scanning ...
        50:63:13:8E:00:29       Dell Wireless 365 Bluetooth Module
        00:22:68:EE:F5:FE       VLI-L02
        78:DD:08:AF:F4:AF       JJIANG-L01
        20:42:11:04:00:9D       Bluetooth Keyboard
# 
#/etc/init.d/S30dbus start &

# bluetoothd
# hidd --connect 20:42:11:04:00:9D
input: Bluetooth Keyboard as /devices/platform/ehci-omap.0/usb2/2-2/2-2.2/2-2.2:1.0/bluetooth/hci0/hci0:
7/input0
generic-bluetooth 0005:05AC:023C.0001: input,hidraw0: BLUETOOTH HID v0.01 Keyboard [Bluetooth Keyboard] 
on 00:15:83:15:A3:10
# 
# ls /dev/event0 -l
crw-rw----    1 root     root       13,  64 Jan  1 02:31 /dev/event0
#

Bluetooth ALSA lib and voice headset service

The most common use of bluetooth audio is to make a wireless connection to a cellphone. A special transport, Synchronous Connection-Oriented, or SCO, was invented to provide this low-delay monophonic audio. An ALSA plug-in library is designed to reroute the sound stream from ALSA player to bluetooth SCO device. Following example shows the steps to configure a bluetooth SCO headset through USB bluetooth controller.

Configure kernel to enable bluetooth controller on USB

  • Configure USB host driver. Select ISP1362, ISP1760 and SL811 for bf533 stamp and bf537 stamp; select Inventra Highspeed for bf548 ezkit and bf527 ezkit.
Device Drivers  --->
    USB support  --->
        <*> Support for Host-side USB
            < >   ISP1362 HCD support
            < >   ISP1760 HCD support
            <*>   SL811HS HCD support
            (54)    GPIO IRQ pin for Interrupt
            < > Inventra Highspeed Dual Role Controller (TI, ADI, ...) 
  • Configure Bluetooth socket stack
Networking  ---> 
    [*] Networking support
      Networking options  --->
    [ ]   Amateur Radio support  --->
    < >   IrDA (infrared) subsystem support  --->
    <*>   Bluetooth subsystem support  --->
        <*>   RFCOMM protocol support
        [ ]     RFCOMM TTY support
        < >   BNEP protocol support
        < >   HIDP protocol support
              Bluetooth device drivers  --->
            <*> HCI USB driver

Configure Bluetooth ALSA lib and daemon

  • Always build in FDPIC format when you want to use ALSA lib and applcations.
Target ABI (FDPIC)  --->
Package Selection for the target  --->
    Libraries  --->
        JSON/XML  --->
            -*- expat
        Audio/Sound  --->
            -*- alsa-lib
    Hardware handling  --->
        -*- dbus
    Audio and video applications  --->
        [*] alsa-utils
    Networking applications  --->
        [*] bluez-utils
        [*]   audio support

Boot kernel and play sound

Bluez4-compatible

  • scan bluetooth devices and set up headset address in asound.conf
root:/> hciconfig hci0 up
root:/> hcitool scan
Scanning ...
        30:F9:ED:E1:9E:A9       DR-BT140Q
root:/> vi /etc/asound.conf
######################################################################
pcm.bluetooth {       
        type bluetooth
        device "30:F9:ED:E1:9E:A9"
}
  • Enable bluez Socket in audio.conf

root:/> vi /etc/bluetooth/audio.conf

[General]
Enable=Socket,Control
  • start bluetooth daemons and create devices
root:/> /etc/init.d/S30dbus start &
root:/> bluetoothd &
root:/> agent 0000 &
root:/> export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter | tail -n 1 | sed 's/^.*"\(.*\)".*$/\1/'`
root:/>
root:/> dbus-send --system --print-reply --dest=org.bluez $BTADAPTER org.bluez.Adapter.CreateDevice string:30:F9:ED:E1:9E:A9
root:/>
root:/> dbus-send --system --print-reply --dest=org.bluez $BTADAPTER/dev_30_F9_ED_E1_9E_A9 org.bluez.Audio.Connect
root:/> 
  • play sound
root:/> aplay -D bluetooth sample.wav

Deprecated bluez-specific usage

  • build uClinux-dist
~/your-uClinux-dist/ # make
  • copy example asound.conf and bluepin to /etc/. You can change the PIN code for you bluetooth device in sample.bluepin.
~/your-uClinux-dist/ # cp user/blkfin-apps/btsco/btsco-0.5/alsa-plugins/asound.conf romfs/etc/
~/your-uClinux-dist/ # cp user/blkfin-apps/btsco/btsco-0.5/alsa-plugins/sample.bluepin romfs/usr/bin/
sample.bluepin
######################################################################
#!/bin/sh
echo "PIN:0000"
  • build image
~/your-uClinux-dist/ # make image
~/your-uClinux-dist/ # cp images/linux /tftpboot/
  • boot image and set up hcid.conf file to use sample.bluepin as the pin_helper shell
root:/> vi /etc/bluetooth/hcid.conf
hcid.conf
######################################################################
# HCId options
options {
	# Automatically initialize new devices
	autoinit yes;

	# Security Manager mode
	#   none - Security manager disabled
	#   auto - Use local PIN for incoming connections
	#   user - Always ask user for a PIN
	#
	security auto;

	# Pairing mode
	#   none  - Pairing disabled
	#   multi - Allow pairing with already paired devices
	#   once  - Pair once and deny successive attempts
	pairing multi;

	# PIN helper
	pin_helper /usr/bin/sample.bluepin;

	# D-Bus PIN helper
	#dbus_pin_helper;
}
  • scan bluetooth devices and set up headset address in asound.conf
root:/> hciconfig hci0 up
root:/> hcitool scan
Scanning ...
        00:1A:45:4A:EA:39       Jabra BT125
root:/> vi /etc/asound.conf
asound.conf
######################################################################
pcm.headset {
	type plug;
	slave.pcm "hw_headset";
}

pcm.hw_headset {
	@args [BDADDR TIMEOUT MAX_PERIODS]
	
	# The Bluetooth device address for target headset, used for Audio Gateway (PC) initiated connections
        # Please note that this value is ignored when the connection is Headset initiated
	@args.BDADDR {
		type string
		default "00:1A:45:4A:EA:39" # Put your HS address here
	}

	# This value represents how long we will try to reach the headset, until we give up.
	# Value is in milliseconds
	@args.TIMEOUT {
		type integer
		default 6000
	}

	# This is the size of the buffer used to queue Voice packets. Value must be between 
	# 2 and 334 (~ 1 second). Default value is 2 buffers, which works well most of the
        # time, and has the advantage of giving us an ultra low delay
	@args.MAX_PERIODS {		
		type integer
		default 334
	}

	type        sco
	bdaddr      $BDADDR
	timeout     $TIMEOUT
	max_periods $MAX_PERIODS
}

ctl.headset {
	type sco
}

pcm.a2dpd {
        type a2dpd
}
  • start bluetooth daemons
root:/> hcid -n &
139
root:/> hcid[139]: Bluetooth HCI daemon
hcid[139]: Starting security manager 0
hdev=0
root:/> sdpd &
140
root:/> headsetd -n &
145
root:/> headsetd[145]: Bluetooth headset daemon version 0.42
  • play sound
root:/> aplay -D headset b.wav
headsetd[145]: Configuration phase ended: target bdaddr is 00:1A:45:4A:EA:39, timeout is 200000 ms
headsetd[145]: Changing state: Idle-->Paging
headsetd[145]: Changing state: Paging-->Connecting
hcid[139]: link_key_request (sba=00:10:60:D0:8C:41, dba=00:1A:45:4A:EA:39)
hcid[139]: pin_code_request (sba=00:10:60:D0:8C:41, dba=00:1A:45:4A:EA:39)
hcid[139]: link_key_notify (sba=00:10:60:D0:8C:41, dba=00:1A:45:4A:EA:39)
Headset connected
headsetd[145]: Changing state: Connecting-->Ready
headsetd[145]: Changing state: Ready-->Opening
headsetd[145]: SCO channel opened handle=0x002d mtu=64
headsetd[145]: Changing state: Opening-->Streaming
Playing WAVE 'b.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono
headsetd[145]: Appli closed socket
headsetd[145]: Changing state: Streaming-->Closewaiting
root:/> headsetd[145]: Nobody uses SCO channel anymore, closing it.
headsetd[145]: Changing state: Closewaiting-->Connected

root:/>

More Bluetooth HOWTOs

Complete Table of Contents/Topics