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

@ -1,12 +1,39 @@
{ config, lib, pkgs, ... }:
with lib;
let
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
@ -18,7 +45,7 @@ in {
hsphfpd.enable = mkEnableOption "support for hsphfpd[-prototype] implementation";
powerOnBoot = mkOption {
type = types.bool;
type = types.bool;
default = true;
description = "Whether to power up the default Bluetooth controller on boot.";
};
@ -38,8 +65,15 @@ in {
'';
};
config = mkOption {
type = with types; attrsOf (attrsOf (oneOf [ bool int str ]));
disabledPlugins = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Built-in plugins to disable";
};
settings = mkOption {
type = cfgFmt.type;
default = { };
example = {
General = {
ControllerMode = "bredr";
@ -47,79 +81,65 @@ in {
};
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
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 = {
Policy = {
AutoEnable = mkDefault cfg.powerOnBoot;
};
};
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 ];
environment.etc."bluetooth/main.conf".source =
cfgFmt.generate "main.conf" (recursiveUpdate defaults cfg.settings);
services.udev.packages = [ package ];
services.dbus.packages = [ package ]
++ optional cfg.hsphfpd.enable pkgs.hsphfpd;
systemd.packages = [ package ];
systemd.services = {
bluetooth = {
wantedBy = [ "bluetooth.target" ];
aliases = [ "dbus-org.bluez.service" ];
# restarting can leave people without a mouse/keyboard
unitConfig.X-RestartIfChanged = false;
};
}
// (optionalAttrs cfg.hsphfpd.enable {
hsphfpd = {
after = [ "bluetooth.service" ];
requires = [ "bluetooth.service" ];
wantedBy = [ "multi-user.target" ];
description = "A prototype implementation used for connecting HSP/HFP Bluetooth devices";
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/hsphfpd.pl";
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" ];
aliases = [ "dbus-org.bluez.service" ];
serviceConfig.ExecStart = [
""
"${package}/libexec/bluetooth/bluetoothd ${escapeShellArgs " " args}"
];
# restarting can leave people without a mouse/keyboard
unitConfig.X-RestartIfChanged = false;
};
})
;
}
// (optionalAttrs cfg.hsphfpd.enable {
hsphfpd = {
after = [ "bluetooth.service" ];
requires = [ "bluetooth.service" ];
wantedBy = [ "bluetooth.target" ];
description = "A prototype implementation used for connecting HSP/HFP Bluetooth devices";
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/hsphfpd.pl";
};
});
systemd.user.services = {
obex.aliases = [ "dbus-org.bluez.obex.service" ];
}
// (optionalAttrs cfg.hsphfpd.enable {
telephony_client = {
wantedBy = [ "default.target"];
description = "telephony_client for hsphfpd";
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/telephony_client.pl";
};
})
;
// optionalAttrs cfg.hsphfpd.enable {
telephony_client = {
wantedBy = [ "default.target" ];
description = "telephony_client for hsphfpd";
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/telephony_client.pl";
};
};
};
}