X-Git-Url: http://dolda2000.com/gitweb/?p=utils.git;a=blobdiff_plain;f=gpio.c;h=5c1d7187a818a856c63d4cb373c98870cdf9fc90;hp=1d8b322869e3b15f691cdd9a6ccd856aaad30887;hb=f7bd9b51138dbccb7cc2fd27f07ef66d5d2d79cf;hpb=cc450aa9fb0792ca0c5ae05f648e04dba0fc19d1 diff --git a/gpio.c b/gpio.c index 1d8b322..5c1d718 100644 --- a/gpio.c +++ b/gpio.c @@ -17,6 +17,7 @@ static const int imap[] = { }; static const int *umap = bmap; static int mapn = sizeof(bmap) / sizeof(*bmap); +static int preserve = 0; static int mappin(int num) { @@ -25,29 +26,67 @@ static int mappin(int num) return(umap[num]); } -static void setport(int p, int v) +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, rp; + int rv; + size_t ln; - if((rp = mappin(p)) < 0) { - fprintf(stderr, "gpio: %i: no such port\n", p); - exit(1); - } 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 || strcmp(line, "out\n")) { + 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, "out\n"); fflush(fp); + fprintf(fp, "%s\n", dir); fflush(fp); if(ferror(fp)) - errx(1, "gpio%i: could not set to output", rp); + 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); @@ -57,17 +96,41 @@ static void setport(int p, int v) 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 [-hi] PORT=VAL...\n"); + fprintf(out, "usage: gpio [-hip] {PORT=VAL|PORT==VAL|PORT?}...\n"); } int main(int argc, char **argv) { int c, i, port, val; - char *p, *e; + char *e; - while((c = getopt(argc, argv, "hi")) >= 0) { + while((c = getopt(argc, argv, "hip")) >= 0) { switch(c) { case 'h': usage(stdout); @@ -76,6 +139,9 @@ int main(int argc, char **argv) umap = imap; mapn = sizeof(imap) / sizeof(*imap); break; + case 'p': + preserve = 1; + break; default: usage(stderr); return(1); @@ -86,27 +152,31 @@ int main(int argc, char **argv) return(1); } for(i = optind; i < argc; i++) { - if((p = strchr(argv[i], '=')) == NULL) { - fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]); - exit(1); - } port = strtol(argv[i], &e, 10); - if(e != p) { - fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]); - exit(1); - } - val = strtol(p + 1, &e, 10); - if(*e) { - fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]); - exit(1); + 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]); } - setport(port, val); } return(0); } /* * Local Variables: - * compile-command: "gcc -Wall -g -O2 -march=native -o gpio gpio.c" + * compile-command: "gcc -Wall -g -O2 -march=native -c -o gpio.o gpio.c && gcc -o gpio gpio.o" * End: */