diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2004-06-03 19:13:25 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2004-06-03 19:13:25 +0000 |
commit | 8f6044f76d552ae6611ae890f08afbadc2511a15 (patch) | |
tree | c4ba6c7bbe2f19050af9fef53e90cb190b527aba | |
parent | 358a087edc42851bcd9fa6f72ba0a78dbde8f2c2 (diff) |
gpioctl -- program to control GPIO devices.
The gpioctl program allows to manipulate GPIO devices pins
Quick start for the Soekris net4801 users:
# gpioctl -c 20 out pp
# gpioctl 20 1
This will turn on the red error led.
If you want to use JP5 I/O pins, just use the /dev/gpio1 device.
Quick start for the PC Engines WRAP.1C users:
# gpioctl 40
This will read the state of the button (0 means pressed).
# gpioctl -c 2 pp out
This will turn the first led on, to turn off write 1 to the pin,
it's reversed. For the second and the third leds use pins 3 and 18.
ok deraadt@
-rw-r--r-- | usr.sbin/gpioctl/Makefile | 22 | ||||
-rw-r--r-- | usr.sbin/gpioctl/gpioctl.8 | 160 | ||||
-rw-r--r-- | usr.sbin/gpioctl/gpioctl.c | 231 |
3 files changed, 413 insertions, 0 deletions
diff --git a/usr.sbin/gpioctl/Makefile b/usr.sbin/gpioctl/Makefile new file mode 100644 index 00000000000..2f260c9d775 --- /dev/null +++ b/usr.sbin/gpioctl/Makefile @@ -0,0 +1,22 @@ +# $OpenBSD: Makefile,v 1.1 2004/06/03 19:13:24 grange Exp $ + +.if ${MACHINE} == "i386" + +PROG= gpioctl +SRCS= gpioctl.c + +CFLAGS+=-Wall +CFLAGS+=-Wstrict-prototypes -Wmissing-prototypes +CLFAGS+=-Wmissing-declarations -Wredundant-decls +CFLAGS+=-Wshadow -Wpointer-arith -Wcast-qual + +.else + +NOPROG= yes + +.endif + +MAN= gpioctl.8 +MANSUBDIR=i386 + +.include <bsd.prog.mk> diff --git a/usr.sbin/gpioctl/gpioctl.8 b/usr.sbin/gpioctl/gpioctl.8 new file mode 100644 index 00000000000..7bb7a507737 --- /dev/null +++ b/usr.sbin/gpioctl/gpioctl.8 @@ -0,0 +1,160 @@ +.\" $OpenBSD: gpioctl.8,v 1.1 2004/06/03 19:13:24 grange Exp $ +.\" +.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd May 3, 2004 +.Dt GPIOCTL 8 +.Os +.Sh NAME +.Nm gpioctl +.Nd control GPIO devices +.Sh SYNOPSIS +.Nm gpioctl +.Op Fl hq +.Op Fl d Ar device +.Op Ar pin +.Op Ar 0 | Ar 1 | Ar 2 +.Nm gpioctl +.Op Fl hq +.Op Fl d Ar device +.Fl c +.Ar pin +.Op Ar flags +.Sh DESCRIPTION +The +.Nm +program allows to manipulate +.Tn GPIO +(General Purpose Input/Output) devices pins. +Such devices can be either part of the chipset or embedded +.Tn CPU , +or the separate chip. +The usual way of using +.Tn GPIO +is to connect some simple devices such as leds, 1-wire termal sensors, +etc to its pins. +.Pp +Each +.Tn GPIO +device has associated device file in the +.Pa /dev +directory. +By default +.Nm +uses file +.Pa /dev/gpio0 +which corresponds to the first found +.Tn GPIO +device in the system. +If more than one +.Tn GPIO +devices present alternative device file can be specified with the +.Fl d +option +in order to access particular +.Tn GPIO +device. +.Pp +When executed without any arguments +.Nm +program reads information about the +.Tn GPIO +device and displays it. +.Pp +.Tn GPIO +pins can be either ``read'' or ``written'' with the values of +logical 0 or 1. +If only +.Ar pin +number is specified in the command line pin state will be read +from the +.Tn GPIO +controller and dispalyed. +To write to a pin a value must be specified after the +.Ar pin +number. +Values can be either 0 or 1. +Value of 2 has a special meaning to ``toggle'' the pin, i.e. change its +state to the opposite. +.Pp +Each pin can be configured with the different flags with the +.Fl c +option. +The following configuration flags are supported by the +.Tn GPIO +framework: +.Pp +.Bl -tag -width XXXXX -compact +.It in +input direction +.It out +output direction +.It inout +bi-directional +.It od +open-drain output +.It pp +push-pull output +.It tri +tri-state (output disabled) +.It pu +internal pull-up enabled +.El +.Pp +Note that not all the flags can be supported by the particular +.Tn GPIO +controller. +The list of supported flags is always displayed when executing +.Nm +program with the +.Fl c +option. +If only +.Ar pin +number is specified in the command line current pin flags will be +dispalyed. +To change pin flags new flags set separated with the spaces must be +specified after the +.Ar pin +number. +.Sh FILES +.Bl -tag -width "/dev/gpiou" -compact +.It /dev/gpio Ns Ar u +GPIO device unit +.Ar u +file. +.El +.Sh EXAMPLES +.Li # gpioctl -c 20 out pp +.Pp +Configures pin 20 to have push-pull output. +.Pp +.Li # gpioctl 20 1 +.Pp +Writes logical 1 to the pin 20. +.Sh SEE ALSO +.Xr gpio 4 , +.Xr gscpcib 4 , +.Xr nsclpcsio 4 +.Sh HISTORY +The +.Nm +command first appeared in +.Ox 3.6 . +.Sh AUTHORS +The +.Nm +program was written by +.An Alexander Yurchenko Aq grange@openbsd.org . diff --git a/usr.sbin/gpioctl/gpioctl.c b/usr.sbin/gpioctl/gpioctl.c new file mode 100644 index 00000000000..5962a34638e --- /dev/null +++ b/usr.sbin/gpioctl/gpioctl.c @@ -0,0 +1,231 @@ +/* $OpenBSD: gpioctl.c,v 1.1 2004/06/03 19:13:24 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Program to control GPIO devices. + */ + +#include <sys/types.h> +#include <sys/gpio.h> +#include <sys/ioctl.h> + +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define _PATH_DEV_GPIO "/dev/gpio0" + +char *device = _PATH_DEV_GPIO; +int devfd = -1; +int quiet = 0; + +void getinfo(void); +void pinread(int); +void pinwrite(int, int); +void pinctl(int, char *[], int); + +__dead void usage(void); + +const struct bitstr { + unsigned int mask; + const char *string; +} pinflags[] = { + { GPIO_PIN_INPUT, "in" }, + { GPIO_PIN_OUTPUT, "out" }, + { GPIO_PIN_INOUT, "inout" }, + { GPIO_PIN_OPENDRAIN, "od" }, + { GPIO_PIN_PUSHPULL, "pp" }, + { GPIO_PIN_TRISTATE, "tri" }, + { GPIO_PIN_PULLUP, "pu" }, + { 0, NULL }, +}; + +int +main(int argc, char *argv[]) +{ + int ch; + char *ep; + int do_ctl = 0; + int pin = 0, value = 0; + + while ((ch = getopt(argc, argv, "cd:hq")) != -1) + switch (ch) { + case 'c': + do_ctl = 1; + break; + case 'd': + device = optarg; + break; + case 'q': + quiet = 1; + break; + case 'h': + case '?': + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + if (argc > 0) { + pin = strtol(argv[0], &ep, 10); + if (*argv[0] == '\0' || *ep != '\0' || pin < 0) + errx(1, "%s: invalid pin", argv[0]); + } + + if ((devfd = open(device, O_RDWR)) == -1) + err(1, "%s", device); + + if (argc == 0 && !do_ctl) { + getinfo(); + } else if (argc == 1) { + if (do_ctl) + pinctl(pin, NULL, 0); + else + pinread(pin); + } else if (argc > 1) { + if (do_ctl) { + pinctl(pin, argv + 1, argc - 1); + } else { + value = strtol(argv[1], &ep, 10); + if (*argv[1] == '\0' || *ep != '\0') + errx(1, "%s: invalid value", argv[1]); + pinwrite(pin, value); + } + } else { + usage(); + /* NOTREACHED */ + } + + return (0); +} + +void +getinfo(void) +{ + struct gpio_info info; + + bzero(&info, sizeof(info)); + if (ioctl(devfd, GPIOINFO, &info) == -1) + err(1, "GPIOINFO"); + + if (quiet) + return; + + printf("%s: %d pins\n", device, info.gpio_npins); +} + +void +pinread(int pin) +{ + struct gpio_pin_op op; + + bzero(&op, sizeof(op)); + op.gp_pin = pin; + if (ioctl(devfd, GPIOPINREAD, &op) == -1) + err(1, "GPIOPINREAD"); + + if (quiet) + return; + + printf("pin %d: state %d\n", pin, op.gp_value); +} + +void +pinwrite(int pin, int value) +{ + struct gpio_pin_op op; + + if (value < 0 || value > 2) + errx(1, "%d: invalid value", value); + + bzero(&op, sizeof(op)); + op.gp_pin = pin; + op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH); + if (value < 2) { + if (ioctl(devfd, GPIOPINWRITE, &op) == -1) + err(1, "GPIOPINWRITE"); + } else { + if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1) + err(1, "GPIOPINTOGGLE"); + } + + if (quiet) + return; + + printf("pin %d: state %d -> %d\n", pin, op.gp_value, + (value < 2 ? value : 1 - op.gp_value)); +} + +void +pinctl(int pin, char *flags[], int nflags) +{ + struct gpio_pin_ctl ctl; + int fl = 0; + const struct bitstr *bs; + int i; + + bzero(&ctl, sizeof(ctl)); + ctl.gp_pin = pin; + if (flags != NULL) { + for (i = 0; i < nflags; i++) + for (bs = pinflags; bs->string != NULL; bs++) + if (strcmp(flags[i], bs->string) == 0) { + fl |= bs->mask; + break; + } + } + ctl.gp_flags = fl; + if (ioctl(devfd, GPIOPINCTL, &ctl) == -1) + err(1, "GPIOPINCTL"); + + if (quiet) + return; + + printf("pin %d: caps:", pin); + for (bs = pinflags; bs->string != NULL; bs++) + if (ctl.gp_caps & bs->mask) + printf(" %s", bs->string); + printf(", flags:"); + for (bs = pinflags; bs->string != NULL; bs++) + if (ctl.gp_flags & bs->mask) + printf(" %s", bs->string); + if (fl > 0) { + printf(" ->"); + for (bs = pinflags; bs->string != NULL; bs++) + if (fl & bs->mask) + printf(" %s", bs->string); + } + printf("\n"); +} + +void +usage(void) +{ + extern char *__progname; + + fprintf(stderr, "usage:\t%s [-hq] [-d device] [pin] [0 | 1 | 2]\n", + __progname); + fprintf(stderr, "\t%s [-hq] [-d device] -c pin [flags]\n", + __progname); + + exit(1); +} |