xref: /netbsd-src/usr.sbin/gpioctl/gpioctl.c (revision 404fbe5fb94ca1e054339640cabb2801ce52dd30)
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@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