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
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=296682
@ -27,7 +27,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd March 8, 2015
|
.Dd March 11, 2016
|
||||||
.Dt GPIOCTL 1
|
.Dt GPIOCTL 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -40,21 +40,25 @@
|
|||||||
.Op Fl v
|
.Op Fl v
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl f Ar ctldev
|
.Op Fl f Ar ctldev
|
||||||
|
.Op Fl pN
|
||||||
.Cm -t
|
.Cm -t
|
||||||
.Ar pin
|
.Ar pin
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl f Ar ctldev
|
.Op Fl f Ar ctldev
|
||||||
|
.Op Fl pN
|
||||||
.Cm -c
|
.Cm -c
|
||||||
.Ar pin
|
.Ar pin
|
||||||
.Ar flag
|
.Ar flag
|
||||||
.Op flag ...
|
.Op flag ...
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl f Ar ctldev
|
.Op Fl f Ar ctldev
|
||||||
|
.Op Fl pN
|
||||||
.Cm -n
|
.Cm -n
|
||||||
.Ar pin
|
.Ar pin
|
||||||
.Ar pin-name
|
.Ar pin-name
|
||||||
.Nm
|
.Nm
|
||||||
.Op Cm -f Ar ctldev
|
.Op Cm -f Ar ctldev
|
||||||
|
.Op Fl pN
|
||||||
.Ar pin
|
.Ar pin
|
||||||
.Ar [0|1]
|
.Ar [0|1]
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
@ -62,6 +66,20 @@ The
|
|||||||
.Nm
|
.Nm
|
||||||
utility could be used to manage GPIO pins from userland and list available pins.
|
utility could be used to manage GPIO pins from userland and list available pins.
|
||||||
.Pp
|
.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:
|
The options are as follows:
|
||||||
.Bl -tag -width ".Fl f Ar ctldev"
|
.Bl -tag -width ".Fl f Ar ctldev"
|
||||||
.It Fl c Ar pin Ar flag Op flag ...
|
.It Fl c Ar pin Ar flag Op flag ...
|
||||||
@ -96,9 +114,17 @@ list available pins
|
|||||||
.It Fl n Ar pin Ar pin-name
|
.It Fl n Ar pin Ar pin-name
|
||||||
set the name used to describe the pin
|
set the name used to describe the pin
|
||||||
.It Fl t Ar pin
|
.It Fl t Ar pin
|
||||||
toggle value of provided pin number
|
toggle value of provided pin
|
||||||
.It Fl v
|
.It Fl v
|
||||||
be verbose: for each listed pin print current configuration
|
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
|
.El
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
.Bl -bullet
|
.Bl -bullet
|
||||||
@ -114,6 +140,18 @@ gpioctl -f /dev/gpioc0 12 1
|
|||||||
Configure pin 12 to be input pin
|
Configure pin 12 to be input pin
|
||||||
.Pp
|
.Pp
|
||||||
gpioctl -f /dev/gpioc0 -c 12 IN
|
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
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr gpio 4 ,
|
.Xr gpio 4 ,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
|
* Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
|
||||||
* Copyright (c) 2014, Rui Paulo <rpaulo@FreeBSD.org>
|
* Copyright (c) 2014, Rui Paulo <rpaulo@FreeBSD.org>
|
||||||
|
* Copyright (c) 2015, Emmanuel Vadot <manu@bidouilliste.com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -40,6 +41,10 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <libgpio.h>
|
#include <libgpio.h>
|
||||||
|
|
||||||
|
#define PIN_TYPE_UNKNOWN 0
|
||||||
|
#define PIN_TYPE_NUMBER 1
|
||||||
|
#define PIN_TYPE_NAME 2
|
||||||
|
|
||||||
struct flag_desc {
|
struct flag_desc {
|
||||||
const char *name;
|
const char *name;
|
||||||
uint32_t flag;
|
uint32_t flag;
|
||||||
@ -66,10 +71,10 @@ usage(void)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "Usage:\n");
|
fprintf(stderr, "Usage:\n");
|
||||||
fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n");
|
fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n");
|
||||||
fprintf(stderr, "\tgpioctl [-f ctldev] -t pin\n");
|
fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -t pin\n");
|
||||||
fprintf(stderr, "\tgpioctl [-f ctldev] -c pin flag ...\n");
|
fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -c pin flag ...\n");
|
||||||
fprintf(stderr, "\tgpioctl [-f ctldev] -n pin pin-name\n");
|
fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -n pin pin-name\n");
|
||||||
fprintf(stderr, "\tgpioctl [-f ctldev] pin [0|1]\n");
|
fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] pin [0|1]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,6 +168,32 @@ dump_pins(gpio_handle_t handle, int verbose)
|
|||||||
free(cfgs);
|
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
|
static void
|
||||||
fail(const char *fmt, ...)
|
fail(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -181,19 +212,16 @@ main(int argc, char **argv)
|
|||||||
gpio_config_t pin;
|
gpio_config_t pin;
|
||||||
gpio_handle_t handle;
|
gpio_handle_t handle;
|
||||||
char *ctlfile = NULL;
|
char *ctlfile = NULL;
|
||||||
int pinn, pinv, ch;
|
int pinn, pinv, pin_type, ch;
|
||||||
int flags, flag, ok;
|
int flags, flag, ok;
|
||||||
int config, list, name, toggle, verbose;
|
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) {
|
switch (ch) {
|
||||||
case 'c':
|
case 'c':
|
||||||
config = 1;
|
config = 1;
|
||||||
pinn = str2int(optarg, &ok);
|
|
||||||
if (!ok)
|
|
||||||
fail("Invalid pin number: %s\n", optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
ctlfile = optarg;
|
ctlfile = optarg;
|
||||||
@ -203,15 +231,15 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
name = 1;
|
name = 1;
|
||||||
pinn = str2int(optarg, &ok);
|
break;
|
||||||
if (!ok)
|
case 'N':
|
||||||
fail("Invalid pin number: %s\n", optarg);
|
pin_type = PIN_TYPE_NAME;
|
||||||
|
break;
|
||||||
|
case'p':
|
||||||
|
pin_type = PIN_TYPE_NUMBER;
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
toggle = 1;
|
toggle = 1;
|
||||||
pinn = str2int(optarg, &ok);
|
|
||||||
if (!ok)
|
|
||||||
fail("Invalid pin number: %s\n", optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
@ -232,33 +260,58 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
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) {
|
if (list) {
|
||||||
dump_pins(handle, verbose);
|
dump_pins(handle, verbose);
|
||||||
gpio_close(handle);
|
gpio_close(handle);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toggle) {
|
if (argc == 0)
|
||||||
/*
|
usage();
|
||||||
* -t pin assumes no additional arguments
|
|
||||||
*/
|
/* Find the pin number by the name */
|
||||||
if (argc > 0) {
|
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();
|
usage();
|
||||||
|
if (gpio_pin_set_name(handle, pinn, argv[1]) < 0) {
|
||||||
|
perror("gpio_pin_set_name");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toggle) {
|
||||||
|
/*
|
||||||
|
* -t pin assumes no additional arguments
|
||||||
|
*/
|
||||||
|
if (argc > 1)
|
||||||
|
usage();
|
||||||
if (gpio_pin_toggle(handle, pinn) < 0) {
|
if (gpio_pin_toggle(handle, pinn) < 0) {
|
||||||
perror("gpio_pin_toggle");
|
perror("gpio_pin_toggle");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -269,7 +322,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (config) {
|
if (config) {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
flag = str2cap(argv[i]);
|
flag = str2cap(argv[i]);
|
||||||
if (flag < 0)
|
if (flag < 0)
|
||||||
fail("Invalid flag: %s\n", argv[i]);
|
fail("Invalid flag: %s\n", argv[i]);
|
||||||
@ -287,14 +340,8 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Last two cases - set value or print value
|
* Last two cases - set value or print value
|
||||||
*/
|
*/
|
||||||
if ((argc == 0) || (argc > 2)) {
|
if ((argc == 0) || (argc > 2))
|
||||||
usage();
|
usage();
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pinn = str2int(argv[0], &ok);
|
|
||||||
if (!ok)
|
|
||||||
fail("Invalid pin number: %s\n", argv[0]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read pin value
|
* Read pin value
|
||||||
@ -311,7 +358,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
/* Is it valid number (0 or 1) ? */
|
/* Is it valid number (0 or 1) ? */
|
||||||
pinv = str2int(argv[1], &ok);
|
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]);
|
fail("Invalid pin value: %s\n", argv[1]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user