From: Fredrik Tolf Date: Wed, 23 Jan 2019 15:43:34 +0000 (+0100) Subject: Merge branch 'master' of git.dolda2000.com:/srv/git/r/utils X-Git-Url: http://git.dolda2000.com/gitweb/?a=commitdiff_plain;h=f833b96c824951ebeae446977dd12b3eb03b77e6;hp=06282b33ce67d6918f6344c6536aa946cb06c344;p=utils.git Merge branch 'master' of git.dolda2000.com:/srv/git/r/utils --- diff --git a/gpio.c b/gpio.c new file mode 100644 index 0000000..5c1d718 --- /dev/null +++ b/gpio.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include + +static const int bmap[] = { + -1, + -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, + 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 21, 20, -1, 21, +}; +static const int imap[] = { + -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, 27, +}; +static const int *umap = bmap; +static int mapn = sizeof(bmap) / sizeof(*bmap); +static int preserve = 0; + +static int mappin(int num) +{ + if((num < 0) || (num >= mapn)) + return(-1); + return(umap[num]); +} + +static void export(int p) +{ + char path[256]; + FILE *fp; + int rp; + + if((rp = mappin(p)) < 0) + errx(1, "%i: no such port", p); + sprintf(path, "/sys/class/gpio/gpio%i", rp); + if(!access(path, R_OK | X_OK)) + return; + if(preserve) + errx(2, "gpio%i: not exported", rp); + sprintf(path, "/sys/class/gpio/export"); + if((fp = fopen(path, "w")) == NULL) + err(1, "%s", path); + fprintf(fp, "%i\n", rp); fflush(fp); + if(ferror(fp)) + errx(1, "gpio%i: could not export", rp); + fclose(fp); + sprintf(path, "/sys/class/gpio/gpio%i", rp); + if(access(path, R_OK | X_OK)) + errx(1, "gpio%i: still not available after export", rp); +} + +static void checkdir(int rp, char *dir) +{ + char path[256], line[256]; + FILE *fp; + int rv; + size_t ln; + + sprintf(path, "/sys/class/gpio/gpio%i/direction", rp); + if((fp = fopen(path, "r")) == NULL) + err(1, "%s", path); + rv = !!fgets(line, sizeof(line), fp); + fclose(fp); + if(!rv || ((ln = strlen(line)) < 1) || (line[ln - 1] != '\n')) + errx(1, "gpio%i: could not read direction", rp); + line[ln - 1] = 0; + if(strcmp(line, dir)) { + if(preserve) + errx(2, "gpio%i: direction not set to %s", rp, dir); + if((fp = fopen(path, "w")) == NULL) + err(1, "%s", path); + fprintf(fp, "%s\n", dir); fflush(fp); + if(ferror(fp)) + errx(1, "gpio%i: could not set to direction to %s", rp, dir); + fclose(fp); + } +} + +static void setport(int p, int v) +{ + char path[256]; + FILE *fp; + int rp; + + if((rp = mappin(p)) < 0) + errx(1, "%i: no such port", p); + checkdir(rp, "out"); + sprintf(path, "/sys/class/gpio/gpio%i/value", rp); + if((fp = fopen(path, "w")) == NULL) + err(1, "%s", path); + fprintf(fp, "%i\n", v); fflush(fp); + if(ferror(fp)) + errx(1, "gpio%i: could not set value", rp); + fclose(fp); +} + +static int getport(int p) +{ + char path[256], line[256], *ep; + FILE *fp; + int rv, rp; + size_t ln; + + if((rp = mappin(p)) < 0) + errx(1, "%i: no such port", p); + checkdir(rp, "in"); + sprintf(path, "/sys/class/gpio/gpio%i/value", rp); + if((fp = fopen(path, "r")) == NULL) + err(1, "%s", path); + rv = !!fgets(line, sizeof(line), fp); + fclose(fp); + if(!rv || ((ln = strlen(line)) < 1) || (line[ln - 1] != '\n')) + errx(1, "gpio%i: could not read direction", rp); + line[ln - 1] = 0; + rv = (int)strtol(line, &ep, 10); + if(*ep) + errx(1, "gpio%i: unexpected contents: %s", rp, line); + return(rv); +} + +static void usage(FILE *out) +{ + fprintf(out, "usage: gpio [-hip] {PORT=VAL|PORT==VAL|PORT?}...\n"); +} + +int main(int argc, char **argv) +{ + int c, i, port, val; + char *e; + + while((c = getopt(argc, argv, "hip")) >= 0) { + switch(c) { + case 'h': + usage(stdout); + return(0); + case 'i': + umap = imap; + mapn = sizeof(imap) / sizeof(*imap); + break; + case 'p': + preserve = 1; + break; + default: + usage(stderr); + return(1); + } + } + if(optind >= argc) { + usage(stderr); + return(1); + } + for(i = optind; i < argc; i++) { + port = strtol(argv[i], &e, 10); + if((e > argv[i]) && (e[0] == '=') && (e[1] == '=')) { + val = strtol(e + 2, &e, 10); + if(*e) + errx(1, "gpio: %s: not of the form PORT==VAL", argv[i]); + export(port); + return(getport(port) != val); + } else if((e > argv[i]) && (e[0] == '=')) { + val = strtol(e + 1, &e, 10); + if(*e) + errx(1, "gpio: %s: not of the form PORT=VAL", argv[i]); + export(port); + setport(port, val); + } else if((e > argv[i]) && (e[0] == '?') && !e[1]) { + export(port); + printf("%i\n", getport(port)); + } else { + errx(1, "gpio: %s: not a valid argument", argv[i]); + } + } + return(0); +} + +/* + * Local Variables: + * compile-command: "gcc -Wall -g -O2 -march=native -c -o gpio.o gpio.c && gcc -o gpio gpio.o" + * End: + */