Home | History | Annotate | Line # | Download | only in gpioctl
gpioctl.c revision 1.3
      1 /* $NetBSD: gpioctl.c,v 1.3 2008/01/09 15:57:06 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 const 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, "iiout" },
     61 	{ 0, NULL },
     62 };
     63 
     64 int
     65 main(int argc, char *argv[])
     66 {
     67 	int ch;
     68 	char *ep;
     69 	int do_ctl = 0;
     70 	int pin = 0, value = 0;
     71 
     72 	while ((ch = getopt(argc, argv, "cd:hq")) != -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 		case 'h':
     84 		case '?':
     85 		default:
     86 			usage();
     87 			/* NOTREACHED */
     88 		}
     89 	argc -= optind;
     90 	argv += optind;
     91 
     92 	if (argc > 0) {
     93 		pin = strtol(argv[0], &ep, 10);
     94 		if (*argv[0] == '\0' || *ep != '\0' || pin < 0)
     95 			errx(1, "%s: invalid pin", argv[0]);
     96 	}
     97 
     98 	if ((devfd = open(device, O_RDWR)) == -1)
     99 		err(1, "%s", device);
    100 
    101 	if (argc == 0 && !do_ctl) {
    102 		getinfo();
    103 	} else if (argc == 1) {
    104 		if (do_ctl)
    105 			pinctl(pin, NULL, 0);
    106 		else
    107 			pinread(pin);
    108 	} else if (argc > 1) {
    109 		if (do_ctl) {
    110 			pinctl(pin, argv + 1, argc - 1);
    111 		} else {
    112 			value = strtol(argv[1], &ep, 10);
    113 			if (*argv[1] == '\0' || *ep != '\0')
    114 				errx(1, "%s: invalid value", argv[1]);
    115 			pinwrite(pin, value);
    116 		}
    117 	} else {
    118 		usage();
    119 		/* NOTREACHED */
    120 	}
    121 
    122 	return (0);
    123 }
    124 
    125 void
    126 getinfo(void)
    127 {
    128 	struct gpio_info info;
    129 
    130 	bzero(&info, sizeof(info));
    131 	if (ioctl(devfd, GPIOINFO, &info) == -1)
    132 		err(1, "GPIOINFO");
    133 
    134 	if (quiet)
    135 		return;
    136 
    137 	printf("%s: %d pins\n", device, info.gpio_npins);
    138 }
    139 
    140 void
    141 pinread(int pin)
    142 {
    143 	struct gpio_pin_op op;
    144 
    145 	bzero(&op, sizeof(op));
    146 	op.gp_pin = pin;
    147 	if (ioctl(devfd, GPIOPINREAD, &op) == -1)
    148 		err(1, "GPIOPINREAD");
    149 
    150 	if (quiet)
    151 		return;
    152 
    153 	printf("pin %d: state %d\n", pin, op.gp_value);
    154 }
    155 
    156 void
    157 pinwrite(int pin, int value)
    158 {
    159 	struct gpio_pin_op op;
    160 
    161 	if (value < 0 || value > 2)
    162 		errx(1, "%d: invalid value", value);
    163 
    164 	bzero(&op, sizeof(op));
    165 	op.gp_pin = pin;
    166 	op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH);
    167 	if (value < 2) {
    168 		if (ioctl(devfd, GPIOPINWRITE, &op) == -1)
    169 			err(1, "GPIOPINWRITE");
    170 	} else {
    171 		if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1)
    172 			err(1, "GPIOPINTOGGLE");
    173 	}
    174 
    175 	if (quiet)
    176 		return;
    177 
    178 	printf("pin %d: state %d -> %d\n", pin, op.gp_value,
    179 	    (value < 2 ? value : 1 - op.gp_value));
    180 }
    181 
    182 void
    183 pinctl(int pin, char *flags[], int nflags)
    184 {
    185 	struct gpio_pin_ctl ctl;
    186 	int fl = 0;
    187 	const struct bitstr *bs;
    188 	int i;
    189 
    190 	bzero(&ctl, sizeof(ctl));
    191 	ctl.gp_pin = pin;
    192 	if (flags != NULL) {
    193 		for (i = 0; i < nflags; i++)
    194 			for (bs = pinflags; bs->string != NULL; bs++)
    195 				if (strcmp(flags[i], bs->string) == 0) {
    196 					fl |= bs->mask;
    197 					break;
    198 				}
    199 	}
    200 	ctl.gp_flags = fl;
    201 	if (ioctl(devfd, GPIOPINCTL, &ctl) == -1)
    202 		err(1, "GPIOPINCTL");
    203 
    204 	if (quiet)
    205 		return;
    206 
    207 	printf("pin %d: caps:", pin);
    208 	for (bs = pinflags; bs->string != NULL; bs++)
    209 		if (ctl.gp_caps & bs->mask)
    210 			printf(" %s", bs->string);
    211 	printf(", flags:");
    212 	for (bs = pinflags; bs->string != NULL; bs++)
    213 		if (ctl.gp_flags & bs->mask)
    214 			printf(" %s", bs->string);
    215 	if (fl > 0) {
    216 		printf(" ->");
    217 		for (bs = pinflags; bs->string != NULL; bs++)
    218 			if (fl & bs->mask)
    219 				printf(" %s", bs->string);
    220 	}
    221 	printf("\n");
    222 }
    223 
    224 void
    225 usage(void)
    226 {
    227 	extern char *__progname;
    228 
    229 	fprintf(stderr, "usage: %s [-hq] [-d device] [pin] [0 | 1 | 2]\n",
    230 	    __progname);
    231 	fprintf(stderr, "       %s [-hq] [-d device] -c pin [flags]\n",
    232 	    __progname);
    233 
    234 	exit(1);
    235 }
    236