I am attempting to read information from a usb device after it is attached.
The information I require are accessed through two APIs: v4l2 and libusb. Both are used through a script that is correctly called as the v4l2 part executes are expected.
SUBSYSTEM=="usb", ATTRS{idVendor}=="199a", GROUP="video", MODE="0666", TAG+="uaccess", TAG+="udev-acl"
ACTION=="add", SUBSYSTEM=="video4linux", \
ATTRS{idVendor}=="199a" \
RUN+="/usr/bin/camera-infos-wrapper %s{serial}"
When I run the script manually all steps are executed correctly. I have a wrapper around the script to set additional environment variables.
#!/usr/bin/env bash
export DISPLAY=":0"
export XAUTHORITY=/home/user/.Xauthority
# sleep 3 <- does not work
# sleep 4 <- works
# ensure debug output is logged
exec 1> >(logger -s -t $(basename $0)) 2>&1
/usr/bin/tcam-index-camera $1
When I sleep for 3 seconds libusb is unable to correctly open the device. Sleeping for 4 seconds allows correct access. Since this has to run on more than on PC I would prefer a more robust solution.
Is there any way to run the script after all udev rules are through and the device is completely initialized?
The way to go seems to be systemd.
The systemd unit [email protected]
[Unit]
Description=My service
After=dev-ident%i.device
Wants=dev-ident%i.device
[Service]
Type=forking
ExecStart=/usr/bin/script %i
Note the '@' in the file name. It is important as it is required for arguments.
The udev rule looks like:
ACTION=="add", SUBSYSTEM=="video4linux", \
ATTRS{idVendor}=="<vendor id>", \
TAG+="systemd", \
SYMLINK+="ident%s{serial}", \
ENV{SYSTEMD_WANTS}="camera-index@%s{serial}.service"
The systemd unit waits until the symlink is created and executes the script after that.