summaryrefslogtreecommitdiffstats
path: root/nixos/modules/hardware/xpadneo.nix
blob: f2cddd360c77e6a669023482111f7722b4915d4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
{ config, lib, ... }:
let
  cfg = config.hardware.xpadneo;

  modprobeConfig =
    let
      params = lib.mapAttrsToList (name: value: "${name}=${toString value}") cfg.settings;
    in
    lib.optionalString (params != [ ]) "options hid_xpadneo ${lib.concatStringsSep " " params}";
in
{
  options.hardware.xpadneo = {
    enable = lib.mkEnableOption "the xpadneo driver for Xbox One wireless controllers";

    rumbleAttenuation = lib.mkOption {
      type = lib.types.submodule {
        options = {
          overall = lib.mkOption {
            type = lib.types.ints.between 0 100;
            default = 0;
            description = ''
              Overall force feedback attenuation as a percentage.
              `0` means full rumble, `100` means no rumble.
              Applies to both main and trigger rumble.
            '';
          };
          triggers = lib.mkOption {
            type = lib.types.nullOr (lib.types.ints.between 0 100);
            default = null;
            description = ''
              Extra attenuation for trigger rumble as a percentage, applied
              on top of {option}`overall`. For example, `overall = 50` and
              `triggers = 50` results in 50% main rumble and 25% trigger rumble.
              Set to `100` to disable trigger rumble while keeping main rumble.
              `null` means no extra trigger attenuation.
            '';
          };
        };
      };
      default = { };
      example = lib.literalExpression ''
        {
          overall = 50;   # 50% overall rumble
          triggers = 50;  # 25% trigger rumble (50% of 50%)
        }
      '';
      description = ''
        Force feedback attenuation settings. Higher values reduce rumble strength.

        See <https://github.com/atar-axis/xpadneo/blob/master/docs/CONFIGURATION.md>
        for more information.
      '';
    };

    quirks = lib.mkOption {
      type = lib.types.attrsOf (lib.types.ints.u16);
      default = { };
      example = lib.literalExpression ''
        {
          "11:22:33:44:55:66" = 7; # Applies flags 1 + 2 + 4
        }
      '';
      description = ''
        Controller-specific quirk flags, keyed by MAC address.
        Flags are combined as a bitmask to address compatibility issues
        with specific controllers.

        The value is a sum of individual flag values. For example, to apply
        flags 1, 2, and 4, use `7` (1 + 2 + 4). To apply flags 2, 4, and 32,
        use `38` (2 + 4 + 32).

        See <https://github.com/atar-axis/xpadneo/blob/master/docs/CONFIGURATION.md>
        for available quirk flags and their values.
      '';
    };

    settings = lib.mkOption {
      type = lib.types.attrsOf (
        lib.types.oneOf [
          lib.types.int
          lib.types.str
        ]
      );
      default = { };
      example = lib.literalExpression ''
        {
          disable_deadzones = 1;
          trigger_rumble_mode = 2;
          disable_shift_mode = 1;
        }
      '';
      description = ''
        Kernel module parameters for hid_xpadneo. These are passed directly
        to the module via modprobe.

        See <https://github.com/atar-axis/xpadneo/blob/master/docs/CONFIGURATION.md>
        for available parameters and their values.
      '';
    };
  };

  config = lib.mkIf cfg.enable {
    hardware.xpadneo.settings =
      lib.optionalAttrs (cfg.rumbleAttenuation.overall != 0 || cfg.rumbleAttenuation.triggers != null) {
        rumble_attenuation =
          toString cfg.rumbleAttenuation.overall
          + lib.optionalString (cfg.rumbleAttenuation.triggers != null) (
            "," + toString cfg.rumbleAttenuation.triggers
          );
      }
      // lib.optionalAttrs (cfg.quirks != { }) {
        quirks = lib.concatStringsSep "," (
          lib.mapAttrsToList (mac: flags: "${mac}:${toString flags}") cfg.quirks
        );
      };

    boot = {
      extraModprobeConfig = lib.mkMerge [
        # Must disable Enhanced Retransmission Mode to support bluetooth pairing
        # https://wiki.archlinux.org/index.php/Gamepad#Connect_Xbox_Wireless_Controller_with_Bluetooth
        (lib.mkIf (lib.versionOlder config.boot.kernelPackages.kernel.version "5.12") "options bluetooth disable_ertm=1")
        modprobeConfig
      ];
      extraModulePackages = with config.boot.kernelPackages; [ xpadneo ];
      kernelModules = [ "hid_xpadneo" ];
    };

    hardware.bluetooth.enable = true;
  };

  meta = {
    maintainers = with lib.maintainers; [ kira-bruneau ];
  };
}