Bluetooth: Difference between revisions
imported>Fadenb mNo edit summary |
m Fix link |
||
(48 intermediate revisions by 29 users not shown) | |||
Line 1: | Line 1: | ||
== Bluetooth headsets with | ==Enabling Bluetooth support== | ||
To enable support for Bluetooth devices, amend your system configuration as follows: | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ | |||
... | |||
hardware.bluetooth.enable = true; # enables support for Bluetooth | |||
hardware.bluetooth.powerOnBoot = true; # powers up the default Bluetooth controller on boot | |||
... | |||
} | |||
</nowiki>}} | |||
{{evaluate}} | |||
==Pairing Bluetooth devices== | |||
In order to use Bluetooth devices, they must be paired with your NixOS machine. Heavier [[:Category:Desktop_environment|desktop environments]] will usually provide a Bluetooth management GUI which you can use to pair devices. | |||
If your desktop environment does not provide such a GUI, you can additionally enable the blueman service, which provides blueman-applet and blueman-manager with the snippet below. | |||
<syntaxhighlight lang="nix"> | |||
services.blueman.enable = true; | |||
</syntaxhighlight>Another option for a GUI based Bluetooth management GUI can be [https://search.nixos.org/packages?channel=unstable&show=overskride&from=0&size=50&sort=relevance&type=packages&query=overskride overskirde] | |||
Alternatively if you wish to use a TUI<ref>https://en.wikipedia.org/wiki/Text-based_user_interface</ref> then check out [https://search.nixos.org/packages?channel=unstable&show=bluetuith&from=0&size=50&sort=relevance&type=packages&query=bluetui bluetuith] or [https://github.com/pythops/bluetui bluetui] | |||
===Pairing devices from the command line=== | |||
Alternatively, Bluetooth devices can be paired from the command line using <tt>bluetoothctl</tt>. | |||
<syntaxhighlight lang="console">$ bluetoothctl | |||
[bluetooth] # power on | |||
[bluetooth] # agent on | |||
[bluetooth] # default-agent | |||
[bluetooth] # scan on | |||
...put device in pairing mode and wait [hex-address] to appear here... | |||
[bluetooth] # pair [hex-address] | |||
[bluetooth] # connect [hex-address]</syntaxhighlight> | |||
Bluetooth devices automatically connect with <tt>bluetoothctl</tt> as well: | |||
<syntaxhighlight lang="console"> | |||
$ bluetoothctl | |||
[bluetooth] # trust [hex-address] | |||
</syntaxhighlight> | |||
==Using Bluetooth headsets with PulseAudio== | |||
To allow Bluetooth audio devices to be used with [[PulseAudio]], amend <tt>/etc/nixos/configuration.nix</tt> as follows: | |||
<syntaxhighlight lang="nix">{ | <syntaxhighlight lang="nix">{ | ||
hardware.pulseaudio.enable = true; | |||
hardware.bluetooth.enable = true; | |||
}</syntaxhighlight> | |||
{{evaluate}} | |||
You will need to restart PulseAudio; try <tt>systemctl --user daemon-reload; systemctl --user restart pulseaudio</tt>. | |||
You can verify that PulseAudio has loaded the Bluetooth module by running <tt>pactl list | grep -i 'Name.*module.*blue'</tt>; Bluetooth modules should be present in the list. | |||
== Using Bluetooth headset buttons to control media player == | |||
Some bluetooth headsets have buttons for pause/play or to skip to the next track. | |||
To make these buttons usable with media players supporting the dbus-based [https://specifications.freedesktop.org/mpris-spec/latest/ MPRIS] standard, | |||
one can use <code>mpris-proxy</code> that is part of bluez package. | |||
The following snippet can be used in [[Home Manager]] to start this program as a daemon: | |||
<syntaxHighlight lang="nix"> | |||
systemd.user.services.mpris-proxy = { | |||
description = "Mpris proxy"; | |||
after = [ "network.target" "sound.target" ]; | |||
wantedBy = [ "default.target" ]; | |||
serviceConfig.ExecStart = "${pkgs.bluez}/bin/mpris-proxy"; | |||
}; | |||
</syntaxHighlight> | |||
Or, starting with Home Manager 21.05, enable the <code>mpris-proxy</code> service. | |||
===System-Wide PulseAudio === | |||
{{Expansion|When setting up pulseaudio systemWide extra policies needs to be deployed for pulse to be able to connect to the bluetooth stack. The Info below is not enough.}} | |||
When you are running PulseAudio system-wide then you will need to add the following modules to your <code>default.pa</code> configuration: | |||
<syntaxHighlight lang="nix"> | |||
hardware.pulseaudio.configFile = pkgs.writeText "default.pa" '' | |||
load-module module-bluetooth-policy | |||
load-module module-bluetooth-discover | |||
## module fails to load with | |||
## module-bluez5-device.c: Failed to get device path from module arguments | |||
## module.c: Failed to load module "module-bluez5-device" (argument: ""): initialization failed. | |||
# load-module module-bluez5-device | |||
# load-module module-bluez5-discover | |||
''; | |||
</syntaxHighlight> | |||
===Enabling extra codecs=== | |||
While pulseaudio itself only has support for the SBC bluetooth codec there is out-of-tree support for AAC, APTX, APTX-HD and LDAC. | |||
To enable extra codecs add the following to <tt>/etc/nixos/configuration.nix</tt>: | |||
<syntaxHighlight lang="nix"> | |||
{ | |||
... | |||
hardware.pulseaudio = { | hardware.pulseaudio = { | ||
enable = true; | enable = true; | ||
package = pkgs.pulseaudioFull; | package = pkgs.pulseaudioFull; | ||
}; | }; | ||
hardware.bluetooth.enable = true; | ... | ||
} | |||
</syntaxHighlight> | |||
===Enabling A2DP Sink=== | |||
Modern headsets will generally try to connect using the A2DP profile. To enable this for your bluetooth connection, add the following to <tt>/etc/nixos/configuration.nix</tt> | |||
<syntaxhighlight lang="nix"> | |||
{ | |||
hardware.bluetooth.settings = { | |||
General = { | |||
Enable = "Source,Sink,Media,Socket"; | |||
}; | |||
}; | |||
} | |||
</syntaxhighlight> | |||
This configuration may be unnecessary and does not work with bluez5 (<tt>Unknown key Enable for group General</tt> ). | |||
===Managing audio devices=== | |||
<tt>pavucontrol</tt> can be used to reconfigure the device: | |||
* To enable A2DP, change the profile to “High Fidelity Playback (A2DP Sink)” on the “Configuration” tab. | |||
* To set the device as the default audio output, select “set as fallback” on the “Output Devices” tab. | |||
Alternatively, the device can be configured via the command line: | |||
* To enable A2DP, run: <syntaxhighlight lang="console">$ pacmd set-card-profile "$(pactl list cards short | egrep -o bluez_card[[:alnum:]._]+)" a2dp_sink</syntaxhighlight> | |||
* To set the device as the default audio output, run: <syntaxhighlight lang="console">$ pacmd set-default-sink "$(pactl list sinks short | egrep -o bluez_sink[[:alnum:]._]+)"</syntaxhighlight> | |||
You can also set pulseaudio to automatically switch audio to the connected bluetooth device when it connects, in order to do this add the following entry into the pulseaudio config | |||
<syntaxhighlight lang="nix">{ | |||
... | |||
hardware.pulseaudio.extraConfig = " | |||
load-module module-switch-on-connect | |||
"; | |||
... | |||
}</syntaxhighlight> | |||
Note that you may need to clear the pulseaudio config located at ~/.config/pulse to get this to work. Also you may have to unset and then set the default audio device to the bluetooth device, see https://github.com/NixOS/nixpkgs/issues/86441 for more info | |||
==Showing battery charge of bluetooth devices== | |||
If you want to see what charge your bluetooth devices have you have to enable experimental features, which might lead to bugs (according to [https://wiki.archlinux.org/title/Bluetooth_headset#Battery_level_reporting Arch Wiki). You can add the following to your config to enable experimental feature for bluetooth: | |||
<syntaxhighlight lang="nix">{ | |||
... | |||
hardware.bluetooth.settings = { | |||
General = { | |||
Experimental = true; | |||
}; | |||
}; | |||
... | |||
}</syntaxhighlight> | }</syntaxhighlight> | ||
Afterwards rebuild your system and then restart your bluetooth service by executing <syntaxhighlight lang="console">$ systemctl restart bluetooth</syntaxhighlight>. | |||
==Troubleshooting== | |||
===USB device needs to be unplugged/re-plugged after suspend=== | |||
Some USB device/host combinations don't play well with the suspend/resume cycle, and need to be unplugged and then re-plugged to work again. | |||
It is possible to simulate a unplug/re-plug cycle using the <tt>/sys</tt> filesystem. | |||
[https://gist.github.com/samueldr/356e65374d452e4fd45314f818ae3545 This gist] provides a script and instructions to set-up a workaround for these devices. | |||
===When connecting to an audio device: Failed to connect: org.bluez.Error.Failed=== | |||
You need to use pulseaudioFull, see [[#Using Bluetooth headsets with PulseAudio]]. | |||
===Bluetooth fails to power on with Failed to set power on: org.bluez.Error.Blocked=== | |||
If <tt>journalctl -eu bluetooth</tt> shows <tt>Failed to set mode: Blocked through rfkill (0x12)</tt>, rfkill might be blocking it: | |||
<syntaxhighlight lang="console"> | |||
$ rfkill | |||
ID TYPE DEVICE SOFT HARD | |||
1 wlan phy0 unblocked unblocked | |||
37 bluetooth hci0 blocked unblocked | |||
</syntaxhighlight> | |||
Unblock it first: | |||
<syntaxhighlight lang="console"> | |||
$ sudo rfkill unblock bluetooth | |||
</syntaxhighlight> | |||
=== Cannot use bluetooth while it previously worked === | |||
Symptoms: | |||
* When using <code>bluetoothctl</code>, getting "No agent is registered". | |||
* When using <code>blueman</code> or anything using dbus to talk to bluez, getting <code>dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: Rejected send message"</code> | |||
This possibly can be fixed by restarting the display-manager session. The session management may have had an issue with registering your current session and doesn't allow you to control bluetooth. | |||
<syntaxhighlight | <syntaxhighlight lang="console"> | ||
$ sudo systemctl restart display-manager.service | |||
</syntaxhighlight> | |||
=== No audio when using headset in HSP/HFP mode === | |||
If the output of <code>dmesg | grep Bluetooth</code> shows a line similar to <code>Bluetooth: hci0: BCM: Patch brcm/BCM-0a5c-6410.hcd not found</code> then your machine uses a Broadcom chipset without the required firmware installed. | |||
< | To fix this, add <code>hardware.enableAllFirmware = true;</code> to your <tt>/etc/nixos/configuration.nix</tt> then reboot. | ||
== | ==See also== | ||
* [https://web.archive.org/web/20170609072208/http://anderspapitto.com/posts/2016-11-07-scripting_pulseaudio_bluetooth_jack.html Scripting PulseAudio, Bluetooth, JACK] | |||
* [https://wiki.gentoo.org/wiki/Bluetooth Bluetooth (Gentoo Wiki)] | |||
* [https://wiki.archlinux.org/index.php/Bluetooth Bluetooth (Arch Linux Wiki)] | |||
[[Category:Audio]][[Category:Configuration]][[Category:Hardware]] |
Revision as of 22:02, 15 September 2024
Enabling Bluetooth support
To enable support for Bluetooth devices, amend your system configuration as follows:
/etc/nixos/configuration.nix
{
...
hardware.bluetooth.enable = true; # enables support for Bluetooth
hardware.bluetooth.powerOnBoot = true; # powers up the default Bluetooth controller on boot
...
}
Pairing Bluetooth devices
In order to use Bluetooth devices, they must be paired with your NixOS machine. Heavier desktop environments will usually provide a Bluetooth management GUI which you can use to pair devices.
If your desktop environment does not provide such a GUI, you can additionally enable the blueman service, which provides blueman-applet and blueman-manager with the snippet below.
services.blueman.enable = true;
Another option for a GUI based Bluetooth management GUI can be overskirde
Alternatively if you wish to use a TUI[1] then check out bluetuith or bluetui
Pairing devices from the command line
Alternatively, Bluetooth devices can be paired from the command line using bluetoothctl.
$ bluetoothctl
[bluetooth] # power on
[bluetooth] # agent on
[bluetooth] # default-agent
[bluetooth] # scan on
...put device in pairing mode and wait [hex-address] to appear here...
[bluetooth] # pair [hex-address]
[bluetooth] # connect [hex-address]
Bluetooth devices automatically connect with bluetoothctl as well:
$ bluetoothctl
[bluetooth] # trust [hex-address]
Using Bluetooth headsets with PulseAudio
To allow Bluetooth audio devices to be used with PulseAudio, amend /etc/nixos/configuration.nix as follows:
{
hardware.pulseaudio.enable = true;
hardware.bluetooth.enable = true;
}
You will need to restart PulseAudio; try systemctl --user daemon-reload; systemctl --user restart pulseaudio.
You can verify that PulseAudio has loaded the Bluetooth module by running pactl list | grep -i 'Name.*module.*blue'; Bluetooth modules should be present in the list.
Using Bluetooth headset buttons to control media player
Some bluetooth headsets have buttons for pause/play or to skip to the next track.
To make these buttons usable with media players supporting the dbus-based MPRIS standard,
one can use mpris-proxy
that is part of bluez package.
The following snippet can be used in Home Manager to start this program as a daemon:
systemd.user.services.mpris-proxy = {
description = "Mpris proxy";
after = [ "network.target" "sound.target" ];
wantedBy = [ "default.target" ];
serviceConfig.ExecStart = "${pkgs.bluez}/bin/mpris-proxy";
};
Or, starting with Home Manager 21.05, enable the mpris-proxy
service.
System-Wide PulseAudio
When you are running PulseAudio system-wide then you will need to add the following modules to your default.pa
configuration:
hardware.pulseaudio.configFile = pkgs.writeText "default.pa" ''
load-module module-bluetooth-policy
load-module module-bluetooth-discover
## module fails to load with
## module-bluez5-device.c: Failed to get device path from module arguments
## module.c: Failed to load module "module-bluez5-device" (argument: ""): initialization failed.
# load-module module-bluez5-device
# load-module module-bluez5-discover
'';
Enabling extra codecs
While pulseaudio itself only has support for the SBC bluetooth codec there is out-of-tree support for AAC, APTX, APTX-HD and LDAC.
To enable extra codecs add the following to /etc/nixos/configuration.nix:
{
...
hardware.pulseaudio = {
enable = true;
package = pkgs.pulseaudioFull;
};
...
}
Enabling A2DP Sink
Modern headsets will generally try to connect using the A2DP profile. To enable this for your bluetooth connection, add the following to /etc/nixos/configuration.nix
{
hardware.bluetooth.settings = {
General = {
Enable = "Source,Sink,Media,Socket";
};
};
}
This configuration may be unnecessary and does not work with bluez5 (Unknown key Enable for group General ).
Managing audio devices
pavucontrol can be used to reconfigure the device:
- To enable A2DP, change the profile to “High Fidelity Playback (A2DP Sink)” on the “Configuration” tab.
- To set the device as the default audio output, select “set as fallback” on the “Output Devices” tab.
Alternatively, the device can be configured via the command line:
- To enable A2DP, run:
$ pacmd set-card-profile "$(pactl list cards short | egrep -o bluez_card[[:alnum:]._]+)" a2dp_sink
- To set the device as the default audio output, run:
$ pacmd set-default-sink "$(pactl list sinks short | egrep -o bluez_sink[[:alnum:]._]+)"
You can also set pulseaudio to automatically switch audio to the connected bluetooth device when it connects, in order to do this add the following entry into the pulseaudio config
{
...
hardware.pulseaudio.extraConfig = "
load-module module-switch-on-connect
";
...
}
Note that you may need to clear the pulseaudio config located at ~/.config/pulse to get this to work. Also you may have to unset and then set the default audio device to the bluetooth device, see https://github.com/NixOS/nixpkgs/issues/86441 for more info
Showing battery charge of bluetooth devices
If you want to see what charge your bluetooth devices have you have to enable experimental features, which might lead to bugs (according to [https://wiki.archlinux.org/title/Bluetooth_headset#Battery_level_reporting Arch Wiki). You can add the following to your config to enable experimental feature for bluetooth:
{
...
hardware.bluetooth.settings = {
General = {
Experimental = true;
};
};
...
}
Afterwards rebuild your system and then restart your bluetooth service by executing
$ systemctl restart bluetooth
.
Troubleshooting
USB device needs to be unplugged/re-plugged after suspend
Some USB device/host combinations don't play well with the suspend/resume cycle, and need to be unplugged and then re-plugged to work again.
It is possible to simulate a unplug/re-plug cycle using the /sys filesystem.
This gist provides a script and instructions to set-up a workaround for these devices.
When connecting to an audio device: Failed to connect: org.bluez.Error.Failed
You need to use pulseaudioFull, see #Using Bluetooth headsets with PulseAudio.
Bluetooth fails to power on with Failed to set power on: org.bluez.Error.Blocked
If journalctl -eu bluetooth shows Failed to set mode: Blocked through rfkill (0x12), rfkill might be blocking it:
$ rfkill
ID TYPE DEVICE SOFT HARD
1 wlan phy0 unblocked unblocked
37 bluetooth hci0 blocked unblocked
Unblock it first:
$ sudo rfkill unblock bluetooth
Cannot use bluetooth while it previously worked
Symptoms:
- When using
bluetoothctl
, getting "No agent is registered". - When using
blueman
or anything using dbus to talk to bluez, gettingdbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: Rejected send message"
This possibly can be fixed by restarting the display-manager session. The session management may have had an issue with registering your current session and doesn't allow you to control bluetooth.
$ sudo systemctl restart display-manager.service
No audio when using headset in HSP/HFP mode
If the output of dmesg | grep Bluetooth
shows a line similar to Bluetooth: hci0: BCM: Patch brcm/BCM-0a5c-6410.hcd not found
then your machine uses a Broadcom chipset without the required firmware installed.
To fix this, add hardware.enableAllFirmware = true;
to your /etc/nixos/configuration.nix then reboot.