Author: gonzo
Date: Tue Sep 28 03:28:20 2010
New Revision: 213238
URL: http://svn.freebsd.org/changeset/base/213238

Log:
  Add gpioctl(8). Utility for configuring/accessing GPIO pins

Added:
  head/usr.sbin/gpioctl/
  head/usr.sbin/gpioctl/Makefile   (contents, props changed)
  head/usr.sbin/gpioctl/gpioctl.8   (contents, props changed)
  head/usr.sbin/gpioctl/gpioctl.c   (contents, props changed)
Modified:
  head/usr.sbin/Makefile

Modified: head/usr.sbin/Makefile
==============================================================================
--- head/usr.sbin/Makefile      Tue Sep 28 03:24:53 2010        (r213237)
+++ head/usr.sbin/Makefile      Tue Sep 28 03:28:20 2010        (r213238)
@@ -27,6 +27,7 @@ SUBDIR= adduser \
        fwcontrol \
        getfmac \
        getpmac \
+       gpioctl \
        gstat \
        i2c \
        ifmcstat \

Added: head/usr.sbin/gpioctl/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/usr.sbin/gpioctl/Makefile      Tue Sep 28 03:28:20 2010        
(r213238)
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+PROG=  gpioctl
+MAN=   gpioctl.8
+
+.include <bsd.prog.mk>

Added: head/usr.sbin/gpioctl/gpioctl.8
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/usr.sbin/gpioctl/gpioctl.8     Tue Sep 28 03:28:20 2010        
(r213238)
@@ -0,0 +1,124 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 27, 2010
+.Dt GPIOCTL 1
+.Os
+.Sh NAME
+.Nm gpioctl
+.Nd GPIO control utility
+.Sh SYNOPSIS
+.Nm
+.Cm -l 
+.Fl f Ar ctldev
+.Op Fl v
+.Nm
+.Cm -t 
+.Fl f Ar ctldev
+.Ar pin
+.Nm
+.Cm -c 
+.Fl f Ar ctldev
+.Ar pin
+.Ar flag 
+.Op flag ...
+.Nm
+.Cm -f Ar ctldev 
+.Ar pin
+.Ar [0|1]
+.Sh DESCRIPTION
+The
+.Nm
+utility could be used to manage GPIO pins from userland and list available 
pins.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl f Ar ctldev"
+.It Fl c Ar pin Ar flag Op flag ...
+Configure pin by setting provided flags. The following flags are currently 
defined:
+.Bl -tag -offset indent -width ".Cm PULSE"
+.It Cm IN
+Input pin
+.It Cm OUT
+Output pin
+.It Cm OD
+Open drain pin
+.It Cm PP
+Push pull pin
+.It Cm TS
+Tristate pin
+.It Cm PU
+Pull-up pin
+.It Cm PD
+Pull-down pin
+.It Cm II
+Inverted input pin
+.It Cm IO
+Inverted output pin
+.El
+.It Fl f Ar ctldev
+GPIO controller device to use
+.It Fl l
+list available pins
+.It Fl t Ar pin
+toggle value of provided pin number
+.It Fl v
+be verbose: for each listed pin print current configuration
+.El
+.Sh EXAMPLES
+.Pp
+.Bl -bullet
+.It
+List pins available on GPIO controller defined by device /dev/gpioctl0
+.Pp
+gpioctl -f /dev/gpioctl0 -l
+.It
+Set the value of pin 12 to 1
+.Pp
+gpioctl -f /dev/gpioctl0 12 1
+.It
+Configure pin 12 to be input pin
+.Pp
+gpioctl -f /dev/gpioctl0 -c 12 IN
+.El
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility and this manual page were written by
+.An Oleksandr Tymoshenko
+.Aq go...@freebsd.org

Added: head/usr.sbin/gpioctl/gpioctl.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/usr.sbin/gpioctl/gpioctl.c     Tue Sep 28 03:28:20 2010        
(r213238)
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 2009, Oleksandr Tymoshenko <go...@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/gpio.h>
+
+struct flag_desc {
+       const char *name;
+       uint32_t flag;
+};
+
+struct flag_desc gpio_flags[] = {
+       { "IN", GPIO_PIN_INPUT },
+       { "OUT", GPIO_PIN_OUTPUT },
+       { "OD", GPIO_PIN_OPENDRAIN },
+       { "PP", GPIO_PIN_PUSHPULL },
+       { "TS", GPIO_PIN_TRISTATE },
+       { "PU", GPIO_PIN_PULLUP },
+       { "PD", GPIO_PIN_PULLDOWN },
+       { "II", GPIO_PIN_INVIN },
+       { "IO", GPIO_PIN_INVOUT },
+       { "PULSE", GPIO_PIN_PULSATE },
+       { NULL, 0 },
+};
+
+int str2cap(const char *str);
+
+static void
+usage(void)
+{
+       fprintf(stderr, "Usage:\n");
+       fprintf(stderr, "\tgpioctl -f ctldev -l [-v]\n");
+       fprintf(stderr, "\tgpioctl -f ctldev -t pin\n");
+       fprintf(stderr, "\tgpioctl -f ctldev -c pin flag ...\n");
+       fprintf(stderr, "\tgpioctl -f ctldev pin [0|1]\n");
+       exit(1);
+}
+
+static const char *
+cap2str(uint32_t cap)
+{
+       struct flag_desc * pdesc = gpio_flags;
+       while (pdesc->name) {
+               if (pdesc->flag == cap)
+                       return pdesc->name;
+               pdesc++;
+       }
+
+       return "UNKNOWN";
+}
+
+int
+str2cap(const char *str)
+{
+       struct flag_desc * pdesc = gpio_flags;
+       while (pdesc->name) {
+               if (strcasecmp(str, pdesc->name) == 0)
+                       return pdesc->flag;
+               pdesc++;
+       }
+
+       return (-1);
+}
+
+/*
+ * Our handmade function for converting string to number
+ */
+static int 
+str2int(const char *s, int *ok)
+{
+       char *endptr;
+       int res = strtod(s, &endptr);
+       if (endptr != s + strlen(s) )
+               *ok = 0;
+       else
+               *ok = 1;
+
+       return res;
+}
+
+static void
+print_caps(int caps)
+{
+       int i, need_coma;
+
+       need_coma = 0;
+       printf("<");
+       for (i = 0; i < 32; i++) {
+               if (caps & (1 << i)) {
+                       if (need_coma)
+                               printf(",");
+                       printf("%s", cap2str(1 << i));
+                       need_coma = 1;
+               }
+       }
+       printf(">");
+}
+
+static void
+dump_pins(int fd, int verbose)
+{
+       int i, maxpin;
+       struct gpio_pin pin;
+       struct gpio_req req;
+
+       if (ioctl(fd, GPIOMAXPIN, &maxpin) < 0) {
+               perror("ioctl(GPIOMAXPIN)");
+               exit(1);
+       }
+
+       for (i = 0; i <= maxpin; i++) {
+               pin.gp_pin = i;
+               if (ioctl(fd, GPIOGETCONFIG, &pin) < 0)
+                       /* For some reason this pin is inaccessible */
+                       continue;
+
+               req.gp_pin = i;
+               if (ioctl(fd, GPIOGET, &req) < 0) {
+                       /* Now, that's wrong */
+                       perror("ioctl(GPIOGET)");
+                       exit(1);
+               }
+
+               printf("pin %02d:\t%d\t%s", pin.gp_pin, req.gp_value, 
+                   pin.gp_name);
+
+               print_caps(pin.gp_flags);
+
+               if (verbose) {
+                       printf(", caps:");
+                       print_caps(pin.gp_caps);
+               }
+               printf("\n");
+       }
+}
+
+static void 
+fail(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       exit(1);
+}
+
+int 
+main(int argc, char **argv)
+{
+       int i;
+       struct gpio_pin pin;
+       struct gpio_req req;
+       char *ctlfile = NULL;
+       int pinn, pinv, fd, ch;
+       int flags, flag, ok;
+       int config, toggle, verbose, list;
+
+       config = toggle = verbose = list = pinn = 0;
+
+       while ((ch = getopt(argc, argv, "c:f:lt:v")) != -1) {
+               switch (ch) {
+               case 'c':
+                       config = 1;
+                       pinn = str2int(optarg, &ok);
+                       if (!ok)
+                               fail("Invalid pin number: %s\n", optarg);
+                       break;
+               case 'f':
+                       ctlfile = optarg;
+                       break;
+               case 'l':
+                       list = 1;
+                       break;
+               case 't':
+                       toggle = 1;
+                       pinn = str2int(optarg, &ok);
+                       if (!ok)
+                               fail("Invalid pin number: %s\n", optarg);
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               default:
+                       usage();
+                       break;
+               }
+       }
+       argv += optind;
+       argc -= optind;
+       for (i = 0; i < argc; i++)
+               printf("%d/%s\n", i, argv[i]);
+
+       if (ctlfile == NULL)
+               fail("No gpioctl device provided\n");
+
+       fd = open(ctlfile, O_RDONLY);
+       if (fd < 0) {
+               perror("open");
+               exit(1);
+       }
+
+       if (list) {
+               dump_pins(fd, verbose);
+               close(fd);
+               exit(0);
+       }
+
+       if (toggle) {
+               /*
+                * -t pin assumes no additional arguments
+                */
+               if(argc > 0) {
+                       usage();
+                       exit(1);
+               }
+
+               req.gp_pin = pinn;
+               if (ioctl(fd, GPIOTOGGLE, &req) < 0) {
+                       perror("ioctl(GPIOTOGGLE)");
+                       exit(1);
+               }
+
+               close(fd);
+               exit (0);
+       }
+
+       if (config) {
+               flags = 0;
+               for (i = 0; i < argc; i++) {
+                       flag =  str2cap(argv[i]);
+                       if (flag < 0)
+                               fail("Invalid flag: %s\n", argv[i]);
+                       flags |= flag;
+               }
+
+               pin.gp_pin = pinn;
+               pin.gp_flags = flags;
+               if (ioctl(fd, GPIOSETCONFIG, &pin) < 0) {
+                       perror("ioctl(GPIOSETCONFIG)");
+                       exit(1);
+               }
+
+               exit(0);
+       }
+
+       /*
+        * Last two cases - set value or print value
+        */
+       if ((argc == 0) || (argc > 2)) {
+               usage();
+               exit(1);
+       }
+
+       pinn = str2int(argv[0], &ok);
+       if (!ok)
+               fail("Invalid pin number: %s\n", argv[0]);
+
+       /*
+        * Read pin value
+        */
+       if (argc == 1) {
+               req.gp_pin = pinn;
+               if (ioctl(fd, GPIOGET, &req) < 0) {
+                       perror("ioctl(GPIOGET)");
+                       exit(1);
+               }
+               printf("%d\n", req.gp_value);
+               exit (0);
+       }
+
+       /* Is it valid number (0 or 1) ? */
+       pinv = str2int(argv[1], &ok);
+       if (!ok || ((pinv != 0) && (pinv != 1)))
+               fail("Invalid pin value: %s\n", argv[1]);
+
+       /*
+        * Set pin value
+        */
+       req.gp_pin = pinn;
+       req.gp_value = pinv;
+       if (ioctl(fd, GPIOSET, &req) < 0) {
+               perror("ioctl(GPIOSET)");
+               exit(1);
+       }
+
+       close(fd);
+       exit(0);
+}
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to