How do I make libusb work as non-root?
I'm making a custom USB HID device, and a desktop app to go with it, using HIDAPI on Lubuntu 16.04.3 LTS. We'll call it myapp
for now.
Apparently, if I do $ ./myapp
, libusb_open()
fails with LIBUSB_ERROR_ACCESS
. (shown in my debugger as -3
; it took a while to figure that out because the enum doesn't seem to be documented very well)
But if I do $ sudo ./myapp
, it succeeds.
I really don't want myapp
to have root permissions, so how can I talk to my USB device without them?
I was hoping for an answer here, but it seems to have been abandoned at exactly this point. It says something about user permissions, but I can't seem to find that on my system. I thought I might find a group called usb
or libusb
that I could add myself to, but no such luck.
This question on a different SE site has an answer that uses some austere text files to change the permissions either globally (probably a bad idea) or for a specific device, but:
- It's not the "muggle's tweak" that I was looking for.
- Most of those files have a warning against modifying directly because they're auto-generated. So how can I be sure that a random package update isn't going to wipe out my changes and thus break
myapp
? - It doesn't seem to do anything anyway. I followed those instructions and rebooted, and
myapp
with user permissions still can't talk to USB.
Solution 1:
It's still not the "muggle's tweak" that I'm really looking for, but at least this works:
Apparently there are two directories for udev (I have no idea why):
/etc/udev/rules.d
/lib/udev/rules.d
I'd been messing with the /lib
one and getting nowhere. I found the /etc
one here, and it does work:
Put SUBSYSTEM=="usb", ATTRS{idVendor}=="VID", ATTRS{idProduct}=="PID", MODE="0666"
-
VID
is the USB-IF-assigned Vendor ID of the device in question * -
PID
is the Vendor-assigned Product ID of the device in question * -
0666
gives universal read/write access to whatever matches this line*
$ lsusb
to see all attached USB devices and their ID's.
In /etc/udev/rules.d/xx-my-rule.rules
(may need root/sudo permissions)
-
xx
is any number > 50 (the defaults are in 50, and higher numbers take priority) -
my-rule
is whatever you want to call it - must end in
.rules
Then udevadm control --reload-rules
(may also need root/sudo permissions), and it should "just work" for that specific VID/PID pair.
Another option, to tighten the permissions a little bit more, is to use TAG+="uaccess"
in place of MODE="0666"
. This limits access to the currently-logged-in (physical) user instead of all users. Thanks @Lekensteyn!
Solution 2:
For anyone else struggling with this - i needed to add GROUP="plugdev" to my udev rule under Ubuntu 18.04 to make it work.
so for my BTD-400 adapter the file /etc/udev/rules.d/51-usb-device.rules reads:
SUBSYSTEM=="usb", ATTRS{idVendor}=="0a5c", ATTRS{idProduct}=="21e8", GROUP="plugdev", TAG+="uaccess"