I'm currently exploring ways to detect the correct device path (for ex: /dev/input/event0) for an USB scanner. With the following code in Python using the evdev package, I am able to filter down to a device using its physical name:

from evdev import InputDevice, list_devices
devices = [dev for dev in list_devices()
            if InputDevice(dev).phys == config['PHYS_NAME']]

But whenever a new device needs to be connected, I'd require the user to add the right physical name by running evdev's module test. I'm not able to reliably get the device path without going through this cumbersome procedure.

Is there a smarter way around this ? Is it perhaps a driver problem that the scanner doesn't get show up on my Raspbian desktop, like it does for others ?

  • 1
    I don't knwow about evdev module, but you can use udev for that i can guarantee it. pypi.org/project/pyudev. Get the physical path or the name of the device when hot-plug with udev, blacklist/power-OFF the usb bus on detection, display an input with for example command line zenity tool , then the user enter the name of the device . Finally when he click on ok/accept you must power-ON the usb bus.
    – Ephemeral
    Jun 1 '19 at 10:33

⚠ Please read the code before using it because you can lock your USB mouse or keyboard. Add a whitelist of your known devices maybe before running it directly.

I found and modified this script base enough time ago. Maybe you could adapt it quite easily to Raspbian (Edit: I have do it for you finally) and your needs (Edit: but not that).

1) ~$ sudo nano /usr/local/bin/detect-usb.py

# base script of lexsi , modified by Ephemeral.

import sys, os, time, re
import os.path
from subprocess import Popen, PIPE
import subprocess


# Log information
def log(msg):
        if os.path.exists(path):
                # protect log from group and other RWX
                process = Popen(["chmod", "go-rwx", path], stdout=PIPE, stderr=PIPE).communicate()

        with open(path,"a") as logfile:
                date=time.strftime("%d-%m-%Y %H:%M:%S")
                logfile.write("# %s # %s \n" % (date, msg))

# Block a specific device
def block(kernel):
        os.system("echo '0' | sudo tee '/sys/bus/usb/devices/%s/power/autosuspend_delay_ms'"%kernel)
        os.system("echo 'auto' | sudo tee '/sys/bus/usb/devices/%s/power/control'"%kernel)

# Display pop-up message
def popup(msg):
        proc=Popen(msg, shell=True)
        return proc.returncode

if __name__ == '__main__':
        # Get arguments from Udev rules
        kernel=re.sub(r"[^0-9-]+", '', sys.argv[1])
        devname=re.sub(r"[^A-Za-z0-9/]+", '', sys.argv[2])
        manufacturer=re.sub(r"[^A-Za-z0-9]+", '', sys.argv[3])
        zenity_msg = "zenity --question --title 'New device detected' --text 'A new device has been plugged in \n\n <b>Informations</b> \n\n <b>Manufacturer:</b>%s\n <b>Devname:</b> %s\n\nShould I accept it?' --display=:0.0" % (manufacturer,devname)

        #zenity_msg = "zenity --entry --title 'New device detected' --text 'A new device has been plugged in \n\n <b>Informations</b> \n\n <b>Manufacturer:</b>%s\n <b>Devname:</b> %s\n\nPlease enter the device name' --display=:0.0" % (manufacturer,devname)

        # Popup window - ask user for a choice
        if popup(zenity_msg):
                # Block device
                log("Device: %s - %s was blocked" % (manufacturer, devname))
                # Ask for confirmation
                zenity_msg = "zenity --question 'Confirmation' --title 'Are you sure?' --display=:0.0"

                if popup(zenity_msg) == 0:
                        log("Device: %s - %s was allowed" % (manufacturer, devname))
                        # Block
                        log("Device: %s - %s was blocked" % (manufacturer, devname))

sudo chmod +x /usr/local/bin/detect-usb.py

2) ~$ sudo nano /etc/udev/rules.d/99-detectusb.rules

ACTION=="add",ENV{DEVTYPE}=="usb_device",SUBSYSTEM=="usb",RUN+="/usr/local/bin/detect-usb.py %k '%E{DEVNAME}' $attr{manufacturer}"

and then:

~$ sudo /etc/init.d/udev reload

3) ~$ nano ~/.bashrc

xhost local:{username}>/dev/null

You can show zenity --entry for an input. Check in the script this commented line and play with that:

enter image description here

zenity_msg = "zenity --entry --title 'New device detected' --text 'A new device has been plugged in \n\n <b>Informations</b> \n\n <b>Manufacturer:</b>%s\n <b>Devname:</b> %s\n\nPlease enter the device name' --display=:0.0" % (manufacturer,devname)

Also, you can find log events in

  • 1
    udevadm monitor --udev --property is also useful for this task.
    – goldilocks
    Jun 1 '19 at 12:51
  • Upvoted. Thanks for the detailed answer.
    – fixxxer
    Jun 3 '19 at 7:02

In case, you end up on this route of finding the device path of your USB scanner on your Raspberry Pi, you may want to make sure that the device is able to register as a keyboard (this is how most usb scanners do). Using dmesg helps to see what is really happening here.

In my Pi, the under voltage was making the USB scanner re-register very frequently. Once I set max_usb_current=1, the scanner became available as keyboard input. Doing this removed the need to look for the scanner's device path.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.