gpioctl.c revision 1.5 1 /* $NetBSD: gpioctl.c,v 1.5 2008/01/09 16:08:33 xtraeme Exp $ */
2 /* $OpenBSD: gpioctl.c,v 1.2 2004/08/08 00:05:09 deraadt Exp $ */
3 /*
4 * Copyright (c) 2004 Alexander Yurchenko <grange (at) openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * Program to control GPIO devices.
21 */
22
23 #include <sys/types.h>
24 #include <sys/gpio.h>
25 #include <sys/ioctl.h>
26
27 #include <err.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #define _PATH_DEV_GPIO "/dev/gpio0"
35
36 static const char *device = _PATH_DEV_GPIO;
37 static int devfd = -1;
38 static int quiet = 0;
39
40 static void getinfo(void);
41 static void pinread(int);
42 static void pinwrite(int, int);
43 static void pinctl(int, char *[], int);
44 static void usage(void);
45
46 static const struct bitstr {
47 unsigned int mask;
48 const char *string;
49 } pinflags[] = {
50 { GPIO_PIN_INPUT, "in" },
51 { GPIO_PIN_OUTPUT, "out" },
52 { GPIO_PIN_INOUT, "inout" },
53 { GPIO_PIN_OPENDRAIN, "od" },
54 { GPIO_PIN_PUSHPULL, "pp" },
55 { GPIO_PIN_TRISTATE, "tri" },
56 { GPIO_PIN_PULLUP, "pu" },
57 { GPIO_PIN_PULLDOWN, "pd" },
58 { GPIO_PIN_INVIN, "iin" },
59 { GPIO_PIN_INVOUT, "iiout" },
60 { 0, NULL },
61 };
62
63 int
64 main(int argc, char *argv[])
65 {
66 int ch;
67 char *ep;
68 int do_ctl = 0;
69 int pin = 0, value = 0;
70
71 setprogname(argv[0]);
72
73 while ((ch = getopt(argc, argv, "cd:hq")) != -1)
74 switch (ch) {
75 case 'c':
76 do_ctl = 1;
77 break;
78 case 'd':
79 device = optarg;
80 break;
81 case 'q':
82 quiet = 1;
83 break;
84 case 'h':
85 case '?':
86 default:
87 usage();
88 /* NOTREACHED */
89 }
90 argc -= optind;
91 argv += optind;
92
93 if (argc > 0) {
94 pin = strtol(argv[0], &ep, 10);
95 if (*argv[0] == '\0' || *ep != '\0' || pin < 0)
96 errx(EXIT_FAILURE, "%s: invalid pin", argv[0]);
97 }
98
99 if ((devfd = open(device, O_RDWR)) == -1)
100 err(EXIT_FAILURE, "%s", device);
101
102 if (argc == 0 && !do_ctl) {
103 getinfo();
104 } else if (argc == 1) {
105 if (do_ctl)
106 pinctl(pin, NULL, 0);
107 else
108 pinread(pin);
109 } else if (argc > 1) {
110 if (do_ctl) {
111 pinctl(pin, argv + 1, argc - 1);
112 } else {
113 value = strtol(argv[1], &ep, 10);
114 if (*argv[1] == '\0' || *ep != '\0')
115 errx(EXIT_FAILURE, "%s: invalid value",
116 argv[1]);
117 pinwrite(pin, value);
118 }
119 } else {
120 usage();
121 /* NOTREACHED */
122 }
123
124 return EXIT_SUCCESS;
125 }
126
127 static void
128 getinfo(void)
129 {
130 struct gpio_info info;
131
132 memset(&info, 0, sizeof(info));
133 if (ioctl(devfd, GPIOINFO, &info) == -1)
134 err(EXIT_FAILURE, "GPIOINFO");
135
136 if (quiet)
137 return;
138
139 printf("%s: %d pins\n", device, info.gpio_npins);
140 }
141
142 static void
143 pinread(int pin)
144 {
145 struct gpio_pin_op op;
146
147 memset(&op, 0, sizeof(op));
148 op.gp_pin = pin;
149 if (ioctl(devfd, GPIOPINREAD, &op) == -1)
150 err(EXIT_FAILURE, "GPIOPINREAD");
151
152 if (quiet)
153 return;
154
155 printf("pin %d: state %d\n", pin, op.gp_value);
156 }
157
158 static void
159 pinwrite(int pin, int value)
160 {
161 struct gpio_pin_op op;
162
163 if (value < 0 || value > 2)
164 errx(EXIT_FAILURE, "%d: invalid value", value);
165
166 memset(&op, 0, sizeof(op));
167 op.gp_pin = pin;
168 op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH);
169 if (value < 2) {
170 if (ioctl(devfd, GPIOPINWRITE, &op) == -1)
171 err(EXIT_FAILURE, "GPIOPINWRITE");
172 } else {
173 if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1)
174 err(EXIT_FAILURE, "GPIOPINTOGGLE");
175 }
176
177 if (quiet)
178 return;
179
180 printf("pin %d: state %d -> %d\n", pin, op.gp_value,
181 (value < 2 ? value : 1 - op.gp_value));
182 }
183
184 static void
185 pinctl(int pin, char *flags[], int nflags)
186 {
187 struct gpio_pin_ctl ctl;
188 int fl = 0;
189 const struct bitstr *bs;
190 int i;
191
192 memset(&ctl, 0, sizeof(ctl));
193 ctl.gp_pin = pin;
194 if (flags != NULL) {
195 for (i = 0; i < nflags; i++)
196 for (bs = pinflags; bs->string != NULL; bs++)
197 if (strcmp(flags[i], bs->string) == 0) {
198 fl |= bs->mask;
199 break;
200 }
201 }
202 ctl.gp_flags = fl;
203 if (ioctl(devfd, GPIOPINCTL, &ctl) == -1)
204 err(EXIT_FAILURE, "GPIOPINCTL");
205
206 if (quiet)
207 return;
208
209 printf("pin %d: caps:", pin);
210 for (bs = pinflags; bs->string != NULL; bs++)
211 if (ctl.gp_caps & bs->mask)
212 printf(" %s", bs->string);
213 printf(", flags:");
214 for (bs = pinflags; bs->string != NULL; bs++)
215 if (ctl.gp_flags & bs->mask)
216 printf(" %s", bs->string);
217 if (fl > 0) {
218 printf(" ->");
219 for (bs = pinflags; bs->string != NULL; bs++)
220 if (fl & bs->mask)
221 printf(" %s", bs->string);
222 }
223 printf("\n");
224 }
225
226 static void
227 usage(void)
228 {
229 fprintf(stderr, "usage: %s [-hq] [-d device] [pin] [0 | 1 | 2]\n",
230 getprogname());
231 fprintf(stderr, " %s [-hq] [-d device] -c pin [flags]\n",
232 getprogname());
233
234 exit(EXIT_FAILURE);
235 }
236