gpio: Auto-export ports.
authorFredrik Tolf <fredrik@dolda2000.com>
Fri, 14 Sep 2018 18:51:18 +0000 (20:51 +0200)
committerFredrik Tolf <fredrik@dolda2000.com>
Fri, 14 Sep 2018 18:51:18 +0000 (20:51 +0200)
gpio.c

diff --git a/gpio.c b/gpio.c
index 1d8b322..0179c18 100644 (file)
--- 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 const int *umap = bmap;
 static int mapn = sizeof(bmap) / sizeof(*bmap);
+static int preserve = 0;
 
 static int mappin(int num)
 {
 
 static int mappin(int num)
 {
@@ -25,22 +26,47 @@ static int mappin(int num)
     return(umap[num]);
 }
 
     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\n", 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 setport(int p, int v)
 {
     char path[256], line[256];
     FILE *fp;
     int rv, rp;
     
 static void setport(int p, int v)
 {
     char path[256], line[256];
     FILE *fp;
     int rv, rp;
     
-    if((rp = mappin(p)) < 0) {
-       fprintf(stderr, "gpio: %i: no such port\n", p);
-       exit(1);
-    }
+    if((rp = mappin(p)) < 0)
+       errx(1, "%i: no such port\n", p);
     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")) {
     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(preserve)
+           errx(2, "gpio%i: not set to output", rp);
        if((fp = fopen(path, "w")) == NULL)
            err(1, "%s", path);
        fprintf(fp, "out\n"); fflush(fp);
        if((fp = fopen(path, "w")) == NULL)
            err(1, "%s", path);
        fprintf(fp, "out\n"); fflush(fp);
@@ -59,7 +85,7 @@ static void setport(int p, int v)
 
 static void usage(FILE *out)
 {
 
 static void usage(FILE *out)
 {
-    fprintf(out, "usage: gpio [-hi] PORT=VAL...\n");
+    fprintf(out, "usage: gpio [-hip] PORT=VAL...\n");
 }
 
 int main(int argc, char **argv)
 }
 
 int main(int argc, char **argv)
@@ -67,7 +93,7 @@ int main(int argc, char **argv)
     int c, i, port, val;
     char *p, *e;
     
     int c, i, port, val;
     char *p, *e;
     
-    while((c = getopt(argc, argv, "hi")) >= 0) {
+    while((c = getopt(argc, argv, "hip")) >= 0) {
        switch(c) {
        case 'h':
            usage(stdout);
        switch(c) {
        case 'h':
            usage(stdout);
@@ -76,6 +102,9 @@ int main(int argc, char **argv)
            umap = imap;
            mapn = sizeof(imap) / sizeof(*imap);
            break;
            umap = imap;
            mapn = sizeof(imap) / sizeof(*imap);
            break;
+       case 'p':
+           preserve = 1;
+           break;
        default:
            usage(stderr);
            return(1);
        default:
            usage(stderr);
            return(1);
@@ -100,6 +129,7 @@ int main(int argc, char **argv)
            fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
            exit(1);
        }
            fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
            exit(1);
        }
+       export(port);
        setport(port, val);
     }
     return(0);
        setport(port, val);
     }
     return(0);