gpio: Auto-export ports.
[utils.git] / gpio.c
CommitLineData
35647167
FT
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
cc450aa9
FT
9static 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};
14static 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};
18static const int *umap = bmap;
19static int mapn = sizeof(bmap) / sizeof(*bmap);
7243cbb2 20static int preserve = 0;
cc450aa9
FT
21
22static int mappin(int num)
23{
24 if((num < 0) || (num >= mapn))
25 return(-1);
26 return(umap[num]);
27}
28
7243cbb2
FT
29static void export(int p)
30{
31 char path[256];
32 FILE *fp;
33 int rp;
34
35 if((rp = mappin(p)) < 0)
36 errx(1, "%i: no such port\n", p);
37 sprintf(path, "/sys/class/gpio/gpio%i", rp);
38 if(!access(path, R_OK | X_OK))
39 return;
40 if(preserve)
41 errx(2, "gpio%i: not exported", rp);
42 sprintf(path, "/sys/class/gpio/export");
43 if((fp = fopen(path, "w")) == NULL)
44 err(1, "%s", path);
45 fprintf(fp, "%i\n", rp); fflush(fp);
46 if(ferror(fp))
47 errx(1, "gpio%i: could not export", rp);
48 fclose(fp);
49 sprintf(path, "/sys/class/gpio/gpio%i", rp);
50 if(access(path, R_OK | X_OK))
51 errx(1, "gpio%i: still not available after export", rp);
52}
53
35647167
FT
54static void setport(int p, int v)
55{
56 char path[256], line[256];
57 FILE *fp;
cc450aa9 58 int rv, rp;
35647167 59
7243cbb2
FT
60 if((rp = mappin(p)) < 0)
61 errx(1, "%i: no such port\n", p);
cc450aa9 62 sprintf(path, "/sys/class/gpio/gpio%i/direction", rp);
35647167
FT
63 if((fp = fopen(path, "r")) == NULL)
64 err(1, "%s", path);
65 rv = !!fgets(line, sizeof(line), fp);
66 fclose(fp);
67 if(!rv || strcmp(line, "out\n")) {
7243cbb2
FT
68 if(preserve)
69 errx(2, "gpio%i: not set to output", rp);
35647167
FT
70 if((fp = fopen(path, "w")) == NULL)
71 err(1, "%s", path);
72 fprintf(fp, "out\n"); fflush(fp);
73 if(ferror(fp))
cc450aa9 74 errx(1, "gpio%i: could not set to output", rp);
35647167
FT
75 fclose(fp);
76 }
cc450aa9 77 sprintf(path, "/sys/class/gpio/gpio%i/value", rp);
35647167
FT
78 if((fp = fopen(path, "w")) == NULL)
79 err(1, "%s", path);
80 fprintf(fp, "%i\n", v); fflush(fp);
81 if(ferror(fp))
cc450aa9 82 errx(1, "gpio%i: could not set value", rp);
35647167
FT
83 fclose(fp);
84}
85
cc450aa9
FT
86static void usage(FILE *out)
87{
7243cbb2 88 fprintf(out, "usage: gpio [-hip] PORT=VAL...\n");
cc450aa9
FT
89}
90
35647167
FT
91int main(int argc, char **argv)
92{
cc450aa9 93 int c, i, port, val;
35647167
FT
94 char *p, *e;
95
7243cbb2 96 while((c = getopt(argc, argv, "hip")) >= 0) {
cc450aa9
FT
97 switch(c) {
98 case 'h':
99 usage(stdout);
100 return(0);
101 case 'i':
102 umap = imap;
103 mapn = sizeof(imap) / sizeof(*imap);
104 break;
7243cbb2
FT
105 case 'p':
106 preserve = 1;
107 break;
cc450aa9
FT
108 default:
109 usage(stderr);
110 return(1);
111 }
112 }
113 if(optind >= argc) {
114 usage(stderr);
115 return(1);
116 }
117 for(i = optind; i < argc; i++) {
35647167
FT
118 if((p = strchr(argv[i], '=')) == NULL) {
119 fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
120 exit(1);
121 }
122 port = strtol(argv[i], &e, 10);
123 if(e != p) {
124 fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
125 exit(1);
126 }
127 val = strtol(p + 1, &e, 10);
128 if(*e) {
129 fprintf(stderr, "gpio: %s: not of the form PORT=VAL\n", argv[i]);
130 exit(1);
131 }
7243cbb2 132 export(port);
35647167
FT
133 setport(port, val);
134 }
135 return(0);
136}
cc450aa9
FT
137
138/*
139 * Local Variables:
140 * compile-command: "gcc -Wall -g -O2 -march=native -o gpio gpio.c"
141 * End:
142 */