Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using deckbd for password entry during boot #382

Open
wants to merge 5 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/devices/steamdeck/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ in
imports = [
./controller.nix
./fan-control.nix
./fde.nix
./firmware.nix
./graphical.nix
./hw-support.nix
Expand Down
105 changes: 105 additions & 0 deletions modules/devices/steamdeck/fde.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{ config, lib, pkgs, utils, ... }:

let
cfg = config.jovian.devices.steamdeck;
in
{
options = {
jovian.devices.steamdeck = {
fde = {
deckbd = {
Comment on lines +8 to +10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm... not sure about the jovian.devices.steamdeck.fde.deckbd namespace...

I don't have a suggestion at the exact moment, but it's less directly about FDE, but about a device-specific tool and integration to make FDE work, so maybe it should be categorized as such. 🤔 Any thoughts?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My reasoning was that the launch is directly tied to FDE-related password prompting services. I too can't really think of a better name - I'm open to suggestions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(You don't need to do anything. I'll handle moving the option[s].)

So I've spent a few more minutes thinking about it. I think I know why I found the namespacing off. No options in NixOS uses the fde wording, even the word “encryption” isn't used by the NixOS docs around that. (And uuuuh... that's another issue to solve, just an observation.)

Now, couple that with this being a device-specific "service". We have a single one at the moment (jovian.devices.steamdeck.enableGyroDsuService), and it too I think is somewhat miscategorized. (Side-note, this other option was moved since its inception, and was "grandfathered-in" into the steamdeck namespace instead of being globally awkwardly available...)

So, what I want is thoughts about my thought:

Let's have jovian.devices.*.[some word].[tool name].[options]. I'm not sure if .services or .tools or what would be appropriate. Though I think it should encompass things like sdgyrodsu and other device-specific services.

My train of thoughts here is that being for FDE is an implementation detail; it's an input device "interceptor" service that is intended for usage in stage-1 for passphrase input. And it's not strictly limited to being a stage-1 tool. While there's no use-case yet, it could be used in the booted system, too, right?.

So I suppose the enable option might be better described as enableStage1 or /*...*/.deckbd.initrd.enable or something like that?

Sorry if that's a lot of useless stuff to consider / think of, and I know it's pedantry, but I don't want to just declare my pedantry as the way forward, I want to know if I'm missing something, or even if you think I'm wrong :).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(side-note: I'll try to get this tested and verified on my system soon, and make it so the last issues are those tiny little details so it can be merged)

enable = lib.mkOption {
default = cfg.enable;
defaultText = lib.literalExpression "config.jovian.devices.steamdeck.enable";
Comment on lines +12 to +13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good thing I'm testing on my system, I missed this.

This can't be enabled by default. It should be considered an opt-in option from the end-user. Especially since it changes the existing semantics of the gamepad during boot.

Suggested change
default = cfg.enable;
defaultText = lib.literalExpression "config.jovian.devices.steamdeck.enable";
default = false;

(And also because it will cause a sudden assertion failure when not already using systemd stage-1.)

type = lib.types.bool;
description = ''
Whether to enable deckbd for initrd password entry.

You may need hold the option key for a second before entering your
samueldr marked this conversation as resolved.
Show resolved Hide resolved
password.
'';
};
bindsTo = lib.mkOption {
inherit (utils.systemdUtils.unitOptions.commonUnitOptions.options.bindsTo) type;
description = ''
systemd units that require deckbd.

For example, if you want controller input in unl0kr, add `config.boot.initrd.systemd.services.unl0kr-ask-password.name`.

Plymouth and the console work by default.
'';
};
debug = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Enable debug output for deckbd.

This will log keycodes to the journal.
'';
};
};
};
};
};

config = lib.mkMerge [
(lib.mkIf cfg.fde.deckbd.enable {
assertions = [
{
assertion = cfg.enableDefaultStage1Modules;
message = ''
deckbd cannot be used without the required kernel modules.

jovian.devices.steamdeck.enableDefaultStage1Modules must be enabled.
'';
}
{
assertion = config.boot.initrd.systemd.enable;
message = ''
deckbd requires systemd-in-initrd.

boot.initrd.systemd.enable must be set to true. Note that this may impact other NixOS features.
'';
}
];

jovian.devices.steamdeck.fde.deckbd.bindsTo = [
"systemd-ask-password-console.service"
(lib.mkIf config.boot.plymouth.enable config.systemd.services.systemd-ask-password-plymouth.name)
# Note: Agents that have optional keyboard input, such as unl0kr, should not be added here. The user may not want it.
];

boot.initrd = {
kernelModules = [ "uinput" ];

services.udev.packages = [
(pkgs.writeTextDir "lib/udev/rules.d/70-steam-deck-controller.rules" ''
ACTION=="add", SUBSYSTEM=="input", ENV{ID_VENDOR_ID}=="28de", ENV{ID_MODEL_ID}=="1205", ENV{PRODUCT}=="?*", ENV{ID_INPUT_JOYSTICK}=="1", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/class/input/input_steam_deck_controller"
'')
];

systemd = {
storePaths = with pkgs; [ deckbd ]; # https://github.com/NixOS/nixpkgs/issues/309316
services.deckbd = {
description = "Steam Deck controller keymapper";
unitConfig.DefaultDependencies = false;
wantedBy = cfg.fde.deckbd.bindsTo;
before = cfg.fde.deckbd.bindsTo;
inherit (cfg.fde.deckbd) bindsTo;
requires = [ "sys-class-input-input_steam_deck_controller.device" ];
after = [ "sys-class-input-input_steam_deck_controller.device" ];
path = with pkgs; [ deckbd ];
environment.G_MESSAGES_DEBUG = lib.mkIf cfg.fde.deckbd.debug "all";
# Note: The lizard_mode parameter does not work as intended. The
# Steam Deck must also be manually put into gamepad mode by holding
# the option key for a second.
samueldr marked this conversation as resolved.
Show resolved Hide resolved
preStart = "echo 0 > /sys/module/hid_steam/parameters/lizard_mode";
script = "deckbd";
postStop = "echo 1 > /sys/module/hid_steam/parameters/lizard_mode";
};
};
};
})
];
}
1 change: 1 addition & 0 deletions modules/devices/steamdeck/hw-support.nix
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ in

# Gamepad
"usbhid"
"hid-steam"
];
boot.initrd.availableKernelModules = [
"nvme"
Expand Down
2 changes: 2 additions & 0 deletions overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,6 @@ rec {

decky-loader = final.callPackage ./pkgs/decky-loader { };
decky-loader-prerelease = final.callPackage ./pkgs/decky-loader/prerelease.nix { };

deckbd = final.callPackage ./pkgs/deckbd { };
}
33 changes: 33 additions & 0 deletions pkgs/deckbd/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{ lib
, stdenv
, fetchFromGitHub
, pkg-config
, glib
, libevdev
}:

stdenv.mkDerivation {
pname = "deckbd";
version = "0-unstable-2024-07-01";

src = fetchFromGitHub {
owner = "Ninlives";
repo = "deckbd";
rev = "1d2c71f2c096fbfa42624dd820a9d11a35c64826";
hash = "sha256-Svp/5Mo/XkiptbTM3E4QhSRxC6rMeF0t3eTq9BUjLbs=";
};

nativeBuildInputs = [ pkg-config ];

buildInputs = [ glib libevdev ];

makeFlags = [ "PREFIX=$(out)" ];

meta = {
description = "Steam Deck controller keymapper";
homepage = "https://github.com/Ninlives/deckbd";
license = lib.licenses.gpl3Only;
mainProgram = "deckbd";
platforms = lib.platforms.linux;
};
}
Loading