* GPIO fd won't generate signal
@ 2020-04-21 21:09 Benjamin Valentin
0 siblings, 0 replies; only message in thread
From: Benjamin Valentin @ 2020-04-21 21:09 UTC (permalink / raw)
To: linux-gpio
Hi,
AFAIU a GPIO fd will generate a POLLPRI event when an interrupt occurs
on the GPIO.
I can wait for this event using poll() just fine.
fcntl(fd, F_SETOWN, getpid()) should then turn such an event into a
signal that can be caught by the signal handler of the process.
This however does not work. Is this an omission by the GPIO API or am I
understanding the API wrong here?
Attached you find a little program to reproduce this:
When running on a raspberry pi, bridge GPIO20 and GPIO26.
The program will periodically toggle GPIO26, this should generate an
interrupt on GPIO20.
I can poll() GPIO20 but no signal is generated.
#include <fcntl.h>
#include <linux/gpio.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define PIN_IN (20)
#define PIN_OUT (26)
static int fd_in; /* to be read in the signal handler */
/* configure input pin */
static int setup_pin_int(int fd, int pin, int mode, int flank) {
struct gpioevent_request req = {
.lineoffset = pin,
.handleflags = mode,
.eventflags = flank
};
int res = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req);
if (res < 0) {
return res;
}
return req.fd;
}
/* configure output pin */
static int setup_pin_out(int fd, int pin, int mode) {
struct gpiohandle_request req = {
.lineoffsets[0] = pin,
.flags = mode,
.lines = 1
};
int res = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (res < 0) {
return res;
}
return req.fd;
}
static void pin_set(int fd, uint8_t val) {
ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &val);
}
/* print which edge triggered the event */
static void sigurg_handler(void) {
struct gpioevent_data event;
read(fd_in, &event, sizeof(event));
if (event.id == GPIOEVENT_EVENT_RISING_EDGE) {
puts("rising");
}
if (event.id == GPIOEVENT_EVENT_FALLING_EDGE) {
puts("falling");
}
}
static void signal_handler(int signal) {
printf("got signal: %x\n", signal);
if (signal == SIGURG) {
sigurg_handler();
}
}
static void register_signal(int signal, void (*handler)(int)) {
struct sigaction sa = {
.sa_handler = handler
};
sigaction(signal, &sa, NULL);
}
/* calling poll() on the fd works as expected */
static void _do_poll(int fd) {
struct pollfd pfd = {
.fd = fd,
.events = POLLIN | POLLPRI
};
if (poll(&pfd, 1, 1000) > 0) {
sigurg_handler();
}
}
int main(void) {
int pins[2];
int fd = open("/dev/gpiochip0", O_RDWR);
pins[0] = setup_pin_int(fd, PIN_IN, GPIOHANDLE_REQUEST_INPUT,
GPIOEVENT_REQUEST_BOTH_EDGES); pins[1] = setup_pin_out(fd, PIN_OUT,
GPIOHANDLE_REQUEST_OUTPUT);
fd_in = pins[0];
/* register signal handler */
register_signal(SIGIO, signal_handler);
register_signal(SIGURG, signal_handler);
/* make the fd generate signals */
fcntl(fd_in, F_SETOWN, getpid());
fcntl(fd_in, F_SETFL, O_NONBLOCK | O_ASYNC);
/* toggle the output pin each second */
int state;
while (1) {
state = !state;
sleep(1);
printf("set %d\n", state);
pin_set(pins[1], state);
/* poll() is working on the fd */
// _do_poll(fd_in);
}
close(fd);
return 0;
}
I can send signals to the process with kill -23 <pid> just fine and the
signal handler will be caught.
Just not when the GPIO event occurs.
Thank you!
Benjamin
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-04-21 21:16 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-21 21:09 GPIO fd won't generate signal Benjamin Valentin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).