Skip to content

Commit

Permalink
Add PDATA to programmer linuxgpio and move static variables there
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanrueger committed Apr 22, 2024
1 parent 8fe729f commit 8390909
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/avrdude.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern const char *pgmid; // Programmer -c string
#define mmt_strdup(s) cfg_strdup(__func__, s)
#define mmt_malloc(n) cfg_malloc(__func__, n)
#define mmt_realloc(p, n) cfg_realloc(__func__, p, n)
#define mmt_free(p) free(p)

int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...);

Expand Down
81 changes: 43 additions & 38 deletions src/linuxgpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
* Licensed under the GPL-2 or later
*/

#define N_GPIO (PIN_MAX + 1)

struct pdata {
int sysfs_fds[N_GPIO]; // Open FDs of /sys/class/gpio/gpioXX/value for needed pins
};

// Use private programmer data as if they were a global structure my
#define my (*(struct pdata *)(pgm->cookie))


/*
* Sysfs GPIO user space helpers
* The following functions are acting on an "unsigned gpio" argument, which corresponds to the
Expand Down Expand Up @@ -140,19 +150,11 @@ static int linuxgpio_sysfs_dir_in(unsigned int gpio)
* End of Sysfs GPIO user space helpers
*/

#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
*/
static int linuxgpio_sysfs_fds[N_GPIO] ;


static int linuxgpio_sysfs_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
Expand All @@ -162,10 +164,10 @@ static int linuxgpio_sysfs_setpin(const PROGRAMMER *pgm, int pinfunc, int value)
value = !value;
pin &= PIN_MASK;

if (pin > PIN_MAX || linuxgpio_sysfs_fds[pin] < 0)
if (pin > PIN_MAX || my.sysfs_fds[pin] < 0)
return -1;

if (write(linuxgpio_sysfs_fds[pin], value? "1": "0", 1) != 1)
if (write(my.sysfs_fds[pin], value? "1": "0", 1) != 1)
return -1;

if (pgm->ispdelay > 1)
Expand All @@ -182,14 +184,14 @@ static int linuxgpio_sysfs_getpin(const PROGRAMMER *pgm, int pinfunc) {
int invert = !!(pin & PIN_INVERSE);
pin &= PIN_MASK;

if(pin > PIN_MAX || linuxgpio_sysfs_fds[pin] < 0)
if(pin > PIN_MAX || my.sysfs_fds[pin] < 0)
return -1;

if(lseek(linuxgpio_sysfs_fds[pin], 0, SEEK_SET) < 0)
if(lseek(my.sysfs_fds[pin], 0, SEEK_SET) < 0)
return -1;

char c;
if(read(linuxgpio_sysfs_fds[pin], &c, 1) != 1)
if(read(my.sysfs_fds[pin], &c, 1) != 1)
return -1;

return c=='0'? 0+invert: c=='1'? 1-invert: -1;
Expand All @@ -201,7 +203,7 @@ static int linuxgpio_sysfs_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {

unsigned int pin = pgm->pinno[pinfunc] & PIN_MASK;

if (pin > PIN_MAX || linuxgpio_sysfs_fds[pin] < 0 )
if (pin > PIN_MAX || my.sysfs_fds[pin] < 0 )
return -1;

linuxgpio_sysfs_setpin(pgm, pinfunc, 1);
Expand All @@ -218,19 +220,15 @@ static void linuxgpio_sysfs_display(const PROGRAMMER *pgm, const char *p) {
}

static void linuxgpio_enable(PROGRAMMER *pgm, const AVRPART *p) {
/* nothing */
}

static void linuxgpio_disable(const PROGRAMMER *pgm) {
/* nothing */
}

static void linuxgpio_powerup(const PROGRAMMER *pgm) {
/* nothing */
}

static void linuxgpio_powerdown(const PROGRAMMER *pgm) {
/* nothing */
}

static int linuxgpio_sysfs_open(PROGRAMMER *pgm, const char *port) {
Expand All @@ -243,7 +241,7 @@ static int linuxgpio_sysfs_open(PROGRAMMER *pgm, const char *port) {


for (i=0; i<N_GPIO; i++)
linuxgpio_sysfs_fds[i] = -1;
my.sysfs_fds[i] = -1;
// Avrdude assumes that if a pin number is invalid it means not used/available
for (i = 1; i < N_PINS; i++) { // The pin enumeration in libavrdude.h starts with PPI_AVR_VCC = 1
if ((pgm->pinno[i] & PIN_MASK) <= PIN_MAX) {
Expand Down Expand Up @@ -297,8 +295,8 @@ static int linuxgpio_sysfs_open(PROGRAMMER *pgm, const char *port) {
return r;
}

if ((linuxgpio_sysfs_fds[pin]=linuxgpio_sysfs_openfd(pin)) < 0)
return linuxgpio_sysfs_fds[pin];
if ((my.sysfs_fds[pin]=linuxgpio_sysfs_openfd(pin)) < 0)
return my.sysfs_fds[pin];
}
}

Expand All @@ -314,22 +312,31 @@ static void linuxgpio_sysfs_close(PROGRAMMER *pgm)
//first configure all pins as input, except RESET
//this should avoid possible conflicts when AVR firmware starts
for (i=0; i<N_GPIO; i++) {
if (linuxgpio_sysfs_fds[i] >= 0 && i != reset_pin) {
close(linuxgpio_sysfs_fds[i]);
linuxgpio_sysfs_fds[i] = -1;
if (my.sysfs_fds[i] >= 0 && i != reset_pin) {
close(my.sysfs_fds[i]);
my.sysfs_fds[i] = -1;
linuxgpio_sysfs_dir_in(i);
linuxgpio_sysfs_unexport(i);
}
}
//configure RESET as input, if there's external pull up it will go high
if(reset_pin <= PIN_MAX && linuxgpio_sysfs_fds[reset_pin] >= 0) {
close(linuxgpio_sysfs_fds[reset_pin]);
linuxgpio_sysfs_fds[reset_pin] = -1;
if(reset_pin <= PIN_MAX && my.sysfs_fds[reset_pin] >= 0) {
close(my.sysfs_fds[reset_pin]);
my.sysfs_fds[reset_pin] = -1;
linuxgpio_sysfs_dir_in(reset_pin);
linuxgpio_sysfs_unexport(reset_pin);
}
}

void linuxgpio_setup(PROGRAMMER *pgm) {
pgm->cookie = mmt_malloc(sizeof(struct pdata));
}

void linuxgpio_teardown(PROGRAMMER *pgm) {
mmt_free(pgm->cookie);
pgm->cookie = NULL;
}


//
// libgpiod backend for the linuxgpio programmer.
Expand Down Expand Up @@ -470,13 +477,6 @@ int gpiod_line_set_direction_input(struct gpiod_line *gpio_line) {
return retval;
}

/* this helper is not thread safe, but we are not using threads... */
char *gpiod_line_name(struct gpiod_line *gpio_line) {
static char buffer[16];
snprintf(buffer, sizeof(buffer), "%u", gpio_line->gpio_num);
return buffer;
}

void gpiod_line_release(struct gpiod_line *gpio_line) {
gpiod_line_request_release(gpio_line->line_request);
gpiod_chip_close(gpio_line->chip);
Expand Down Expand Up @@ -570,7 +570,8 @@ static void linuxgpio_libgpiod_close(PROGRAMMER *pgm) {
if (linuxgpio_libgpiod_lines[i] != NULL && i != PIN_AVR_RESET) {
int r = gpiod_line_set_direction_input(linuxgpio_libgpiod_lines[i]);
if (r != 0) {
msg_error("failed to set pin %s to input: %s\n", gpiod_line_name(linuxgpio_libgpiod_lines[i]), strerror(errno));
msg_error("failed to set pin %u to input: %s\n",
linuxgpio_libgpiod_lines[i]->gpio_num, strerror(errno));
}
gpiod_line_release(linuxgpio_libgpiod_lines[i]);
linuxgpio_libgpiod_lines[i] = NULL;
Expand All @@ -581,7 +582,8 @@ static void linuxgpio_libgpiod_close(PROGRAMMER *pgm) {
if (linuxgpio_libgpiod_lines[PIN_AVR_RESET] != NULL) {
int r = gpiod_line_set_direction_input(linuxgpio_libgpiod_lines[PIN_AVR_RESET]);
if (r != 0) {
msg_error("failed to set pin %s to input: %s\n", gpiod_line_name(linuxgpio_libgpiod_lines[PIN_AVR_RESET]), strerror(errno));
msg_error("failed to set pin %u to input: %s\n",
linuxgpio_libgpiod_lines[PIN_AVR_RESET]->gpio_num, strerror(errno));
}
gpiod_line_release(linuxgpio_libgpiod_lines[PIN_AVR_RESET]);
linuxgpio_libgpiod_lines[PIN_AVR_RESET] = NULL;
Expand All @@ -606,7 +608,8 @@ static int linuxgpio_libgpiod_setpin(const PROGRAMMER *pgm, int pinfunc, int val

int r = gpiod_line_set_value(linuxgpio_libgpiod_lines[pinfunc], value);
if (r != 0) {
msg_error("failed to set value of %s (%s) to %d: %s\n", avr_pin_name(pinfunc), gpiod_line_name(linuxgpio_libgpiod_lines[pinfunc]), value, strerror(errno));
msg_error("failed to set value of %s (%u) to %d: %s\n", avr_pin_name(pinfunc),
linuxgpio_libgpiod_lines[pinfunc]->gpio_num, value, strerror(errno));
return -1;
}

Expand All @@ -632,7 +635,7 @@ static int linuxgpio_libgpiod_getpin(const PROGRAMMER *pgm, int pinfunc) {

int r = gpiod_line_get_value(linuxgpio_libgpiod_lines[pinfunc]);
if (r == -1) {
msg_error("failed to read %s: %s\n", gpiod_line_name(linuxgpio_libgpiod_lines[pinfunc]), strerror(errno));
msg_error("failed to read %u: %s\n", linuxgpio_libgpiod_lines[pinfunc]->gpio_num, strerror(errno));
return -1;
}

Expand Down Expand Up @@ -696,6 +699,8 @@ void linuxgpio_initpgm(PROGRAMMER *pgm) {
pgm->highpulsepin = linuxgpio_sysfs_highpulsepin;
pgm->read_byte = avr_read_byte_default;
pgm->write_byte = avr_write_byte_default;
pgm->setup = linuxgpio_setup;
pgm->teardown = linuxgpio_teardown;

#ifdef HAVE_LIBGPIOD
if (libgpiod_is_working()) {
Expand Down

0 comments on commit 8390909

Please sign in to comment.