nixos/bluetooth: add support for disabling plugins

This commit is contained in:
Peter Hoeg 2021-02-09 17:27:12 +08:00
parent c3b4c9c99d
commit 1a4c039432

View File

@ -1,12 +1,39 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib;
let let
cfg = config.hardware.bluetooth; cfg = config.hardware.bluetooth;
bluez-bluetooth = cfg.package; package = cfg.package;
in { inherit (lib)
mkDefault mkEnableOption mkIf mkOption
mkRenamedOptionModule mkRemovedOptionModule
concatStringsSep escapeShellArgs
optional optionals optionalAttrs recursiveUpdate types;
cfgFmt = pkgs.formats.ini { };
# bluez will complain if some of the sections are not found, so just make them
# empty (but present in the file) for now
defaults = {
General.ControllerMode = "dual";
Controller = { };
GATT = { };
Policy.AutoEnable = cfg.powerOnBoot;
};
hasDisabledPlugins = builtins.length cfg.disabledPlugins > 0;
in
{
imports = [
(mkRenamedOptionModule [ "hardware" "bluetooth" "config" ] [ "hardware" "bluetooth" "settings" ])
(mkRemovedOptionModule [ "hardware" "bluetooth" "extraConfig" ] ''
Use hardware.bluetooth.settings instead.
This is part of the general move to use structured settings instead of raw
text for config as introduced by RFC0042:
https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md
'')
];
###### interface ###### interface
@ -38,8 +65,15 @@ in {
''; '';
}; };
config = mkOption { disabledPlugins = mkOption {
type = with types; attrsOf (attrsOf (oneOf [ bool int str ])); type = types.listOf types.str;
default = [ ];
description = "Built-in plugins to disable";
};
settings = mkOption {
type = cfgFmt.type;
default = { };
example = { example = {
General = { General = {
ControllerMode = "bredr"; ControllerMode = "bredr";
@ -47,50 +81,40 @@ in {
}; };
description = "Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf)."; description = "Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf).";
}; };
extraConfig = mkOption {
type = with types; nullOr lines;
default = null;
example = ''
[General]
ControllerMode = bredr
'';
description = ''
Set additional configuration for system-wide bluetooth (/etc/bluetooth/main.conf).
'';
}; };
}; };
};
###### implementation ###### implementation
config = mkIf cfg.enable { config = mkIf cfg.enable {
warnings = optional (cfg.extraConfig != null) "hardware.bluetooth.`extraConfig` is deprecated, please use hardware.bluetooth.`config`."; environment.systemPackages = [ package ]
++ optional cfg.hsphfpd.enable pkgs.hsphfpd;
hardware.bluetooth.config = { environment.etc."bluetooth/main.conf".source =
Policy = { cfgFmt.generate "main.conf" (recursiveUpdate defaults cfg.settings);
AutoEnable = mkDefault cfg.powerOnBoot; services.udev.packages = [ package ];
}; services.dbus.packages = [ package ]
}; ++ optional cfg.hsphfpd.enable pkgs.hsphfpd;
systemd.packages = [ package ];
environment.systemPackages = [ bluez-bluetooth ]
++ optionals cfg.hsphfpd.enable [ pkgs.hsphfpd ];
environment.etc."bluetooth/main.conf"= {
source = pkgs.writeText "main.conf"
(generators.toINI { } cfg.config + optionalString (cfg.extraConfig != null) cfg.extraConfig);
};
services.udev.packages = [ bluez-bluetooth ];
services.dbus.packages = [ bluez-bluetooth ]
++ optionals cfg.hsphfpd.enable [ pkgs.hsphfpd ];
systemd.packages = [ bluez-bluetooth ];
systemd.services = { systemd.services = {
bluetooth = { bluetooth =
let
# `man bluetoothd` will refer to main.conf in the nix store but bluez
# will in fact load the configuration file at /etc/bluetooth/main.conf
# so force it here to avoid any ambiguity and things suddenly breaking
# if/when the bluez derivation is changed.
args = [ "-f /etc/bluetooth/main.conf" ]
++ optional hasDisabledPlugins
"--noplugin=${concatStringsSep "," cfg.disabledPlugins}";
in
{
wantedBy = [ "bluetooth.target" ]; wantedBy = [ "bluetooth.target" ];
aliases = [ "dbus-org.bluez.service" ]; aliases = [ "dbus-org.bluez.service" ];
serviceConfig.ExecStart = [
""
"${package}/libexec/bluetooth/bluetoothd ${escapeShellArgs " " args}"
];
# restarting can leave people without a mouse/keyboard # restarting can leave people without a mouse/keyboard
unitConfig.X-RestartIfChanged = false; unitConfig.X-RestartIfChanged = false;
}; };
@ -99,27 +123,23 @@ in {
hsphfpd = { hsphfpd = {
after = [ "bluetooth.service" ]; after = [ "bluetooth.service" ];
requires = [ "bluetooth.service" ]; requires = [ "bluetooth.service" ];
wantedBy = [ "multi-user.target" ]; wantedBy = [ "bluetooth.target" ];
description = "A prototype implementation used for connecting HSP/HFP Bluetooth devices"; description = "A prototype implementation used for connecting HSP/HFP Bluetooth devices";
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/hsphfpd.pl"; serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/hsphfpd.pl";
}; };
}) });
;
systemd.user.services = { systemd.user.services = {
obex.aliases = [ "dbus-org.bluez.obex.service" ]; obex.aliases = [ "dbus-org.bluez.obex.service" ];
} }
// (optionalAttrs cfg.hsphfpd.enable { // optionalAttrs cfg.hsphfpd.enable {
telephony_client = { telephony_client = {
wantedBy = [ "default.target" ]; wantedBy = [ "default.target" ];
description = "telephony_client for hsphfpd"; description = "telephony_client for hsphfpd";
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/telephony_client.pl"; serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/telephony_client.pl";
}; };
})
;
}; };
};
} }