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

Auto-detect how keyboard is attached (USB or not) #2736

Open
jpouellet opened this issue Apr 2, 2017 · 22 comments
Open

Auto-detect how keyboard is attached (USB or not) #2736

jpouellet opened this issue Apr 2, 2017 · 22 comments
Labels
C: installer P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.

Comments

@jpouellet
Copy link
Contributor

jpouellet commented Apr 2, 2017

How the keyboard attaches to the system (over some spi/i2c (via the EC), or through USB) is a very useful property to know when considering to buy a laptop for Qubes.

This is especially true if we intend to move towards sys-usb by default. (I remember some discussion somewhere stating intent to remove "experimental" label in the installer option and enable it by default, but can't seem to find it right now.)

See also #2329.

I'm opening an issue rather than just submitting a PR because I don't know how to reliably determine this information. xinput? /proc/bus/input/devices? lsusb? something else?

/cc @tasket

edit: issue was originally just because this would be nice to have in the HCL, but we would need to reliably autodetect this in the installer as well if we want to enable sys-usb by default (so we could know whether or not to enable the input proxy). Issue title updated accordingly.

@jpouellet
Copy link
Contributor Author

jpouellet commented Apr 2, 2017

A first attempt:

[user@dom0 ~]$ cat /tmp/x
awk '
  function clr() {
    kbd=0
    usb=0
    n=""
  }
  BEGIN {
    clr()
  }
  /^$/ {
    if (kbd)
      print (usb ? "usb" : "non-usb") " keyboard found: " n
    clr()
  }
  /^H: Handlers=.*kbd/ {
    kbd=1
  }
  /^S: Sysfs=.*\/usb[0-9]+\// {
    usb=1
  }
  /N: Name=/{
    sub(/[^"]*"/, "")
    sub(/"$/, "")
    n=$0
  }
' < /proc/bus/input/devices

Does not produce reliable enough results:

[user@dom0 ~]$ sh /tmp/x
non-usb keyboard found: Sleep Button
non-usb keyboard found: Power Button
non-usb keyboard found: AT Translated Set 2 keyboard
non-usb keyboard found: Video Bus
non-usb keyboard found: PC Speaker
non-usb keyboard found: ThinkPad Extra Buttons
[user@dom0 ~]$ qvm-run -p sys-usb sh < /tmp/x
non-usb keyboard found: PC Speaker
usb keyboard found: Apple, Inc Apple Keyboard
usb keyboard found: Apple, Inc Apple Keyboard

There are non-usb "keyboards" present, and one could similarly imagine a laptop having yes-usb "keyboards" as well.

@jpouellet
Copy link
Contributor Author

jpouellet commented Apr 2, 2017

Presence of non-keyboard buttons (extra media keys, random switches, etc.) make just checking for existence of usb or non-usb "keyboard" give false positives/negatives.

At least for autodetection in the installer we might monitor all /dev/input/eventX while the user types something, then find the corresponding device that's actually being used to type on and see what driver it's using? Not sure if this is suitable for qubes-hcl-report as we may not want to require any input for it to complete (for example, I've run it on a remote server once). It would be nice if there were a way to determine the last time a device gave input, but looking through the linux docs the closest thing seems to be MSC_TIMESTAMP which talks about "reset" (apparently not related to EV_KEY). Maybe some higher layer tracks this?

There must be a better way. My knowledge of the linux input stack is not as strong as it could be.

@jpouellet jpouellet changed the title HCL: report how keyboard is attached Auto-detect how keyboard is attached (USB or not) Apr 2, 2017
@unman
Copy link
Member

unman commented Apr 2, 2017 via email

@jpouellet
Copy link
Contributor Author

Tried that, doesn't work as hoped. See above.

I see you're replying from email, and I've edited the comments a bit so you may be missing context I've added later. I have a bad habit of editing perhaps a bit too often... sorry about that.

@andrewdavidwong andrewdavidwong added C: core T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality. labels Apr 2, 2017
@andrewdavidwong andrewdavidwong added this to the Far in the future milestone Apr 2, 2017
@marmarek
Copy link
Member

marmarek commented Apr 2, 2017

@tasket
Copy link

tasket commented Apr 2, 2017

I believe having both Phys= contain /serio and Handlers= contain kdb could reliably detect a PS/2 keyboard. But that's only a 5min assessment. Actually, you could probably do this just by looking at the names in /dev/input/by-path, where -serio- and -kbd are both present.

Also, search seems to indicate i8042 is some near-universal controller for PS/2 ports? But I don't know if we'd want to specify that.

I'd also want to know if functioning-but-empty PS/2 ports were available.

@tasket
Copy link

tasket commented Apr 2, 2017

In bash...

for file in /dev/input/by-path/*-serio-*-kbd ; do
    if [[ -c $file ]]; then
        ps2present=true
    fi
done

@Yethal
Copy link

Yethal commented Apr 2, 2017

@tasket I have a PS/2 keyboard if you want test results from real hardware

@unman
Copy link
Member

unman commented Apr 2, 2017

@jpouellet Keyboards will always have EV=120013 in /proc/bus/input/devices, so you can combine that with the usb test for clear result. This is much cleaner than Phys or Handlers tests.

@jpouellet
Copy link
Contributor Author

@unman Interesting. That does work reliably on my machines, but it seems it would be valid for keyboards to also appear with some superset of that bitmask as well?

@jpouellet
Copy link
Contributor Author

jpouellet commented Apr 2, 2017

Maybe possible to have valid keyboards without EV_LED bit set as well?

@marmarek
Copy link
Member

marmarek commented Apr 2, 2017

AFAIR this is very similar to what udev check when decide on adding ID_INPUT_KEYBOARD=1 additionally it check for actual keys presence.

@tasket
Copy link

tasket commented Apr 2, 2017

@Yethal You could try the above code, with and without the keyboard attached. Actually, here is a shorter version that does the job:

if [ -n "$( find /dev/input/by-path -name '*-serio-*-kbd' )" ]; then echo "PS/2 Detected"; fi

There's a developer wiki with PS/2 information. It indicates that i8042 is the controller used on PC compatibles (and they list a different controller for ARM):
http://wiki.osdev.org/PS/2

@Yethal
Copy link

Yethal commented Apr 2, 2017

@tasket above code echoes "PS/2 detected" regardless of whether the keyboard is actually connected to the PC or not.

@jpouellet
Copy link
Contributor Author

Here's a shot using udev:

#!/bin/sh
udevadm info -e | awk '
  BEGIN {
    found_usb=0
    found_nonusb=0
    kbd=0
    usb=0
  }
  /^$/ {
    if (kbd) {
      if (usb)
        found_usb++
      else
        found_nonusb++
    }
    kbd=0
    usb=0
  }
  /^E: ID_INPUT_KEYBOARD=1$/ { kbd=1 }
  /^E: ID_USB/ { usb=1 }
  END {
    if (found_usb && !found_nonusb)
      print "USB"
    else if (!found_usb && found_nonusb)
      print "non-USB"
    else if (found_usb && found_nonusb)
      print "both"
    else
      print "none"
  }
'

I'm admittedly not very familiar with udev, and there didn't seem to be a way to query for a device matching particular attributes (like you'd do when matching rules), rather udevadm info seems to expect you to query a specific device, or dump everything? I'd like to be wrong about this.

@jpouellet
Copy link
Contributor Author

Enumerating with pyudev like in the installer would be cleaner, but we don't have pyudev in dom0 by default and idk if we'd like to bring it in just for qubes-hcl-report (which is currently all shell anyway).

@tasket
Copy link

tasket commented Apr 2, 2017

@Yethal Can you post a list of your dir /dev/input/by-path with the keyboard unplugged? Its possibly detecting the empty port (which is good).

@jpouellet
Copy link
Contributor Author

Its possibly detecting the empty port (which is good).

Good... unless the laptop simply has a PS/2 controller somewhere with no actual PS/2 port exposed, and the built-in keyboard is attached via internal USB. If udev has logic to attempt to differentiate this case, then I think it makes sense to take advantage of it.

@tasket
Copy link

tasket commented Apr 2, 2017

I don't know what use case would justify a PS/2 controller + internal USB keyboard. Assuming there is, (though I doubt udev can tell between an internal and external PS/2 port) then I'd guess we're looking at involving the user in a hardware test of some kind... "Press the Z and SHIFT keys on your keyboard" for each detected keyboard. But since we're also looking for the ability to plug in a PS/2 keyboard (not so much whether such a keyboard is presently attached) then we may have to ask the user to plug in a PS/2 keyboard if one is available.

More realistic would be detecting PS/2 keyboard devices as above, instruct user to press keys on the "internal laptop keyboard (if any)" ... and ask a separate question "Does your computer have external PS/2 ports"?

This would return multiple pieces of information, and it could be represented on the HCL under a PS/2 Keyboard column with indications 'Controller present', 'Detected' or 'Answered yes'.

Another possibility is 'KISS'... simply show whether a PS/2 keyboard controller was detected and add a footnote explaining what that means. But I like the above idea of having the user answer a question and tap keys.

@tasket
Copy link

tasket commented Apr 2, 2017

To clarify:

Ideally we should look for a PS/2 "internal" laptop keyboard and/or external PS/2 ports.

If we're going to encounter systems with odd combinations like USB internal keyboard + PS/2 touchpad + unused PS/2 keyboard port (or a PS/2 special-key device) then we'll probably need user input to discern what is a real keyboard or accessible port. The alternative is to report simply that PS/2 was detected along with a footnote/disclaimer.

I don't know if Linux distros (or any equipment vendor) ever had reason to care whether a PS/2 device was internal or external...

@Yethal
Copy link

Yethal commented Apr 3, 2017

@tasket here are by-path contents:
platform-i8042-serio-0-event-kbd platform-pcspkr-event-spkr

There is also a possibility that an external PS/2 port is internally connected to a PS/2 to USB converter which is then connected to a USB controller.

@jpouellet
Copy link
Contributor Author

relevant: #2781 (comment)

Keyboards can be weird...

@andrewdavidwong andrewdavidwong removed this from the Release TBD milestone Aug 13, 2023
@andrewdavidwong andrewdavidwong added the P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. label Aug 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: installer P: default Priority: default. Default priority for new issues, to be replaced given sufficient information. T: enhancement Type: enhancement. A new feature that does not yet exist or improvement of existing functionality.
Projects
None yet
Development

No branches or pull requests

6 participants