/* SYSFS gpio interrupt example for Raspberry Pi */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "interrupt.h" static int write_file(const char *path, const char *str) { int fd = 0; if ((fd = open(path, O_WRONLY)) == 0) { fprintf(stderr, "unable to open %s\n", path); return 1; } if (write(fd, str, strlen(str)) < 1) { fprintf(stderr, "unable to write to %s\n", path); close(fd); return 1; } close(fd); return 0; } /* Register a sysfs GPIO pin to be interruptable similar to: $ echo 12 > /sys/class/gpio/export $ echo both > /sys/class/gpio12/edge $ echo in > /sys/class/gpio12/direction */ int int_register(int pin) { char path[1024]; char buffer[64]; /* begin by unregistering supplied pin, just in case */ (void) int_unregister(pin); memset(buffer, 0, 64); sprintf(buffer, "%d", pin); if (write_file("/sys/class/gpio/export", buffer) != 0) { return 1; } /* sleep 500 ms to let linux set up the dir .. */ usleep(500000); memset(path, 0, 1024); sprintf(path, "%s%d/%s", "/sys/class/gpio/gpio", pin, "edge"); if (write_file(path, "both") != 0) { return 1; } memset(path, 0, 1024); sprintf(path, "%s%d/%s", "/sys/class/gpio/gpio", pin, "direction"); if (write_file(path, "in") != 0) { return 1; } return 0; } /* unregister an interrupt gpio config similar to: $ echo 12 > /sys/class/gpio/unexport */ int int_unregister(int pin) { char buffer[64]; memset(buffer, 0, 64); sprintf(buffer, "%d", pin); if (write_file("/sys/class/gpio/unexport", buffer) != 0) { return 1; } return 0; } /* poll a gpio pin for interrupt event blocking */ int int_poll(int pin) { int fd; struct pollfd pfd; char path[1024]; char buf[16]; memset(path, 0, 1024); sprintf(path, "%s%d/%s", "/sys/class/gpio/gpio", pin, "value"); if ((fd = open(path, O_RDONLY)) == 0) { fprintf(stderr, "unable to open %s\n", path); return 1; } pfd.fd = fd; pfd.events = POLLPRI | POLLERR; lseek(fd, 0, SEEK_SET); read(fd, buf, sizeof buf); poll(&pfd, 1, -1); lseek(fd, 0, SEEK_SET); read(fd, buf, sizeof buf); return 0; }