sysfsgpio: give time to udev to change gpio permission
When a gpio is exported by writing in /sys/class/gpio/export, the corresponding gpio control files appear immediately in sysfs but with default access permission for root user only. The daemon udev requires some time to get notified of the new files before it can change the permissions to allow access to unprivileged users. Due to this race condition, sysfsgpio can fail with EACCES error if OpenOCD is executed by any unprivileged user. Give 0.5 seconds to udev to identify the new files and change the permission. Tested with udev rules: SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c 'find -L /sys/class/gpio/ -maxdepth 2 -exec chown root:uucp {} \; -exec chmod g=u {} \; || true'" Change-Id: I1316c66ff103ffe23e5e4720f33372dc272a3766 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/5302 Tested-by: jenkins Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
parent
964c4db9ce
commit
49d71d06d1
|
@ -52,6 +52,7 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <helper/time_support.h>
|
||||
#include <jtag/interface.h>
|
||||
#include "bitbang.h"
|
||||
|
||||
|
@ -112,6 +113,7 @@ static void unexport_sysfs_gpio(int gpio)
|
|||
*/
|
||||
static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
|
||||
{
|
||||
struct timeval timeout, now;
|
||||
char buf[40];
|
||||
char gpiostr[5];
|
||||
int ret;
|
||||
|
@ -131,8 +133,19 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
|
|||
}
|
||||
}
|
||||
|
||||
gettimeofday(&timeout, NULL);
|
||||
timeval_add_time(&timeout, 0, 500000);
|
||||
|
||||
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
|
||||
ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
|
||||
for (;;) {
|
||||
ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
|
||||
if (ret >= 0 || errno != EACCES)
|
||||
break;
|
||||
gettimeofday(&now, NULL);
|
||||
if (timeval_compare(&now, &timeout) >= 0)
|
||||
break;
|
||||
jtag_sleep(10000);
|
||||
}
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("Couldn't set direction for gpio %d", gpio);
|
||||
perror("sysfsgpio: ");
|
||||
|
@ -141,7 +154,15 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
|
|||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
|
||||
ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
|
||||
for (;;) {
|
||||
ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
|
||||
if (ret >= 0 || errno != EACCES)
|
||||
break;
|
||||
gettimeofday(&now, NULL);
|
||||
if (timeval_compare(&now, &timeout) >= 0)
|
||||
break;
|
||||
jtag_sleep(10000);
|
||||
}
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("Couldn't open value for gpio %d", gpio);
|
||||
perror("sysfsgpio: ");
|
||||
|
|
Loading…
Reference in New Issue