How to add or workaround a udev rule

Hey Everyone,

I have a strictly confined snap I’m working on but I am having a permissions/sudo/udev issue.

I am snapping a Go binary that talks to a USB-C monitor in order to adjust brightness. The standalone binary works just fine as long as I use sudo with it. Under the hood it’s using libusb to do it’s work.

When creating the snap, I had to use the plugs raw-usb and hardware-observe in order to get it to work, though again I have to prefix the snap with sudo when running.

I’d like to get this to run without sudo so that I/someone can run this snap from a keyboard shortcut in order to adjust brightness.

I have been able to get both the standalone binary and the snap to not require sudo if I first setup the udev rule:

SUBSYSTEM=="usb", ATTRS{idVendor}=="043e", ATTRS{idProduct}=="9a40", MODE="0666", GROUP="plugdev"

on my Ubuntu 18.04 Desktop.

How do I get my snap to pre-install that udev rule?

As of now, to get my snap to work a user would have to run:

sudo snap install lguf-cli
sudo snap connect lguf-cli:raw-usb
sudo snap connect lguf-cli:hardware-observe

which is more steps than I’d like but I get it. I would like to not have to add another step or two for them to setup the udev rule. I see the UBPorts folks had a similar issue and the solution there was a custom interface created for their/adb needs. That’s clearly overkill here but I haven’t figured out a solution.

The current snapcraft.yml is here.

one option is to split your app in two halves … one daemon part that does all the work, one cli part to have the user send commands… make the cli part talk to the daemon via a socket or some such.

daemons in snaps always run as root so you wont need sudo …

1 Like

Hmm interesting. That might work. Especially if I can maybe use the same binary but have it run in different modes.

Do you happen to have an example to point me to?

Thanks for the idea.

I was thinking about the same question. I think this could be done by the install hook, adding the file to /etc/udev/rules.d/. Can someone confirm that this is a proper way?

An install hook could do this provided you used the system-files interface to allow write access to /etc/udev/rules.d, but this is not the proper way. A classic snap could do the same, but again, that isn’t the proper way.

The way to do this within the ecosystem is add a new/modify an existing interface to update the udev backend for the hardware in question so snapd can put the udev rule(s) in place on behalf of the snap that plugs the interface.

But I think it’s quite hard to convince anybody to add a very specific interface for a private snap (symlink Sony PS4 controller to /dev/input/psc instead of /dev/input/js*) to snapd…

The Sony PS4 controller is not snap-specific though. If a new or modified interface could handle this controller, that would benefit the private snap as well as any other snaps that might use one.

If you are only concerned about a private snap, those few individuals can update their udev rules accordingly. I suggest filing a bug at https://launchpad.net/snapd/+filebug with specific details about the controller. It may be a bug in the distro (eg systemd’s udev rules) that the symlink isn’t being setup correctly.

There is a little bit of a misunderstanding. There is the joystick interface and the PS4 controller acts as a joystick and is mounted to /dev/input/js*. This works fine. There’s no bug at all.

However, the definition of joystick is quite broad (which makes totally sense for this interface). In my case this can sometimes mean that a touchscreen is interpreted as js* and I don’t know which js* is my PS4 controller. Therefore, I have this udev rule which identifies the device and symlinks to /dev/input/psc. I think the best solution I found is to add this specific udev rule to a gadget snap. Or just let the users do it manually.