Home | History | Annotate | Line # | Download | only in gpioctl
gpioctl.c revision 1.4
      1 /* $NetBSD: gpioctl.c,v 1.4 2008/01/09 16:06:21 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 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 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 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