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