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:

  1. It's not the "muggle's tweak" that I was looking for.
  2. 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?
  3. 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"