[[PageOutline]] [[Image(https://upload.wikimedia.org/wikipedia/commons/thumb/d/da/Bluetooth.svg/220px-Bluetooth.svg.png,120px)]] = Goals = The main objective of this page is to describe Bluetooth from a Linux perspective and provide some general notes for specific applications such as reading a Bluetooth serial device or connecting to a Bluetooth HID. = Bluetooth = Bluetooth is a wireless protocol for short distances which encompasses the obvious benefit of low power. There is a concept of a Master device and a Slave device which is synonymous to infrastructure mode in 802.11a/b/g/n/ac (i.e. AP with several STA's). There can be a maximum of 7 active devices connected to the Master, but can have a total of 255 inactive connections. This Bluetooth network is called a Piconet. However, there are several options on how a Bluetooth network can be configured, several of which will be discussed below in the [wiki:bluetooth#Software software] section. There also exist several Bluetooth protocols which are defined by the Bluetooth SIG organization. [http://en.wikipedia.org/wiki/List_of_Bluetooth_protocols This Wikipedia entry has a complete list of protocols.] In order to fully appreciate the flexibility Bluetooth has to offer, the next few sections will be dedicated to these protocols and how to gain access to them. All Bluetooth devices (both controllers and endpoints), like Ethernet devices, have a unique 6-byte MAC address. Common Terminology: - stack - Refers to the software that implements the Bluetooth protocols - device - a Bluetooth end-point device - controller - Refers to the host controller attached to the CPU that can talk to bluetooth devices == Bluetooth Versions == Which version is used is dependent on the Hardware used as well as software. Be sure to check the specifications of the radio / device being used. * Bluetooth 4.0 * Added Bluetooth Low Energy (BLE) protocol * Bluetooth 5.0 * 4x the range ov Bluetooth 4.x (with lower throughput) * 2x the datarate of 4.x (1Mbps to 2Mbps) * Advertising packets move to 255 bytes * More advertising channels == Bluetooth Low Energy (BLE) == Also called Bluetooth LE, BLE, and Bluetooth Smart. This is primarily used for data sensing, and not intended for continuous data-rate applications such as streaming audio or video. This enables new-use cases like beacons and sensors that have low-bandwidth periodic and sporodic data points. This also brings lower power to some use cases such as human interface devices (keyboard and mouse) input that is sporadic in nature, greatly increasing battery life for those devices. Bluetooth Low Energy is much lower power than classic Bluetooth, possibly lasting months on a coincell. BLE is also cheaper for each peripheral devices. BLE has many defined profiles, including specific profiles for the healthcare industry, sports and fitness and more. These are all based on the Generic Attribute Profile (GATT). Bluetooth 4.x+ Devices will support Bluetooth Classic (aka BR/EDR) and/or Bluetooth Low Energy. Be away they may not support both and if you have a device that supports 'only' BLE it will not be able to use audio streaming such as the A2DP profile as support for BR/EDR is required for that. [=#hardware] == Bluetooth Controller Hardware == Gateworks has used and tested the following USB based controllers. === USB based (btusb) === Their is a large variety of USB based Bluetooth controllers supported by the {{{btusb}}} kernel driver. Here are some common ones that Gateworks has tested: * [http://plugable.com/products/usb-bt4le Pluggable USB-BT4LE]: USB ID 0a5c:21e8 Broadcom BCM20702A0 * CSR 4.0 ([http://www.csr.com/products/bluecore-csr8510-a10-wlcsp CSR8510 A10 Bluetooth USB host]): USB ID 0a12:0001 - Available from various vendors for <$10 - https://www.adafruit.com/products/1327 * [http://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/dual-band-wireless-ac-7260-bluetooth-brief.pdf Intel 7260HWM] - MiniPCIe form-factor 802.11ac / Bluetooth 4.0: * Firmware: [http://git.kernel.org/cgit/linux/kernel/git/balbi/linux-firmware.git/plain/intel/ibt-hw-37.7.10-fw-1.80.2.3.d.bseq ibt-hw-37.7.10-fw-1.80.2.3.d.bseq] should be placed in /lib/firmware/intel/. For OpenWrt the driver/firmware is provided by the kmod-btusb kernel module package and the ibt-firmware package which are installed by default in our Ventana BSP since r621 * Main Ant is Wifi * Aux Ant is Wifi + Bluetooth * Canyon CN-BTU1: USB ID 0c10:0000 === Laird Sterling-LWB 2.4GHz Wifi / Bluetooth module (450-0148) * This is not offered as a Mini-PCIe card, but rather embedded on some Gateworks SBCs, such as the GW5910 * BT 2.1+EDR and BLE 4.2 * Find all Laird Sterling information on this dedicated wiki page: [wiki:expansion/sterling-lwb] === GW17039 (DHXA-335D)=== The [https://unex.com.tw/products/wi-fi/interfaces/pcie-wifi/80211n-bluetooth/detail/dhxa-335d Unex DHXA-335D] is a PCIe half-mini card using Atheros WB222/AR9565 [https://shop.gateworks.com/index.php?route=product/product&search=bluetooth&product_id=208 available on Gateworks store]. Some of it's features include: * Wifi: 802.11b,802.11g,802.11n, Bluetooth v4.0 * MIMO: 1x1(1-stream) * Spectral Band 2.400~2.497 * Channel Spacing: Wifi 5MHz, BT 1MHz * Output power: 18dB Wifi, 2dBm BT * Other Specifications: * Connectors: 2x U.FL * Dimensions: 26.8mm x 29.85mm * ath9k driver support * Operation temprature: -10C,+60C ambient * RoHS === DHXA-225 (EOL) === The [http://www.unex.com.tw/product/dhxa-225 Unex DHXA-225] is a MiniPCIe form-factor combo card using Atheros WB225/AR9485+AR3012 providing: * 802.11bgn 1x1 MIMO wifi (PCIe device supported by the linux [http://wireless.kernel.org/en/users/Drivers/ath9k ath9k] driver) * For OpenWrt this is provided by the kmod-ath9k kernel module package and is built into our default root filesystems by default * Bluetooth 4.0 HCI (USB device supported by the linux [http://wireless.kernel.org/en/users/Drivers/ath3k ath3k] driver) * Firmware: all *.dfu files in [https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/ar3k] should be copied to /lib/firmware/ar3k/ or /lib/firmware/4.11.0-14-generic/ar3k/ if using Xenial. * For OpenWrt this is provided by the kmod-btusb kernel module package and ar3k-firmware package which are installed by default on our Ventana BSP since r621 [=#bsp] == Gateworks BSP Support == Gateworks supports multiple Board Support Packages. The following table shows details on bluetooth support for each: ||= BSP =||= Product Families =||= Drivers =||= Stack =|| || OpenWrt 14.08 || All || btusb/hciuart || bluez3 || || [wiki:Yocto Yocto] || Ventana || btusb/hciuart || bluez4 || || [wiki:Android] 5.1 || Ventana || btusb || bluez5 || || OpenWrt 16.02 || Ventana || btusb/hciuart/bnep/rfcomm|| Fixed in commit ??? || [=#openwrt1408] === OpenWrt 14.08 === Gateworks OpenWrt 14.08 supports Bluetooth via BlueZ 3.36 The following packages are installed by default on Gateworks firmware images: * btusb and bluetooth core kernel drivers * bluez-utils (bluetooth daemon and utils) * bluez-libs (bluetooth lib) * kmod-bluetooth (hci_uart, btusb, rfcomm, bnep, bluetooth, hidp, ath3k) By default dbus-daemon and bluetooth daemon (hcid) are running and the controller is powered up with ISCAN and PSCAN enabled (discovery enabled) and the name is configured as 'OpenWrt' (the system hostname). The {{{dbus-send}}} application is not installed by default (it is included in the dbus-util) package if you wish to install it, and no passkey agent is installed by default. OpenWrt 14.08 supports UCI configuration for the Bluetooth daemon storing its configs in {{{/etc/config/bluetooth}}}. The default configuration provides: - hcid: enabled by default (controller discoverable via 'iscan enable; pscan enable' in /etc/bluetooth/hcid.conf) - hciattach: disabled by default - rfcomm: disabled by default - dund: disabled by default - pand: disabled by default The Gateworks OpenWrt 14.08 BSP default firmware image provides support for the following: * most common USB based based BT controllers (via btusb, ath3k, btintel drivers) * HCI core protocol kernel support (HCI/L2CAP/SMP/SCO) * RFCOMM/BNPEP/HIDP kernel support * hciconfig/hcitool/sdptool/bluetoothd/rfcomm applications and daemones * scan/pair/discovery of bluetooth devices * Serial Port Profile (SP) via rfcomm app * Personal Area Network (PAN) Profile via pand app A patch is needed to add the {{{hidd}}} application in order to support Human Interface Device Profile (HID): {{{ diff --git a/utils/bluez-utils/Makefile b/utils/bluez-utils/Makefile index 4f3f787..80d626f 100644 --- a/utils/bluez-utils/Makefile +++ b/utils/bluez-utils/Makefile @@ -43,6 +43,8 @@ CONFIGURE_ARGS += \ --enable-network \ --enable-usb \ --enable-input \ + --enable-hidd \ --disable-audio \ --with-bluez="$(STAGING_DIR)/usr/include" \ --with-usb=yes \ @@ -58,9 +60,19 @@ endef }}} [=#yocto] === Yocto 1.8 === Gateworks Yocto 1.8 BSP supports Bluetooth via BlueZ 4.101. Note that Yocto 1.3 also supported BlueZ 4 but the Yocto 1.6 and 1.7 BSP's do not have bluetooth enabled in the kernel. The following packages are installed by default on Gateworks firmware images: * btusb and bluetooth core kernel drivers * bluez4 (bluetoothd daemon, libs, and utils) * bluez4-testtools * bluez-hcidump * gstreamer1.0-plugins-bad-bluze * libasound-module-bluez The Gateworks Yocto 1.8 BSP default firmware images provides support for the following: * most common USB based based BT controllers (via btusb, ath3k, btintel drivers) * HCI core protocol kernel support (HCI/L2CAP/SMP/SCO) * RFCOMM/BNPEP/HIDP kernel support * hciconfig/hcitool/sdptool/bluetoothd/rfcomm applications and daemones * scan/discovery of bluetooth devices * Serial Port Profile (SP) via rfcomm app * Human Interface Device (HID) Profile via hidd dbus-send By default the Bluetooth daemon (bluetoothd) is not running as there is no default init script. The {{{dbus-send}}} application exists and can be used for establishing HID connections. No passkey agent is installed by default for pairing (see how to install the pyton test tools for the bluez-simple-agent below). To run bluetoothd: {{{#!bash bluetoothd }}} ''' Installing Extra Bluetooth Packages ''' Depending on your needs, you may also need to install the test tools that are missing from the Yocto bluez package (and patch them to use the version of python-object installed on Yocto). This will add support for: * Personal Area Network (PAN) Profile (test-nap & test-network) * Simple Pairing agent (simple-agent) {{{#!bash mkdir -p /usr/local/bin for i in simple-agent simple-service test-adapter test-audio test-device test-discovery test-input test-manager test-nap test-network test-oob test-serial; do \ wget "http://git.kernel.org/cgit/bluetooth/bluez.git/plain/test/${i}?h=4.101" -O /usr/local/bin/bluez-${i}; \ sed -i 's/from gi.repository import GObject/import gobject/' /usr/local/bin/bluez-${i}; \ sed -i 's/mainloop = GObject.MainLoop/mainloop = gobject.MainLoop/' /usr/local/bin/bluez-${i}; \ chmod +x /usr/local/bin/bluez-${i}; \ done }}} - On Ubuntu for example, these are packaged in the 'bluez' package already If you are interested in using OBEX/FTP/OPP for binary file transfers you may want to build and install the {{{obexftp}}} and/or {{{openobex}}} Yocto packages. [=#trusty] === Ubuntu 14.04 === Ubuntu 14.04 uses the BlueZ 4.x stack and provides the following packages related to bluetooth: * bluez - core bluetooth daemon, utils and python test scripts (You will need to also install python-gobject and python-dbus if you wish to use the python test scripts) * bluez-compat - pand, hidd, dund for backwards compatibility with BlueZ 3 instructions and methods * bluez-btsco - Bluetooth SCO tool * bluez-cups - Bluetooth printer driver for CUPS * bluez-hcidump - Analyses Bluetooth HCI packets * [https://code.google.com/archive/p/bluez-tools/alternative bluez-tools] - An alternative set of tools to manage bluetooth devices for linux (not documented here) * bluez-alsa - ALSA plugin for A2DP profile * bluez-gstreamer - GStreamer plugin for A2DP profile * pulseaudio-module-bluetooth - Bluetooth module for !PulseAudio sound server (not documented here) * obexfs - mount filesystem of devices supporting OBEX FTP profile * obexftp - file transfer utility and daemon for devices supporting OBEX FTP profile * obexpushd - program for receiving files via OBEX OPP profile For example: * to install all bluetooth related packages (174MB on top of a base Ubuntu system as described in [wiki:ventana/ubuntu]): {{{#!bash apt-get install bluez bluez-compat bluez-alsa bluez-gstreamer bluez-utils bluez-tools python-gobject python-dbus }}} * if you want the minimize you can just install bluez (which does depend on dbus, systemd, and python among some others) (14.9MB on top of a base Ubuntu system as described in [wiki:ventana/ubuntu]): {{{#!bash apt-get install bluez }}} With the bluetooth packages above installed this allows for the following support: * most common USB based based BT controllers (via btusb, ath3k, btintel drivers) * HCI core protocol kernel support (HCI/L2CAP/SMP/SCO) * RFCOMM/BNPEP/HIDP kernel support * hciconfig/hcitool/sdptool/bluetoothd/rfcomm applications and daemones * scan/discovery of bluetooth devices * Serial Port Profile (SP) via rfcomm app * Human Interface Device (HID) Profile via hidd/dbus-send/bluez-test-input * Personal Area Network (PAN) Profile via pand app * File Transfer Protocol (FTP) Profile via obexftp and obxfs * Object Push Profile (OOP) via obexpushd * Advanced Audio Distribution Profile (A2DP) via bluez-alsa [=#android] === Android === The Gateworks Android BSP replaces the standard Android Bluetooth 'bluedroid' stack with BlueZ. Please see [wiki:Android#bluetooth Android Bluetooth] for details on Android Bluetooth support. == Software (Linux) == A Bluetooth stack refers to the software that implements the protocol layers. This software can reside in the Linux kernel as well as userspace. [=#bluez] === BlueZ (Standard Linux) === [http://www.bluez.org/ BlueZ] is the Open Source Linux bluetooth protocol stack implemented in userspace using the Linux Bluetooth HCI core drivers. It also provides several tools for managing your Bluetooth connections, whether you're acting as a Slave (device) or Master (controller). BlueZ offers support for multiple Bluetooth devices, security, and several other features. It also provides several Protocols, or "Profiles", such as PAN, HID, and A2DP. The upcoming sections will discuss software generally compiled when building BlueZ BlueZ general features: * flexible, efficient, modular architecture * support for multiple Bluetooth devices * multithreaded * hardware abstraction * standard socket interface to all layers BlueZ consists of: * Linux kernel side: - Bluetooth Core: - HCI (Host Controller Interface) device and connection manager, schedule - SCO (Synchronous Connection Oriented) audio links - L2CAP (Logical Link Control and Adaptation Protocol) - SMP (Security Manager Protocol) on LE (Low Energy) links - HCI Device drivers (Interface to the hardware) - USB (btusb) - UART (hciuart) - SDIO - RFCOMM (RFCOMM Protocol for serial communication) Module (creates /dev/rfcomm serial devices) - BNEP (Bluetooth Network Encapsulation Protocol) Module (creates /sys/class/net/bnep network interfaces) - CMTP (CAPI Message Transport Protocol) Module - HIDP (Human Interface Device Protocol) Module (creates /sys/class/input devices) * Userspace side: - config and test utilities Various linux distros will package BlueZ in a number of packages: * bluez - Bluetooth tools and daemons * bluez-alsa - Bluetooth ALSA support * bluez-btsco - Bluez Bluetooth SCO tool * bluez-cups - Bluetooth printder driver for CUPS * bluez-gstreamer - Bluetooth GStreamer support * bluez-hcidump - Analyze Bluetooth packets * bluez-tools - manage Bluetooth devices While Bluez5 is the current stable release many Linux distros including Ubuntu 14.04, Gateworks Yocto 1.8 BSP still use Bluez4. See [#bsp above] regarding which Gateworks BSP's have what version of BlueZ Recent BlueZ Version history: * [http://www.bluez.org/release-of-bluez-5-0/ BlueZ 5]: Dec 2012 - use standard D-Bus Properties and !ObjectManager interfaces - different (and incompatible) D-Bus API (see the [http://www.bluez.org/bluez-5-api-introduction-and-porting-guide/ BlueZ 5 API porting-guide]) - introduction of interface versions - simplification or removal of per-profile interfaces and the addition of a general org.bluez.Device1.Connect method - removal of org.bluez.Service interface - Dynamic device object creation during discovery - Introduction of an AgentManager1 interface - base path moved to "/org/bluez" * [http://www.bluez.org/bluez-40/ bluez-4.0]: Aug 2008: - merged bluez-libs and bluez-utils together - main daemon now called bluetoothd (instead of hcid) - main config file is /etc/bluetoth/main.conf following an INI-style syntax - GLib no longer optional (eglib support fully removed) - old D-Bus API from 3.x series fully removed [=#kernel] ==== Linux Kernel Drivers ==== The Linux Kernel defines a Bluetooth Host Controller Interface (HCI) for communication between hardware kernel drivers and userspace applications. Several Linux kernel drivers implement a standard bluetooth HCI API in the form of a device node and ioctls. Each of these drivers implements support for a specific HCI presenting and a list of them can be found in /sys/class/bluetooth/hci* The more standard HCI device drivers can be broken down into the following: * USB based HCI's (typically added to a system by the user) - [http://lxr.missinglinkelectronics.com/linux/drivers/bluetooth/btusb.c linux/drivers/bluetooth/btusb.c] usually built as the '''btusb.ko''' kernel module * UART based HCI's (typically embedded onto a board) - [http://lxr.missinglinkelectronics.com/linux/drivers/bluetooth/btuart.c linux/drivers/bluetooth/btuart_cs.c] usually build as the '''btuart.ko''' kernel module * SDIO based HCI's (typically embedded onto a board) - [http://lxr.missinglinkelectronics.com/linux/drivers/bluetooth/btsdio.c drivers/bluetooth/btsdio.c] usually built as the '''btsdio.ko''' kernel module * addition drivers exist in drivers/bluetooth for specific hardware implmentaitons While Gateworks does not currently have bluetooth HCI's directly on its boards, our customers often add USB based HCI's in the form of miniPCIe combo cards (see [#hardware hardware] section below) or USB form-factor peripherals. You can see what Bluetooth controllers are registered with the kernel by looking at the {{{/sys/class/bluetooth}}} directory: {{{#!bash # ls /sys/class/bluetooth hci0 }}} [=#bluez5] ==== BlueZ 5.x ==== The Bluez5 bluetooth daemon (/usr/lib/bluez5/bluetooth/bluetoothd) runs in the background and the {{{bluetoothctl}}} application provides a Command Line Interface (CLI) to the daemon to perform all device and controller management. '''NOTE: Bluez5 is not properly configured in Gateworks !OpenWrt 16.02.''' A typical session may look like this: 1. Use {{{list}}} to list available controllers, and {{{select }}} to select one 1. Turn the power on to a controller via {{{power on}}} (its off by default) 1. Enable device discovery mode for the selected controller with {{{scan on}}} (its off by default) - New devices will be presented as they are found - Periodic messages will appear for each device found along with its signal strength (RSSI) 1. You can list current devices with the {{{devices}}} command 1. Turn the pairing agent on with the {{{agent on}}} command 1. Pair a device via {{{pair }}} - If using a device without a PIN, you man need to manually trust the device before it can reconnect successfully. To do so use {{{trust }}} 1. Establish a connection to the device via {{{connect }}} Note that while in the CLI: - Tab completion works - Periodic asynchonous/unsolicited messages will appear for devices being scanned while scanning is on Examples: * Pairing and connecting an HID keyboard: {{{#!bash bluetoothctl [NEW] Controller 00:06:C6:FF:AD:1A ventana-0 [default] [bluetooth]# list Controller 00:06:C6:FF:AD:1A ventana-0 [default] [bluetooth]# show 00:06:C6:FF:AD:1A Controller 00:06:C6:FF:AD:1A Name: BlueZ 5.28 Alias: ventana-0 Class: 0x000000 Powered: yes Discoverable: no Pairable: yes UUID: PnP Information (00001200-0000-1000-8000-00805f9b34fb) UUID: Generic Access Profile (00001800-0000-1000-8000-00805f9b34fb) UUID: Generic Attribute Profile (00001801-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control (0000110e-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb) UUID: Handsfree (0000111e-0000-1000-8000-00805f9b34fb) Modalias: usb:v1D6Bp0246d051C Discovering: no [bluetooth]# select 00:06:C6:FF:AD:1A [bluetooth]# scan on Discovery started [CHG] Controller 00:06:C6:FF:AD:1A Discovering: yes [NEW] Device 54:46:6B:01:7B:2B 54-46-6B-01-7B-2B [CHG] Device 54:46:6B:01:7B:2B LegacyPairing: no [CHG] Device 54:46:6B:01:7B:2B Name: Bluetooth FAVI [CHG] Device 54:46:6B:01:7B:2B Alias: Bluetooth FAVI [bluetooth]# devices Device 54:46:6B:01:7B:2B Bluetooth FAVI [bluetooth]# pair 54:46:6B:01:7B:2B Attempting to pair with 54:46:6B:01:7B:2B Failed to pair: org.bluez.Error.ConnectionAttemptFailed [bluetooth]# pair 54:46:6B:01:7B:2B Attempting to pair with 54:46:6B:01:7B:2B [CHG] Device 54:46:6B:01:7B:2B Connected: yes [CHG] Device 54:46:6B:01:7B:2B Modalias: usb:v0A5Cp8502d011B [CHG] Device 54:46:6B:01:7B:2B UUIDs: 00001000-0000-1000-8000-00805f9b34fb 00001124-0000-1000-8000-00805f9b34fb 00001200-0000-1000-8000-00805f9b34fb [CHG] Device 54:46:6B:01:7B:2B Paired: yes Pairing successful [CHG] Device 54:46:6B:01:7B:2B Connected: no [bluetooth]# connect 54:46:6B:01:7B:2B Attempting to connect to 54:46:6B:01:7B:2B [ 2178.501028] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [ 2178.507023] Bluetooth: HIDP socket layer initialized [CHG] Device 54:46:6B:01:7B:2B Connected: yes Connection successful }}} - If using a device without a PIN you can manually trust the device in order to connect: {{{#!bash [bluetooth]# trust 54:46:6B:01:7B:2B }}} To bring up a bluetooth controller (HCI) on boot, you can use a udev rule such as: - /etc/udev/rules.d/10-local.rules {{{#!bash # bring up bluetooth host controller ACTION=="add", KERNEL=="hci0", RUN+="/usr/bin/hciconfig hci0 up" }}} After a suspend/resume cycle you can use a systemd service to bring the controller back up: - /etc/systemd/system/bluetooth-auto-power@.service {{{#!bash [Unit] Description=Bluetooth auto power on After=bluetooth.service sys-subsystem-bluetooth-devices-%i.device suspend.target [Service] Type=oneshot ExecStart=/usr/bin/hciconfig %i up [Install] WantedBy=suspend.target }}} Configuration: - bluetooth daemon configuruation is in /etc/bluetooth/main.conf: * !AutoEnable=true in [Policy] section will bring up HCI on startup - bluetooth dbus configuration is in /etc/dbus-1/system.d/bluetooth.conf (can specify group there, defaults to lp group) Notes: - must turn power on to controller by entering 'power on' (off by default) or by using hciconfig up - enter device desovery mode with 'scan on' - tab completion works in CLI - to pair, the bluetooth device must be in pairing mode (consult devices documentation). Typically this involves pressing or holding a button for a few seconds and results in a blinking blue LED to indicate the device is in pairing mode. Pairing typically stops after a minute or so depending on the device References: - https://wiki.archlinux.org/index.php/Bluetooth [=#bluez4] ==== BlueZ 4.x ==== BlueZ 4.x was released in Aug 2008 with the following major changes over BlueZ 3.x: - Merged bluez-libs and bluez-utils together - Main daemon now called bluetoothd (instead of hcid) - Main config file is /etc/bluetooth/main.conf following an INI-style syntax - GLib no longer optional (eglib support fully removed) - Old D-Bus API from 3.x series fully removed - New D-Bus API is defined in [http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/network-api.txt?id=4.101 doc/network-api.txt] The standard userpsace tools are: - bluetoothd - Bluetooth Daemon that manages all Bluetooth devices and configured via /etc/bluetooth/main.conf. Provides a number of services via D-Bus message bus system - hcitool - hciattach - hciconfig - l2ping - l2test - sdptool some distros (ie Ubuntu) will provide a set of bluetooth compatibility binaries in a {{{bluez-compat}}} package that provide the following tools which were removed from bluez4: - Personal Area Network (PAN) networking daemon - Dial-Up Networking daemon - Bluetooth HID daemon Configuration: - /etc/init/bluetooth.conf - bluetooth daemon init - /etc/bluetooth/main.conf - main bluetooth daemon config - name of device (when discoverable) - /etc/bluetooth/input.conf - configuration of the input service - /etc/bluetooth/audio.conf - configuration of the audio service (SCO routing: PCM or HCI) - /etc/bluetooth/network.conf - configuration of the network service (link encryption) - /etc/bluetooth/rfcomm.conf - configuration of rfcomm layer - /etc/bluetooth/serial.conf - configuration of serial (DUN tty, UID) [=#bluez3] ==== BlueZ 3.x ==== BlueZ 3.x has the following features: - uses dbus and system.d configured via /etc/dbus-1/system.d/bluetooth.conf - D-Bus API is defined in [http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/network-api.txt?id=utils-3.36 doc/network-api.txt] - bluetooth daemon (hidc) - /etc/bluetooth/hcid.conf daemon configuration The standard userspace tools are: - hcid - Bluetooth Daemon that manages all Bluetooth devices and configured via /etc/bluetooth/hcid.conf. Provides a number of services via D-Bus message bus system - hciconfig/hcitool/hciattach - HCI configuration tools - l2ping - Layer2 ping utility - sdptool - SDP browser - hidd - Human Interface Devices (HID) daemon - pand - Personal Area Network (PAN) networking daemon - dund - Dial-up networking daemon [=#dbus] === D-Bus Message Bus System === The BlueZ stack uses the [https://www.freedesktop.org/wiki/Software/dbus/ D-Bus message bus system] which is a simple way for applications to talk to one another. ==== BlueZ 4 D-Bus API ==== The BlueZ 4 D-Bus API is defined in [http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/network-api.txt?id=4.101 doc/network-api.txt]. Some example usage using {{{dbus-send}}}: * First you need to get the path to the bluetooth controller you wish to use. We will assign it to a shell env variable and export it for future use: {{{#!bash export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter | tail -1 | sed 's/^.*"\(.*\)".*$/\1/'` }}} * To introspect with you can use something like: {{{#!bash # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.freedesktop.DBus.Introspectable.Introspect }}} * To make your controller discoverable: {{{#!bash # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.bluez.Adapter.SetProperty string:Discoverable variant:boolean:true }}} * To disable discovery: {{{#!bash # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.bluez.Adapter.SetProperty string:Discoverable variant:boolean:false }}} * To list paired devices: {{{#!bash # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.bluez.Adapter.ListDevices }}} * To trust a device: {{{#!bash dbus-send --system --dest=org.bluez --print-reply $BTADAPTER/dev_54_46_6B_01_7B_2B org.bluez.Device.SetProperty string:Trusted variant:boolean:true }}} * To connect to an HID device (must pair first and can see the path above): {{{#!bash # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER/dev_54_46_6B_01_7B_2B org.bluez.Input.Connect [ 2710.946655] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [ 2710.952642] Bluetooth: HIDP socket layer initialized method return sender=:1.3 -> dest=:1.13 reply_serial=2 root@ventana:~# [ 2711.352289] hid-generic 0005:0A5C:8502.0001: unknown main item tag 0x0 [ 2711.359234] input: Bluetooth FAVI as /devices/soc0/soc.0/2100000.aips-bus/2184000.usb/ci_hdrc.0/usb1/1-1/1-1:1.0/bluetooth/hci0/hci0:42/0005:0A5C:8502.0001/input/input1 [ 2711.374829] hid-generic 0005:0A5C:8502.0001: input: BLUETOOTH HID v1.1b Keyboard [Bluetooth FAVI] on 00:15:83:3d:0a:57 evtest /dev/input/event1 }}} [=#bluedroid] === !BlueDroid (Android) === While Android used to use the standard Linux BlueZ stack, in 4.2.2 it switched to its own native stack called !BlueDroid. For Android Bluetooth details please see the [wiki:ventana/Android Android wiki pages]. [=#profiles] == Bluetooth Profiles == In order to use Bluetooth a device must be compatible with a subset of Bluetooth '''profiles''' for specific services. These profiles sit on top of the Bluetooth Core specification and protocols. The way a device uses Bluetooth technology depends on its profile capabilities. The profiles provide standards which manufacturers follow to allow devices to be compatible. A full list of profiles can be found [https://en.wikipedia.org/wiki/List_of_Bluetooth_profiles here] however here are some common ones are described in detail in the sections below [=#sp] === Serial Port Profile (SP) === The Serial Port Profile is based on ETSI 07.10 and the RFCOMM protocol. It emulates a serial cable to provide a simple substitude for existing RS-232 including control signals. This is the basis for DUN, FAX, HSP and AVRCP profiles. SPP maximum payload capacity is 128 bytes. An example of a device using this profile would be a Bluetooth GPS device. The Linux kernel has an RFCOMM driver that ties into the bluetooth stack and registers /dev/rfcomm device nodes when necessary. Use the {{{rfcomm}}} utility from the bluez package to listen for or connect so bluetooth connections. It is not necessary to be paired or trusted in this case. For example, to create a serial link between two Linux systems: * Machine1: SP server {{{#!bash # hciconfig hci0 piscan # make us discoverable # hciconfig hci0 -a hci0: Type: BR/EDR Bus: USB BD Address: 00:02:72:C9:56:47 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING PSCAN ISCAN RX bytes:7258 acl:121 sco:0 events:203 errors:0 TX bytes:4561 acl:119 sco:0 commands:91 errors:0 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH SNIFF Link mode: SLAVE ACCEPT Name: 'ventana-0' Class: 0x000100 Service Classes: Unspecified Device Class: Computer, Uncategorized HCI Version: 4.0 (0x6) Revision: 0x1000 LMP Version: 4.0 (0x6) Subversion: 0x220e Manufacturer: Broadcom Corporation (15) # sdptool add SP --channel=1 # advertise an SP service record for channel 1 # rfcomm listen hci0 1 # listen on hci0 for SP requests on channel 1 (cntl-C to exit) Waiting for connection on channel 1 }}} * Machine2: SP client {{{#!bash # hciconfig hci0 up # hcitool scan Scanning ... 00:02:72:C9:56:47 ventana-0 # sdptool search SP Inquiring ... Searching for SP on 00:02:72:C9:56:47 ... Service Name: Serial Port Service Description: COM Port Service Provider: BlueZ 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 # rfcomm connect hci0 00:02:72:C9:56:47 1 Press CTRL-C for hangup }}} - once a connection is established the {{{rfcomm}}} processes on both the client and server will display 'Press CTRL-C for hangup' at which point they will create a {{{/dev/rfcomm0}}} node that can be used with any terminal application. When you wish to close the connection kill the rfcomm process. - terminal characterists such as baudrate and line control have no effect on rfcomm devices You can configure the bluetooth daemon to bind to a device on startup via {{{/etc/bluetooth/rfcomm.conf}}}. For example: For example: {{{ rfcomm0 { # Automatically bind the device at startup bind no; # Bluetooth address of the device device 00:11:22:33:44:55; # RFCOMM channel for the connection (check your GPS docs for details) channel 1; # Description of the connection comment "Bluetooth GPS"; } }}} Restart the Bluetooth daemon or services following this change: {{{#!bash # /etc/init.d/bluetoothd restart }}} You should now be able to bind the GPS to /dev/rfcomm0 like this: {{{#!bash # rfcomm bind 0 }}} And you can confirm the connection: {{{#!bash # rfcomm rfcomm0: 00:11:22:33:44:55 channel 1 clean }}} Now you can use {{{/dev/rfcomm0}}} like any other serial device (ie 'stty', 'screen', etc): {{{#!bash # stty -F /dev/rfcomm0 115200 # set baudrate # cat /dev/rfcomm0 $GPGGA,111748.000,5907.6964,N,01121.1787,E,1,06,1.2,57.7,M,40.1,M,,0000*6F $GPRMC,111748.000,A,5907.6964,N,01121.1787,E,0.00,94.94,160807,,,A*50 $GPVTG,94.94,T,,M,0.00,N,0.0,K,A*3D }}} References: * http://wiki.openmoko.org/wiki/Manually_using_Bluetooth#RFCOMM [=#hsp] === Headset Profile (HSP) === The Headset Profile (HSP) was encoropred in the initial Bluetooth specification for mono headsets. If a microphone is present on a stereo headphone device, it uses HSP for the audio channel. HSP uses a RFCOMM channel for control based on standard AT commands with bluetooth specific extensions for volume control and accept/reject buttons. The transport for audio is an SCO channel which allows a single (mono) 8kHz PCM encoded using Continuous Variable Slope Delta (CVSD) modulation amounting to 64kbps. This audio transferred over SCO can be provided to the HCI hardware driver (typical) or in highly embedded applications directly to an audio codec chip via a PCM back-channel depending on the bluetooth chipset. [=#hfp] === Handsfree Profile (HFP) === The Handsfree profile (HFP) is a more advanced version of HSP but also designed for mono headsets. It adds support for additional remote functions such as dialing and later versions add optional support for better-quality mono audio using the SBC codec. [=#hid] === Human Interface Device Profile (HID) === The Human Interface Device Profile (HID) is implemented with a kernel module (hidp) that registers a Linux Input device upon request from the bluetooth daemon. Configuration of HID depends upon the version of BlueZ (see [#bsp BSP table above]). In general the HID device must be paired with (or trusted) and the bluetooth daemon must register it for use with the {{{hidp}}} kernel module which creates a Linux Input device that can be seen in {{{/sys/class/input}}}. Notes: * BT HID devices (ie keyboard or mouse) and controllers (HCI) need to be paired once. See [#pairing Pairing] for more details. * Once connected a {{{/dev/input/event}}} device node will be registered and can be used for Linux Input events as long as the connection persists. * You can test the connection (if connected through a TTY session) by running a tool such as {{{evtest}}} or {{{event_test}}} which will show you events on Linux Input devices. BlueZ 5: * The {{{bluetoothctl}}} utility allows for HID's to connect to the Bluetooth adapter. This provides a Command Line Interface (CLI): {{{#!bash # bluetoothctl [NEW] Controller 00:06:C6:FF:AD:1A ventana-0 [default] [bluetooth]# power on Changing power on succeeded [CHG] Controller 00:06:C6:FF:AD:1A Powered: yes [bluetooth]# scan on Discovery started [CHG] Controller 00:06:C6:FF:AD:1A Discovering: yes [NEW] Device 54:46:6B:01:7B:2B 54-46-6B-01-7B-2B [CHG] Device 54:46:6B:01:7B:2B LegacyPairing: no [CHG] Device 54:46:6B:01:7B:2B Name: Bluetooth FAVI [CHG] Device 54:46:6B:01:7B:2B Alias: Bluetooth FAVI [bluetooth]# devices Device 54:46:6B:01:7B:2B Bluetooth FAVI [bluetooth]# pair 54:46:6B:01:7B:2B Attempting to pair with 54:46:6B:01:7B:2B [CHG] Device 54:46:6B:01:7B:2B Connected: yes [CHG] Device 54:46:6B:01:7B:2B Modalias: usb:v0A5Cp8502d011B [CHG] Device 54:46:6B:01:7B:2B UUIDs: 00001000-0000-1000-8000-00805f9b34fb 00001124-0000-1000-8000-00805f9b34fb 00001200-0000-1000-8000-00805f9b34fb [CHG] Device 54:46:6B:01:7B:2B Paired: yes Pairing successful [CHG] Device 54:46:6B:01:7B:2B Connected: no [bluetooth]# connect 54:46:6B:01:7B:2B Attempting to connect to 54:46:6B:01:7B:2B [ 2178.501028] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [ 2178.507023] Bluetooth: HIDP socket layer initialized [CHG] Device 54:46:6B:01:7B:2B Connected: yes Connection successful [bluetooth]# exit }}} BlueZ 4: * Using D-Bus via the {{{dbus-send}}} to interact with {{{bluetoothd}}} (requires [#pairing pairing]): {{{#!bash # hciconfig hci0 up # hcitool -i hci0 scan Scanning ... 54:46:6B:01:7B:2B Bluetooth FAVI # sdptool search HID # search for and show all discoverable devices advertising an HID service Inquiring ... Searching for HID on 54:46:6B:01:7B:2B ... Service Name: Broadcom Bluetooth Wireless Keyboard Service Description: Keyboard Service Provider: Broadcom Corp. Service RecHandle: 0x10000 Service Class ID List: "Human Interface Device" (0x1124) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 17 "HIDP" (0x0011) Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Human Interface Device" (0x1124) Version: 0x0100 # bluez-simple-agent hci0 54:46:6B:01:7B:2B # request pairing (specify pin code when requested then enter this code followed by a Enter on the keyboard to pair) RequestPinCode (/org/bluez/471/hci0/dev_54_46_6B_01_7B_2B) Enter PIN Code: 0000 Release New device (/org/bluez/471/hci0/dev_54_46_6B_01_7B_2B) # export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter | tail -1 | sed 's/^.*"\(.*\)".*$/\1/'` # get the adapter path # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.bluez.Adapter.ListDevices # list paired adapters # dbus-send --system --dest=org.bluez --print-reply $BTADAPTER/dev_54_46_6B_01_7B_2B org.bluez.Input.Connect # connect to an adapter method return sender=:1.3 -> dest=:1.8 reply_serial=2 [ 2710.946655] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [ 2710.952642] Bluetooth: HIDP socket layer initialized [ 2711.352289] hid-generic 0005:0A5C:8502.0001: unknown main item tag 0x0 [ 2711.359234] input: Bluetooth FAVI as /devices/soc0/soc.0/2100000.aips-bus/2184000.usb/ci_hdrc.0/usb1/1-1/1-1:1.0/bluetooth/hci0/hci0:42/0005:0A5C:8502.0001/input/input1 [ 2711.374829] hid-generic 0005:0A5C:8502.0001: input: BLUETOOTH HID v1.1b Keyboard [Bluetooth FAVI] on 00:15:83:3d:0a:57 evtest /dev/input/event1 }}} * Using D-Bus via {{{bluez-test-input}}} python script (requires [#pairing pairing]): {{{#!bash # hciconfig hci0 up # hcitool -i hci0 scan Scanning ... 54:46:6B:01:7B:2B Bluetooth FAVI # bluez-simple-agent hci0 54:46:6B:01:7B:2B # request pairing (specify pin code when requested then enter this code followed by a Enter on the keyboard to pair) RequestPinCode (/org/bluez/471/hci0/dev_54_46_6B_01_7B_2B) Enter PIN Code: 0000 Release New device (/org/bluez/471/hci0/dev_54_46_6B_01_7B_2B) # bluez-test-input connect 54:46:6B:01:7B:2B [ 1654.853401] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [ 1654.859353] Bluetooth: HIDP socket layer initialized [ 1655.633452] hid-generic 0005:0A5C:8502.0001: unknown main item tag 0x0 [ 1655.640391] input: Bluetooth FAVI as /devices/soc0/soc.0/2100000.aips-bus/2184000.usb/ci_hdrc.0/usb1/1-1/1-1:1.0/bluetooth/hci0/hci0:12/0005:0A5C:8502.0001/input/input1 [ 1655.655952] hid-generic 0005:0A5C:8502.0001: input: BLUETOOTH HID v1.1b Keyboard [Bluetooth FAVI] on 00:02:72:c9:56:47 }}} * Use {{{hidd}}} from the {{{bluez-compat}}} package to connect (see [#hidd below]) * In all of the above cases the kernel has registered a new input device input1 (/sys/class/input/input1, /dev/input/event1) [=#hidd] BlueZ 3: * Use {{{hidd}}} from the {{{bluez}}} package to connect (does not require pairing, or more specifically performs automatic pairing for you): {{{#!bash # hciconfig hci0 up # hcitool -i hci0 scan # show all discverable devices Scanning ... 54:46:6B:01:7B:2B Bluetooth FAVI # sdptool search HID # search for and show all discoverable devices advertising an HID service Inquiring ... Searching for HID on 54:46:6B:01:7B:2B ... Service Name: Broadcom Bluetooth Wireless Keyboard Service Description: Keyboard Service Provider: Broadcom Corp. Service RecHandle: 0x10000 Service Class ID List: "Human Interface Device" (0x1124) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 17 "HIDP" (0x0011) Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Human Interface Device" (0x1124) Version: 0x0100 # hidd --connect 54:46:6B:01:7B:2B [28013.797391] Bluetooth: HIDP (Human Interface Emulation) ver 1.2 [28013.798954] Bluetooth: HIDP socket layer initialized [28018.300685] hid-generic 0005:0A5C:8502.0001: unknown main item tag 0x0 [28018.309052] input: Broadcom Bluetooth Wireless Keyboard as /devices/soc0/soc.0/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.1/1-1.1:1.0/bluetooth/hci0/hci0:40/0005:0A5C:8502.0001/input/input5 [28018.309767] hid-generic 0005:0A5C:8502.0001: input: BLUETOOTH HID v1.1b Keyboard [Broadcom Bluetooth Wireless Keyboard ] on 00:15:83:6b:e2:bd }}} - use {{{hidd unplug }}} to disconnect the HID connection - use {{{hidd kill }}} to kill the HID connection - use {{{hidd show}}} to show all HID connections - use {{{hidd search}}} to search for HID devices in range and automatically connect to them - use {{{-i }}} to specify the bluetooth controller [=#pan] === Personal Area Network Device Profile (PAN) === The Personal Area Network Device Profile (PAN) allows encapsulating IP over bluetooth using the Bluetooth Network Encapsulation Protocol (BNEP). The kernel bnep module (CONFIG_BT_BNEP) is responsible for registering a bnep network interface when requested by the Bluetooth daemon. You do not need to use pairing for PAN connections. Once a PAN connection is active and you have a bnep interface you can use standard networking tools to configure and/or bridge the interface. There are three PAN roles: * NAP - Network Access Point * PANU - PAN User (client to a PAN NAP) * GN - Group Network (adhoc based) Configuration of PAN depends upon the version of BlueZ (see [#bsp BSP table above]). BlueZ 5: * Using D-Bus via a [https://github.com/mk-fg/fgtk/blob/master/bt-pan bt-pan] python script and the {{{bluetoothctl}}} CLI (requires python, python-dbus): - Machine1: server / NAP {{{#!bash # bluetoothctl [NEW] Controller 00:02:72:C9:56:47 BlueZ 5.37 [default] [bluetooth]# power on Changing power on succeeded [CHG] Controller 00:02:72:C9:56:47 Powered: yes [bluetooth]# discoverable on Changing discoverable on succeeded [CHG] Controller 00:02:72:C9:56:47 Discoverable: yes [bluetooth]# agent on Agent registered [bluetooth]# default-agent Default agent request successful [NEW] Device 00:15:83:3D:0A:57 yocto18-0 Request PIN code [agent] Enter PIN code: 0000 [CHG] Device 00:15:83:3D:0A:57 Paired: yes [CHG] Device 00:15:83:3D:0A:57 Connected: no [bluetooth]# paired-devices Device 00:15:83:3D:0A:57 yocto18-0 [bluetooth]# trust 00:15:83:3D:0A:57 [CHG] Device 00:15:83:3D:0A:57 Trusted: yes Changing 00:15:83:3D:0A:57 trust succeeded [bluetooth]# exit Agent unregistered [DEL] Controller 00:02:72:C9:56:47 BlueZ 5.37 [default] # sdptool add NAP # advertise NAP service # brctl addbr br0 # wget https://raw.githubusercontent.com/mk-fg/fgtk/master/bt-pan # chmod +x bt-pan # ./bt-pan --debug server br0 & DEBUG:root:Using local device (addr: 00:02:72:C9:56:47): /org/bluez/hci0 DEBUG:root:Registered uuid 'nap' with bridge/dev: br0 / 00:02:72:C9:56:47 # ifconfig br0 br0 Link encap:Ethernet HWaddr 00:02:72:c9:56:47 BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) # brctl show br0 bridge name bridge id STP enabled interfaces br0 8000.000272c95647 no bnep0 }}} - first we used {{{bluetoothctl}}} to bring up the controller, make it discoverable, and pair with and trust the client. Next we created a bridge, fetched the bt-pan python script and used it to resiter a NAP server which registers a bnep0 network interface with Linux upon successful connection with a PANU client. The bnpeg0 network interface will be added to the bridge. Make sure you use standard networking tools to configure the bridge as desired. - Machine2: client / PANU {{{#!bash # bluetoothctl [NEW] Controller 00:02:72:C9:56:47 BlueZ 5.37 [default] [bluetooth]# power on Changing power on succeeded [bluetooth]# discoverable on Changing discoverable on succeeded [CHG] Controller 00:02:72:C9:56:47 Discoverable: yes [bluetooth]# agent on Agent registered [bluetooth]# default-agent Default agent request successful [NEW] Device 00:15:83:6B:E2:BD ventana-trusty-0 Request confirmation [agent] Confirm passkey 744563 (yes/no): yes [CHG] Device 00:15:83:6B:E2:BD UUIDs: 0000110c-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD UUIDs: 0000110e-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD UUIDs: 00001112-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD UUIDs: 00001116-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD UUIDs: 0000111e-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD UUIDs: 0000111f-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD UUIDs: 0000112d-0000-1000-8000-00805f9b34fb [CHG] Device 00:15:83:6B:E2:BD Paired: yes [CHG] Device 00:15:83:6B:E2:BD Connected: no [bluetooth]# trust 00:15:83:6B:E2:BD [CHG] Device 00:15:83:6B:E2:BD Trusted: yes Changing 00:15:83:6B:E2:BD trust succeeded [bluetooth]# exit Agent unregistered [DEL] Controller 00:02:72:C9:56:47 BlueZ 5.37 [default] root@xenial:~# bluetoothctl [NEW] Controller 00:02:72:C9:56:47 BlueZ 5.37 [default] [NEW] Device 00:15:83:6B:E2:BD ventana-trusty-0 [bluetooth]# paired-devices Device 00:15:83:6B:E2:BD ventana-trusty-0 [bluetooth]# exit [DEL] Controller 00:02:72:C9:56:47 BlueZ 5.37 [default] # sdptool search NAP Inquiring ... Searching for NAP on 00:15:83:6B:E2:BD ... Service Name: Network Access Point Service Description: BlueZ PAN Service Service Provider: BlueZ PAN Service RecHandle: 0x10006 Service Class ID List: "Network Access Point" (0x1116) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 15 "BNEP" (0x000f) Version: 0x0100 SEQ16: 800 806 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Network Access Point" (0x1116) Version: 0x0100 # wget https://raw.githubusercontent.com/mk-fg/fgtk/master/bt-pan # chmod +x bt-pan # ./bt-pan --debug client 00:15:83:6B:E2:BD DEBUG:root:Using local device (addr: 00:02:72:C9:56:47): /org/bluez/hci0 DEBUG:root:Using remote device (addr: 00:15:83:6B:E2:BD): /org/bluez/hci0/dev_00_15_83_6B_E2_BD DEBUG:root:Connected to network (dev_remote: /org/bluez/hci0/dev_00_15_83_6B_E2_BD, addr: 00:15:83:6B:E2:BD) uuid 'nap' with iface: bnep0 DEBUG:root:Finished root@xenial:~# ifconfig bnep0 bnep0 Link encap:Ethernet HWaddr 00:02:72:c9:56:47 inet6 addr: fe80::202:72ff:fec9:5647/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:4 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:16 (16.0 B) TX bytes:148 (148.0 B) }}} - first we used {{{bluetoothctl}}} to pair with and trust the client. Next we fetched the bt-pan python script and used it to connect to the client which registers a bnep0 network interface with Linux upon successful connection with a NAP server. Make sure you use standard networking tools to configure the bridge as desired. BlueZ 4: * Using the {{{pand}}} tool from the {{{bluez-compat}}} package (see [#pand below]) - '''to use the {{{pand}}} application for BlueZ 4.x you must disable the internal network plugin in its bluetooth daemon. To do this add a '!DisablePlugins=network' to /etc/bluetooth/main.conf under the [General] section and restart the bluetooth daemon)''' * Using the {{{bt-network}}} application from the {{{bluez-tools}}} package (requires [#pairing pairing]): - Machine1: server / NAP: {{{#!bash # hciconfig hci0 up # bring up controller # hciconfig hci0 piscan # make discoverable # brctl addbr br0 # add a bridge # bt-network --server nap br0 # run NAP service NAP server registered }}} - Machine2: client / PANU: {{{ # hciconfig hci0 up # bring up controller # hciconfig hci0 piscan # make discoverable # sdptool search NAP # search for NAP service # bt-network --connect 00:02:72:C9:56:47 nap & }}} [=#pand] BlueZ 3: * Using the {{{pand}}} tool from the {{{bluez}}} package: - '''to use the {{{pand}}} application for BlueZ 4.x you must disable the internal network plugin in its bluetooth daemon. To do this add a '!DisablePlugins=network' to /etc/bluetooth/main.conf under the [General] section and restart the bluetooth daemon)''' - Machine1: server / NAP: {{{#!bash # hciconfig hci0 up # bring up bluetooth controller # hciconfig hci0 piscan # make discoverable # pand --listen --role NAP --master }}} * Once connected to a PANU you will see a message such as {{{pand[872]: New connection from 00:15:83:3D:0A:57 at bnep0}}} - Machine2: client / PANU: {{{#!bash # hciconfig hci0 up # bring up bluetooth controller # hcitool -i hci0 scan # show all discoverable bluetooth devices Scanning ... 00:15:83:6B:E2:BD ventana-trusty-0 # sdptool search NAP # show all discoverable bluetooth devices advertising NAP service Inquiring ... Searching for NAP on 00:15:83:6B:E2:BD ... Service Name: Network Access Point Service Description: BlueZ PAN Service Service Provider: BlueZ PAN Service RecHandle: 0x10008 Service Class ID List: "Network Access Point" (0x1116) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 15 "BNEP" (0x000f) Version: 0x0100 SEQ16: 800 806 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Network Access Point" (0x1116) Version: 0x0100 # pand --connect 00:15:83:6B:E2:BD --service NAP --nodetach pand[717]: Bluetooth PAN daemon version 4.101 pand[717]: Connecting to 00:15:83:6B:E2:BD pand[717]: bnep0 connected }}} - You can remove the {{{--nodetach}}} to run as a daemon (in which case you won't see the pand messages on the console indicating the connection status) - You can use {{{pand --role PANU --search}}} to search for and auto-connect to the first NAP server found: {{{#!bash # pand --role PANU --search --nodetach pand[723]: Bluetooth PAN daemon version 4.101 pand[723]: Inquiring pand[723]: Searching for NAP on 00:15:83:6B:E2:BD pand[723]: Connecting to 00:15:83:6B:E2:BD pand[723]: bnep0 connected }}} * Using D-Bus messages via {{{dbus-send}}}: - Machine1: server / NAP: {{{#!bash export BTADAPTER=`dbus-send --system --dest=org.bluez --print-reply / org.bluez.Manager.DefaultAdapter | tail -1 | sed 's/^.*"\(.*\)".*$/\1/'` # get the adapter path dbus-send --system --dest=org.bluez --print-reply $BTADAPTER org.bluez.NetworkHub.SetProperty string:Enabled variant:boolean:true }}} [=#opp] === Object Push Profile (OPP) === The Object Push Profile (OPP) is used to send binary data objects. An OPP server is needed to receive files via OPP. OOP defines the roles of 'push server' and 'push client': - Push Server - the device that provides an object exchange server. - Push Client - the device that pushes and pulls objects to and from the Push Server. You can use the {{{obexpushd}}} tool to create an OPP Push Server and listen for incoming files. You can use the {{{obexftp}}} tool as a Push Client to send files to a Push Server. Devices do not need to be previously paired for the OPP profile. Note that the [#ftp FTP profile] is much more capable profile. Android devices: * Several Android applications can use OPP to push files to a device with an OPP Push Server. For example, Google photos and the Google Camera app use this when you select the 'share icon' when viewing an image followed by the 'Bluetooth' icon (at which point it will show you all bluetooth devices that provide an OPP Push server) * There are several applications in the Google Play Store that provide the ability to push files to an 'OBEX OPP' server such as 'Bluetooth File Transfer' by Medieval Software: Note that by default this application enables an OOP and an FTP server without authentication (but pairing is required) while the app is running. Examples: * Discover devices providing a Push Server: {{{#!bash # sdptool search OPUSH }}} * Receive a file via {{{obexpushd}}}: {{{#!bash # hciconfig hci0 piscan # make sure we are discoverable # obexpushd -B5 -o /tmp -n # start Push Server on bluetooth channel 9 using /tmp as a directory store obexpushd 0.11.2 Copyright (C) 2006-2010 Hendrik Sattler This software comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. Warning: local character set is not Unicode. Listening on bluetooth/[00:00:00:00:00:00]:5 Creating file "/tmp/0001.patch" ^C }}} - remove the {{{-n}}} to run in the background - above shows a file accepted called 00001.patch * Binary file transfer to a device providing an OBEX OPP Push server using {{{obexftp}}}: {{{#!bash # sdptool search OPUSH Inquiring ... Searching for OPUSH on 00:15:83:6B:E2:BD ... Service Name: OBEX Object Push Service Description: a free OBEX server Service Provider: obexpushd Service RecHandle: 0x10006 Service Class ID List: "OBEX Object Push" (0x1105) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 5 "OBEX" (0x0008) Profile Descriptor List: "OBEX Object Push" (0x1105) Version: 0x0100 # obexftp --bluetooth 00:15:83:6B:E2:BDE --channel 5 --put file.pdf Connecting..\done Tried to connect for 129ms Sending "file.pdf".../done Disconnecting..-done }}} [=#ftp] === File Transfer Profile (FTP) === Provides the capability to browse, manipulate and transfer objects (files and folders) in an object store (file system) of another system. This uses GOEP as a basis. You can use this with the {{{obexftp}}} and {{{obexfs}}} Linux tools when paired with the right service: - obexftp - a file transfer protocol client using the OBEX FTP profile - obexfs - a FUSE-based filesystem that uses the OBEX FTP profile to connect to an OBEX server Devices need to be previously paired (see [#pairing pairing]). Android devices: * There are several applications in the Google Play Store that provide an 'OBEX FTP' server: - 'Bluetooth File Transfer' by Medieval Software: Note that by default this application enables an OOP and an FTP server without authentication (but pairing is required) while the app is running. Examples: * Discover devices providing a FTP service: {{{#!bash # sdptool search FTP }}} * List available files on a device providing an OBEX FTP service using {{{obexftp}}}: {{{#!bash # sdptool search FTP # search for devices advertising FTP profile Inquiring ... Searching for FTP on 98:E7:F5:A1:A1:EE ... Service Name: OBEX FTP Service RecHandle: 0x1000d Service Class ID List: UUID 128: 00001106-0000-1000-8000-00805f9b34fb Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 # obexftp --bluetooth 98:E7:F5:A1:A1:EE --channel 6 --list }}} * Delete a file from a device providing an OBEX FTP service using {{{obexftp}}}: {{{#!bash # sdptool search FTP # search for devices advertising FTP profile Inquiring ... Searching for FTP on 98:E7:F5:A1:A1:EE ... Service Name: OBEX FTP Service RecHandle: 0x1000d Service Class ID List: UUID 128: 00001106-0000-1000-8000-00805f9b34fb Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 # obexftp --bluetooth 98:E7:F5:A1:A1:EE --channel 6 --delete }}} * Binary file transfer to a device providing an OBEX FTP service using {{{obexftp}}}: {{{#!bash # sdptool search FTP # search for devices advertising FTP profile Inquiring ... Searching for FTP on 98:E7:F5:A1:A1:EE ... Service Name: OBEX FTP Service RecHandle: 0x1000d Service Class ID List: UUID 128: 00001106-0000-1000-8000-00805f9b34fb Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 # obexftp --bluetooth 98:E7:F5:A1:A1:EE --channel 6 --put file.pdf Connecting..\done Tried to connect for 129ms Sending "file.pdf".../done Disconnecting..-done }}} * Binary file transfer from a device providing an OBEX FTP service using {{{obexftp}}}: {{{#!bash # sdptool search FTP # search for devices advertising FTP profile Inquiring ... Searching for FTP on 98:E7:F5:A1:A1:EE ... Service Name: OBEX FTP Service RecHandle: 0x1000d Service Class ID List: UUID 128: 00001106-0000-1000-8000-00805f9b34fb Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 # obexftp --bluetooth 98:E7:F5:A1:A1:EE --channel 6 --get file.pdf Connecting..\done Tried to connect for 60ms Receiving "file.pdf".../done Disconnecting..-done }}} * Run an OBEX FTP server using {{{obexftpd}}}: {{{#!bash # hciconfig hci0 piscan # make us discoverable # cd /tmp # obexftpd -b5 # start OBEX FTP server via bluetooth channel 5 }}} * Mount a filesystem from an 'OBEX FTP' service using {{{obexfs}}}: {{{#!bash # sdptool search FTP # search for devices advertising FTP profile Inquiring ... Searching for FTP on 98:E7:F5:A1:A1:EE ... Service Name: OBEX FTP Service RecHandle: 0x1000d Service Class ID List: UUID 128: 00001106-0000-1000-8000-00805f9b34fb Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 6 # obexfs --bluetooth 98:E7:F5:A1:A1:EE --channel 6 /mnt # mount | grep obexfs obexfs on /mnt type fuse.obexfs (rw,nosuid,nodev) # ls /mnt Alarms LinkLocalStorage Notifications UnityAdsVideoCache file.pdf Android Logs Pictures camera-p.jpg games DCIM Movies Podcasts docs panoramas Download Music Ringtones foo }}} Note that the {{{obexftp}}} application also supports pushing files to an OBEX OPP server (see [#opp above]). [=#a2dp] === Advanced Audio Distribution Profile (A2DP) === The Advanced Audio Distribution Profile (A2DP) is a bluetooth profile that many devices support and is what is used for high fidelity headphone stereo audio. All stereo headphones support A2DP and AVRCP. The Logical Link Controller and Adaptation Protocol (L2CAP) is used in conjunction with the Audio/Video Distribution Transport Protocol (AVDTP) for control and streaming audio. This defines a binary protocol and binary streaming protocol based on RTP. A royalty free Subband-codec (SBC) is included i n the A2DP spec as a mandatory protocol but it is possible for BT devices to also optionally support MP3, AAC or other codecs. The quality of audio sent to a wireless headphone is determined by the codec. After the audio source (ie phone) selects the appropriate profile it chooses a codec which the audio sink (ie headhpone) the decodes for playback. Although it is theoretically possible to send mp3's or any other digital format straight to the headphones over Bluetooth instead the A2DP profile specifies its own set of audio codecs: * SBC (Subband Coding) - the mandatory default codec for A2DP supported by all Bluetooth stereo devices. It was deisgned to provide reasonably good audio quality over the limited bandwidth of Bluetooth without heavy processing requirements. SBC is capable of bitrates up to about 328kbps at 44.1kHz sampling which is not far off from the maximum for mp3 encoding though mp3 is superior to SBC in terms of audio quality given similar bitrates. SBC is also capable of mid and low quality streams which sound quite compressed to the ears and are unacceptable for music streaming and sound quality varies widly between different SBC implementations. * aptX is a proprietary audio codec developed for demanding audio applications designed to encode CD-quality (16bit 44.1kHz) or better (up to 24bit 96kHz) without loss of quality using a slightly higher data rate but more efficient compared to SBC. The aptX codec is not required by A2DP and currently aptX is only supported by CSR chipsets typically used in high-end Android devices. Both the headphone and the source must support aptX and if not the default SBC codec will be used instead. Currently aptX support is limited to mostly high-end Android smartphones and Hi-Fi wireless devices. * AAC (Advanced Audio Coding) is a popular codec in general designed to achieve better sound quality than mp3 at similar bit rates. Unlike aptX it is supported by iOS devices (Apple implements AAC over bluetooth at about 250kbps) which should compete in fidelity. Support for AAC is not common in bluetooth devices. Requirements: * userspace bluteooth-alsa libs (libasound_module_{pcm,ctl}_bluetooth.so) (Ubuntu: bluez-alsa, Yocto: libasound-module-bluez) The process to connect Bluetooth A2DP devices differs based on the version of the BlueZ stack you are using as well as the audio back-end that you are using: - ALSA: bluez-alsa (Ubuntu) / libasound-module-bluez (Yocto) package providing libasound_module_{pcm,ctl}_bluetooth.so - GStreamer: bluez-gstreamer (Ubuntu) providing libgstbluetooth.so / gstreamer1.0-plugins-bad-bluez (Yocto) providing libgstbluez.so - !PulseAudio: pulseaudio-module-blueeooth (Ubuntu) providing module-bluetooth-{policy,device,discover,proximity}.so BlueZ 4.x / ALSA: - Using Bluetooth headphones to playback audio from Linux device (Linux device is an A2DP Source and connecting to an A2DP Sink) 1. Identify (put headphones into pairing mode) {{{#!bash # hcitool scan Scanning ... A4:15:66:5B:B9:79 Motorola Buds # sdptool search A2SNK Inquiring ... Searching for A2SNK on A4:15:66:5B:B9:79 ... Service Provider: AVExtension_Device Service RecHandle: 0x10002 Service Class ID List: "Audio Sink" (0x110b) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 25 "AVDTP" (0x0019) uint16: 0x0100 Profile Descriptor List: "Advanced Audio" (0x110d) Version: 0x0100 }}} 2. Pair {{{#!bash # bluez-simple-agent hci0 A4:15:66:5B:B9:79 RequestPinCode (/org/bluez/506/hci0/dev_A4_15_66_5B_B9_79) Enter PIN Code: 0000 Release New device (/org/bluez/391/hci0/dev_A4_15_66_5B_B9_79) }}} - refer to your headset documentation for the correct PIN (0000 shown above or 1234 is typical) 3. Bluetooth audio configuration: - Make sure you have 'Source' and 'Media' enabled under [General] in /etc/bluetooth/audio.conf: {{{#!bash # sed 's/#Disable=\(.*\)/Enable=Source,Sink,Headset,Gateway,Control,Socket,Media/' /etc/bluetooth/audio.conf -i # enable all modules }}} - Restart the bluetooth daemon 4. bluetooth-alsa configuration: Configure a 'btheadset' audio device: {{{#!bash # cat </etc/asound.conf pcm.btheadset { type plug slave { pcm { type bluetooth device A4:15:66:5B:B9:79 profile "auto" } } hint { show on description "BT Headset" } } ctl.btheadset { type bluetooth } EOT }}} 5. You should now be able to play audio to the paired headset via ALSA: - For example with the {{{aplay}}} tool from the {{{alsa-utils}}} package: {{{#!bash # aplay -D btheadset /usr/share/sounds/alsa/Front_Center.wav # play }}} - or mplayer: {{{#!bash # mplayer -ao alsa:device=btheadset /usr/share/sounds/alsa/Front_Center.wav }}} - In order to get your headet's multimedia buttons (play,pause,next,previous) you need to create /etc/modules-load.d/uinput.conf containing uinput - For !PulseAudio you need to have !PulseAudio installed (pulseaudio-module-blueeooth) and have the !PulseAudio sound server started: {{{pulseaudio --start}}} and do not need to have /etc/asound.conf configured References: * https://www.kernel.org/doc/ols/2008/ols2008v1-pages-193-196.pdf * http://theheadphonelist.com/wireless-fidelity-making-sense-bluetooth-headphone-technology/ === Generic Access Protocol GAP === Protocol when devices are continuously advertising and there is no bonded connection. Example: temperature sensor advertising its value. Two device roles: * Central - device such as Gateworks SBC * Peripheral - device such as a temperature sensor Packets are 31 bytes. [=#gatt] === Generic Attribute Profile GATT Generic Attribute Profile (GATT) is used for Bluetooth Low Energy communication. This for a dedicated connection between two devices after GAP has already been completed. A BLE peripheral can only be connected to on central device at a time. GATT has the following: * Client - A device who initates a GATT command or request. Ex: Gateworks SBC * Server - A device that receives GATT requests and then responds. Ex: Temperature Sensor * Characteristic - A data value, such as a battery voltage * Service - Collection of Characteristics * Descriptor - Additional information for a characteristic. * Identifiers - a UUID for services, descriptors, and characteristics. * Notifications - Client can be notified when a characteristic changes on a server. Avoids the need for the client to poll the server * Indication - The same as a notification, but the client must confirm to the server it received the message. Using GATT with BlueZ 5.x with the {{{gatttool}}}: - Example: Controlling a MagicHue Bluetooth Smart Candle: {{{#!bash root@bionic-newport:~# timeout 5s hcitool lescan LE Scan ... 3C:A3:08:10:51:FE LEDBlue-081051FE root@bionic-newport:~# gatttool -i hci0 -b 3C:A3:08:10:51:FE --primary attr handle = 0x0001, end grp handle = 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle = 0x000c, end grp handle = 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle = 0x0010, end grp handle = 0x0022 uuid: 0000180a-0000-1000-8000-00805f9b34fb attr handle = 0x0023, end grp handle = 0x0033 uuid: 0000ffe5-0000-1000-8000-00805f9b34fb attr handle = 0x0034, end grp handle = 0x0044 uuid: 0000ffe0-0000-1000-8000-00805f9b34fb attr handle = 0x0045, end grp handle = 0xffff uuid: 0000fff0-0000-1000-8000-00805f9b34fb root@bionic-newport:~# gatttool -i hci0 -b 3C:A3:08:10:51:FE --characteristics handle = 0x0002, char properties = 0x02, char value handle = 0x0003, uuid = 00002a00-0000-1000-8000-00805f9b34fb handle = 0x0004, char properties = 0x02, char value handle = 0x0005, uuid = 00002a01-0000-1000-8000-00805f9b34fb handle = 0x0006, char properties = 0x0a, char value handle = 0x0007, uuid = 00002a02-0000-1000-8000-00805f9b34fb handle = 0x0008, char properties = 0x08, char value handle = 0x0009, uuid = 00002a03-0000-1000-8000-00805f9b34fb handle = 0x000a, char properties = 0x02, char value handle = 0x000b, uuid = 00002a04-0000-1000-8000-00805f9b34fb handle = 0x000d, char properties = 0x20, char value handle = 0x000e, uuid = 00002a05-0000-1000-8000-00805f9b34fb handle = 0x0011, char properties = 0x02, char value handle = 0x0012, uuid = 00002a23-0000-1000-8000-00805f9b34fb handle = 0x0013, char properties = 0x02, char value handle = 0x0014, uuid = 00002a24-0000-1000-8000-00805f9b34fb handle = 0x0015, char properties = 0x02, char value handle = 0x0016, uuid = 00002a25-0000-1000-8000-00805f9b34fb handle = 0x0017, char properties = 0x02, char value handle = 0x0018, uuid = 00002a26-0000-1000-8000-00805f9b34fb handle = 0x0019, char properties = 0x02, char value handle = 0x001a, uuid = 00002a27-0000-1000-8000-00805f9b34fb handle = 0x001b, char properties = 0x02, char value handle = 0x001c, uuid = 00002a28-0000-1000-8000-00805f9b34fb handle = 0x001d, char properties = 0x02, char value handle = 0x001e, uuid = 00002a29-0000-1000-8000-00805f9b34fb handle = 0x001f, char properties = 0x02, char value handle = 0x0020, uuid = 00002a2a-0000-1000-8000-00805f9b34fb handle = 0x0021, char properties = 0x02, char value handle = 0x0022, uuid = 00002a50-0000-1000-8000-00805f9b34fb handle = 0x0024, char properties = 0x0a, char value handle = 0x0025, uuid = 0000ffe6-0000-1000-8000-00805f9b34fb handle = 0x0027, char properties = 0x0a, char value handle = 0x0028, uuid = 0000ffe7-0000-1000-8000-00805f9b34fb handle = 0x002a, char properties = 0x0a, char value handle = 0x002b, uuid = 0000ffe8-0000-1000-8000-00805f9b34fb handle = 0x002d, char properties = 0x04, char value handle = 0x002e, uuid = 0000ffe9-0000-1000-8000-00805f9b34fb handle = 0x0030, char properties = 0x0a, char value handle = 0x0031, uuid = 0000ffea-0000-1000-8000-00805f9b34fb handle = 0x0035, char properties = 0x0a, char value handle = 0x0036, uuid = 0000ffe1-0000-1000-8000-00805f9b34fb handle = 0x0038, char properties = 0x02, char value handle = 0x0039, uuid = 0000ffe2-0000-1000-8000-00805f9b34fb handle = 0x003b, char properties = 0x08, char value handle = 0x003c, uuid = 0000ffe3-0000-1000-8000-00805f9b34fb handle = 0x003e, char properties = 0x10, char value handle = 0x003f, uuid = 0000ffe4-0000-1000-8000-00805f9b34fb handle = 0x0042, char properties = 0x02, char value handle = 0x0043, uuid = 0000ffeb-0000-1000-8000-00805f9b34fb handle = 0x0046, char properties = 0x0a, char value handle = 0x0047, uuid = 0000fff1-0000-1000-8000-00805f9b34fb handle = 0x0049, char properties = 0x02, char value handle = 0x004a, uuid = 0000fff2-0000-1000-8000-00805f9b34fb handle = 0x004c, char properties = 0x08, char value handle = 0x004d, uuid = 0000fff3-0000-1000-8000-00805f9b34fb handle = 0x004f, char properties = 0x10, char value handle = 0x0050, uuid = 0000fff4-0000-1000-8000-00805f9b34fb handle = 0x0053, char properties = 0x02, char value handle = 0x0054, uuid = 0000fff5-0000-1000-8000-00805f9b34fb root@bionic-newport:~# gatttool -i hci0 -b 3C:A3:08:10:51:FE --char-write-req -a 0x002e -n 56ff000000f0aa # red Characteristic value was written successfully gatttool -i hci0 -b 3C:A3:08:10:51:FE --char-write-req -a 0x002e -n 5600ff0000f0aa # green Characteristic value was written successfully gatttool -i hci0 -b 3C:A3:08:10:51:FE --char-write-req -a 0x002e -n 560000ff00f0aa # blue Characteristic value was written successfully }}} - The specific handle (denoting the GATT service and characteristic) and its values were determined by enabling HCI logging on an Android device while using the MagicHue Android app then viewing the log in Wireshark to see what values were being changed. This 'reverse engineering' technique is fairly common and widely described on the Internet. == Common Commandline Tools and Operations == Several command-line tools and operations are consistent among the various versions of the BlueZ stack. [=#hciconfig] === Configuring Bluetooth Controller (hciconfig) === The {{{hciconfig}}} tool will allow you to identify and configure Bluetooth controllers. It is very similar to ifconfig in that it shows Bluetooth devices, their TX/RX bytes, MAC and some other relevant information. A Bluetooth device generally shows up as hciX where X is a zero-based number. That is, if there is only one Bluetooth adapter on your system, it would usually show up as hci0. You can see the available Bluetooth controllers on a Linux system by looking in the {{{/sys/class/bluetooth}}} directory: {{{#!bash # ls /sys/class/bluetooth hci0 }}} Example uses: * show configuration for all controllers: {{{#!bash # hciconfig hci0: Type: BR/EDR Bus: USB BD Address: 2C:3D:4F:04:12:55 ACL MTU: 339:6 SCO MTU: 180:1 DOWN RX bytes:488 acl:0 sco:0 events:20 errors:0 TX bytes:82 acl:0 sco:0 commands:20 errors:0 }}} - The above shows a single controller named 'hci0' with unique MAC of 2C:3D:4F:04:12:55 currently in the power down state * bring up controller (if you don't have a bluetooth daemon that automatically does this for you): {{{#!bash hciconfig hci0 up }}} - If this fails with an error like {{{Operation not possible due to RF-kill}}} then you need to unblock it via a hardware button/gpio or use the {{{rfkill}}} utility to unblock it: {{{#!bash rfkill unblock all }}} The {{{hciconfig}}} command will show you the state of controllers as well (UP/DOWN, RUNNING, PSCAN, ISCAN). The Inquiry Scan (ISCAN) and Page Scan (PSCAN) settings determine device discover-ability ([#discovery see discovery below]). [=#hciattach] === UART based HCI configuration (hciattach) === The {{{hciattach}}} tool is used to attach serial devices via UART HCI to the BlueZ stack. This is useful for on-board Bluetooth controllers that are connected directly to a processor UART. Gateworks does not use any such controllers. [=#discoverable] === Discoverability (hciconfig) === Every Bluetooth end-point device and controller has a unique MAC address (also known as a BDADDR) and a name. A Bluetooth device needs to be in discovery mode to show up in a scan. Refer to the device documentation for details. Typically this involves holding a button down (often the power on button) for several seconds and results in a flashing blue LED indicating the device is in pairing or discovery mode. The {{{hciconfig}}} command can be used to configure the discover-ability and the name of a bluetooth controller. A Bluetooth controller may start off in hidden mode and needs to be in the 'Inquiry Scan' state to be discoverable. Examples: * show state of 'Inquiry Scan' and 'Page Scan': {{{#!bash # hciconfig hci0 }}} * enable 'Inquiry Scan' state: {{{#!bash # hciconfig hci0 iscan }}} * enable 'Page Scan' state: {{{#!bash # hciconfig hci0 pscan }}} * enable both 'Page Scan' and 'Inquiry Scan' states: {{{#!bash # hciconfig hci0 piscan }}} * disable discovery mode (be hidden): {{{#!bash # hciconfig hci0 noscan }}} The name that is shown with the MAC address of discovered nearby devices is configurable. For Linux Bluetooth controllers the {{{name}}} sub-command will configure the controllers name. You can also specify this in the Bluetooth daemon's configuration file. Examples: * show the name of a controller: {{{#!bash # hciconfig hci0 name hci0: Type: BR/EDR Bus: SDIO BD Address: 00:06:C6:FF:AD:1A ACL MTU: 1021:7 SCO MTU: 120:6 Name: 'ventana-0' }}} * use the name instead of the device name: {{{#!bash # hciconfig ventana-0 hci0: Type: BR/EDR Bus: SDIO BD Address: 00:06:C6:FF:AD:1A ACL MTU: 1021:7 SCO MTU: 120:6 UP RUNNING PSCAN RX bytes:18030 acl:121 sco:0 events:910 errors:0 TX bytes:7916 acl:76 sco:0 commands:448 errors:0 }}} * Set the name: {{{#!bash # hciconfig hci0 name "MyUCI" # hciconfig hci0 name hci0: Type: BR/EDR Bus: SDIO BD Address: 00:06:C6:FF:AD:1A ACL MTU: 1021:7 SCO MTU: 120:6 Name: 'MyUCI' # hciconfig MyUCI hci0: Type: BR/EDR Bus: SDIO BD Address: 00:06:C6:FF:AD:1A ACL MTU: 1021:7 SCO MTU: 120:6 UP RUNNING PSCAN RX bytes:18393 acl:123 sco:0 events:917 errors:0 TX bytes:8238 acl:79 sco:0 commands:450 errors:0 }}} [=#scan] === Scanning for Bluetooth devices available for pairing (hcitool) === The {{{hcitool}}} app from the bluez package can also be used to scan for and connect to Bluetooth devices in the area as well as give you information as to their identity (user defined name) and signal quality. Examples: * Scan for nearby discoverable Bluetooth devices: {{{#!bash # hciconfig hci0 up # make sure controller is powered on # hcitool -i hci0 scan # shows MAC and name of nearby devices which are configured as discoverable Scanning .. 09:40:A4:45:B1:4B P6 }}} - The above shows a single device found named 'P6' with a unique MAC address of '09:40:A4:45:B1:4B' * Connects to a specific Bluetooth device and show its link quality {{{#!bash # hcitool cc 09:40:A4:45:B1:4B; hcitool lq 09:40:A4:45:B1:4B; hcitool con Link quality: 255 Connections: < ACL 09:40:A4:45:B1:4B handle 256 state 7 lm MASTER # hcitool con Connections: # }}} - The above connects to the device with the specified MAC address and shows the active connection link quality * To scan for Bluetooth Low Energy devices, use the following command: {{{ hcitool lescan }}} [=#l2ping] === Pinging a device to test its connection (l2ping) === When a device has been discovered you can use {{{l2ping}}} from the bluez package to test the connection. This requires you to know the unique MAC address of the device: {{{#!bash # l2ping 09:40:a4:45:b1:4b 0 bytes from 09:40:a4:45:b1:4b id 0 time 9.12ms 0 bytes from 09:40:a4:45:b1:4b id 1 time 52.33ms 0 bytes from 09:40:a4:45:b1:4b id 2 time 22.50ms 0 bytes from 09:40:a4:45:b1:4b id 3 time 25.92ms ^C4 sent, 4 received, 0% loss }}} * Use 'cntl-C' to stop the ping if you did not specify a -c parameter to limit the number of ping counts * You can ping a device even if it is no longer responding to scanning (because its no longer in discovery mode) as long as the device is powered on [=#connect] === Open A Connection (hcitool) === Use {{{hcitool}}} to open a connection between an HCI and a bluetooth device: {{{#!bash # hcitool cc 54:46:6B:01:7B:2B }}} [=#linkqual] === Link Quality (hcitool) === Use {{{hcitool}}} to open a connection and determine hte link quality of a connection: {{{#!bash # hcitool cc 54:46:6B:01:7B:2B; hcitool lq 54:46:6B:01:7B:2B; hcitool con }}} [#sdptool] === Bluetooth Service Discovery Protocol (SDP) (sdptool) === The Bluetooth Service Discovery Protocol (SDP) provides a means by which service applications running on different Bluetooth enabled devices may discover each other's existence and exchange info to determine their characteristics. Use {{{sdptool}}} from the bluez package to perform SDP queries on Bluetooth devices and for administering a local SDP daemon, or {{{sdpd}}}. Example: * Show characteristics of the Sound Intone Bluetooth headset by showing all possible service records: {{{#!bash # sdptool records 09:40:a4:45:b1:4b Service Name: JL_A2DP Service RecHandle: 0x10001 Service Class ID List: "Audio Sink" (0x110b) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 25 "AVDTP" (0x0019) uint16: 0x100 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Advanced Audio" (0x110d) Version: 0x0100 Service RecHandle: 0x10002 Service Class ID List: "AV Remote" (0x110e) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 23 "AVCTP" (0x0017) uint16: 0x100 Profile Descriptor List: "AV Remote" (0x110e) Version: 0x0100 Service Name: JL_HFP Service RecHandle: 0x10003 Service Class ID List: "Handsfree" (0x111e) "Generic Audio" (0x1203) Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 4 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Handsfree" (0x111e) Version: 0x0105 }}} * Show records of a bluetooth keyboard: {{{#!bash # sdptool records 54:46:6B:01:7B:2B Service Name: Broadcom Bluetooth Wireless Keyboard Service Description: Keyboard Service Provider: Broadcom Corp. Service RecHandle: 0x10000 Service Class ID List: "Human Interface Device" (0x1124) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 17 "HIDP" (0x0011) Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Human Interface Device" (0x1124) Version: 0x0100 Service Name: Broadcom Bluetooth Wireless Keyboard PnP Server Service Description: Keyboard Service RecHandle: 0x10001 Service Class ID List: "PnP Information" (0x1200) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 1 "SDP" (0x0001) Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "PnP Information" (0x1200) Version: 0x0100 }}} * Show all devices advertising the A2DP Profile: {{{#!bash # sdptool search A2DP Service Name: JL_A2DP Service RecHandle: 0x10001 Service Class ID List: "Audio Sink" (0x110b) Protocol Descriptor List: "L2CAP" (0x0100) PSM: 25 "AVDTP" (0x0019) uint16: 0x100 Language Base Attr List: code_ISO639: 0x656e encoding: 0x6a base_offset: 0x100 Profile Descriptor List: "Advanced Audio" (0x110d) Version: 0x0100 }}} Reference: * https://www.bluetooth.com/ * http://linux.die.net/man/1/sdptool [=#pairing] === Pairing and bonding (Setting up connections) === Many of the bluetooth services can expose private data or allow control of a device, therefore for security reasons it is desired to securely pair devices in a fashion that doesn't make it too difficult to use conveniently. Bluetooth uses a process called '''bonding''' where a bond is generated through a process called '''pairing'''. Pairing is triggered either by a specific request or triggered automatically when connecting to a service for the first time. There is usually some form of user interaction to confirm the identify of the devices but once pairing is complete a bond will have been formed between the two devices, enabling them to connect to each other in the future without requiring the pairing process again. If desired the bonding relationship can later be removed by the user which would force a pairing to be completed again. You can also tell your controller to specifically trust a device based on its MAC address which eliminates the need for pairing. It is the controller that decides to pair or trust a device, not the device itself. The configuration for paired devices is stored in {{{/var/lib/bluetooth//}}}. The method used for pairing a controller to a device differs depending on the version of the BlueZ stack being used: * BlueZ 5: * The BlueZ 5 bluetooth daemon stores its persistent pairing details in {{{/var/lib/bluetooth///info}}} with the format of: {{{ [LinkKey] Key String Type Integer PINLength Integer }}} - therefore you can remove all pairing history by removing that file and restarting bluetoothd * You can request pairing with devices using the {{{bluetoothctl}}} CLI {{{pair }}} command: {{{#!bash # bluetoothctl [NEW] Controller 00:15:83:6B:E2:BD BlueZ 5.37 [default] [bluetooth]# power on Changing power on succeeded [bluetooth]# scan on Discovery started [CHG] Controller 00:15:83:6B:E2:BD Discovering: yes [NEW] Device 54:46:6B:01:7B:2B 54-46-6B-01-7B-2B [CHG] Device 54:46:6B:01:7B:2B RSSI: -75 [CHG] Device 54:46:6B:01:7B:2B LegacyPairing: no [CHG] Device 54:46:6B:01:7B:2B Name: Bluetooth FAVI [CHG] Device 54:46:6B:01:7B:2B Alias: Bluetooth FAVI [bluetooth]# pair 54:46:6B:01:7B:2B Attempting to pair with 54:46:6B:01:7B:2B [CHG] Device 54:46:6B:01:7B:2B Connected: yes [CHG] Device 54:46:6B:01:7B:2B Modalias: usb:v0A5Cp8502d011B [CHG] Device 54:46:6B:01:7B:2B UUIDs: 00001000-0000-1000-8000-00805f9b34fb [CHG] Device 54:46:6B:01:7B:2B UUIDs: 00001124-0000-1000-8000-00805f9b34fb [CHG] Device 54:46:6B:01:7B:2B UUIDs: 00001200-0000-1000-8000-00805f9b34fb [CHG] Device 54:46:6B:01:7B:2B Paired: yes Pairing successful [CHG] Device 54:46:6B:01:7B:2B Connected: no [CHG] Device 54:46:6B:01:7B:2B LegacyPairing: yes [CHG] Device 54:46:6B:01:7B:2B RSSI: -66 [CHG] Device 54:46:6B:01:7B:2B RSSI: -66 [bluetooth]# scan off [CHG] Controller 00:15:83:6B:E2:BD Discovering: no Discovery stopped [bluetooth]# paired-devices Device 54:46:6B:01:7B:2B Bluetooth FAVI Device 09:40:A4:45:B1:4B P6 [bluetooth]# }}} - above first we enable scanning, then we pair with a device, next we disable scanning (optional), and lastly we show paired devices * You can respond to pairing requests using the bluetoothd internal agent using the {{{bluetoothctl}}} CLI: {{{#!bash # bluetoothctl [NEW] Controller 00:15:83:6B:E2:BD BlueZ 5.37 [default] [bluetooth]# power on Changing power on succeeded [bluetooth]# agent on Agent registered [bluetooth]# default-agent Default agent request successful [NEW] Device 00:15:83:3D:0A:57 yocto18-0 Request PIN code [agent] Enter PIN code: 0000 [CHG] Device 00:15:83:3D:0A:57 Paired: yes [CHG] Device 00:15:83:3D:0A:57 Connected: no [bluetooth]# paired-devices Device 00:15:83:3D:0A:57 yocto18-0 }}} - above we first enable the agent, then set it to the default agent and wait for pairing requests. A pairing request comes from a device with a bdaddr or 00:15:83:3D:0A:57 and a name of yocto18-0 and we enter in the PIN that the device is expecting and we pair with it * BlueZ 4: * The BlueZ 4.x bluetooth daemon stores persistent pairing details {{{/var/lib/bluetooth//linkkeys}}} with the following format: {{{ <128bit_link_key> }}} - therefore you can remove all pairing history by removing that file and restarting bluetoothd * You can pair with a device using the python 'simple-agent' found in the bluez4 git tree [http://git.kernel.org/cgit/bluetooth/bluez.git/plain/test/simple-agent?h=4.101 here] (requires python, python-dbus and python-gobject) {{{#!bash # ./simple-agent hci0 54:46:6B:01:7B:2B RequestPinCode (/org/bluez/449/hci0/dev_54_46_6B_01_7B_2B) Enter PIN Code: 1234 Release New device (/org/bluez/449/hci0/dev_54_46_6B_01_7B_2B) # ls /var/lib/bluetooth/00\:15\:83\:3D\:0A\:57/ classes did linkkeys profiles config lastused names sdp # cat /var/lib/bluetooth/00\:15\:83\:3D\:0A\:57/linkkeys 54:46:6B:01:7B:2B E45EED6C956306606A306EA1A2E22B68 0 4 }}} - Depending on the version of python you have installed, you may need to patch simple-agent with the following changes: {{{#!bash --- simple-agent.orig +++ simple-agent @@ -2,8 +2,7 @@ from __future__ import absolute_import, print_function, unicode_literals -from gi.repository import GObject - +import gobject import sys import dbus import dbus.service @@ -122,7 +121,7 @@ path = "/test/agent" agent = Agent(bus, path) - mainloop = GObject.MainLoop() + mainloop = gobject.MainLoop() if len(args) > 1: if len(args) > 2: }}} * Alternatively you can also pair using the compiled agent.c found in the bluez4 git tree [http://git.kernel.org/cgit/bluetooth/bluez.git/plain/test/agent.c?h=4.101 here] {{{#!bash # bluetoothd # ./agent 1234 54:46:6B:01:7B:2B Pincode request for device /org/bluez/2039/hci0/dev_54_46_6B_01_7B_2B Agent has been released }}} - if this exist without the 'Agent has been released' message then pairing was unsuccessful - this can be cross-compiled with the following (ie Yocto SDK): {{{#!bash $CC -DVERSION=4.101 $(pkg-config --cflags dbus-1) agent.c $(pkg-config --libs dbus-1) -o agent }}} * For examples on how to pair using dbus messages see the simple-agent and agent.c source code * BlueZ 3: - The BlueZ 3.x bluetooth daemon stores persistent pairing details in {{{/var/lib/bluetooth//pincodes}}} in the form of: {{{ }}} - therefore you can remove all pairing history by removing that file and restarting bluetoothd - If you manually edit this file, you will need to restart the hcid bluetooth daemon: {{{#!bash # echo "00:02:72:C9:56:47 0000" >> /var/lib/bluetooth/00\:15\:83\:3D\:0A\:57/pincodes # /etc/init.d/bluez-utils restart }}} References: * http://en.wikipedia.org/wiki/Bluetooth#Pairing_and_bonding [=#code] == Writing code supporting Bluetooth == If you wish to or need to write your own applications to support Bluetooth there are a variety of great resources out there on the Internet: * http://people.csail.mit.edu/rudolph/Teaching/Articles/BTBook.pdf (PyBluez, libbluetooth, cmdline tools) * [http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc BlueZ 5 API Documentation] * [http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc?id=4.101 BlueZ 4 API Documentation] * [http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc?h=utils-3.36 BlueZ 3 API Documentation] * Don't forget to refer to the source code: - bluez - see the docs/examples/test directories - bluez-tools - C applications == iBeacon == iBeacon is a form of BLE that was created by Apple to provide location based information and services to iPhones. For example, someone is walking around with an iPhone with a specific app loaded that is listening for these iBeacons. The app on the phone will respond when the iBeacon comes in range. (retail environment, sale special)