2022-03-19
md
Bluetooth and BlueALSA in Raspberry Pi OS Lite (November 2021)
Bluetooth®, PulseAudio, and BlueALSA in Raspberry Pi OS Lite (March 2022)-> <-Bluetooth, BlueALSA and Buster
<-Baby Bluetooth Steps on Raspberry Pi 3 - Raspbian (Stretch)
The newer versions of Raspberry Pi OS break things. For a quick update about streaming sound with Bluetooth® in the newest version of the OS see: Bluetooth®, PulseAudio, and BlueALSA in Raspberry Pi OS Lite (March 2022)
March 17, 2022

It has been a couple of years since I last looked at Bluetooth on the Raspberry Pi. Back then the operating system was Raspbian which corresponded to Debian 9 (Stretch) and the 4.9.59 Linux kernel, now the operating system has been renamed Raspberry Pi OS which corresponds to Debian 10 (Buster with a 5.10.63 kernel). What do these changes mean for the wireless technology? Actually, very little. As before, some tweaking still needs to be done to use Bluetooth for audio streaming in the Lite version of the operating system. I assume that this is not needed in the desktop version of the OS. As before, the SAP profile is still being loaded as if the Pi has a built-in SIM card. That remains a simple thing to fix. Unfortunately, I have been unable to find a reliable work around for the Failed to set privacy: Rejected (0x0b) error, but there does not seem to be any adverse consequences.

If so little has changed then why write a new post? To be honest, I originally ran into some problems and wanted to write about them in the hope of getting some help. The problems were entirely my fault, but as a consequence, I have an expanded exploration of using a Bluetooth keyboard with a headless Pi. I know that is an obvious contradiction but it should be seen as an exploration of the wireless technology. Much more in keeping with the headless theme, I have added sections on disabling and removing Bluetooth. I also showed how to reverse both of these, because nothing is ever permanent.

Table of Content

  1. Raspberry Pi OS Lite
  2. Membership in the bluetooth Group
  3. Bluetooth Keyboard
    1. First Connection
    2. Subsequent Connections
    3. Quick Disconnections
  4. Streaming Audio to a Bluetooth Speaker
    1. Test ALSA
    2. Install bluealsa
    3. Streaming an Audio Source out to Bluetooth Devices
  5. Streaming Audio from a Bluetooth Device, an Android Telephone
  6. Modifying the bluetooth.service Unit File
  7. Bluetooth Scripting
  8. Disable Bluetooth
  9. Remove Bluetooth

Raspberry Pi OS Lite toc

First, let's look at the state of things when booting the Raspberry Pi after installing Raspberry Pi OS Lite and doing an update and upgrade.

michel@hp:~$ ssh nostra@damus.local Opening an ssh session from the desktop computer ... nostra@damus:~ $ sudo apt update && sudo apt upgrade -y ... nostra@damus:~ $ uname -a Linux damus 5.10.63-v7+ #1459 SMP Wed Oct 6 16:41:10 BST 2021 armv7l GNU/Linux

When an upgrade bring about many changes, I prefer to reboot (sudo reboot) and then open a new session. Let's look at the bluetooth service which should be running on any Raspberry Pi equipped with the Wi-Fi/Bluetooth chip. Hopefully, a USB Bluetooth dongle can be used with older models with equivalent results.

nostra@damus:~ $ sudo systemctl status blue* ● bluetooth.service - Bluetooth service Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2021-10-25 21:13:46 ADT; 1h 39min ago Docs: man:bluetoothd(8) Main PID: 505 (bluetoothd) Status: "Running" Tasks: 1 (limit: 1935) CGroup: /system.slice/bluetooth.service └─505 /usr/lib/bluetooth/bluetoothd Oct 25 21:13:46 damus systemd[1]: Starting Bluetooth service... Oct 25 21:13:46 damus bluetoothd[505]: Bluetooth daemon 5.50 Oct 25 21:13:46 damus systemd[1]: Started Bluetooth service. Oct 25 21:13:46 damus bluetoothd[505]: Starting SDP server Oct 25 21:13:46 damus bluetoothd[505]: Bluetooth management interface 1.18 initialized Oct 25 21:13:46 damus bluetoothd[505]: Sap driver initialization failed. Oct 25 21:13:46 damus bluetoothd[505]: sap-server: Operation not permitted (1) Oct 25 21:13:46 damus bluetoothd[505]: Failed to set privacy: Rejected (0x0b) Oct 25 21:13:46 damus systemd[1]: Reached target Bluetooth.

As can be seen, it is version 5.50 of BlueZ the "Official Linux Bluetooth protocol stack" that is installed by default as in 2019. This is by no means the most recent version; my desktop, a Mint 20.1 system, is running version 5.53 and version 5.62 was released on October 17, 2021. It is not too surprising that problems encountered previously remain. Before examining the details, let's take the BlueZ stack out for a spin.

nostra@damus:~ $ bluetoothctl press Enter if the system hangs [bluetooth]# scan on No default controller available

This is not right. At this point, the BlueZ interactive bluetooth control utility must be launched by a user with root privileges. That will be changed later.

[bluetooth]# quit nostra@damus:~ $ sudo bluetoothctl Agent registered [bluetooth]# scan on Discovery started [CHG] Controller B8:27:EB:00:00:01 Discovering: yes [NEW] Device B8:78:2E:00:00:01 B8-78-2E-00-00-01 an Apple product [NEW] Device 04:92:26:00:00:01 ASUS_X00PD an Asus phone ... [bluetooth]# info 04:92:26:00:00:01 Device 04:92:26:00:00:01 (public) Name: ASUS_X00PD Alias: ASUS_X00PD Class: 0x005a020c Icon: phone Paired: no Trusted: no Blocked: no Connected: no ... [bluetooth]# info B8:78:2E:00:00:01 Device B8:78:2E:00:00:01 (public) Alias: B8-78-2E-00-00-01 Paired: no Trusted: no Blocked: no Connected: no ... [bluetooth]# discoverable on Changing discoverable on succeeded [CHG] Controller B8:27:EB:00:00:01 Discoverable: yes [bluetooth]# connect 04:92:26:00:00:01 Attempting to connect to 04:92:26:00:00:01 [CHG] Device 04:92:26:00:00:01 Connected: yes ... [CHG] Device 04:92:26:00:00:01 ServicesResolved: yes Failed to connect: org.bluez.Error.Failed [bluetooth]# quit

Once the Pi was made discoverable, it did show up on an Android phone as a nearby Bluetooth device named damus which is the host name of the Raspberry Pi used as a test bed. But as can be seen the Pi could not connect to the phone, nor could the connection be established in the opposite direction. This does not mean that the BlueZ stack is not working, it is just that, by default, bits needed for establishing the usual audio connection between a phone and devices are missing. I did manage to connect a keyboard to the Pi, but first let's fix the problem with the user privileges.

Membership in the bluetooth Group toc

Since bluetoothctl is used for pairing devices, a manual operation done by the user, it makes sense to make it available without requiring explicit upgrades in privileges. That problem is easily fixed by adding the default user to the bluetooth group whose existence we first check.

nostra@damus:~ $ groups nostra adm dialout cdrom sudo audio video plugdev games users input netdev gpio i2c spi nostra@damus:~ $ cat /etc/group | grep bluetooth bluetooth:x:112: the group exists but nostra is not a member nostra@damus:~ $ sudo adduser nostra bluetooth Adding user `nostra' to group `bluetooth' ... Adding user nostra to group bluetooth Done.

For some reason closing and reopening the session did not work, I found it necessary to reboot for this to take effect.

nostra@damus:~ $ bluetoothctl Agent registered [bluetooth]# scan on Discovery started ... [NEW] Device 30:21:5C:00:00:01 AUDIOPOD2 [bluetooth]# connect 30:21:5C:00:00:01 Attempting to connect to 30:21:5C:00:00:01 [CHG] Device 30:21:5C:00:00:01 Connected: yes [CHG] Device 30:21:5C:00:00:01 UUIDs: 00001108-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 ServicesResolved: yes Failed to connect: org.bluez.Error.Failed [CHG] Device 30:21:5C:00:00:01 ServicesResolved: no [CHG] Device 30:21:5C:00:00:01 Connected: no

While the Bluetooth speakers were found, it was again impossible to connect to them, for the same reason that it was impossible to connect to the phone. As explained later, there is a missing bridge between the bluetooth service and the Linux sound system. Nevertheless, BlueZ is functioning properly as shown next.

Bluetooth Keyboard toc

Before looking at audio streaming, let's try to connect to a Bluetooth keyboard as a way of testing the BlueZ stack. This test is performed with an Adesso WBK-1000BA keyboard which I borrowed from my spouse who uses it with an early model IPad.

Two SSH sessions with the Pi will be used in this test. They can be identified with the different background colour. First let's prove that there is no input device except for what I take it is a placeholder for a mouse since none is connected.

nostra@damus:~ $ ls /dev/input mice

First Connection toc

Let us connect to the keyboard which uses a PIN code to authenticate the connection. Note that the code changes every time a connection is attempted. The procedure resembles a little ballet. Here is the gist of what is done to establish an initial connection.

  1. In bluetoothctl start scaning for devices.
  2. Press the connect button on the Bluetooth keyboard. The button is labelled <<o>> on the Adesso, but could be different on other brands.
  3. Once the keyboard shows up in bluetoothctl, pair with it.
  4. Enter the PIN code displayed in blueetoothctl on the Bluetooth keyboard and press on Enter.
  5. Back in bluetoothctl, trust the keyboard once it is paired.
  6. Still in bluetoothctl, connect to the keyboard.

The order of the last two steps is probably not important.

[bluetooth]# scan on Discovery started [CHG] Controller B8:27:EB:00:00:01 Discovering: yes [CHG] Device B8:78:2E:00:00:01 RSSI: -87 [CHG] Device B8:78:2E:00:00:01 ManufacturerData Key: 0x004c [CHG] Device B8:78:2E:00:00:01 ManufacturerData Value: 09 06 03 23 c0 a8 00 a6 ...#.... Pressed the connect Bluetooth <<o>> button on the keyboard [NEW] Device DC:2C:26:21:7B:F6 Adesso Bluetooth 3.0 Keyboard [CHG] Device 30:21:5C:00:00:01 RSSI: -54 [bluetooth]# pair DC:2C:26:21:7B:F6 Attempting to pair with DC:2C:26:21:7B:F6 [CHG] Device DC:2C:26:21:7B:F6 Connected: yes [agent] PIN code: 361939 Entered 361939 Enter on the keyboard [CHG] Device DC:2C:26:21:7B:F6 Modalias: usb:v0A5Cp8502d011B [CHG] Device DC:2C:26:21:7B:F6 UUIDs: 00001000-0000-1000-8000-00805f9b34fb [CHG] Device DC:2C:26:21:7B:F6 UUIDs: 00001124-0000-1000-8000-00805f9b34fb [CHG] Device DC:2C:26:21:7B:F6 UUIDs: 00001200-0000-1000-8000-00805f9b34fb [CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: yes [CHG] Device DC:2C:26:21:7B:F6 Paired: yes Pairing successful [CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: no [CHG] Device DC:2C:26:21:7B:F6 Connected: no [CHG] Device DC:2C:26:21:7B:F6 RSSI: -72 [bluetooth]# trust DC:2C:26:21:7B:F6 [CHG] Device DC:2C:26:21:7B:F6 Trusted: yes Changing DC:2C:26:21:7B:F6 trust succeeded [bluetooth]# connect DC:2C:26:21:7B:F6 Attempting to connect to DC:2C:26:21:7B:F6 [CHG] Device DC:2C:26:21:7B:F6 Connected: yes Connection successful [CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: yes [Adesso Bluetooth 3.0 Keyboard]#

The keyboard is connected and can be used.

Subsequent Connections toc

Since the Bluetooth keyboard is trusted, the next time it needs to be connected, the task is much simpler because it will not be necessary to enter a PID code. So, reconnecting to a trusted keyboard is usually a two-step procedure, three if you forget the first one as shown next.

bluetooth]# connect DC:2C:26:21:7B:F6 Attempting to connect to DC:2C:26:21:7B:F6 Failed to connect: org.bluez.Error.Failed Is the keyboard turned on? Press the connect Bluetooth <<o>> button on the keyboard! [bluetooth]# connect DC:2C:26:21:7B:F6 Attempting to connect to DC:2C:26:21:7B:F6 [CHG] Device DC:2C:26:21:7B:F6 Connected: yes Connection successful [CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: yes

Quick Disconnections toc

In my previous discussion about using a Bluetooth keyboard, I stopped at simply connecting the device. Now I can go a bit further and test if the keyboard works because this old dog learned some new things while adding an IR receiver to a Pi. A keyboard shows up as an input device in the /dev directory.

nostra@damus:~ $ ls /dev/input event0 event1 event2 mice

Let's pipe the result received through a hex conversion utility, xdd, and display it on the screen.

nostra@damus:~ $ cat /dev/input/event0 | xxd 1 pressed on the keyboard 00000000: e2ad 7961 556b 0600 0400 0400 1e00 0700 ..yaUk.......... 00000010: e2ad 7961 556b 0600 0100 0200 0100 0000 ..yaUk.......... 00000020: e2ad 7961 556b 0600 0000 0000 0000 0000 ..yaUk.......... 00000030: e2ad 7961 0c1b 0700 0400 0400 1e00 0700 ..ya............ 00000040: e2ad 7961 0c1b 0700 0100 0200 0000 0000 ..ya............ 00000050: e2ad 7961 0c1b 0700 0000 0000 0000 0000 ..ya............ 0 pressed on the keyboard 00000060: e5ad 7961 afe6 0300 0400 0400 2700 0700 ..ya........'... 00000070: e5ad 7961 afe6 0300 0100 0b00 0100 0000 ..ya............ 00000080: e5ad 7961 afe6 0300 0000 0000 0000 0000 ..ya............ 00000090: e5ad 7961 5f96 0400 0400 0400 2700 0700 ..ya_.......'... 000000a0: e5ad 7961 5f96 0400 0100 0b00 0000 0000 ..ya_........... 000000b0: e5ad 7961 5f96 0400 0000 0000 0000 0000 ..ya_...........

Most of what is shown will be different on subsequent tries because timestamps make up a large part of these messages. Be aware that the keyboard will disconnect after about one minute of inactivity, to conserve the battery of the keyboard.

cat: /dev/input/event0: No such device

[CHG] Device DC:2C:26:21:7B:F6 Connected: no [CHG] Device DC:2C:26:21:7B:F6 ServicesResolved: no

Pressing a key on the Bluetooth keyboard will reestablish the connection. It is not easy to follow the events because /dev/input/event0 will not be available until the reconnection is established again. But once it is, then cat /dev/input/event0 | xxd can be used to follow the keystrokes, however the first keystroke that reestablished the connection will be lost. Here is what the control utility shows as the keyboard repeatedly goes to sleep and is subsequently awakened and it reconnects when a key is pressed.

[CHG] Device DC:2C:26:21:7B:F6 Connected: yes [CHG] Device DC:2C:26:21:7B:F6 Connected: no [CHG] Device DC:2C:26:21:7B:F6 Connected: yes ...

It is disconcerting to see that these connections are the cause of apparent errors.

nostra@damus:~ $ journalctl -u bluetooth ... Oct 28 19:24:36 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:24:36 damus bluetoothd[484]: device_request_pin: Operation not permitted Oct 28 19:31:54 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:31:54 damus bluetoothd[484]: device_request_pin: Operation not permitted ...

The same error messages show up in the BlueZ service status.

nostra@damus:~ $ systemctl status bluetooth ● bluetooth.service - Bluetooth service Loaded: loaded (/lib/systemd/system/bluetooth.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2021-10-28 19:14:04 ADT; 32min ago Docs: man:bluetoothd(8) Main PID: 484 (bluetoothd) Status: "Running" Tasks: 1 (limit: 1935) CGroup: /system.slice/bluetooth.service └─484 /usr/lib/bluetooth/bluetoothd --noplugin=sap Oct 28 19:17:08 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:17:08 damus bluetoothd[484]: device_request_pin: Operation not permitted ... Oct 28 19:24:36 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:24:36 damus bluetoothd[484]: device_request_pin: Operation not permitted Oct 28 19:31:54 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:31:54 damus bluetoothd[484]: device_request_pin: Operation not permitted

There is actually a lot more going on.

nostra@damus:~ $ journalctl | grep -i blue ... Oct 28 19:24:36 damus kernel: input: Adesso Bluetooth 3.0 Keyboard as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:12/0005:0A5C:8502.0004/input/input9 Oct 28 19:24:36 damus kernel: input: Adesso Bluetooth 3.0 Keyboard Consumer Control as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:12/0005:0A5C:8502.0004/input/input10 Oct 28 19:24:36 damus kernel: input: Adesso Bluetooth 3.0 Keyboard System Control as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:12/0005:0A5C:8502.0004/input/input11 Oct 28 19:24:36 damus kernel: hid-generic 0005:0A5C:8502.0004: input,hidraw0: BLUETOOTH HID v1.1b Keyboard [Adesso Bluetooth 3.0 Keyboard] on B8:27:EB:00:00:01 Oct 28 19:24:36 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:24:36 damus bluetoothd[484]: device_request_pin: Operation not permitted Oct 28 19:24:36 damus systemd-logind[358]: Watching system buttons on /dev/input/event2 (Adesso Bluetooth 3.0 Keyboard System Control) Oct 28 19:24:36 damus systemd-logind[358]: Watching system buttons on /dev/input/event0 (Adesso Bluetooth 3.0 Keyboard) Oct 28 19:24:36 damus systemd-logind[358]: Watching system buttons on /dev/input/event1 (Adesso Bluetooth 3.0 Keyboard Consumer Control) Oct 28 19:31:54 damus kernel: input: Adesso Bluetooth 3.0 Keyboard as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:0A5C:8502.0005/input/input12 Oct 28 19:31:54 damus kernel: input: Adesso Bluetooth 3.0 Keyboard Consumer Control as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:0A5C:8502.0005/input/input13 Oct 28 19:31:54 damus kernel: input: Adesso Bluetooth 3.0 Keyboard System Control as /devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0/hci0:11/0005:0A5C:8502.0005/input/input14 Oct 28 19:31:54 damus kernel: hid-generic 0005:0A5C:8502.0005: input,hidraw0: BLUETOOTH HID v1.1b Keyboard [Adesso Bluetooth 3.0 Keyboard] on B8:27:EB:00:00:01 Oct 28 19:31:54 damus bluetoothd[484]: No agent available for request type 0 Oct 28 19:31:54 damus bluetoothd[484]: device_request_pin: Operation not permitted Oct 28 19:31:54 damus systemd-logind[358]: Watching system buttons on /dev/input/event1 (Adesso Bluetooth 3.0 Keyboard Consumer Control) Oct 28 19:31:54 damus systemd-logind[358]: Watching system buttons on /dev/input/event2 (Adesso Bluetooth 3.0 Keyboard System Control) Oct 28 19:31:54 damus systemd-logind[358]: Watching system buttons on /dev/input/event0 (Adesso Bluetooth 3.0 Keyboard)

I will not pretend that I understand all of this, or even any of it, except maybe the part about Watching system button on /dev/input/event0 since that was monitored. If you really want to be swamped with information, use the btmon utility.

nostra@damus:~ $ sudo btmon 2>&1 ... 0 pressed on the keyboard > ACL Data RX: Handle 11 flags 0x02 dlen 14 #73 [hci0] 73.137203 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 27 00 00 00 00 00 ....'..... > ACL Data RX: Handle 11 flags 0x02 dlen 14 #74 [hci0] 73.204702 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 00 00 00 00 00 00 .......... 1 pressed on the keyboard > ACL Data RX: Handle 11 flags 0x02 dlen 14 #75 [hci0] 84.477197 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 1e 00 00 00 00 00 .......... > ACL Data RX: Handle 11 flags 0x02 dlen 14 #76 [hci0] 84.544696 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 00 00 00 00 00 00 .......... keyboard disconnecting > ACL Data RX: Handle 11 flags 0x02 dlen 12 #77 [hci0] 206.224541 L2CAP: Disconnection Request (0x06) ident 6 len 4 Destination CID: 65 Source CID: 68 < ACL Data TX: Handle 11 flags 0x00 dlen 12 #78 [hci0] 206.224692 L2CAP: Disconnection Response (0x07) ident 6 len 4 Destination CID: 65 Source CID: 68 < HCI Command: Exit Sniff Mode (0x02|0x0004) plen 2 #79 [hci0] 206.224729 Handle: 11 > HCI Event: Command Status (0x0f) plen 4 #80 [hci0] 206.227494 Exit Sniff Mode (0x02|0x0004) ncmd 1 Status: Success (0x00) > HCI Event: Mode Change (0x14) plen 6 #81 [hci0] 206.273366 Status: Success (0x00) Handle: 11 Mode: Active (0x00) Interval: 0.000 msec (0x0000) > ACL Data RX: Handle 11 flags 0x02 dlen 12 #82 [hci0] 206.299640 L2CAP: Disconnection Request (0x06) ident 7 len 4 Destination CID: 64 Source CID: 64 > HCI Event: Number of Completed Packets (0x13) plen 5 #83 [hci0] 206.537577 Num handles: 1 Handle: 11 Count: 1 < ACL Data TX: Handle 11 flags 0x00 dlen 12 #84 [hci0] 206.838335 L2CAP: Disconnection Response (0x07) ident 7 len 4 Destination CID: 64 Source CID: 64 > HCI Event: Number of Completed Packets (0x13) plen 5 #85 [hci0] 207.004426 Num handles: 1 Handle: 11 Count: 1 > HCI Event: Disconnect Complete (0x05) plen 4 #86 [hci0] 207.004640 Status: Success (0x00) Handle: 11 Reason: Remote User Terminated Connection (0x13) @ MGMT Event: Device Disconnected (0x000c) plen 8 {0x0002} [hci0] 207.004672 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Reason: Connection terminated due to authentication failure (0x04) @ MGMT Event: Device Disconnected (0x000c) plen 8 {0x0001} [hci0] 207.004672 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Reason: Connection terminated due to authentication failure (0x04) 2 pressed on the keyboard > HCI Event: Connect Request (0x04) plen 10 #87 [hci0] 406.250489 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Class: 0x000540 Major class: Peripheral (mouse, joystick, keyboards) Minor class: 0x10 Link type: ACL (0x01) < HCI Command: Accept Connection Request (0x01|0x0009) plen 7 #88 [hci0] 406.250569 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Role: Master (0x00) > HCI Event: Command Status (0x0f) plen 4 #89 [hci0] 406.251668 Accept Connection Request (0x01|0x0009) ncmd 1 Status: Success (0x00) > HCI Event: Role Change (0x12) plen 8 #90 [hci0] 406.410640 Status: Success (0x00) Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Role: Master (0x00) > HCI Event: Connect Complete (0x03) plen 11 #91 [hci0] 406.436758 Status: Success (0x00) Handle: 12 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Link type: ACL (0x01) Encryption: Disabled (0x00) < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 #92 [hci0] 406.436948 Handle: 12 > HCI Event: Command Status (0x0f) plen 4 #93 [hci0] 406.437941 Read Remote Supported Features (0x01|0x001b) ncmd 1 Status: Success (0x00) > HCI Event: Read Remote Supported Features (0x0b) plen 11 #94 [hci0] 406.437954 Status: Success (0x00) Handle: 12 Features: 0xbf 0x06 0x86 0x78 0x18 0x1e 0x59 0x87 3 slot packets 5 slot packets Encryption Slot offset Timing accuracy Role switch Sniff mode Power control requests Channel quality driven data rate (CQDDR) Paging parameter negotiation Power control Broadcast Encryption Enhanced inquiry scan Interlaced inquiry scan Interlaced page scan RSSI with inquiry results AFH capable slave AFH classification slave Sniff subrating Pause encryption AFH capable master AFH classification master Extended Inquiry Response Secure Simple Pairing Encapsulated PDU Non-flushable Packet Boundary Flag Link Supervision Timeout Changed Event Inquiry TX Power Level Enhanced Power Control Extended features < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 #95 [hci0] 406.438014 Handle: 12 Page: 1 > HCI Event: Command Status (0x0f) plen 4 #96 [hci0] 406.438418 Read Remote Extended Features (0x01|0x001c) ncmd 1 Status: Success (0x00) > HCI Event: Read Remote Extended Features (0x23) plen 13 #97 [hci0] 406.438585 Status: Success (0x00) Handle: 12 Page: 1/0 Features: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 #98 [hci0] 406.438664 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Page scan repetition mode: R2 (0x02) Page scan mode: Mandatory (0x00) Clock offset: 0x0000 < ACL Data TX: Handle 12 flags 0x00 dlen 10 #99 [hci0] 406.438689 L2CAP: Information Request (0x0a) ident 1 len 2 Type: Extended features supported (0x0002) > HCI Event: Max Slots Change (0x1b) plen 3 #100 [hci0] 406.439485 Handle: 12 Max slots: 5 > HCI Event: Command Status (0x0f) plen 4 #101 [hci0] 406.439628 Remote Name Request (0x01|0x0019) ncmd 1 Status: Success (0x00) > ACL Data RX: Handle 12 flags 0x02 dlen 16 #102 [hci0] 406.444548 L2CAP: Information Response (0x0b) ident 1 len 8 Type: Extended features supported (0x0002) Result: Success (0x0000) Features: 0x00000280 Fixed Channels Unicast Connectionless Data Reception < ACL Data TX: Handle 12 flags 0x00 dlen 10 #103 [hci0] 406.444612 L2CAP: Information Request (0x0a) ident 2 len 2 Type: Fixed channels supported (0x0003) > HCI Event: Number of Completed Packets (0x13) plen 5 #104 [hci0] 406.450859 Num handles: 1 Handle: 12 Count: 2 > ACL Data RX: Handle 12 flags 0x02 dlen 12 #105 [hci0] 406.452003 L2CAP: Connection Request (0x02) ident 2 len 4 PSM: 17 (0x0011) Source CID: 67 @ MGMT Event: Device Connected (0x000b) plen 18 {0x0002} [hci0] 406.452033 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Flags: 0x00000000 Data length: 5 Class: 0x000540 Major class: Peripheral (mouse, joystick, keyboards) Minor class: 0x10 @ MGMT Event: Device Connected (0x000b) plen 18 {0x0001} [hci0] 406.452033 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Flags: 0x00000000 Data length: 5 Class: 0x000540 Major class: Peripheral (mouse, joystick, keyboards) Minor class: 0x10 < ACL Data TX: Handle 12 flags 0x00 dlen 16 #106 [hci0] 406.452120 L2CAP: Connection Response (0x03) ident 2 len 8 Destination CID: 64 Source CID: 67 Result: Connection pending (0x0001) Status: No further information available (0x0000) < ACL Data TX: Handle 12 flags 0x00 dlen 10 #107 [hci0] 406.452134 L2CAP: Information Request (0x0a) ident 3 len 2 Type: Extended features supported (0x0002) > ACL Data RX: Handle 12 flags 0x02 dlen 20 #108 [hci0] 406.454590 L2CAP: Information Response (0x0b) ident 2 len 12 Type: Fixed channels supported (0x0003) Result: Success (0x0000) Channels: 0x0000000000000006 L2CAP Signaling (BR/EDR) Connectionless reception > HCI Event: Remote Name Req Complete (0x07) plen 255 #109 [hci0] 406.459745 Status: Success (0x00) Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Name: Adesso Bluetooth 3.0 Keyboard > ACL Data RX: Handle 12 flags 0x02 dlen 16 #110 [hci0] 406.459918 L2CAP: Information Response (0x0b) ident 3 len 8 Type: Extended features supported (0x0002) Result: Success (0x0000) Features: 0x00000280 Fixed Channels Unicast Connectionless Data Reception < ACL Data TX: Handle 12 flags 0x00 dlen 10 #111 [hci0] 406.459977 L2CAP: Information Request (0x0a) ident 4 len 2 Type: Fixed channels supported (0x0003) > HCI Event: Number of Completed Packets (0x13) plen 5 #112 [hci0] 406.460036 Num handles: 1 Handle: 12 Count: 2 > ACL Data RX: Handle 12 flags 0x02 dlen 20 #113 [hci0] 406.488361 L2CAP: Information Response (0x0b) ident 4 len 12 Type: Fixed channels supported (0x0003) Result: Success (0x0000) Channels: 0x0000000000000006 L2CAP Signaling (BR/EDR) Connectionless reception < ACL Data TX: Handle 12 flags 0x00 dlen 16 #114 [hci0] 406.488440 L2CAP: Connection Response (0x03) ident 2 len 8 Destination CID: 64 Source CID: 67 Result: Connection successful (0x0000) Status: No further information available (0x0000) < ACL Data TX: Handle 12 flags 0x00 dlen 12 #115 [hci0] 406.488454 L2CAP: Configure Request (0x04) ident 5 len 4 Destination CID: 67 Flags: 0x0000 > HCI Event: Number of Completed Packets (0x13) plen 5 #116 [hci0] 406.491970 Num handles: 1 Handle: 12 Count: 2 > ACL Data RX: Handle 12 flags 0x02 dlen 16 #117 [hci0] 406.493340 L2CAP: Configure Request (0x04) ident 3 len 8 Destination CID: 64 Flags: 0x0000 Option: Maximum Transmission Unit (0x01) [mandatory] MTU: 48 < ACL Data TX: Handle 12 flags 0x00 dlen 18 #118 [hci0] 406.493392 L2CAP: Configure Response (0x05) ident 3 len 10 Source CID: 67 Flags: 0x0000 Result: Success (0x0000) Option: Maximum Transmission Unit (0x01) [mandatory] MTU: 48 > ACL Data RX: Handle 12 flags 0x02 dlen 14 #119 [hci0] 406.494527 L2CAP: Configure Response (0x05) ident 5 len 6 Source CID: 64 Flags: 0x0000 Result: Success (0x0000) > HCI Event: Number of Completed Packets (0x13) plen 5 #120 [hci0] 406.496987 Num handles: 1 Handle: 12 Count: 2 > ACL Data RX: Handle 12 flags 0x02 dlen 12 #121 [hci0] 406.498272 L2CAP: Connection Request (0x02) ident 4 len 4 PSM: 19 (0x0013) Source CID: 66 < ACL Data TX: Handle 12 flags 0x00 dlen 16 #122 [hci0] 406.498352 L2CAP: Connection Response (0x03) ident 4 len 8 Destination CID: 65 Source CID: 66 Result: Connection pending (0x0001) Status: Authorization pending (0x0002) < ACL Data TX: Handle 12 flags 0x00 dlen 16 #123 [hci0] 406.498560 L2CAP: Connection Response (0x03) ident 4 len 8 Destination CID: 65 Source CID: 66 Result: Connection successful (0x0000) Status: No further information available (0x0000) < ACL Data TX: Handle 12 flags 0x00 dlen 12 #124 [hci0] 406.498575 L2CAP: Configure Request (0x04) ident 6 len 4 Destination CID: 66 Flags: 0x0000 > HCI Event: Number of Completed Packets (0x13) plen 5 #125 [hci0] 406.503236 Num handles: 1 Handle: 12 Count: 2 > ACL Data RX: Handle 12 flags 0x02 dlen 16 #126 [hci0] 406.504572 L2CAP: Configure Request (0x04) ident 5 len 8 Destination CID: 65 Flags: 0x0000 Option: Maximum Transmission Unit (0x01) [mandatory] MTU: 48 < ACL Data TX: Handle 12 flags 0x00 dlen 18 #127 [hci0] 406.504617 L2CAP: Configure Response (0x05) ident 5 len 10 Source CID: 66 Flags: 0x0000 Result: Success (0x0000) Option: Maximum Transmission Unit (0x01) [mandatory] MTU: 48 > ACL Data RX: Handle 12 flags 0x02 dlen 14 #128 [hci0] 406.505815 L2CAP: Configure Response (0x05) ident 6 len 6 Source CID: 65 Flags: 0x0000 Result: Success (0x0000) > HCI Event: Number of Completed Packets (0x13) plen 5 #129 [hci0] 406.508262 Num handles: 1 Handle: 12 Count: 2 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 #130 [hci0] 406.510809 Handle: 12 > HCI Event: Command Status (0x0f) plen 4 #131 [hci0] 406.511335 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 #132 [hci0] 406.511548 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 #133 [hci0] 406.511589 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Link key: f506601ff32d5a93f99933bd146182fe > HCI Event: Command Complete (0x0e) plen 10 #134 [hci0] 406.513314 Link Key Request Reply (0x01|0x000b) ncmd 1 Status: Success (0x00) Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) < ACL Data TX: Handle 12 flags 0x00 dlen 6 #135 [hci0] 406.515291 Channel: 67 len 2 [PSM 17 mode 0] {chan 0} 41 03 A. > ACL Data RX: Handle 12 flags 0x02 dlen 13 #136 [hci0] 406.515488 Channel: 65 len 9 [PSM 19 mode 0] {chan 1} a1 03 b5 dc 2c 26 21 7b f6 ....,&!{. > ACL Data RX: Handle 12 flags 0x02 dlen 14 #137 [hci0] 406.515796 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 1f 00 00 00 00 00 .......... > ACL Data RX: Handle 12 flags 0x02 dlen 14 #138 [hci0] 406.517883 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 00 00 00 00 00 00 .......... > HCI Event: PIN Code Request (0x16) plen 6 #139 [hci0] 406.542052 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) @ MGMT Event: PIN Code Request (0x000e) plen 8 {0x0002} [hci0] 406.542112 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Secure PIN: 0x00 @ MGMT Event: PIN Code Request (0x000e) plen 8 {0x0001} [hci0] 406.542112 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Secure PIN: 0x00 = bluetoothd: No agent available for request type 0 406.544175 = bluetoothd: device_request_pin: Operation not permitted [hci0] 406.544229 @ MGMT Command: PIN Code Negative Reply (0x0017) plen 7 {0x0001} [hci0] 406.542661 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) < HCI Command: PIN Code Request Negative Reply (0x01|0x000e) plen 6 #140 [hci0] 406.542798 Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) > HCI Event: Command Complete (0x0e) plen 10 #141 [hci0] 406.545078 PIN Code Request Negative Reply (0x01|0x000e) ncmd 1 Status: Success (0x00) Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) @ MGMT Event: Command Complete (0x0001) plen 10 {0x0001} [hci0] 406.545121 PIN Code Negative Reply (0x0017) plen 7 Status: Success (0x00) BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) > HCI Event: Auth Complete (0x06) plen 3 #142 [hci0] 406.545420 Status: PIN or Key Missing (0x06) Handle: 12 @ MGMT Event: Authentication Failed (0x0011) plen 8 {0x0002} [hci0] 406.545452 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Status: Authentication Failed (0x05) @ MGMT Event: Authentication Failed (0x0011) plen 8 {0x0001} [hci0] 406.545452 BR/EDR Address: DC:2C:26:21:7B:F6 (Iton Technology Limited) Status: Authentication Failed (0x05) > ACL Data RX: Handle 12 flags 0x02 dlen 14 #143 [hci0] 406.545764 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 e1 00 00 00 00 00 .......... > ACL Data RX: Handle 12 flags 0x02 dlen 14 #144 [hci0] 406.546969 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 00 00 00 00 00 00 .......... > ACL Data RX: Handle 12 flags 0x02 dlen 13 #145 [hci0] 406.548149 Channel: 64 len 9 [PSM 17 mode 0] {chan 0} a1 03 b5 dc 2c 26 21 7b f6 ....,&!{. > HCI Event: Mode Change (0x14) plen 6 #146 [hci0] 406.549392 Status: Success (0x00) Handle: 12 Mode: Sniff (0x02) Interval: 22.500 msec (0x0024) > ACL Data RX: Handle 12 flags 0x02 dlen 14 #147 [hci0] 406.721994 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 e1 00 00 00 00 00 .......... > ACL Data RX: Handle 12 flags 0x02 dlen 14 #148 [hci0] 406.723243 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 00 00 00 00 00 00 .......... > HCI Event: Number of Completed Packets (0x13) plen 5 #149 [hci0] 406.786516 Num handles: 1 Handle: 12 Count: 1 > ACL Data RX: Handle 12 flags 0x02 dlen 14 #150 [hci0] 406.901995 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 e1 00 00 00 00 00 .......... > ACL Data RX: Handle 12 flags 0x02 dlen 14 #151 [hci0] 406.903245 Channel: 65 len 10 [PSM 19 mode 0] {chan 1} a1 01 00 00 00 00 00 00 00 00 .......... > ACL Data RX: Handle 12 flags 0x02 dlen 13 #152 [hci0] 427.939477 Channel: 65 len 9 [PSM 19 mode 0] {chan 1} a1 03 b4 dc 2c 26 21 7b f6 ....,&!{.

Nothwithstanding all the complaining, it does look like the BlueZ stack is working, at least when it comes to input devices such as a keyboard.

Streaming Audio to a Bluetooth Speaker toc

It used to be that BlueZ worked directly with ALSA. But starting with version 5, the stack ... acts as a middleware between an audio application, which implements Bluetooth audio profile, and a Bluetooth audio device. Consequently, to stream audio from/to a Bluetooth device, one has to install PulseAudio ... [or] BlueALSA [which has] less dependencies and [is] more bare-metal-like. (Source:Bluetooth Audio ALSA Backend). Given that this is a Lite distribution from which PulseAudio was explicitly removed in the past, the bluealsa package will be installed. But first what is ALSA ? And let's make sure it is working.

Test ALSA toc

ALSA (Advanced Linux Sound Architecture) is set of drivers, libraries and utilities that manage sound cards in, you guessed it, Linux. To test that it is working, copy some wav sound file to a directory and play it with the aplay utility. The sound file should be long enough, say at least 5 minutes, so to run some tests. In principle, it should be very easy to output the sound: neither .asoundrc or /etc/asound.conf is normally required. You should be able to play and record sound without either Source: Alsa Opensrc Org .asoundrc.

nostra@damus:~ $ aplay -vv Music/test.wav Playing WAVE 'Music/test.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono Plug PCM: Hardware PCM card 0 'bcm2835 ALSA' device 0 subdevice 0 Its setup is: stream : PLAYBACK access : RW_INTERLEAVED format : S16_LE subformat : STD channels : 1 rate : 8000 exact rate : 8000 (8000/1) msbits : 16 buffer_size : 4000 period_size : 1000 period_time : 125000 tstamp_mode : NONE tstamp_type : MONOTONIC period_step : 1 avail_min : 1000 period_event : 0 start_threshold : 4000 stop_threshold : 4000 silence_threshold: 0 silence_size : 0 boundary : 2097152000 appl_ptr : 0 hw_ptr : 0 ###### + | 21%

You should see an emulated VU-meter (sound level) meter at the bottom of the terminal which more or less confirms that sound is being played. The best test is to plug headphones or powered speakers into 3.5mm jack to actually hear the sound.

Let's adjust the volume of the using another ALSA utility, alsamixer. Open another session with the Pi and launch it.

nostra@damus:~ $ alsamixer

The following interactive text-based user interface will be displayed.

alsamixer

There is only one volume control, Headphone, which stands for the 3.5 mm jack output. The volume is increased by pressing + on the keyboard and decreased by pressing -. The up and down cursor keys and could also be used. Entering a digit d = 0, 1 to 9 sets the volume control at d*10%. If the channel is muted, then MM is displayed at the bottom instead of the OO seen above. Muting can be toggled by pressing the M key. See the manual page (man alsamixer) for more details.

Install bluealsa toc

Time to install Bluetooth Audio ALSA Backend a.k.a bluez-alsa a.k.a BlueALSA. The package is called bluealsa.

nostra@damus:~ $ sudo apt install bluealsa -y Reading package lists... Done ... The following NEW packages will be installed: bluealsa libbluetooth3 libsbc1 0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. Need to get 182 kB of archives. After this operation, 557 kB of additional disk space will be used. ... Setting up bluealsa (0.13) ... bluealsa.service is a disabled or a static unit, not starting it. Processing triggers for dbus (1.12.20-0+deb10u1) ... Processing triggers for libc-bin (2.28-10+rpt2+rpi1) ...

The installation did not start the service, so let's do it manually.

nostra@damus:~ $ sudo systemctl status bluealsa.service ● bluealsa.service - BluezALSA proxy Loaded: loaded (/lib/systemd/system/bluealsa.service; static; vendor preset: enabled) Active: inactive (dead) nostra@damus:~ $ sudo systemctl start bluealsa.service nostra@damus:~ $ sudo systemctl status bluealsa.service ● bluealsa.service - BluezALSA proxy Loaded: loaded (/lib/systemd/system/bluealsa.service; static; vendor preset: enabled) Active: active (running) since Tue 2021-10-26 15:29:38 ADT; 1s ago Main PID: 1135 (bluealsa) Tasks: 3 (limit: 1935) CGroup: /system.slice/bluealsa.service └─1135 /usr/bin/bluealsa Oct 26 15:29:38 damus systemd[1]: Started BluezALSA proxy.

Streaming an Audio Source out to Bluetooth Devices toc

It is now possible to connect to the Bluetooth speakers.

nostra@damus:~ $ bluetoothctl Agent registered [bluetooth]# scan on Discovery started [CHG] Controller B8:27:EB:00:00:01 Discovering: yes ... [NEW] Device 30:21:5C:00:00:01 AUDIOPOD2 ... bluetooth]# devices ... Device 30:21:5C:00:00:01 AUDIOPOD2 ... bluetooth]# connect 30:21:5C:00:00:01 Attempting to connect to 30:21:5C:00:00:01 [CHG] Device 30:21:5C:00:00:01 Connected: yes [CHG] Device 30:21:5C:00:00:01 UUIDs: 00001108-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 ServicesResolved: yes [CHG] Device 30:21:5C:00:00:01 Paired: yes Connection successful [AUDIOPOD2]# quit

Time to test this connection.

nostra@damus:~ $ aplay -vv -D bluealsa:DEV=30:21:5C:00:00:01 music/test.wav Playing WAVE 'music/test.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Mono Plug PCM: Rate conversion PCM (48000, sformat=S16_LE) Converter: linear-interpolation Protocol version: 10002 Its setup is: stream : PLAYBACK access : RW_INTERLEAVED format : S16_LE subformat : STD channels : 1 rate : 8000 exact rate : 8000 (8000/1) msbits : 16 buffer_size : 4095 period_size : 682 period_time : 85333 tstamp_mode : NONE tstamp_type : GETTIMEOFDAY period_step : 1 avail_min : 682 period_event : 0 start_threshold : 4095 stop_threshold : 4095 silence_threshold: 0 silence_size : 0 boundary : 268369920 Slave: Route conversion PCM (sformat=S16_LE) Transformation table: 0 <- 0 1 <- 0 Its setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 1 rate : 48000 exact rate : 48000 (48000/1) msbits : 16 buffer_size : 24576 period_size : 4096 period_time : 85333 tstamp_mode : NONE tstamp_type : GETTIMEOFDAY period_step : 1 avail_min : 4096 period_event : 0 start_threshold : 24576 stop_threshold : 24576 silence_threshold: 0 silence_size : 0 boundary : 1610612736 Slave: BlueALSA PCM: /org/bluealsa/hci0/dev_30_21_5C_30_F1_C4/a2dp BlueALSA BlueZ device: /org/bluez/hci0/dev_30_21_5C_30_F1_C4 BlueALSA Bluetooth codec: 0 ################+ | 31%

Again let's start alsamixer in another terminal but this time adding that the bluealsa device must be used.

nostra@damus:~ $ alsamixer -D bluealsa

alsamixer with bluealsa device

Move from control to control by typing p or n on the keyboard or using the cursor arrow keys or . The volume control for the Bluetooth speaker is named AUDIOPOD2 - A2DP. Of course, the number of controls and their names depends on the particular speaker.

Streaming Audio from a Bluetooth Device: an Android Telephone toc

By default, bluealsa enables the a2dp profile as a source, meaning that the Pi can stream out audio over Bluetooth only. To sink (i.e. receive) Bluetooth audio streams, the configuration file must be modified.

nostra@damus:~ $ sudo nano /lib/systemd/system/bluealsa.service
[Unit] Description=BluezALSA proxy Requires=bluetooth.service After=bluetooth.service [Service] Type=simple User=root ExecStart=/usr/bin/bluealsa -p a2dp-source -p a2dp-sink

While -p a2dp-source is the default, it must be included in the command line when adding -p a2dp-sink otherwise it will be disabled.

To be honest it is not that simple to start streaming audio from a phone or tablet to the Pi and have it play the output on the 3.5 mm jack or hdmi output. The basic idea is to pair the phone and the Pi on both devices and then connect to the phone with bluetoothctl. Play a source of sound on the phone such as a song or a video. The sound should not be heard from the phone speakers, but do make sure that the volume is set near the maximum. Then on the Pi start the bleualsa-aplay utility with the Bluetooth address of the telephone.

nostra@damus:~ $ sudo bluealsa-aplay 04:92:26:00:00:01

You could try the simpler address 00:00:00:00:00:00 which should work.

Do not forget that there are two volume controls at play, the phone or tablet volume control and the headphone playback device volume control. As mentioned above, I find it easier to start with the phone or tablet playing at full volume or near that.

The problem with latency remains. In practice, audio from videos being viewed on the phone or tablet cannot be streamed to the Pi, unless you happen to be among those that enjoy looking and listening to overdubbed films about monsters from outer space dating back to the 50s or 60s. I tested to see if using different hardware would improve the situation. This involved disabling the Wi-Fi and Bluetooth chip altogether (the Broadcom BCM43438 on the Pi 3 B) and streaming the audio of a video to a cheap Bluetooth USB dongle.

nostra@damus:~ $ lsusb Bus 001 Device 004: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) ...

The result was no better. The problem may be the dongle which only implements Bluetooth 4.0 while the Pi 3 B runs the marginally better Bluetooth 4.1. The Broadcomm chip has been replaced with a Cypress chip on the Pi 3 B+ and PI 4 B. This is particularly meaningful on the Pi 4 which supports Bluetooth 5.0 ( only 4.2 on the 3 B+) and it is reported to offer 4 times the range and almost twice the speed. Something to test in the future, if I ever get hold of a Pi 4 or another system with Bluetooth 5.0. Of course, the audio device playing the sound, be it a speaker or a headphone set, must also implement Bluetooth 5.0 because the older profile will necessarily be used when sink and source have different capabilities. In any case, I think the latency problem is inherent in the technology which explains why some video players can delay the video playback to help with synchronising the sound.

Modifying the bluetooth.service Unit File toc

Recall the three errors reported when bluetooth.service is started.

Oct 25 21:13:46 damus bluetoothd[505]: Sap driver initialization failed. Oct 25 21:13:46 damus bluetoothd[505]: sap-server: Operation not permitted (1) Oct 25 21:13:46 damus bluetoothd[505]: Failed to set privacy: Rejected (0x0b)

The first two messages report a failed attempt at loading the SIM access profile (sap). Given that there is no SIM card on a Raspberry Pi, this failure is to be expected. It is simple enough to modify the unit file to instruct the service to ignore that profile.

nostra@damus:~ $ sudo nano /lib/systemd/system/bluetooth.service

[Unit] Description=Bluetooth service Documentation=man:bluetoothd(8) ConditionPathIsDirectory=/sys/class/bluetooth [Service] Type=dbus BusName=org.bluez ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap NotifyAccess=main #WatchdogSec=10 Restart=on-failure CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE LimitNPROC=1 ProtectHome=true ProtectSystem=full [Install] WantedBy=bluetooth.target Alias=dbus-org.bluez.service

The added command line option will get rid of the sap related error messages. At the same time, I enabled restart on failure for the only reason that this was done on my desktop machine.

The Failed to set privacy error, which seems much more important, has proven intractable. My previous solutions which involved restarting the bluetooth.service in a cron task at boot time or using the one line addition to a service file as proposed by Ben Windsor no longer work. I have not been able to obtain reliable results with the other workarounds found in the regression from 0.8 to 0.9 -- BLE connection fails until bluetooth service is restarted #8 issue on the Pi distrubution GitHub.

I should mention that most of these, which use hciconfig which [...] deprecated and [will] no longer [be] there in newer bluez versions, will break when BlueZ is updated in Raspberry Pi OS. Hence fixes based on those utilities will no longer work.

Bluetooth Scripting toc

Commands can be passed to the Bluetooth control utility, bluetoothctl on its command line. To connect the wireless speaker, I can use the following bluetoothctl connect 30:21:5C:00:00:01 either at the console prompt or in a script file. If there is no need to display the output to the terminal then it can be redirected to nul: bluetoothctl connect 30:21:5C:00:00:01 > /dev/null. When the connection is made, the speaker will output characteristic connected sound. Disconnecting the speaker is just as easy: bluetoothctl disconnect 30:21:5C:00:00:01 > /dev/null. These commands could be used as one line scripts and easily activated by a virtual switch in Domoticz. There is one problem however; the command to connect will only work if the speaker (or whatever device) has already been paired or connected (which implicitly pairs the device). To test this, let us remove the device, and immediately try to connect to it.

nostra@damus:~ $ bluetoothctl remove 30:21:5C:00:00:01 [CHG] Device 30:21:5C:00:00:01 ServicesResolved: no Device has been removed nostra@damus:~ $ bluetoothctl connect 30:21:5C:00:00:01 Device 30:21:5C:00:00:01 not available

It is necessary to wait until the device is discovered, which means than scanning must be enabled.

[bluetooth]# scan on Failed to start discovery: org.bluez.Error.InProgress no problem, that just means scanning was already enabled. wait a few seconds until: [NEW] Device AUDIOPOD2 it is now possible to pair or connect [bluetooth]# pair 30:21:5C:00:00:01 Attempting to pair with 30:21:5C:00:00:01 [CHG] Device 30:21:5C:00:00:01 Connected: yes [CHG] Device 30:21:5C:00:00:01 UUIDs: 00001108-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110b-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110c-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000110e-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 UUIDs: 0000111e-0000-1000-8000-00805f9b34fb [CHG] Device 30:21:5C:00:00:01 ServicesResolved: yes [CHG] Device 30:21:5C:00:00:01 Paired: yes Pairing successful [CHG] Device 30:21:5C:00:00:01 ServicesResolved: no [CHG] Device 30:21:5C:00:00:01 Connected: no

Turning the discovery on if the device is not paired can be done in an improved connect script. Here is a simple version.

# Use the MAC given on the command line or the default MAC if none given BTMAC=${1:-30:21:5C:00:00:01} # check if the device is paired bluetoothctl info $BTMAC >/dev/null if [ $? -ne 0 ] then # dev not paired, enable scanning for 15 seconds to pair bluetoothctl --timeout 15 scan on>/dev/null fi bluetoothctl connect $BTMAC >/dev/null exit $?

When scanning is started, bluetooth goes into interactive mode and runs in the foreground until an explicit quit or exit command is typed in. The --timeout 15 option ensures that the utility will close after scanning for devices for 15 seconds which allows the script to resume. A test is performed to see if the device is already paired to avoid this 15 second delay. I am assuming that if information on a device can be displayed by the bluetoothctl utility, then the device is already paired. In that case a connection can be attempted immediately. If information about a device cannot be shown then presumably the device is not paired so discovery is turned on for 15 seconds before the connection is attempted and hopefully the speaker will be discovered before that delay expires so that the connection will be successful.

Here is a somewhat more useful version because the MAC address of the Bluetooth device, the time to scan for devices and the delay before connecting if needed can all be specified on the command line.

#!/bin/bash # default values BTMAC="30:21:5C:00:00:01" CDELAY=15 STIME=60 usage() { echo "Usage: $(basename $0) [ -m MAC_ADDRESS ] [ -d CONNECT_DELAY ] [-t SCAN_TIME]" 1>&2 } exit_abnormal() { usage exit 1 } # test number is a positive integer, syntax: test_number value var_name test_number() { re='^[0-9]+$' if ! [[ $1 =~ $re ]] then echo "Error: $2 is not an integer" >&2; exit_abnormal fi if [[ $1 == "0" ]] then echo "Error: $2 must be greater than 0" >&2; exit_abnormal fi } cline=$1 if [ "$cline" != "" ] && [ "${cline:0:1}" != "-" ] then echo "Error: $1 is an invalid option" exit_abnormal fi while getopts ":m:d:t:h" options do case "${options}" in m) BTMAC=${OPTARG} ;; d) CDELAY=${OPTARG} ;; t) STIME=${OPTARG} ;; h) usage exit 0 ;; :) echo "Error: -${OPTARG} requires an argument." exit_abnormal ;; ?) echo "Error: -${OPTARG} is an unknown flag." exit_abnormal ;; *) exit_abnormal ;; esac done # test validity of parameters test_number $CDELAY "CONNECT_DELAY" test_number $STIME "SCAN_TIME" if ! [[ $BTMAC =~ ^([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}$ ]] then echo "Error: \"$BTMAC\" is not a valid MAC address." exit_abnormal fi # echo "OK:" # echo " BTMAC: $BTMAC" # echo " CDELAY: $CDELAY" # echo " STIME: $STIME" # check if the devide is paired bluetoothctl info $BTMAC >/dev/null if [ $? -ne 0 ] then # dev not paired, enable scanning for 60 seconds to pair # but waiting only 15 seconds before trying to connect nohup bluetoothctl --timeout $STIME scan on>/dev/null &>/dev/null & sleep $CDELAY fi bluetoothctl connect $BTMAC >/dev/null exit $?

Download the script: connect_bt_spearker and place it in a directory that is in the search path such as ~/.local/bin. Do not forget to edit the default values at the start of the script, especially as the MAC address is, without doubt, of no use. The script can be seen in action with the htop utility, where processes are listed in the order of their PID number.

bluetooth services in htop

Because the device was not paired, scanning is turned on for 60 seconds (default value). However is done in the background. So immediately after scanning is started, the script sleeps for 15 seconds (again a default that can be modified). Both processes can be seen on the screen capture. Once the delay is passed an attempt will be made to connect to the device. It is one of the desirable properties of bluetoothctl that many instances can be run simultaneously, so device discovery is still going on in the background while a connection with the speaker is being performed. Presumably, if it takes more than 15 seconds to discover the speaker, then it will be done within a minute so that when running the script later, the likelihood of a successful connection is improved. See Running bash commands in the background properly by Felix Milea-Ciobanu, about using hup and & to run a program as a daemon.

Actually, I don't imagine that script will be of much use. To use it, one must know the MAC address of the speaker. And how would that be possible? In all likelihood, by pairing the device manually. So unless the device is deliberately removed, there should not be any difficulty connecting to the speaker. Besides, I suspect most would trust the speaker.

[bluetooth]# trust 30:21:5C:00:00:01

From then on, the connection with the speaker will be automatically reestablished whenever the Pi and the Bluetooth speaker are brought close enough to each other.

Commands to increase or decrease the volume could be of value. The volume can be set to a given percentage or decrease or increased by a percentage using the - or + suffix.

nostra@damus:~ $ amixer -D bluealsa sset "AUDIOPOD2 - A2DP" 90% Simple mixer control 'AUDIOPOD2 - A2DP',0 Capabilities: pvolume pswitch Playback channels: Front Left - Front Right Limits: Playback 0 - 127 Mono: Front Left: Playback 115 [91%] [on] Front Right: Playback 115 [91%] [on] nostra@damus:~ $ amixer -D bluealsa sset "AUDIOPOD2 - A2DP" 10%- Simple mixer control 'AUDIOPOD2 - A2DP',0 Capabilities: pvolume pswitch Playback channels: Front Left - Front Right Limits: Playback 0 - 127 Mono: Front Left: Playback 102 [80%] [on] Front Right: Playback 102 [80%] [on]

It is possible to remove all output from the command with the -q option. In that case, the playback volume can be obtained explictely.

nostra@damus:~ $ amixer -q -D bluealsa sset "AUDIOPOD2 - A2DP" 50% nostra@damus:~ $ amixer -D bluealsa sget "AUDIOPOD2 - A2DP" Simple mixer control 'AUDIOPOD2 - A2DP',0 Capabilities: pvolume pswitch Playback channels: Front Left - Front Right Limits: Playback 0 - 127 Mono: Front Left: Playback 64 [50%] [on] Front Right: Playback 64 [50%] [on]

Here is an alternate way of setting the playback volume. Note that both the left and right channel volumes can be independently specified.

nostra@damus:~ $ amixer -D bluealsa cset numid=2 60,30 numid=2,iface=MIXER,name='AUDIOPOD2 - A2DP Playback Volume' ; type=INTEGER,access=rw------,values=2,min=0,max=127,step=1 : values=60,30 nostra@damus:~ $ amixer -D bluealsa cset numid=2 60%,30% numid=2,iface=MIXER,name='AUDIOPOD2 - A2DP Playback Volume' ; type=INTEGER,access=rw------,values=2,min=0,max=127,step=1 : values=77,39

How does one know that the playbakc volume is a numid of 2? By listing the contents of the hardware.

nostra@damus:~ $ amixer -D bluealsa contents numid=1,iface=MIXER,name='AUDIOPOD2 - A2DP Playback Switch' ; type=BOOLEAN,access=rw------,values=2 : values=on,on numid=2,iface=MIXER,name='AUDIOPOD2 - A2DP Playback Volume' ; type=INTEGER,access=rw------,values=2,min=0,max=127,step=1 : values=83,83

These volume commands are linear. More explicitely, the volume of each channel is a value from 0 to 127. When the volume is set at 50% or 30%, amixer sets the actual value at 0.5*127 or 0.3*127 rounding to the nearest integer. But this does not correspond at all to how we perceive loudness. The utility does provide a "mapped" mode for setting the volume using the -M option. This does not work with bluealsa as far as I can tell.

Disable Bluetooth toc

While it is certainly possible to use Bluetooth beacons to enable presence detection in Domoticz or other home automation systems, it is not something which I do. As a matter of fact, there is no longer any reason or even possibility to connect short-range Bluetooth devices to my automation server tucked away in a remote corner of the house. In that case it makes sense to disable the service. First, let us get a handle on the kernel modules, devices and services involved.

nostra@damus:~ $ lsmod | grep -i -E 'blue|hci' hci_uart 40960 1 btbcm 16384 1 hci_uart bluetooth 393216 27 hidp,hci_uart,bnep,btbcm ecdh_generic 16384 2 bluetooth rfkill 32768 4 bluetooth,cfg80211 nostra@damus:~ $ systemctl --all | grep -i -E 'blue|hci|bt' sys-devices-platform-soc-3f201000.serial-tty-ttyAMA0-hci0.device loaded active plugged /sys/devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0 sys-subsystem-bluetooth-devices-hci0.device loaded active plugged /sys/subsystem/bluetooth/devices/hci0 bluealsa.service loaded active running BluezALSA proxy bluetooth.service loaded active running Bluetooth service bthelper@hci0.service loaded active exited Raspberry Pi bluetooth helper hciuart.service loaded active running Configure Bluetooth Modems connected by UART system-bthelper.slice loaded active active system-bthelper.slice bluetooth.target loaded active active Bluetooth

Bluetooth is easily disabled with an overlay.

nostra@damus:~ $ sudo nano /boot/config.txt

Add the following line in the file.

... # Additional overlays and parameters are documented /boot/overlays/README # comment to enable Bluetooth dtoverlay=disable-bt ...

Disable a few services.

nostra@damus:~ $ sudo systemctl disable hciuart.service Removed /etc/systemd/system/multi-user.target.wants/hciuart.service. nostra@damus:~ $ sudo systemctl disable bluetooth.service Synchronizing state of bluetooth.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable bluetooth Removed /etc/systemd/system/bluetooth.target.wants/bluetooth.service. Removed /etc/systemd/system/dbus-org.bluez.service.

Reboot and test that everything is no longer active.

nostra@damus:~ $ lsmod | grep -i -E 'blue|hci|bt' nostra@damus:~ $ systemctl -all | grep -i -E 'blue|hci|bt' nostra@damus:~ $

All the packages are still available so it is fairly simple to reverse this operation. First enable the services once again.

nostra@damus:~ $ sudo systemctl enable hciuart.service Created symlink /etc/systemd/system/multi-user.target.wants/hciuart.service → /lib/systemd/system/hciuart.service. nostra@damus:~ $ sudo systemctl disable bluetooth.service Synchronizing state of bluetooth.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable bluetooth

Second, remove the disabling overlay.

nostra@damus:~ $ sudo nano /boot/config.txt

... # Additional overlays and parameters are documented /boot/overlays/README # uncomment to disable Bluetooth #dtoverlay=disable-bt ...

After rebooting, everything should be back as before.

nostra@damus:~ $ lsmod | grep -i -E 'blue|hci' hci_uart 40960 1 btbcm 16384 1 hci_uart bluetooth 393216 27 hidp,hci_uart,bnep,btbcm ecdh_generic 16384 2 bluetooth rfkill 32768 4 bluetooth,cfg80211 nostra@damus:~ $ systemctl --all | grep -i -E 'blue|hci|bt' sys-devices-platform-soc-3f201000.serial-tty-ttyAMA0-hci0.device loaded active plugged /sys/devices/platform/soc/3f201000.serial/tty/ttyAMA0/hci0 sys-subsystem-bluetooth-devices-hci0.device loaded active plugged /sys/subsystem/bluetooth/devices/hci0 bluealsa.service loaded active running BluezALSA proxy bluetooth.service loaded active running Bluetooth service bthelper@hci0.service loaded active exited Raspberry Pi bluetooth helper hciuart.service loaded active running Configure Bluetooth Modems connected by UART system-bthelper.slice loaded active active system-bthelper.slice bluetooth.target loaded active active Bluetooth

Remove Bluetooth toc

If there is a low possibility that Bluetooth will be needed, it can be entirely removed. In any case, it is not permanent and can be reversed. First it would be best to disable the services as shown in the previous section. Then proceed with removing the packages.

nostra@damus:~ $ sudo apt remove --purge bluez -y ... Removing bluealsa (0.13) ... Removing pi-bluetooth (0.1.18) ... Removing bluez (5.50-1.2~deb10u2+rpt1) ... nostra@damus:~ $ sudo apt autoremove ... Removing bluez-firmware (1.2-4+rpt8) ... Removing libbluetooth3:armhf (5.50-1.2~deb10u2+rpt1) ... Removing libsbc1:armhf (1.4-1) ...

To reverse this operation

nostra@damus:~ $ sudo apt install bluez pi-bluetooth

If audio over Bluetooth is needed then install bluealsa as explained above in Streaming Audio to a Bluetooth Speaker.

Bluetooth®, PulseAudio, and BlueALSA in Raspberry Pi OS Lite (March 2022)-> <-Bluetooth, BlueALSA and Buster
<-Baby Bluetooth Steps on Raspberry Pi 3 - Raspbian (Stretch)