Change Bluetooth Address

Recently i bought a few bluetooth dongles for both personal and official use. Since i bought them at different times the modules were either based on Broadcom or CSR (mostly) based bluetooth chipsets.

These modules worked well but there was a peculiar issue which i ran into. The bluetooth address on these modules were the same. Let me be more clear, i ordered more than 2 bluetooth modules of the same chipset and the shipped modules were all having the same bluetooth address. In other words, two bluetooth modules based on CSR chipset which i bought from amazon were having the same bluetooth addresses.

This scenario was true to the bluetooth modules based on Broadcom chipset also.

How to fix this

There is a simple solution to this which is available in the latest bluez package. “bdaddr” is a binary provided by the latest bluez package which helps us in this scenario. Using this tool we can easily change the bluetooth addresses of the dongle’s we have.

Availability of the bdaddr

In case of the Ubuntu Mate distro (based on Ubuntu 16.04 LTS) this binary was not provided by any package.

kasi@kasi-desktop:~/bt/bluez-5.42$ cat /etc/issue
Ubuntu 16.04.1 LTS \n \l

Unfortunately it is not as simple as using “apt-get <pkg_name> install” to install the package as it is not available in the canonical package repo’s at least as far i have checked.

But they cant stop us from changing the bluetooth address right. Can they ? No, not by a long shot.

Compilation of Bluez package

Getting the source code:

kasi@kasi-desktop:~/bt$ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.42.tar.xz

Untar the code:

kasi@kasi-desktop:~/bt$ tar xf bluez-5.42.tar.xz
kasi@kasi-desktop:~/bt$ cd bluez-5.42/
kasi@kasi-desktop:~/bt/bluez-5.42$

Configure the package:

By default bdaddr binary is not compiled by the bluez package as they are part of the experimental code. Now we need to configure bluez so that it compile’s bdaddr.c file under the tools directory. To do that we need to add “–enable-experimental” switch along with ./configure. As said above this makes sure that the bdaddr.c source file under tools directory gets compiled.

Installation issues:

Pls note that during the below step you may face issues with missing dependency packages that is not installed in your machine. Since i have already gone through this painful process many times while compiling other packages i didn’t face any issues this time around. If the configuration fails it can be easily fixed by installing the missing packages.

Pls pay more attention to the output of the configuration which itself is more than enough to solve the underlying issues.

kasi@kasi-desktop:~/bt/bluez-5.42$ ./configure –enable-experimental
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… yes
checking for a thread-safe mkdir -p… /bin/mkdir -p
checking for gawk… gawk
checking whether make sets $(MAKE)… yes
checking whether make supports nested variables… yes
checking how to create a pax tar archive… gnutar
checking for style of include used by make… GNU
checking for gcc… gcc
checking whether the C compiler works… yes
checking for C compiler default output file name… a.out
checking for suffix of executables…
checking whether we are cross compiling… no
checking for suffix of object files… o
checking whether we are using the GNU C compiler… yes
checking whether gcc accepts -g… yes
checking for gcc option to accept ISO C89… none needed
checking whether gcc understands -c and -o together… yes
checking dependency style of gcc… gcc3
checking how to run the C preprocessor… gcc -E
checking for grep that handles long lines and -e… /bin/grep
checking for egrep… /bin/grep -E
checking for ANSI C header files… yes
checking for sys/types.h… yes
checking for sys/stat.h… yes
checking for stdlib.h… yes
checking for string.h… yes
checking for memory.h… yes
checking for strings.h… yes
checking for inttypes.h… yes
checking for stdint.h… yes
checking for unistd.h… yes
checking minix/config.h usability… no
checking minix/config.h presence… no
checking for minix/config.h… no
checking whether it is safe to define __EXTENSIONS__… yes
checking whether make supports nested variables… (cached) yes
checking whether to enable maintainer-specific portions of Makefiles… no
checking for pkg-config… /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0… yes
checking for C/C++ restrict keyword… __restrict
checking for gcc… (cached) gcc
checking whether we are using the GNU C compiler… (cached) yes
checking whether gcc accepts -g… (cached) yes
checking for gcc option to accept ISO C89… (cached) none needed
checking whether gcc understands -c and -o together… (cached) yes
checking dependency style of gcc… (cached) gcc3
checking whether gcc accepts -fPIE… yes
checking build system type… x86_64-unknown-linux-gnu
checking host system type… x86_64-unknown-linux-gnu
checking how to print strings… printf
checking for a sed that does not truncate output… /bin/sed
checking for fgrep… /bin/grep -F
checking for ld used by gcc… /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld… yes
checking for BSD- or MS-compatible name lister (nm)… /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface… BSD nm
checking whether ln -s works… yes
checking the maximum length of command line arguments… 1572864
checking whether the shell understands some XSI constructs… yes
checking whether the shell understands “+=”… yes
checking how to convert x86_64-unknown-linux-gnu file names to x86_64-unknown-linux-gnu format… func_convert_file_noop
checking how to convert x86_64-unknown-linux-gnu file names to toolchain format… func_convert_file_noop
checking for /usr/bin/ld option to reload object files… -r
checking for objdump… objdump
checking how to recognize dependent libraries… pass_all
checking for dlltool… no
checking how to associate runtime and link libraries… printf %s\n
checking for ar… ar
checking for archiver @FILE support… @
checking for strip… strip
checking for ranlib… ranlib
checking command to parse /usr/bin/nm -B output from gcc object… ok
checking for sysroot… no
checking for mt… mt
checking if mt is a manifest tool… no
checking for dlfcn.h… yes
checking for objdir… .libs
checking if gcc supports -fno-rtti -fno-exceptions… no
checking for gcc option to produce PIC… -fPIC -DPIC
checking if gcc PIC flag -fPIC -DPIC works… yes
checking if gcc static flag -static works… yes
checking if gcc supports -c -o file.o… yes
checking if gcc supports -c -o file.o… (cached) yes
checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries… yes
checking whether -lc should be explicitly linked in… no
checking dynamic linker characteristics… GNU/Linux ld.so
checking how to hardcode library paths into programs… immediate
checking whether stripping libraries is possible… yes
checking if libtool supports shared libraries… yes
checking whether to build shared libraries… yes
checking whether to build static libraries… no
checking for signalfd… yes
checking for clock_gettime in -lrt… yes
checking for pthread_create in -lpthread… yes
checking for dlopen in -ldl… yes
checking linux/types.h usability… yes
checking linux/types.h presence… yes
checking for linux/types.h… yes
checking linux/if_alg.h usability… yes
checking linux/if_alg.h presence… yes
checking for linux/if_alg.h… yes
checking for GLIB… yes
checking for DBUS… yes
checking D-Bus configuration directory… /etc
checking D-Bus system bus services dir… /usr/share/dbus-1/system-services
checking D-Bus session bus services dir… /usr/share/dbus-1/services
checking for UDEV… yes
checking for udev_hwdb_new in -ludev… yes
checking udev directory… /lib/udev
checking for ICAL… yes
checking readline/readline.h usability… yes
checking readline/readline.h presence… yes
checking for readline/readline.h… yes
checking systemd system unit dir… /lib/systemd/system
checking systemd user unit dir… /usr/lib/systemd/user
checking that generated files are newer than configure… done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/bluetoothd.8
config.status: creating lib/bluez.pc
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands
kasi@kasi-desktop:~/bt/bluez-5.42$

I have left the complete output of the configuration just in case if anyone needs to cross verify with their output.

Time to fire make and wait …

kasi@kasi-desktop:~/bt/bluez-5.42$ make
GEN      lib/bluetooth/bluetooth.h
GEN      lib/bluetooth/hci.h
GEN      lib/bluetooth/hci_lib.h
GEN      lib/bluetooth/sco.h

< — CUT HERE TO REDUCE THE LOGS –>

CC       tools/gatt-service.o
CCLD     tools/gatt-service
CC       profiles/iap/main.o
CCLD     profiles/iap/iapd
CC       tools/hid2hci.o
CCLD     tools/hid2hci
GEN      tools/97-hid2hci.rules
GEN      obexd/src/obex.service
kasi@kasi-desktop:~/bt/bluez-5.42$

The compiled binary is available in tools directory.

kasi@kasi-desktop:~/bt/bluez-5.42$ ls tools/bdaddr*
tools/bdaddr  tools/bdaddr.c  tools/bdaddr.o
kasi@kasi-desktop:~/bt/bluez-5.42

How it works:

Let us look into the basic output from the bdaddr command.

kasi@kasi-desktop:~/bt/bluez-5.42$ sudo ./tools/bdaddr
Manufacturer:   Cambridge Silicon Radio (10)
Device address: 00:1A:7D:DA:71:0A (cyber-blue(HK)Ltd)
kasi@kasi-desktop:~/bt/bluez-5.42$

Time to change the Bluetooth/BD address:

kasi@kasi-desktop:~/bt/bluez-5.42$ sudo ./tools/bdaddr -i hci0 00:1A:7D:DA:71:0B
Manufacturer:   Cambridge Silicon Radio (10)
Device address: 00:1A:7D:DA:71:0A (cyber-blue(HK)Ltd)
New BD address: 00:1A:7D:DA:71:0B (cyber-blue(HK)Ltd)

Address changed – Reset device now

kasi@kasi-desktop:~/bt/bluez-5.42$

As you can see, i have just modified the last octet of the bluetooth address alone to make it simple. hci0 is the name of the interface which i have in my machine. It could be different in your machine. Pls check the name using the basic hciconfig command.

kasi@kasi-desktop:~/bt/bluez-5.42$ hciconfig -a
hci0:    Type: BR/EDR  Bus: USB
BD Address: 00:1A:7D:DA:71:0A  ACL MTU: 310:10  SCO MTU: 64:8
UP RUNNING
RX bytes:671 acl:0 sco:0 events:40 errors:0
TX bytes:982 acl:0 sco:0 commands:40 errors:0
Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: SLAVE ACCEPT
Name: ‘kasi-desktop’
Class: 0x1c0104
Service Classes: Rendering, Capturing, Object Transfer
Device Class: Computer, Desktop workstation
HCI Version: 4.0 (0x6)  Revision: 0x22bb
LMP Version: 4.0 (0x6)  Subversion: 0x22bb
Manufacturer: Cambridge Silicon Radio (10)

kasi@kasi-desktop:~/bt/bluez-5.42$

Disconnect and reconnect:

Now its time to reset the device so that the address change gets reflected. You can unplug and reconnect it again for the changes to take effect.

kasi@kasi-desktop:~/bt/bluez-5.42$ hciconfig -a
hci0:    Type: BR/EDR  Bus: USB
BD Address: 00:1A:7D:DA:71:0B  ACL MTU: 310:10  SCO MTU: 64:8
UP RUNNING
RX bytes:616 acl:0 sco:0 events:37 errors:0
TX bytes:948 acl:0 sco:0 commands:37 errors:0
Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x87
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: SLAVE ACCEPT
Name: ‘kasi-desktop’
Class: 0x1c0104
Service Classes: Rendering, Capturing, Object Transfer
Device Class: Computer, Desktop workstation
HCI Version: 4.0 (0x6)  Revision: 0x22bb
LMP Version: 4.0 (0x6)  Subversion: 0x22bb
Manufacturer: Cambridge Silicon Radio (10)

Soft reset didnt work on modules based on CSR chipsets and only physical disconnection and re-connection worked.

Modules based on Broadcom chipset:

In case of broadcom based bluetooth devices, all the above steps worked along with soft reset but when i unplug and reconnect this module again, the address gets reverted to the old address. So the changes to bluetooth address are not persistent in case of bluetooth modules based on broadcom chipset but soft reset works and this device can be used with the modified address without unplugging and reconnecting.

kasi@kasi-desktop:~/bt/bluez-5.42$ sudo hciconfig hci0 reset
kasi@kasi-desktop:~/bt/bluez-5.42$ hciconfig
hci0:    Type: BR/EDR  Bus: USB
BD Address: 5C:F3:70:68:07:12  ACL MTU: 1021:8  SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:1734 acl:0 sco:0 events:107 errors:0
TX bytes:5698 acl:0 sco:0 commands:107 errors:0

kasi@kasi-desktop:~/bt/bluez-5.42$

I have checked this on the Broadcom and CSR chipsets based bluetooth modules and it works on both them.

If you look into the source code we can see the list of supported chipset vendors.

  • CSR.
  • Broadcom.
  • Ericsson.
  • TI.
  • Marvell.

Almost all of the major vendors are supported.

Why i like Arch based distro’s:

In arch based distro (apricity), this binary bdaddr was provided by the bluez-utils package and it is available out of the box. This is one of the main reasons why i like arch based distro’s as you get the bleeding edge packages.

root  ~  pkgfile /usr/bin/bdaddr
extra/bluez-utils

root  ~  pacman -Ql bluez-utils
bluez-utils /usr/
bluez-utils /usr/bin/
bluez-utils /usr/bin/3dsp
bluez-utils /usr/bin/amptest
bluez-utils /usr/bin/avinfo
bluez-utils /usr/bin/avtest
bluez-utils /usr/bin/bccmd
bluez-utils /usr/bin/bdaddr
bluez-utils /usr/bin/bluemoon

Hope this blog was helpful in case if you are also facing the same issue with multiple bluetooth dongles.

Advertisements