0

I am using a Raspberry Pi4 with a USB Logitech Extreme 3D joystick. I have a Python 3 application using the evdev library to read the joystick which works fantastic, however, when I first boot the pi, the program cannot access the joystick until I disconnect and reconnect it. I have a udev rule which creates a symlink to the joystick.

I have verified that the joystick is being recognized and the symlink is being created upon bootup.

I also installed PyUSB to do some testing. If I boot the pi and go into a terminal, run python 3 and try to configure the joystick using PyUSB, it gives me the following error.

import usb.core
import usb.util
dev = usb.core.find(idVendor=0x046d, idProduct=0xc215)
print(dev)                #This outputs the correct information, indicating I am finding it
dev.set_configuration()   #This throws the following error

usb.core.USBError: [Error 16] Resource busy

This makes me think something else is binding to the joystick during boot before my application can grab it. I'm not sure how to troubleshoot this. Can anyone offer suggestions?

I have been searching for answers but can't find a solution to this exact problem.

Any help is much appreciated

**UPDATE 1 ** with info from a comment:
I have a bash script that is called from /etc/X11/xinit/xinitrc when the X system is started and I run startx from systemd at startup. The systemd waits for the device to be present and sets the environment XAUTHORITY=/home/pi/.Xauthority which is the user I am running the script under.

**UPDATE 2 ** After trying suggested answer from @Ingo, this is my systemd file:

[Unit]
Description=Start-Program
After=graphical.target

[Service]
User=pi
Environment=DISPLAY=:0.0
Environment=XAUTHORITY=/home/pi/.Xauthority
ExecStart=/home/pi/myprog/program-start.sh

[Install]
WantedBy=graphical.target
6
  • How do you start the python script on boot up?
    – Ingo
    Nov 3, 2020 at 18:40
  • @Ingo I have a bash script that is called from /etc/X11/xinit/xinitrc when the X system is started and I run startx from systemd at startup. The systemd waits for the device to be present and sets the environment XAUTHORITY=/home/pi/.Xauthority which is the user I am running the script under.
    – ChrisE
    Nov 3, 2020 at 19:30
  • If all else fails, you could kill power to the usb and turn it back on again via uhubctl. Not a proper solution so much as a workaround, but this would avoid having to unplug and re-plug at least.
    – Abel
    Nov 7, 2020 at 18:34
  • 1
    @Abel I really hate to "resolve" issues like this but this is actually solves my problem. Thank you for suggesting this.
    – ChrisE
    Nov 9, 2020 at 15:40
  • You are welcome. There's a lot of potential nuances involved with what a black box device might be expecting when it is powered. Without logging and comparing what happens on the wire, you may be limited. In theory if you had that knowledge and ditched evdev for pure ioctls, you could make the pi produce exactly what the stick needed when it needed it, but it may not be worth the effort.
    – Abel
    Nov 10, 2020 at 2:05

1 Answer 1

3

Starting a script with dependencies is one of the main functions of systemd. Seems you try to do it past systemd. It is very likely that this is confusing it. You should just use a Unit file and nothing else. All other things are managed very good by systemd.

Here is a simple suggestion. it may need some additional settings, if it doesn't run on the first try. We can look at it then. Create a new service with:

rpi ~$ sudo systemctl edit --force --full your-script.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=Your bash script
After=graphical.target

[Service]
User=pi
Environment=XAUTHORITY=/home/pi/.Xauthority
#ExecStartPre=/usr/bin/printenv
ExecStart=/full/path/to/your-script.sh

[Install]
WantedBy=graphical.target

To get the environment on runtime, uncomment ExecStartPre=... You will find its output with journalctl -b. Enable the service:

rpi ~$ sudo systemctl enable your-script.service

and reboot. Check it with:

rpi ~$ systemctl status your-script.service

If you are interested what systemd all is doing in the background you can show it with:

rpi ~$ systemctl show your-script.service

This may give an idea that it's the best to let only systemd do the work.

4
  • thanks for this detailed response. I had originally tried starting the app this way but couldn't get it to work. This does successfully start the app but I still have the original issue with the joystick not functioning until I disconnect and reconnect. One step closer. Any other ideas? I will edit my original post with the new systemd config. I did have to include the display environment variable.
    – ChrisE
    Nov 5, 2020 at 23:17
  • @ChrisE Why to add the display environment variable? The joystick doesn't do any graphical output on the screen. When reconnecting the joystick, the driver should give some messages shown with journalctl and/or dmesg. I would look why these are not executed on startup. I have updated the answer to debug the environment of the running service.
    – Ingo
    Nov 6, 2020 at 11:27
  • Because my application uses tkinter and if I dont add that display variable, it doesnt always show on the raspberry pi touch display. I agree it has nothing to do with the joystick. I will do some digging into your suggestion. Thanks
    – ChrisE
    Nov 6, 2020 at 15:54
  • I have searched the logs. The system is finding and loading the joystick on every boot. I am not seeing any error messages related to the joystick. Also, one other interesting thing is that after rebooting three or four times it decided to stop loading the application. I went back to my old method of starting the app and it is loading again. What a PITA
    – ChrisE
    Nov 6, 2020 at 22:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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