c382780e9b
Say this 10 times so I don't forget: - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. - just because something has been tested and confirmed working, doesn't mean that a trivial change can go in without testing simply because it looks OK. test, test, test. I'm sorry guys.
145 lines
4.3 KiB
Nix
145 lines
4.3 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
let
|
|
cfg = config.hardware.bluetooth;
|
|
package = cfg.package;
|
|
|
|
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
|
|
|
|
options = {
|
|
|
|
hardware.bluetooth = {
|
|
enable = mkEnableOption "support for Bluetooth";
|
|
|
|
hsphfpd.enable = mkEnableOption "support for hsphfpd[-prototype] implementation";
|
|
|
|
powerOnBoot = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Whether to power up the default Bluetooth controller on boot.";
|
|
};
|
|
|
|
package = mkOption {
|
|
type = types.package;
|
|
default = pkgs.bluez;
|
|
defaultText = "pkgs.bluez";
|
|
example = "pkgs.bluezFull";
|
|
description = ''
|
|
Which BlueZ package to use.
|
|
|
|
<note><para>
|
|
Use the <literal>pkgs.bluezFull</literal> package to enable all
|
|
bluez plugins.
|
|
</para></note>
|
|
'';
|
|
};
|
|
|
|
disabledPlugins = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [ ];
|
|
description = "Built-in plugins to disable";
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = cfgFmt.type;
|
|
default = { };
|
|
example = {
|
|
General = {
|
|
ControllerMode = "bredr";
|
|
};
|
|
};
|
|
description = "Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf).";
|
|
};
|
|
};
|
|
};
|
|
|
|
###### implementation
|
|
|
|
config = mkIf cfg.enable {
|
|
environment.systemPackages = [ package ]
|
|
++ optional cfg.hsphfpd.enable pkgs.hsphfpd;
|
|
|
|
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 =
|
|
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";
|
|
};
|
|
};
|
|
};
|
|
}
|