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*". Commented 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. Commented Jul 7, 2013 at 23:31
  • Can you give us an example? Commented Jul 7, 2013 at 23:32
  • @slm: Here is an example of one entry. Commented 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.) Commented 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. Commented 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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.