gpio: Added port-number mapping.
[utils.git] / gpio.c
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <err.h>
8
9 static const int bmap[] = {
10     -1,
11     -1, -1,  2, -1,  3, -1,  4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1,
12      9, 25, 11,  8, -1,  7, -1, -1,  5, -1,  6, 12, 13, -1, 19, 16, 21, 20, -1, 21,
13 };
14 static const int imap[] = {
15     -1, -1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
16     14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, 27,
17 };
18 static const int *umap = bmap;
19 static int mapn = sizeof(bmap) / sizeof(*bmap);
20
21 static int mappin(int num)
22 {
23     if((num < 0) || (num >= mapn))
24         return(-1);
25     return(umap[num]);
26 }
27
28 static void setport(int p, int v)
29 {
30     char path[256], line[256];
31     FILE *fp;
32     int rv, rp;
33     
34     if((rp = mappin(p)) < 0) {
35         fprintf(stderr, "gpio: %i: no such port\n", p);
36         exit(1);
37     }
38     sprintf(path, "/sys/class/gpio/gpio%i/direction", rp);
39     if((fp = fopen(path, "r")) == NULL)
40         err(1, "%s", path);
41     rv = !!fgets(line, sizeof(line), fp);
42     fclose(fp);
43     if(!rv || strcmp(line, "out\n")) {
44         if((fp = fopen(path, "w")) == NULL)
45             err(1, "%s", path);
46         fprintf(fp, "out\n"); fflush(fp);
47         if(ferror(fp))
48             errx(1, "gpio%i: could not set to output", rp);
49         fclose(fp);
50     }
51     sprintf(path, "/sys/class/gpio/gpio%i/value", rp);
52     if((fp = fopen(path, "w")) == NULL)
53         err(1, "%s", path);
54     fprintf(fp, "%i\n", v); fflush(fp);
55     if(ferror(fp))
56         errx(1, "gpio%i: could not set value", rp);
57     fclose(fp);
58 }
59
60 static void usage(FILE *out)
61 {
62     fprintf(out, "usage: gpio [-hi] PORT=VAL...\n");
63 }
64
65 int main(int argc, char **argv)
66 {
67     int c, i, port, val;
68     char *p, *e;
69     
70     while((c = getopt(argc, argv, "hi")) >= 0) {
71         switch(c) {
72         case 'h':
73             usage(stdout);
74             return(0);
75         case 'i':
76             umap = imap;
77             mapn = sizeof(imap) / sizeof(*imap);
78             break;
79         default:
80             usage(stderr);
81             return(1);
82         }
83     }
84     if(optind >= argc) {
85         usage(stderr);
86         return(1);
87     }
88     for(i = optind; i < argc; i++) {
89         if((p = strchr(argv[i], '=')) == NULL) {
90             fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
91             exit(1);
92         }
93         port = strtol(argv[i], &e, 10);
94         if(e != p) {
95             fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
96             exit(1);
97         }
98         val = strtol(p + 1, &e, 10);
99         if(*e) {
100             fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
101             exit(1);
102         }
103         setport(port, val);
104     }
105     return(0);
106 }
107
108 /*
109  * Local Variables:
110  * compile-command: "gcc -Wall -g -O2 -march=native -o gpio gpio.c"
111  * End:
112  */