gpioctl.c revision 1.1
1/*	$OpenBSD: gpioctl.c,v 1.1 2004/06/03 19:13:24 grange 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
26#include <err.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32
33#define _PATH_DEV_GPIO	"/dev/gpio0"
34
35char *device = _PATH_DEV_GPIO;
36int devfd = -1;
37int quiet = 0;
38
39void	getinfo(void);
40void	pinread(int);
41void	pinwrite(int, int);
42void	pinctl(int, char *[], int);
43
44__dead void usage(void);
45
46const 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	{ 0, NULL },
58};
59
60int
61main(int argc, char *argv[])
62{
63	int ch;
64	char *ep;
65	int do_ctl = 0;
66	int pin = 0, value = 0;
67
68	while ((ch = getopt(argc, argv, "cd:hq")) != -1)
69		switch (ch) {
70		case 'c':
71			do_ctl = 1;
72			break;
73		case 'd':
74			device = optarg;
75			break;
76		case 'q':
77			quiet = 1;
78			break;
79		case 'h':
80		case '?':
81		default:
82			usage();
83			/* NOTREACHED */
84		}
85	argc -= optind;
86	argv += optind;
87
88	if (argc > 0) {
89		pin = strtol(argv[0], &ep, 10);
90		if (*argv[0] == '\0' || *ep != '\0' || pin < 0)
91			errx(1, "%s: invalid pin", argv[0]);
92	}
93
94	if ((devfd = open(device, O_RDWR)) == -1)
95		err(1, "%s", device);
96
97	if (argc == 0 && !do_ctl) {
98		getinfo();
99	} else if (argc == 1) {
100		if (do_ctl)
101			pinctl(pin, NULL, 0);
102		else
103			pinread(pin);
104	} else if (argc > 1) {
105		if (do_ctl) {
106			pinctl(pin, argv + 1, argc - 1);
107		} else {
108			value = strtol(argv[1], &ep, 10);
109			if (*argv[1] == '\0' || *ep != '\0')
110				errx(1, "%s: invalid value", argv[1]);
111			pinwrite(pin, value);
112		}
113	} else {
114		usage();
115		/* NOTREACHED */
116	}
117
118	return (0);
119}
120
121void
122getinfo(void)
123{
124	struct gpio_info info;
125
126	bzero(&info, sizeof(info));
127	if (ioctl(devfd, GPIOINFO, &info) == -1)
128		err(1, "GPIOINFO");
129
130	if (quiet)
131		return;
132
133	printf("%s: %d pins\n", device, info.gpio_npins);
134}
135
136void
137pinread(int pin)
138{
139	struct gpio_pin_op op;
140
141	bzero(&op, sizeof(op));
142	op.gp_pin = pin;
143	if (ioctl(devfd, GPIOPINREAD, &op) == -1)
144		err(1, "GPIOPINREAD");
145
146	if (quiet)
147		return;
148
149	printf("pin %d: state %d\n", pin, op.gp_value);
150}
151
152void
153pinwrite(int pin, int value)
154{
155	struct gpio_pin_op op;
156
157	if (value < 0 || value > 2)
158		errx(1, "%d: invalid value", value);
159
160	bzero(&op, sizeof(op));
161	op.gp_pin = pin;
162	op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH);
163	if (value < 2) {
164		if (ioctl(devfd, GPIOPINWRITE, &op) == -1)
165			err(1, "GPIOPINWRITE");
166	} else {
167		if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1)
168			err(1, "GPIOPINTOGGLE");
169	}
170
171	if (quiet)
172		return;
173
174	printf("pin %d: state %d -> %d\n", pin, op.gp_value,
175	    (value < 2 ? value : 1 - op.gp_value));
176}
177
178void
179pinctl(int pin, char *flags[], int nflags)
180{
181	struct gpio_pin_ctl ctl;
182	int fl = 0;
183	const struct bitstr *bs;
184	int i;
185
186	bzero(&ctl, sizeof(ctl));
187	ctl.gp_pin = pin;
188	if (flags != NULL) {
189		for (i = 0; i < nflags; i++)
190			for (bs = pinflags; bs->string != NULL; bs++)
191				if (strcmp(flags[i], bs->string) == 0) {
192					fl |= bs->mask;
193					break;
194				}
195	}
196	ctl.gp_flags = fl;
197	if (ioctl(devfd, GPIOPINCTL, &ctl) == -1)
198		err(1, "GPIOPINCTL");
199
200	if (quiet)
201		return;
202
203	printf("pin %d: caps:", pin);
204	for (bs = pinflags; bs->string != NULL; bs++)
205		if (ctl.gp_caps & bs->mask)
206			printf(" %s", bs->string);
207	printf(", flags:");
208	for (bs = pinflags; bs->string != NULL; bs++)
209		if (ctl.gp_flags & bs->mask)
210			printf(" %s", bs->string);
211	if (fl > 0) {
212		printf(" ->");
213		for (bs = pinflags; bs->string != NULL; bs++)
214			if (fl & bs->mask)
215				printf(" %s", bs->string);
216	}
217	printf("\n");
218}
219
220void
221usage(void)
222{
223	extern char *__progname;
224
225	fprintf(stderr, "usage:\t%s [-hq] [-d device] [pin] [0 | 1 | 2]\n",
226	    __progname);
227	fprintf(stderr, "\t%s [-hq] [-d device] -c pin [flags]\n",
228	    __progname);
229
230	exit(1);
231}
232