8

Excuse my ignorance of linux OS/hardware issues...I'm just a programmer :)

I have an application that calls out to some bash scripts to launch external applications, in this case Firefox. The application runs on a kiosk with touch screen capability. When launching Firefox, I also launch a virtual keyboard application that allows the user to have keyboard input.

However, the kiosk also has both PS/2 and USB slots that would allow a user to plug in a keyboard. If a keyboard were plugged in, it would be nice if I didn't have to launch the virtual keyboard and provide more screen space for the Firefox window.

Is there a way for me to detect if a keyboard is plugged in from the bash script? Would it show up in /dev, and if so, would it show up at a consistent location? Would it make a difference if the user used a PS/2 or USB keyboard?

Thanks!

5 Answers 5

7

For a USB device you can use lsusb and search for a Human Interface Device (interface class 3) with keyboard protocol (interface protocol 1), e.g.

$ lsusb -v
... loads of stuff deleted ...
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      1 Keyboard
      iInterface              0 
... loads of stuff deleted ...

Also, you can let udev help you. List the devices under /dev/input/by-path/ and the keyboard devices end in -kdb (at least in Ubuntu, where udev rules specify it), e.g.

$ ls -l /dev/input/by-path/*-kbd
lrwxrwxrwx 1 root root 9 2010-03-25 09:14 /dev/input/by-path/pci-0000:00:1a.2-usb-0:1:1.0-event-kbd -> ../event4

$ ls -l /dev/input/by-path/*-kbd
lrwxrwxrwx 1 root root 9 2009-08-29 09:46 /dev/input/by-path/platform-i8042-serio-0-event-kbd -> ../event1
1
  • Thanks Dan! The second method seems like it would work for me. Mar 26, 2010 at 13:45
2

One way would be to do this:

dmesg | grep keyboard

You might also be able to use Upstart and udev to detect and act on the presence of a keyboard.

2

For USB Keyboards, I usually find the keyboard device by simply searching through "lsusb -v" output for the word "Keyboard":

lsusb -v 2>/dev/null | egrep '(^Bus|Keyboard)' | grep -B1 Keyboard

Example output:

Bus 001 Device 004: ID 413c:2006 Dell Computer Corp. 
  bInterfaceProtocol      1 Keyboard

A more generic method is to search /sys/bus for any device which is both bInterfaceClass 03 and bInterfaceProtocol 01. Since you have to detect non-USB devices, and you want to use the output in a script, this method will probably work better for you:

grep -l 03 /sys/bus/*/*/*/bInterfaceClass |
sed 's/Class$/Protocol/' |
xargs grep -l 01 |
xargs dirname

Example output:

/sys/bus/usb/devices/1-4.1:1.0

Caveat: I can't find a PS/2 keyboard to test this script. Since this thread is over seven years old now, I'm guessing that the author of the original question has long since moved on and doesn't need PS/2 detection anymore. I'll leave this answer anyway in the hope that someone else might find it useful, but be advised that I haven't tested this with non-USB devices.

1
1

PS/2 keyboards are listed among /sys/class/input devices. USB keyboards might be present there as well, because the mouse below is USB one:

$ grep "" /sys/class/input/*/name
/sys/class/input/input0/name:Power Button
/sys/class/input/input1/name:Power Button
/sys/class/input/input2/name:AT Translated Set 2 keyboard
/sys/class/input/input3/name:Microsoft Comfort Mouse 6000

$ grep keyboard /sys/class/input/*/name
/sys/class/input/input2/name

Another discovery is that keyboard dirs contain subdirs for status keys:

$ ls -d /sys/class/input/*/*::capslock
/sys/class/input/input2/input2::capslock
0

For USB, you can search /sys/bus/usb/devices for a device with a configuration with an interface with class HID (0x03) and protocol Keyboard (0x01).

Bash script:

#!/bin/bash
for dev in /sys/bus/usb/devices/*-*:*
do
  if [ -f $dev/bInterfaceClass ]
  then
    if [[ "$(cat $dev/bInterfaceClass)" == "03" && "$(cat $dev/bInterfaceProtocol)" == "01" ]]
    then
      echo "Keyboard detected: $dev"
    fi
  fi
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .