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

Conversation

hacker1024
Copy link

@hacker1024 hacker1024 commented Jun 29, 2024

There are a few options available when it comes to using an encrypted system partition on the Steam Deck.

For password-based solutions in particular, we have unl0kr for an on-screen keyboard during boot (works well, though runs in portrait, and does not work with Plymouth), as well as deckbd and deckrypt for mapping controller keys to keyboard input.

This PR allows using deckbd for password entry at boot. When the encryption password is requested, various buttons map to numbers ranging from 0-9, with L2 and R2 mapping to backspace and enter respectively. It runs nicely, though there are a few hiccups:

  • Only configurations with boot.initrd.systemd.enable are supported (it is possible to do it in another way, but systemd allows us to integrate more nicely with udev and the boot process in general).
  • It appears that hid_steam's lizard_mode parameter cannot properly disable lizard mode on its own. The option button must be held for a second before password entry to truly enable gamepad input.
  • deckbd is currently unlicensed.

@hacker1024 hacker1024 marked this pull request as ready for review June 30, 2024 03:43
@hacker1024 hacker1024 changed the title Allow using deckbd during boot Allow using deckbd for password entry during boot Jun 30, 2024
@jptrzy
Copy link

jptrzy commented Jul 7, 2024

Amazing - I myself wanted this feature from the moment that I had steam deck in my hands.

@hacker1024
Copy link
Author

Rebased to resolve merge conflicts.

@samueldr
Copy link
Member

[last push seems to be a mostly uneventful rebase on development]

@samueldr
Copy link
Member

As a courtesy I wanted to ping @Ninlives, as they are part of the broader NixOS ecosystem, though looks like they've been made aware already, so I guess that's task done already :).

@samueldr samueldr added 2. priority: 2. normal 2. topic: system integration About our integration of Steam stuff within NixOS 2. topic: packaging About our packaging of additional stuff 1. type: Enhancement Contributes a new feature, or a new package labels Oct 13, 2024
Copy link
Member

@samueldr samueldr left a comment

Choose a reason for hiding this comment

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

Hi, 👋

Thank you for your contribution, sorry it wasn't really looked at in those few weeks months.

Some notes from a first read, I haven't tested the changes.

modules/devices/steamdeck/fde.nix Outdated Show resolved Hide resolved
modules/devices/steamdeck/fde.nix Outdated Show resolved Hide resolved
Comment on lines +8 to +10
jovian.devices.steamdeck = {
fde = {
deckbd = {
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)

alisonjenkins added a commit to alisonjenkins/nix-config that referenced this pull request Oct 18, 2024
@hacker1024
Copy link
Author

I have made the button instructions more clear.

Comment on lines +12 to +13
default = cfg.enable;
defaultText = lib.literalExpression "config.jovian.devices.steamdeck.enable";
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.)

Comment on lines +94 to +99
# Note: The lizard_mode parameter does not work as intended. The
# Steam Deck must also be manually put into gamepad mode by holding
# the menu button (≡) for a second.
preStart = "echo 0 > /sys/module/hid_steam/parameters/lizard_mode";
script = "deckbd";
postStop = "echo 1 > /sys/module/hid_steam/parameters/lizard_mode";
Copy link
Member

@samueldr samueldr Oct 30, 2024

Choose a reason for hiding this comment

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

I've dived into trying to understand why it wouldn't work "as expected".

First, here's what the lizard_mode parameter is documented to do:

This driver will disable the lizard mode when the input device is opened
and re-enable it when the input device is closed, so as not to break user
mode behaviour. The lizard_mode parameter can be used to change that.

This comment has aged poorly... That's only true for the original Steam controller... But still has interesting hints as to what is happening.

So, here's one reason why it "doesn't work" for the Steam Deck controller:

... Except that this is only about automatically enabling/disabling lizard mode on open. And that's why things gets kinda confusing fast.

When the parameter is changed live, this happens:

See how there's no check for the hardware in use? So, as long as the device is not opened, the switch will happen... EXCEPT it's not that easy...

If the device has been “forced” into gamepad mode, attempting to set it to lizard mode won't work.

In turn this is what the (≡) button does; it flips that flag:

(Though also notice how if lizard_mode is disabled, it will not be put into lizard_mode...)


So, to recap, for a steam deck, when the device is registered to the driver, if it was not already opened, it will be out into the mode set by the kernel module parameter:

If the device is not opened, changing the kernel module parameter will change the mode of the controller...

... unless it's been “put” into gamepad mode (via the ≡ button)

And the last situation where the lizard_mode parameter takes effect on the Steam Deck is when the hid_ll_driver interface for it is closed (which is of no importance for us here):


Did you get all that? :) (I'm still somewhat confused.)

@samueldr
Copy link
Member

samueldr commented Oct 30, 2024

Hmmm... This is awkward:

Oct 29 22:32:05 dashdingo kernel: hid-steam 0003:28DE:1205.0003: input,hidraw2: USB HID v1.11 Mouse [Valve Software Steam Deck Controller] on usb-0000:04:00.4-3/input1
Oct 29 22:32:05 dashdingo kernel: hid-steam 0003:28DE:1205.0004: hiddev96: USB HID v1.11 Device [Valve Software Steam Deck Controller] on usb-0000:04:00.4-3/input2
Oct 29 22:32:05 dashdingo kernel: hid-steam 0003:28DE:1205.0004: Steam Controller 'FWAA15200AAC' connected
Oct 29 22:32:05 dashdingo kernel: input: Steam Deck as /devices/pci0000:00/0000:00:08.1/0000:04:00.4/usb3/3-3/3-3:1.2/0003:28DE:1205.0004/input/input7
Oct 29 22:32:05 dashdingo kernel: input: Steam Deck Motion Sensors as /devices/pci0000:00/0000:00:08.1/0000:04:00.4/usb3/3-3/3-3:1.2/0003:28DE:1205.0004/input/input8
Oct 29 22:32:05 dashdingo kernel: hid-steam 0003:28DE:1205.0005: hidraw3: USB HID v1.11 Device [Valve Software Steam Deck Controller] on usb-0000:04:00.4-3/input2
Oct 29 22:32:05 dashdingo systemd[1]: Found device Steam_Deck_Controller.
Oct 29 22:32:05 dashdingo systemd[1]: Started Steam Deck controller keymapper.
Oct 29 22:32:05 dashdingo systemd[1]: Started Dispatch Password Requests to Console.
...
Oct 29 22:32:05 dashdingo deckbd[211]: Initializing.
Oct 29 22:32:05 dashdingo deckbd[211]: Failed to open /dev/input
Oct 29 22:32:05 dashdingo deckbd[211]: Failed to find controller.
Oct 29 22:32:05 dashdingo systemd[1]: deckbd.service: Main process exited, code=exited, status=1/FAILURE
...
Oct 29 22:32:05 dashdingo systemd[1]: deckbd.service: Failed with result 'exit-code'.
{
  specialisation = {
    deckbd = {
      configuration = {
        samueldr.use-case.stage-1.chosen = "systemd";
        jovian.devices.steamdeck.fde.deckbd = {
          debug = true;
          enable = true;
        };
        # XXX testing
        samueldr.use-case.graphical-boot.flickerFree.enable = lib.mkForce false;
        samueldr.use-case.graphical-boot.enable = lib.mkForce false;
        boot.plymouth.enable = lib.mkForce false;
      };
    };
  };
}

My options there that are the one that enables systemd stage-1 without fuss, and then undoing some fanciness at boot to make debugging easier. So it should be relatively stock systemd stage-1 semantics here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1. type: Enhancement Contributes a new feature, or a new package 2. priority: 2. normal 2. topic: packaging About our packaging of additional stuff 2. topic: system integration About our integration of Steam stuff within NixOS 8. hardware: steamdeck
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants