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
This commit is contained in:
parent
645e6cf5cc
commit
3b2bb13317
@ -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 ,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/* Set the pin name. */
|
||||
if (name) {
|
||||
if (argc == 0) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
if (gpio_pin_set_name(handle, pinn, argv[0]) < 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) {
|
||||
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 != 2)
|
||||
usage();
|
||||
if (gpio_pin_set_name(handle, pinn, argv[1]) < 0) {
|
||||
perror("gpio_pin_set_name");
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (toggle) {
|
||||
/*
|
||||
* -t pin assumes no additional arguments
|
||||
*/
|
||||
if (argc > 1)
|
||||
usage();
|
||||
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]);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user