4

When I run:

cat /proc/bus/input/devices

...I receive the following output:

...

I: Bus=0003 Vendor=040b Product=2000 Version=0110
N: Name="Generic USB Keyboard"
P: Phys=usb-0000:00:1d.0-1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb5/5-1/5-1:1.0/input/input14
U: Uniq=
H: Handlers=sysrq kbd event7 
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7

...

Is there any way that a script could parse this information and determine the corresponding device (in /dev/input/...) that represents this keyboard?

I intend to use the device name in xorg.conf if that helps.

4
  • Can you elaborate on how you're planning to use them? I have these in my xorg.conf.d files: "MatchDevicePath "/dev/input/event*".
    – slm
    Jul 7, 2013 at 8:14
  • @slm: I'm trying to configure X for multiseat and need to specify the device files in the InputDevice sections. Jul 7, 2013 at 23:31
  • Can you give us an example?
    – slm
    Jul 7, 2013 at 23:32
  • @slm: Here is an example of one entry. Jul 7, 2013 at 23:41

3 Answers 3

2

See in your output:

H: Handlers=[...] event7

Where event7 is the device:

/dev/input/event7
2
  • How do I know which of sysrq, kbd, and event7 is the actual device? (I'm thinking from the perspective of an automated script here.) Jul 7, 2013 at 5:56
  • Hmm not sure to be honest. All devices in /dev/input seem to be named eventX or mouseX so I would use that.
    – MLu
    Jul 7, 2013 at 6:07
0

I was just forced write a bash parser for this purpose. Here's the source:

#!/bin/sh

inputDevicesInfoFilePath ()
{
    echo "/proc/bus/input/devices"
}


inputDevicesInfo ()
{
    cat $(inputDevicesInfoFilePath)
}

# arguments: device name, file line prefix
inputDeviceValue ()
{
    # constants
    local INFO_FILE=$(inputDevicesInfoFilePath)
    local NAME_PREFIX="N: Name="

    # name the function arguments
    local devName=$1
    local linePrefix=$2 

    # find the line number in the info file containing 
    # both the name prefix and device name argument 
    local lnNo=$(grep -n "${NAME_PREFIX}" ${INFO_FILE} | grep ${devName} | head -n1 | cut -d: -f1)

    # starting from the line number previously determined,
    # find the first line which contains the prefix argument
    # and extract the value token from that line
    local value=$(tail +${lnNo} ${INFO_FILE} | grep "${linePrefix}" | head -n1 | cut -d= -f2)

    # "return" the value via an echo  
    # if no value was found, don't echo anything 
    # but (literally) return an error code 
    if [ -z "${value}" ] ; then return 1; fi;
    echo ${value}
}

# arguments: device name
inputDevicePhys ()
{
    echo $(inputDeviceValue $1 "P: Phys=")
}

# arguments: device name
inputDeviceSysfs ()
{
    echo $(inputDeviceValue $1 "S: Sysfs=")
}

# arguments: device name
inputDeviceHandlers ()
{
    echo $(inputDeviceValue $1 "H: Handlers=")
}

# arguments: device name
inputDeviceEventHandlerPath ()
{
   # constants
    local INPUT_DEVICE_DIR_PATH="/dev/input/"

    # get the handlers for the device (as a space delimited list) 
    # if nothing is found return error code 1 and don't echo anything
    local handlers=$(inputDeviceHandlers $1)
    if [ -z "${handlers}" ] ; then return 1; fi;

    # interate through the list (splits on white space implictly)
    for handler in ${handlers}
    do
        # if the handler starts with "event", then echo the path 
        # and return from the function successfully 
        case ${handler} in event*)
            echo ${INPUT_DEVICE_DIR_PATH}${handler}  
            return
        esac
    done

    # if no event handler was found, don't echo anything 
    # but (literally) return an error code 
    return 1
}

I made that into a standalone script named input-device-info.sh, and put that in the /usr/bin directory (which may or may not be the "correct" place, but it seemed to make sense in my use case).

Then, from another client implementation script, I sourced that and called the inputDeviceEventHandlerPath function like so:

. /usr/bin/input-device-info.sh   

MY_DEVICE_PATH=$(inputDeviceEventHandlerPath "my-device-name")
echo 'MY_DEVICE_PATH:' ${MY_DEVICE_PATH}
0

If you want a smaller snippet as an alternative to @BuvinJ's code in adjacent answer:

#! /usr/bin/env bash

# Somewhat stolen from: <https://unix.stackexchange.com/a/507209>
# Problem: multiple devices with the same name
find_event() {
    local lnNo handlers
    local INFO_FILE='/proc/bus/input/devices'
    lnNo=$(grep -n 'N: Name=' $INFO_FILE | grep "$1" | head -n1 | cut -d: -f1)
    handlers="$(tail +"$lnNo" $INFO_FILE | grep 'H: Handlers=' | head -n1 | cut -d= -f2)"

    [ -z "$handlers" ] && return 1

    for handler in $handlers; do
        case $handler in event*)
            echo "/dev/input/$handler"
            return 0
        esac
    done

    return 1
}

You must log in to answer this question.

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