Wait and retry until deplayed udev permission rule applies after exporting gpio pin
This commit is contained in:
parent
e069871c8e
commit
3dc1e4e72b
|
@ -27,6 +27,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
@ -108,7 +109,8 @@ static int linuxgpio_dir(unsigned int gpio, unsigned int dir)
|
||||||
|
|
||||||
fd = open(buf, O_WRONLY);
|
fd = open(buf, O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("Can't open gpioX/direction");
|
snprintf(buf, sizeof(buf), "Can't open gpio%u/direction", gpio);
|
||||||
|
perror(buf);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +140,11 @@ static int linuxgpio_dir_in(unsigned int gpio)
|
||||||
|
|
||||||
#define N_GPIO (PIN_MAX + 1)
|
#define N_GPIO (PIN_MAX + 1)
|
||||||
|
|
||||||
|
/* Delay between checks for successful GPIO export (100ms) */
|
||||||
|
#define GPIO_SYSFS_OPEN_DELAY 100000
|
||||||
|
/* Number of retries to check for successful GPIO exports */
|
||||||
|
#define GPIO_SYSFS_OPEN_RETRIES 10
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* an array which holds open FDs to /sys/class/gpio/gpioXX/value for all needed pins
|
* an array which holds open FDs to /sys/class/gpio/gpioXX/value for all needed pins
|
||||||
*/
|
*/
|
||||||
|
@ -245,6 +252,8 @@ static void linuxgpio_powerdown(PROGRAMMER *pgm)
|
||||||
static int linuxgpio_open(PROGRAMMER *pgm, char *port)
|
static int linuxgpio_open(PROGRAMMER *pgm, char *port)
|
||||||
{
|
{
|
||||||
int r, i, pin;
|
int r, i, pin;
|
||||||
|
char gpio_path[60];
|
||||||
|
struct stat stat_buf;
|
||||||
|
|
||||||
if (bitbang_check_prerequisites(pgm) < 0)
|
if (bitbang_check_prerequisites(pgm) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -272,13 +281,46 @@ static int linuxgpio_open(PROGRAMMER *pgm, char *port)
|
||||||
pin, strerror(errno));
|
pin, strerror(errno));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wait until GPIO directory appears */
|
||||||
|
snprintf(gpio_path, sizeof(gpio_path), "/sys/class/gpio/gpio%u", pin);
|
||||||
|
unsigned int retry_count;
|
||||||
|
for (retry_count = 0; retry_count < GPIO_SYSFS_OPEN_RETRIES; retry_count++) {
|
||||||
|
int ret = stat(gpio_path, &stat_buf);
|
||||||
|
if (ret == 0) {
|
||||||
|
break;
|
||||||
|
} else if (ret < 0 && errno != ENOENT) {
|
||||||
|
linuxgpio_unexport(pin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(GPIO_SYSFS_OPEN_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write direction, looping in case of EACCES errors due to delayed
|
||||||
|
* udev permission rule application after export */
|
||||||
|
for (retry_count = GPIO_SYSFS_OPEN_RETRIES; retry_count > 0; retry_count--) {
|
||||||
|
usleep(GPIO_SYSFS_OPEN_DELAY);
|
||||||
if (i == PIN_AVR_MISO)
|
if (i == PIN_AVR_MISO)
|
||||||
r=linuxgpio_dir_in(pin);
|
r=linuxgpio_dir_in(pin);
|
||||||
else
|
else
|
||||||
r=linuxgpio_dir_out(pin);
|
r=linuxgpio_dir_out(pin);
|
||||||
|
|
||||||
if (r < 0)
|
if (r >= 0) {
|
||||||
|
break;
|
||||||
|
} else if (errno != EACCES) {
|
||||||
|
linuxgpio_unexport(pin);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
if (retry_count > 1) {
|
||||||
|
printf("Retrying...\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
linuxgpio_unexport(pin);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if ((linuxgpio_fds[pin]=linuxgpio_openfd(pin)) < 0)
|
if ((linuxgpio_fds[pin]=linuxgpio_openfd(pin)) < 0)
|
||||||
return linuxgpio_fds[pin];
|
return linuxgpio_fds[pin];
|
||||||
|
|
Loading…
Reference in New Issue