2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
47 static struct flag_desc gpio_flags[] = {
48 { "IN", GPIO_PIN_INPUT },
49 { "OUT", GPIO_PIN_OUTPUT },
50 { "OD", GPIO_PIN_OPENDRAIN },
51 { "PP", GPIO_PIN_PUSHPULL },
52 { "TS", GPIO_PIN_TRISTATE },
53 { "PU", GPIO_PIN_PULLUP },
54 { "PD", GPIO_PIN_PULLDOWN },
55 { "II", GPIO_PIN_INVIN },
56 { "IO", GPIO_PIN_INVOUT },
57 { "PULSE", GPIO_PIN_PULSATE },
61 int str2cap(const char *str);
66 fprintf(stderr, "Usage:\n");
67 fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n");
68 fprintf(stderr, "\tgpioctl [-f ctldev] -t pin\n");
69 fprintf(stderr, "\tgpioctl [-f ctldev] -c pin flag ...\n");
70 fprintf(stderr, "\tgpioctl [-f ctldev] pin [0|1]\n");
77 struct flag_desc * pdesc = gpio_flags;
79 if (pdesc->flag == cap)
88 str2cap(const char *str)
90 struct flag_desc * pdesc = gpio_flags;
92 if (strcasecmp(str, pdesc->name) == 0)
101 * Our handmade function for converting string to number
104 str2int(const char *s, int *ok)
107 int res = strtod(s, &endptr);
108 if (endptr != s + strlen(s) )
123 for (i = 0; i < 32; i++) {
124 if (caps & (1 << i)) {
127 printf("%s", cap2str(1 << i));
135 dump_pins(int fd, int verbose)
141 if (ioctl(fd, GPIOMAXPIN, &maxpin) < 0) {
142 perror("ioctl(GPIOMAXPIN)");
146 for (i = 0; i <= maxpin; i++) {
148 if (ioctl(fd, GPIOGETCONFIG, &pin) < 0)
149 /* For some reason this pin is inaccessible */
153 if (ioctl(fd, GPIOGET, &req) < 0) {
154 /* Now, that's wrong */
155 perror("ioctl(GPIOGET)");
159 printf("pin %02d:\t%d\t%s", pin.gp_pin, req.gp_value,
162 print_caps(pin.gp_flags);
166 print_caps(pin.gp_caps);
173 fail(const char *fmt, ...)
178 vfprintf(stderr, fmt, ap);
184 main(int argc, char **argv)
189 char defctlfile[] = _PATH_DEVGPIOC "0";
190 char *ctlfile = NULL;
191 int pinn, pinv, fd, ch;
193 int config, toggle, verbose, list;
195 config = toggle = verbose = list = pinn = 0;
197 while ((ch = getopt(argc, argv, "c:f:lt:v")) != -1) {
201 pinn = str2int(optarg, &ok);
203 fail("Invalid pin number: %s\n", optarg);
213 pinn = str2int(optarg, &ok);
215 fail("Invalid pin number: %s\n", optarg);
227 for (i = 0; i < argc; i++)
228 printf("%d/%s\n", i, argv[i]);
231 ctlfile = defctlfile;
233 fd = open(ctlfile, O_RDONLY);
240 dump_pins(fd, verbose);
247 * -t pin assumes no additional arguments
255 if (ioctl(fd, GPIOTOGGLE, &req) < 0) {
256 perror("ioctl(GPIOTOGGLE)");
266 for (i = 0; i < argc; i++) {
267 flag = str2cap(argv[i]);
269 fail("Invalid flag: %s\n", argv[i]);
274 pin.gp_flags = flags;
275 if (ioctl(fd, GPIOSETCONFIG, &pin) < 0) {
276 perror("ioctl(GPIOSETCONFIG)");
284 * Last two cases - set value or print value
286 if ((argc == 0) || (argc > 2)) {
291 pinn = str2int(argv[0], &ok);
293 fail("Invalid pin number: %s\n", argv[0]);
300 if (ioctl(fd, GPIOGET, &req) < 0) {
301 perror("ioctl(GPIOGET)");
304 printf("%d\n", req.gp_value);
308 /* Is it valid number (0 or 1) ? */
309 pinv = str2int(argv[1], &ok);
310 if (!ok || ((pinv != 0) && (pinv != 1)))
311 fail("Invalid pin value: %s\n", argv[1]);
318 if (ioctl(fd, GPIOSET, &req) < 0) {
319 perror("ioctl(GPIOSET)");