summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2004-06-03 19:13:25 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2004-06-03 19:13:25 +0000
commit8f6044f76d552ae6611ae890f08afbadc2511a15 (patch)
treec4ba6c7bbe2f19050af9fef53e90cb190b527aba
parent358a087edc42851bcd9fa6f72ba0a78dbde8f2c2 (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/Makefile22
-rw-r--r--usr.sbin/gpioctl/gpioctl.8160
-rw-r--r--usr.sbin/gpioctl/gpioctl.c231
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);
+}