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
- Raspberry Pi OS Lite
- Membership in the
bluetooth
Group
- Bluetooth Keyboard
- First Connection
- Subsequent Connections
- Quick Disconnections
- Streaming Audio to a Bluetooth Speaker
- Test ALSA
- Install
bluealsa
- Streaming an Audio Source out to Bluetooth Devices
- Streaming Audio from a Bluetooth Device, an Android Telephone
- Modifying the
bluetooth.service
Unit File
- Bluetooth Scripting
- Disable Bluetooth
- Remove Bluetooth
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.
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.
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
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.
- In
bluetoothctl
start scaning for devices.
- Press the connect button on the Bluetooth keyboard. The button is labelled <<o>> on the Adesso, but could be different on other brands.
- Once the keyboard shows up in
bluetoothctl
, pair with it.
- Enter the PIN code displayed in
blueetoothctl
on the Bluetooth keyboard and press on Enter.
- Back in
bluetoothctl
, trust the keyboard once it is paired.
- 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.
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
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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
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.