summaryrefslogtreecommitdiffstats
path: root/usr.sbin/gpioctl
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2016-03-11 21:05:16 +0000
committergonzo <gonzo@FreeBSD.org>2016-03-11 21:05:16 +0000
commitd652802e2431dec69e6586378b0a804c9aa5d4f7 (patch)
tree7714e7306104fd69d4a49e29eab0ed5c0c2486fd /usr.sbin/gpioctl
parent2bf5979518a20dca9b6102d3b6271d65a65fb46b (diff)
downloadFreeBSD-src-d652802e2431dec69e6586378b0a804c9aa5d4f7.zip
FreeBSD-src-d652802e2431dec69e6586378b0a804c9aa5d4f7.tar.gz
Make it possible for operations to refer to GPIO pins by name
- Try to guess what is provided as a pin spec for -t or for get/set operation: number or name. Fails in case of ambiguity. - Add -p and -N switches to force pin specification interpretation: -p forces spec to be pin number, -N forces it to be name Submitted by: Emmanuel Vadot <manu@bidouilliste.com> Differential Revision: https://reviews.freebsd.org/D5201
Diffstat (limited to 'usr.sbin/gpioctl')
-rw-r--r--usr.sbin/gpioctl/gpioctl.842
-rw-r--r--usr.sbin/gpioctl/gpioctl.c127
2 files changed, 127 insertions, 42 deletions
diff --git a/usr.sbin/gpioctl/gpioctl.8 b/usr.sbin/gpioctl/gpioctl.8
index dc2a554..358f75e 100644
--- a/usr.sbin/gpioctl/gpioctl.8
+++ b/usr.sbin/gpioctl/gpioctl.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 8, 2015
+.Dd March 11, 2016
.Dt GPIOCTL 1
.Os
.Sh NAME
@@ -40,21 +40,25 @@
.Op Fl v
.Nm
.Op Fl f Ar ctldev
+.Op Fl pN
.Cm -t
.Ar pin
.Nm
.Op Fl f Ar ctldev
+.Op Fl pN
.Cm -c
.Ar pin
.Ar flag
.Op flag ...
.Nm
.Op Fl f Ar ctldev
+.Op Fl pN
.Cm -n
.Ar pin
.Ar pin-name
.Nm
.Op Cm -f Ar ctldev
+.Op Fl pN
.Ar pin
.Ar [0|1]
.Sh DESCRIPTION
@@ -62,6 +66,20 @@ The
.Nm
utility could be used to manage GPIO pins from userland and list available pins.
.Pp
+The
+.Pa pin
+argument can either be a
+.Pa pin-number
+or a
+.Pa pin-name .
+If it is a number and a pin has this number as its name and you did not use
+.Fl N
+or
+.Fl p
+, then
+.Nm
+exits.
+.Pp
The options are as follows:
.Bl -tag -width ".Fl f Ar ctldev"
.It Fl c Ar pin Ar flag Op flag ...
@@ -96,9 +114,17 @@ list available pins
.It Fl n Ar pin Ar pin-name
set the name used to describe the pin
.It Fl t Ar pin
-toggle value of provided pin number
+toggle value of provided pin
.It Fl v
be verbose: for each listed pin print current configuration
+.It Fl p
+Force
+.Pa pin
+to be interpreted as a pin number
+.It Fl N
+Force
+.Pa pin
+to be interpreted as a pin name
.El
.Sh EXAMPLES
.Bl -bullet
@@ -114,6 +140,18 @@ gpioctl -f /dev/gpioc0 12 1
Configure pin 12 to be input pin
.Pp
gpioctl -f /dev/gpioc0 -c 12 IN
+.It
+Set the name of pin 12 to test
+.Pp
+gpioctl -f /dev/gpioc0 -n 12 test
+.It
+Toggle the value the pin named test
+.Pp
+gpioctl -f /dev/gpioc0 -t test
+.It
+Toggle the value of pin number 12 even if another pin has the name 12
+.Pp
+gpioctl -f /dev/gpioc0 -pt 12
.El
.Sh SEE ALSO
.Xr gpio 4 ,
diff --git a/usr.sbin/gpioctl/gpioctl.c b/usr.sbin/gpioctl/gpioctl.c
index 38e53e7..42287e9 100644
--- a/usr.sbin/gpioctl/gpioctl.c
+++ b/usr.sbin/gpioctl/gpioctl.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
* Copyright (c) 2014, Rui Paulo <rpaulo@FreeBSD.org>
+ * Copyright (c) 2015, Emmanuel Vadot <manu@bidouilliste.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +41,10 @@ __FBSDID("$FreeBSD$");
#include <libgpio.h>
+#define PIN_TYPE_UNKNOWN 0
+#define PIN_TYPE_NUMBER 1
+#define PIN_TYPE_NAME 2
+
struct flag_desc {
const char *name;
uint32_t flag;
@@ -66,10 +71,10 @@ 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] -n pin pin-name\n");
- fprintf(stderr, "\tgpioctl [-f ctldev] pin [0|1]\n");
+ fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -t pin\n");
+ fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -c pin flag ...\n");
+ fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -n pin pin-name\n");
+ fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] pin [0|1]\n");
exit(1);
}
@@ -163,6 +168,32 @@ dump_pins(gpio_handle_t handle, int verbose)
free(cfgs);
}
+static int
+get_pinnum_by_name(gpio_handle_t handle, const char *name) {
+ int i, maxpin, pinn;
+ gpio_config_t *cfgs;
+ gpio_config_t *pin;
+
+ pinn = -1;
+ maxpin = gpio_pin_list(handle, &cfgs);
+ if (maxpin < 0) {
+ perror("gpio_pin_list");
+ exit(1);
+ }
+
+ for (i = 0; i <= maxpin; i++) {
+ pin = cfgs + i;
+ gpio_pin_get(handle, pin->g_pin);
+ if (!strcmp(name, pin->g_name)) {
+ pinn = i;
+ break;
+ }
+ }
+ free(cfgs);
+
+ return pinn;
+}
+
static void
fail(const char *fmt, ...)
{
@@ -181,19 +212,16 @@ main(int argc, char **argv)
gpio_config_t pin;
gpio_handle_t handle;
char *ctlfile = NULL;
- int pinn, pinv, ch;
+ int pinn, pinv, pin_type, ch;
int flags, flag, ok;
int config, list, name, toggle, verbose;
- config = toggle = verbose = list = name = pinn = 0;
+ config = toggle = verbose = list = name = pin_type = 0;
- while ((ch = getopt(argc, argv, "c:f:ln:t:v")) != -1) {
+ while ((ch = getopt(argc, argv, "cf:lntvNp")) != -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;
@@ -203,15 +231,15 @@ main(int argc, char **argv)
break;
case 'n':
name = 1;
- pinn = str2int(optarg, &ok);
- if (!ok)
- fail("Invalid pin number: %s\n", optarg);
+ break;
+ case 'N':
+ pin_type = PIN_TYPE_NAME;
+ break;
+ case'p':
+ pin_type = PIN_TYPE_NUMBER;
break;
case 't':
toggle = 1;
- pinn = str2int(optarg, &ok);
- if (!ok)
- fail("Invalid pin number: %s\n", optarg);
break;
case 'v':
verbose = 1;
@@ -232,33 +260,58 @@ main(int argc, char **argv)
exit(1);
}
+ if (list) {
+ dump_pins(handle, verbose);
+ gpio_close(handle);
+ exit(0);
+ }
+
+ if (argc == 0)
+ usage();
+
+ /* Find the pin number by the name */
+ switch (pin_type) {
+ case PIN_TYPE_UNKNOWN:
+ /* First test if it is a pin number */
+ pinn = str2int(argv[0], &ok);
+ if (ok) {
+ /* Test if we have any pin named by this number and tell the user */
+ if (get_pinnum_by_name(handle, argv[0]) != -1)
+ fail("%s is also a pin name, use -p or -N\n", argv[0]);
+ } else {
+ /* Test if it is a name */
+ if ((pinn = get_pinnum_by_name(handle, argv[0])) == -1)
+ fail("Can't find pin named \"%s\"\n", argv[0]);
+ }
+ break;
+ case PIN_TYPE_NUMBER:
+ pinn = str2int(argv[0], &ok);
+ if (!ok)
+ fail("Invalid pin number: %s\n", argv[0]);
+ break;
+ case PIN_TYPE_NAME:
+ if ((pinn = get_pinnum_by_name(handle, argv[0])) == -1)
+ fail("Can't find pin named \"%s\"\n", argv[0]);
+ break;
+ }
+
/* Set the pin name. */
if (name) {
- if (argc == 0) {
+ if (argc != 2)
usage();
- exit(1);
- }
- if (gpio_pin_set_name(handle, pinn, argv[0]) < 0) {
+ if (gpio_pin_set_name(handle, pinn, argv[1]) < 0) {
perror("gpio_pin_set_name");
exit(1);
}
exit(0);
}
- if (list) {
- dump_pins(handle, verbose);
- gpio_close(handle);
- exit(0);
- }
-
if (toggle) {
/*
- * -t pin assumes no additional arguments
- */
- if (argc > 0) {
+ * -t pin assumes no additional arguments
+ */
+ if (argc > 1)
usage();
- exit(1);
- }
if (gpio_pin_toggle(handle, pinn) < 0) {
perror("gpio_pin_toggle");
exit(1);
@@ -269,7 +322,7 @@ main(int argc, char **argv)
if (config) {
flags = 0;
- for (i = 0; i < argc; i++) {
+ for (i = 1; i < argc; i++) {
flag = str2cap(argv[i]);
if (flag < 0)
fail("Invalid flag: %s\n", argv[i]);
@@ -287,14 +340,8 @@ main(int argc, char **argv)
/*
* Last two cases - set value or print value
*/
- if ((argc == 0) || (argc > 2)) {
+ 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
@@ -311,7 +358,7 @@ main(int argc, char **argv)
/* Is it valid number (0 or 1) ? */
pinv = str2int(argv[1], &ok);
- if (!ok || ((pinv != 0) && (pinv != 1)))
+ if (ok == 0 || ((pinv != 0) && (pinv != 1)))
fail("Invalid pin value: %s\n", argv[1]);
/*
OpenPOWER on IntegriCloud