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