tiny-pilot / tinypilot

Use your Raspberry Pi as a browser-based KVM.
https://tinypilotkvm.com
MIT License
2.99k stars 249 forks source link

No longer possible to enter the Magic SysRq key combination #1167

Open cghague opened 1 year ago

cghague commented 1 year ago

Description

It isn't possible to use the Magic SysRq key combination on the TinyPilot keyboard. This appears to be a regression as this functionality was previously added and then subsequently lost during a refactor.

What's the behavior that you expect?

What's happening instead?

What are the steps to reproduce this behavior?

  1. Connect a TinyPilot device to a Linux system and open the interface in Chrome.
  2. Attempt to display the help text by pressing "Alt"+"SysRq"/"Print"+"h".
  3. Note that the combination ends before "h" can be pressed.

Screenshots

N/A

Logs

N/A

Geekdude commented 1 year ago

I would also like to see this fixed and to have a way to easily enter Magic SysrRq key combinations. This fix will make resetting the machine remotely when it is in a non-responsive state much easier.

jdeanwallace commented 8 months ago

Yes, TinyPilot is currently unable to send SysRq to the target system. However, I'm also struggling to recreate the expected behavior directly on my target linux system. I can't get the Chrome help text to display via "Alt" + "SysRq"/"PrintScreen" + "h". The only thing that does work for me is "Alt" + "SysRq"/"PrintScreen" + "b" which immediately reboots the system and puts a damper on further testing.

Out of curiosity, do we recall "SysRq" commands ever working? I see that a "SysRq" button was added to the on-screen keyboard via https://github.com/tiny-pilot/tinypilot/pull/150, but I'm starting to doubt that the backend was interpreting it at all.

Geekdude commented 8 months ago

@jdeanwallace "Alt" + "SysRq" + "h" is working on my Ubuntu 22.04 system.

Here is the output from the command. This system is headless, and the output is printed to dmesg.

image

In order to enable sysreq commands in Ubuntu, edit the file /etc/sysctl.d/10-magic-sysrq.conf and change the value to 1.

I have an external keyboard plugged into the same system as the TinyPilot and I am able to issue the system required commands via this keyboard, but I am unable to issue them from the TinyPilot Gui.

It would be nice to either be able to enter these commands via the on-screen keyboard (Currently, alt+print is captured and sent, so the combination with another letter is not possible) or have them listed as commands in the actions -> Keyboard Shortcuts command list.

Geekdude commented 8 months ago

I added the following two scripts to the TinyPilot, which can send the sysreq keyboard commands.

pilot@tinypilot:~ $ ls
sysreq-help.sh  sysreq-reisub.sh
pilot@tinypilot:~ $ cat sysreq-help.sh
#!/bin/bash
echo -ne "\x4\0\x46\xb\0\0\0\0" > /dev/hidg0 # ALT+PRINT+H
echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0 # Release Keys
pilot@tinypilot:~ $ cat sysreq-reisub.sh
#!/bin/bash
echo -ne "\x4\0\x46\x15\0\0\0\0" > /dev/hidg0 # ALT+PRINT+R
echo -ne "\x4\0\x46\x8\0\0\0\0" > /dev/hidg0 # ALT+PRINT+E
echo -ne "\x4\0\x46\xc\0\0\0\0" > /dev/hidg0 # ALT+PRINT+I
echo -ne "\x4\0\x46\x16\0\0\0\0" > /dev/hidg0 # ALT+PRINT+S
echo -ne "\x4\0\x46\x18\0\0\0\0" > /dev/hidg0 # ALT+PRINT+U
echo -ne "\x4\0\x46\x5\0\0\0\0" > /dev/hidg0 # ALT+PRINT+B
echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0 # Release Keys

Now, by sshing into the TinyPilot and running these scripts, I can reset the target computer using magic SysRq key combinations.

jdeanwallace commented 8 months ago

@Geekdude - Ah, you're right! Thanks for sharing your scripts!

On my Ubuntu desktop, I was able to view dmesg via:

dmesg --follow --human

Then I could see the output of Alt + Print + h.

Your scripts also helped me find another reason why TinyPilot doesn't support SysRq key combinations (yet). It seems that TinyPilot always only writes a single keycode to the HID (at byte index 2): https://github.com/tiny-pilot/tinypilot/blob/d3739b57953ba89672a6f1c74b1f32dd2dfab077/app/hid/keyboard.py#L4-L7 However, we could be writing up to 6 keycode combinations to the HID by writing additional keycodes to byte index 3–7.

I have a path forward now.

jdeanwallace commented 8 months ago

2023-12-14

I created a POC PR that demonstrates pressing Alt + SysRq + H via the on-screen keyboard. However, my approach created a lot of code churn for what we what we wanted achieve.

To recap, this is my current understanding:

  1. This feature is not a regression and SysRq key combinations via TinyPilot web UI never worked.

    Looking at the code, the PR that resolved the original issue was only a frontend change and the backend never wrote more than a single keycode byte to the HID: https://github.com/tiny-pilot/tinypilot/blob/4587f989b6d479034a64b2411c1c9964cdad7261/app/hid.py#L44

    Disclaimer: I did not try resurrect the historic build to a device.

  2. FYI SysRq is not a modifier key, so it's not the same as AltLeft or MetaRight

  3. What is needed to get SysRq key combinations working?

    1. Write multiple (2-6) non-modifier keycodes to the HID
    2. The /keystroke socket API to accept multiple keycodes per keystroke event.
    3. The web UI to keep track of multiple keycodes being pressed simultaneously and send them to the /keystroke API as a single event.
    4. Add SysRq label to the PrintScreen key on the on-screen keyboard and allow it to be pressed on it own or in combination with Alt and one other non-modifier key.
mtlynch commented 8 months ago

Yeah, I think if it requires such deep architectural changes, this isn't worth it right now.

For reference, here's a build from around that time that would have had the SysRq behavior:

https://os-images.tinypilotkvm.com/legacy/1.1.3/tinypilot-2020-10-26T1806-0400.img

cghague commented 8 months ago

It might be beneficial to take a step back and examine how a user might issue these commands and whether there is a more straightforward way to implement this feature as a result.

It's unlikely that any user will enter these commands using a physical keyboard, as on a Linux client, the operating system would think the commands are for it, and on a Windows client, the operating system would take a screenshot.

If the assumption above is correct, a user must enter the commands with the on-screen keyboard. However, a three-key combination takes a while to input, and it would be very time-consuming for a user to enter a combination command such as reisub.

That leads me to think we should instead consider implementing these as shortcuts, where the front end simply tells the backend to output a predefined value to /dev/hidg0. This approach would avoid the need for a complex rewrite of the existing keystroke system.

We already have an issue open for adding/improving shortcut support, so my suggestion would be to divert our attention to that issue and to implement it in a way that these commands can just be another shortcut.

Geekdude commented 8 months ago

@cghague I agree that better keyboard shortcut support via the actions->keyboard shortcuts menu and the ability to define custom shortcuts for this menu is a good approach forward. Having the sysreq-reisub sequence added by default to this menu or giving user the ability to add this shortcut will solve my use case and be more user friendly than having to type the full sequence via the on-screen keyboard.

image

mtlynch commented 8 months ago

That leads me to think we should instead consider implementing these as shortcuts, where the front end simply tells the backend to output a predefined value to /dev/hidg0. This approach would avoid the need for a complex rewrite of the existing keystroke system.

The hard part here is that we still would need to extend hid.py similar to @jdeanwallace's proof of concept in #1707. It's not that that's scarily hard to do, but it requires us to add complexity to a delicate part of the system and maintain that complexity in perpetuity. It's always going to be more complex to support an API that accepts between one and eight keys as opposed to an API that accepts exactly one key.

Supporting macros might make this easier, but the two features are mostly orthogonal. We can support macros without having to extend our HID logic to multiple keys, and we can support the SysRq combinations without supporting macros.

We took this on because it looked like a feature we could add with 4-8 hours of work. From investigating more, it's seeming like it will be significantly more work and more maintenance burden than we initially thought.

The feature is certainly doable, but I think for the implementation and maintenance cost, there are higher-impact features we could deliver at this point.

Geekdude commented 8 months ago

For my specific use case, I'm happy with SSH'ing into the Tiny Pilot and running the scripts I showed earlier in this conversation. Configuration is needed on the target system to enable Magic SysRq combinations, and the need to reset the system is infrequent, so I'm okay not having the combination be part of the web GUI. I like having a way to reset a non-responsive system remotely.

One approach that would be easier to implement and maintain is to have the script approach to sending key presses added to the advanced FAQ section in the documentation. Then, advanced users can create scripts to do any combination of key presses they want. It would be nice if these scripts could be called from a custom drop-down in the web GUI (instead of having the backend issue the key presses, it would only call the script.), but documentation would be sufficient for now since you have other higher impact features to develop.

mtlynch commented 8 months ago

One approach that would be easier to implement and maintain is to have the script approach to sending key presses added to the advanced FAQ section in the documentation.

That's a good idea.

@cghague - Can you add a work item for this on our website repo?