Closed amigalemming closed 6 years ago
By default, writes to Linux's sysfs
's GPIO filesystem can only be performed by root. There are ways around that, but I think they're outside the scope of what a package like hpio
should be doing.
Regardless, this is a relevant issue because it will come up for anyone who wants to use hpio
in its current form [1]. At least one solution to the problem is to:
gpio
group.hpio
program as a user who is a member of that group.udev
to ensure that the pseudo-files and pseudo-directories created by sysfs
s GPIO subsystem are writable by the gpio
group. This is the solution I use on my own systems where I run hpio
programs.There are numerous ways to accomplish this in udev
, but here are the rules I use:
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"
SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
A Google search will turn up quite a few alternative ways to accomplish more or less the same thing:
https://www.google.com/search?hl=en&q=linux%20gpio%20udev%20rules
One flaw with any udev
-based approach is that there is a slight delay between when the kernel creates the pseudo-devices and when the udev
script runs. This can cause a race where, if your program tries to write a file before its permissions have been fixed, the program will fail. The way I solve that is to run a shell script which exports the devices my program needs before I run the program, so that by the time the program runs, the permissions will have been fixed; but a more robust solution would be to build a delay into in hpio
's sysfs
monad to accommodate this race condition. There is another race condition issue (#70) that I need to address, and the fix for that should probably handle any udev
delay, as well. I will try to fix that in the next couple of weeks (pretty busy here at the moment), but a workaround script like the one I mentioned should work in the meantime.
[1] Eventually I want to support libgpiod
(see #71) and deprecate the sysfs
interface, which I presume will have its own way of dealing with privileged operations.
Thank you for the detailed explanation! The default user on the Raspberry Pi is already in the gpio
group. Setting sysfs
groups is the missing part for me.
How does the Python interface avoid these problems? Does it use libgpio
?
I'm not that familiar with GPIO in Python, and it obviously depends on which Python module you were using, but I believe that at least some of the Python RPi modules wrap the bcm2835 RPi-specific C library (see http://www.airspayce.com/mikem/bcm2835/). According to the home page for that project, recent versions of Raspbian allow non-root access to the /dev/gpiomem
device used by that library.
Anyway, I'm glad this helped. I will close this issue if you don't object.
I wrote a simple program that switches a light on and plays a sound if a motion sensor triggers: https://hub.darcs.net/thielema/deep-thought/browse/src/DeepThought.hs
However, when I start the program it fails with a Permission error. It only works when run as root, in contrast to the Python programs I tested before. Is this due to
hpio
's use of sysfs?Running as root is problematic. I like to test the program in GHCi but as root I am missing the user packages. When running as root, I can no longer abort the program with CTRL-C. If I terminate it with
kill
then the finalization code (switching off LED) is skipped. How can I cleanup properly at the end?