From 1a4c039432f742be58d400dd596eacad8cb2348b Mon Sep 17 00:00:00 2001 From: Peter Hoeg Date: Tue, 9 Feb 2021 17:27:12 +0800 Subject: [PATCH] nixos/bluetooth: add support for disabling plugins --- nixos/modules/services/hardware/bluetooth.nix | 154 ++++++++++-------- 1 file changed, 87 insertions(+), 67 deletions(-) diff --git a/nixos/modules/services/hardware/bluetooth.nix b/nixos/modules/services/hardware/bluetooth.nix index 6f5a6d3bf288..02c03136f3a5 100644 --- a/nixos/modules/services/hardware/bluetooth.nix +++ b/nixos/modules/services/hardware/bluetooth.nix @@ -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"; + }; + }; }; - }