summaryrefslogtreecommitdiff
path: root/usr.sbin/gpioctl/gpioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/gpioctl/gpioctl.c')
-rw-r--r--usr.sbin/gpioctl/gpioctl.c231
1 files changed, 231 insertions, 0 deletions
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);
+}