2014-04-14 16:26:48 +02:00
|
|
|
{
|
|
|
|
config,
|
|
|
|
lib,
|
|
|
|
pkgs,
|
2025-01-30 13:05:35 +01:00
|
|
|
utils,
|
2014-04-14 16:26:48 +02:00
|
|
|
...
|
|
|
|
}:
|
2016-01-29 22:08:42 +00:00
|
|
|
let
|
2017-02-17 19:44:04 +01:00
|
|
|
cfg = config.hardware.bluetooth;
|
2021-02-09 17:27:12 +08:00
|
|
|
package = cfg.package;
|
|
|
|
|
|
|
|
inherit (lib)
|
2023-11-27 01:19:27 +01:00
|
|
|
mkEnableOption
|
|
|
|
mkIf
|
|
|
|
mkOption
|
|
|
|
mkPackageOption
|
2021-02-09 17:27:12 +08:00
|
|
|
mkRenamedOptionModule
|
|
|
|
mkRemovedOptionModule
|
2021-10-03 18:06:03 +02:00
|
|
|
concatStringsSep
|
2021-02-09 17:27:12 +08:00
|
|
|
optional
|
|
|
|
optionalAttrs
|
|
|
|
recursiveUpdate
|
|
|
|
types
|
|
|
|
;
|
|
|
|
|
|
|
|
cfgFmt = pkgs.formats.ini { };
|
|
|
|
|
|
|
|
defaults = {
|
|
|
|
General.ControllerMode = "dual";
|
|
|
|
Policy.AutoEnable = cfg.powerOnBoot;
|
|
|
|
};
|
|
|
|
|
|
|
|
hasDisabledPlugins = builtins.length cfg.disabledPlugins > 0;
|
2017-02-17 19:44:04 +01:00
|
|
|
|
2021-02-09 17:27:12 +08:00
|
|
|
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
|
|
|
|
'')
|
|
|
|
];
|
2009-08-10 18:25:09 +00:00
|
|
|
|
|
|
|
###### interface
|
|
|
|
|
|
|
|
options = {
|
2010-08-27 15:32:49 +00:00
|
|
|
|
2017-03-20 14:28:02 +01:00
|
|
|
hardware.bluetooth = {
|
2019-04-19 21:41:48 -04:00
|
|
|
enable = mkEnableOption "support for Bluetooth";
|
2017-02-17 19:44:04 +01:00
|
|
|
|
2020-10-24 21:12:05 -04:00
|
|
|
hsphfpd.enable = mkEnableOption "support for hsphfpd[-prototype] implementation";
|
|
|
|
|
2017-03-20 14:28:02 +01:00
|
|
|
powerOnBoot = mkOption {
|
2021-02-09 17:27:12 +08:00
|
|
|
type = types.bool;
|
2017-03-20 14:28:02 +01:00
|
|
|
default = true;
|
|
|
|
description = "Whether to power up the default Bluetooth controller on boot.";
|
|
|
|
};
|
|
|
|
|
2023-11-27 01:19:27 +01:00
|
|
|
package = mkPackageOption pkgs "bluez" { };
|
2018-03-07 15:12:22 +11:00
|
|
|
|
2021-02-09 17:27:12 +08:00
|
|
|
disabledPlugins = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = [ ];
|
|
|
|
description = "Built-in plugins to disable";
|
|
|
|
};
|
|
|
|
|
|
|
|
settings = mkOption {
|
|
|
|
type = cfgFmt.type;
|
|
|
|
default = { };
|
2019-11-21 18:35:45 +02:00
|
|
|
example = {
|
|
|
|
General = {
|
|
|
|
ControllerMode = "bredr";
|
|
|
|
};
|
|
|
|
};
|
2024-11-01 20:54:00 +01:00
|
|
|
description = ''
|
|
|
|
Set configuration for system-wide bluetooth (/etc/bluetooth/main.conf).
|
|
|
|
See <https://github.com/bluez/bluez/blob/master/src/main.conf> for full list of options.
|
|
|
|
'';
|
2019-11-21 18:35:45 +02:00
|
|
|
};
|
2022-12-05 17:11:52 +01:00
|
|
|
|
|
|
|
input = mkOption {
|
|
|
|
type = cfgFmt.type;
|
|
|
|
default = { };
|
|
|
|
example = {
|
|
|
|
General = {
|
|
|
|
IdleTimeout = 30;
|
|
|
|
ClassicBondedOnly = true;
|
|
|
|
};
|
|
|
|
};
|
2024-11-01 20:54:00 +01:00
|
|
|
description = ''
|
|
|
|
Set configuration for the input service (/etc/bluetooth/input.conf).
|
|
|
|
See <https://github.com/bluez/bluez/blob/master/profiles/input/input.conf> for full list of options.
|
|
|
|
'';
|
2022-12-05 17:11:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
network = mkOption {
|
|
|
|
type = cfgFmt.type;
|
|
|
|
default = { };
|
|
|
|
example = {
|
|
|
|
General = {
|
|
|
|
DisableSecurity = true;
|
|
|
|
};
|
|
|
|
};
|
2024-11-01 20:54:00 +01:00
|
|
|
description = ''
|
|
|
|
Set configuration for the network service (/etc/bluetooth/network.conf).
|
|
|
|
See <https://github.com/bluez/bluez/blob/master/profiles/network/network.conf> for full list of options.
|
|
|
|
'';
|
2022-12-05 17:11:52 +01:00
|
|
|
};
|
2010-08-27 15:32:49 +00:00
|
|
|
};
|
2009-08-10 18:25:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
###### implementation
|
2017-02-09 21:25:03 -05:00
|
|
|
|
2017-02-17 19:44:04 +01:00
|
|
|
config = mkIf cfg.enable {
|
2021-02-09 17:27:12 +08:00
|
|
|
environment.systemPackages = [ package ] ++ optional cfg.hsphfpd.enable pkgs.hsphfpd;
|
2024-12-10 20:26:33 +01:00
|
|
|
|
2022-12-05 17:11:52 +01:00
|
|
|
environment.etc."bluetooth/input.conf".source = cfgFmt.generate "input.conf" cfg.input;
|
|
|
|
environment.etc."bluetooth/network.conf".source = cfgFmt.generate "network.conf" cfg.network;
|
2021-02-09 17:27:12 +08:00
|
|
|
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 ];
|
2017-02-17 19:44:04 +01:00
|
|
|
|
|
|
|
systemd.services =
|
|
|
|
{
|
2021-02-09 17:27:12 +08:00
|
|
|
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.
|
nixos/bluetooth: fix more stupidity on my part
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.
2021-02-18 22:06:19 +08:00
|
|
|
args = [
|
|
|
|
"-f"
|
|
|
|
"/etc/bluetooth/main.conf"
|
2021-02-09 17:27:12 +08:00
|
|
|
] ++ optional hasDisabledPlugins "--noplugin=${concatStringsSep "," cfg.disabledPlugins}";
|
|
|
|
in
|
2024-12-10 20:26:33 +01:00
|
|
|
{
|
2017-02-17 19:44:04 +01:00
|
|
|
wantedBy = [ "bluetooth.target" ];
|
2021-02-09 17:27:12 +08:00
|
|
|
aliases = [ "dbus-org.bluez.service" ];
|
2025-04-08 22:22:12 +02:00
|
|
|
# restarting can leave people without a mouse/keyboard
|
|
|
|
restartIfChanged = false;
|
2025-01-30 09:53:55 +01:00
|
|
|
serviceConfig = {
|
|
|
|
ExecStart = [
|
|
|
|
""
|
2025-01-30 13:05:35 +01:00
|
|
|
"${package}/libexec/bluetooth/bluetoothd ${utils.escapeSystemdExecArgs args}"
|
2025-01-30 09:53:55 +01:00
|
|
|
];
|
|
|
|
CapabilityBoundingSet = [
|
|
|
|
"CAP_NET_BIND_SERVICE" # sockets and tethering
|
|
|
|
];
|
2025-04-04 08:59:53 -05:00
|
|
|
ConfigurationDirectoryMode = "0755";
|
2025-01-30 09:53:55 +01:00
|
|
|
NoNewPrivileges = true;
|
|
|
|
RestrictNamespaces = true;
|
|
|
|
ProtectControlGroups = true;
|
|
|
|
MemoryDenyWriteExecute = true;
|
|
|
|
RestrictSUIDSGID = true;
|
|
|
|
SystemCallArchitectures = "native";
|
|
|
|
SystemCallFilter = "@system-service";
|
|
|
|
LockPersonality = true;
|
|
|
|
RestrictRealtime = true;
|
|
|
|
ProtectProc = "invisible";
|
|
|
|
PrivateTmp = true;
|
|
|
|
|
|
|
|
PrivateUsers = false;
|
|
|
|
|
|
|
|
# loading hardware modules
|
|
|
|
ProtectKernelModules = false;
|
|
|
|
ProtectKernelTunables = false;
|
|
|
|
|
|
|
|
PrivateNetwork = false; # tethering
|
|
|
|
};
|
2024-12-10 20:26:33 +01:00
|
|
|
};
|
|
|
|
}
|
2021-02-09 17:27:12 +08:00
|
|
|
// (optionalAttrs cfg.hsphfpd.enable {
|
|
|
|
hsphfpd = {
|
|
|
|
after = [ "bluetooth.service" ];
|
|
|
|
requires = [ "bluetooth.service" ];
|
|
|
|
wantedBy = [ "bluetooth.target" ];
|
2017-02-02 00:52:12 +03:00
|
|
|
|
2021-02-09 17:27:12 +08:00
|
|
|
description = "A prototype implementation used for connecting HSP/HFP Bluetooth devices";
|
|
|
|
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/hsphfpd.pl";
|
2024-12-10 20:26:33 +01:00
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2017-02-17 19:44:04 +01:00
|
|
|
systemd.user.services =
|
|
|
|
{
|
|
|
|
obex.aliases = [ "dbus-org.bluez.obex.service" ];
|
2020-10-24 21:12:05 -04:00
|
|
|
}
|
2021-02-09 17:27:12 +08:00
|
|
|
// optionalAttrs cfg.hsphfpd.enable {
|
|
|
|
telephony_client = {
|
|
|
|
wantedBy = [ "default.target" ];
|
2024-12-10 20:26:33 +01:00
|
|
|
|
2021-02-09 17:27:12 +08:00
|
|
|
description = "telephony_client for hsphfpd";
|
|
|
|
serviceConfig.ExecStart = "${pkgs.hsphfpd}/bin/telephony_client.pl";
|
2024-12-10 20:26:33 +01:00
|
|
|
};
|
2021-02-09 17:27:12 +08:00
|
|
|
};
|
2011-09-14 18:20:50 +00:00
|
|
|
};
|
2009-08-10 18:25:09 +00:00
|
|
|
}
|