summaryrefslogtreecommitdiffstats
path: root/usr.sbin/gpioctl
diff options
context:
space:
mode:
authormbalmer <mbalmer@openbsd.org>2008-11-26 14:56:10 +0000
committermbalmer <mbalmer@openbsd.org>2008-11-26 14:56:10 +0000
commit2e6ed72b7002203ea621102be9946fc9fc2d3fa8 (patch)
tree5e067b62fd9940f6f647b9f95a927563f984c91f /usr.sbin/gpioctl
parentChange the semantics of gpio(4) devices by locking down pin (diff)
downloadwireguard-openbsd-2e6ed72b7002203ea621102be9946fc9fc2d3fa8.tar.xz
wireguard-openbsd-2e6ed72b7002203ea621102be9946fc9fc2d3fa8.zip
Use the new gpio(4) semantics and change the command line syntax to a
more readable and straightforward format. Note that there is no longer a default GPIO device, but it has to be sepcified on the command line always (and as Theo mentioned, newfs also does not default to /dev/sd0a...) You must do a 'make includesi' in /usr/src before building this command or before your next system build. ok uwe@
Diffstat (limited to 'usr.sbin/gpioctl')
-rw-r--r--usr.sbin/gpioctl/gpioctl.8114
-rw-r--r--usr.sbin/gpioctl/gpioctl.c256
2 files changed, 203 insertions, 167 deletions
diff --git a/usr.sbin/gpioctl/gpioctl.8 b/usr.sbin/gpioctl/gpioctl.8
index 7b5a9e5893b..f51a5c07c3e 100644
--- a/usr.sbin/gpioctl/gpioctl.8
+++ b/usr.sbin/gpioctl/gpioctl.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: gpioctl.8,v 1.14 2008/11/24 15:27:52 jmc Exp $
+.\" $OpenBSD: gpioctl.8,v 1.15 2008/11/26 14:56:10 mbalmer Exp $
.\"
.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: November 24 2008 $
+.Dd $Mdocdate: November 26 2008 $
.Dt GPIOCTL 8
.Os
.Sh NAME
@@ -23,21 +23,33 @@
.Sh SYNOPSIS
.Nm gpioctl
.Op Fl q
-.Op Fl d Ar device
-.Op Ar pin
+.Ar device
+attach
+.Ar device
+.Ar offset
+.Ar mask
+.Nm gpioctl
+.Op Fl q
+.Ar device
+detach
+.Ar device
+.Nm gpioctl
+.Op Fl q
+.Ar device
+.Ar pin
.Op Ar 0 | 1 | 2
.Nm gpioctl
.Op Fl q
-.Op Fl d Ar device
-.Fl c
+.Ar device
.Ar pin
+set
.Op Ar flags
+.Op Ar name
.Nm gpioctl
-.Fl A Ar device
-.Fl o Ar offset
-.Fl m Ar mask
-.Nm gpioctl
-.Fl D Ar device
+.Op Fl q
+.Ar device
+.Ar pin
+unset
.Sh DESCRIPTION
The
.Nm
@@ -76,6 +88,16 @@ A value of 2 has a special meaning: it
.Dq toggles
the pin, i.e. changes its state to the opposite.
.Pp
+Only pins that have been configured at securelevel 0, typically during system
+startup, are accessible once the securelevel has been raised.
+Pins can be given symbolic names for easier use.
+Besides using individual pins, device drivers that use GPIO pins can be
+attached to a
+.Xr gpio 4
+device using the
+.Nm
+command.
+.Pp
The following configuration
.Ar flags
are supported by the GPIO framework:
@@ -105,58 +127,18 @@ invert output
.Pp
Note that not all the flags can be supported by the particular GPIO controller.
.Pp
-When executed without any arguments,
+When executed with only the
+.Xr gpio 4
+device name as argument,
.Nm
reads information about the
-GPIO device and displays it.
+.Tn GPIO
+device and displays it.
+At securelevel 0 the number of physically available pins is displayed,
+at higher securelevels the number of configured (set) pins is displayed.
.Pp
The options are as follows:
.Bl -tag -width Ds
-.It Fl A Ar device
-Attach
-.Ar device
-at this gpiobus.
-An
-.Fl o Ar offset
-(a pin number) and
-.Fl m Ar mask
-(a binary mask)
-must also be specified.
-.It Fl c Ar pin
-Configure
-.Ar pin
-with any of the various flags,
-as documented above.
-The list of supported flags is always displayed when executing
-.Nm
-with this option.
-To change pin flags,
-a new flags set separated by spaces must be specified
-after the pin number.
-.It Fl D Ar device
-Detach
-.Ar device
-from this gpiobus.
-Only devices that have been attached using the
-.Fl a
-option can be detached.
-.It Fl d Ar device
-If more than one GPIO device is present,
-an alternative
-.Ar device
-file can be specified with the
-.Fl d
-option in order to access a particular GPIO device.
-.It Fl m Ar mask
-Specify a binary mask,
-.Ar mask ,
-for the device being attached
-.Pq Fl A .
-.It Fl o Ar offset
-Specify a pin number,
-.Ar offset ,
-for the device being attached
-.Pq Fl A .
.It Fl q
Operate quietly i.e. nothing is printed to stdout.
.El
@@ -170,11 +152,11 @@ file.
.Sh EXAMPLES
Configure pin 20 to have push-pull output:
.Pp
-.Dl # gpioctl -c 20 out pp
+.Dl # gpioctl gpio0 20 out pp
.Pp
Write logical 1 to pin 20:
.Pp
-.Dl # gpioctl 20 1
+.Dl # gpioctl gpio0 20 1
.Pp
Attach a
.Xr onewire 4
@@ -182,11 +164,19 @@ bus on a
.Xr gpioow 4
device on pin 4:
.Pp
-.Dl # gpioctl -A gpioow -o 4 -m 0x01
+.Dl # gpioctl gpio0 attach gpioow 4 0x01
.Pp
Detach the gpioow0 device:
.Pp
-.Dl # gpioctl -D gpioow0
+.Dl # gpioctl gpio0 detach gpioow0
+.Pp
+Configure pin 5 as output and name it error_led:
+.Pp
+.Dl # gpioctl gpio0 5 set out error_led
+.Pp
+Toggle the error_led:
+.Pp
+.Dl # gpioctl gpio0 error_led 2
.Sh SEE ALSO
.Xr gpio 4
.Sh HISTORY
diff --git a/usr.sbin/gpioctl/gpioctl.c b/usr.sbin/gpioctl/gpioctl.c
index 408ae38df84..490401be092 100644
--- a/usr.sbin/gpioctl/gpioctl.c
+++ b/usr.sbin/gpioctl/gpioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpioctl.c,v 1.9 2008/11/24 15:27:52 jmc Exp $ */
+/* $OpenBSD: gpioctl.c,v 1.10 2008/11/26 14:56:10 mbalmer Exp $ */
/*
* Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
*
@@ -27,21 +27,23 @@
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#define _PATH_DEV_GPIO "/dev/gpio0"
-char *device = _PATH_DEV_GPIO;
+char *dev;
int devfd = -1;
int quiet = 0;
void getinfo(void);
-void pinread(int);
-void pinwrite(int, int);
-void pinctl(int, char *[], int);
+void pinread(int, char *);
+void pinwrite(int, char *, int);
+void pinctl(int, char *, char *[], int);
+void pinset(int pin, char *name, int flags, char *alias);
+void unset(int pin, char *name);
void devattach(char *, int, u_int32_t);
void devdetach(char *);
@@ -69,46 +71,17 @@ main(int argc, char *argv[])
{
int ch;
const char *errstr;
- char *ga_dvname = NULL, *ep;
- int do_ctl = 0;
- int pin = 0, value = 0, attach = 0, detach = 0;
+ const struct bitstr *bs;
+ char *ep;
+ int n, fl = 0, value = 0;
u_int32_t ga_mask = 0, ga_offset = -1;
long lval;
+ char devn[32];
+ int pin;
+ char *nam = NULL;
- while ((ch = getopt(argc, argv, "A:cd:D:m:o:q")) != -1)
+ while ((ch = getopt(argc, argv, "q")) != -1)
switch (ch) {
- case 'A':
- if (detach)
- errx(1, "-A and -D are mutual exclusive");
- ga_dvname = optarg;
- attach = 1;
- break;
- case 'c':
- do_ctl = 1;
- break;
- case 'd':
- device = optarg;
- break;
- case 'D':
- if (attach)
- errx(1, "-D and -A are mutual exclusive");
- ga_dvname = optarg;
- detach = 1;
- break;
- case 'm':
- lval = strtol(optarg, &ep, 0);
- if (*optarg == '\0' || *ep != '\0')
- errx(1, "invalid mask (not a number)");
- if ((errno == ERANGE && (lval == LONG_MAX
- || lval == LONG_MIN)) || lval > UINT_MAX)
- errx(1, "mask out of range");
- ga_mask = lval;
- break;
- case 'o':
- ga_offset = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr)
- errx(1, "offset is %s: %s", errstr, optarg);
- break;
case 'q':
quiet = 1;
break;
@@ -119,40 +92,83 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (argc > 0) {
- pin = strtonum(argv[0], 0, INT_MAX, &errstr);
- if (errstr)
- errx(1, "%s: invalid pin", argv[0]);
+ if (argc < 1)
+ usage();
+ dev = argv[0];
+
+ if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
+ (void)snprintf(devn, sizeof(devn), "%s/%s", _PATH_DEV, dev);
+ dev = devn;
}
- if ((devfd = open(device, O_RDWR)) == -1)
- err(1, "%s", device);
+ if ((devfd = open(dev, O_RDWR)) == -1)
+ err(1, "%s", dev);
- if (attach) {
- if (ga_offset == -1 || ga_mask == 0)
- errx(1, "gpio attach needs an offset and a mask");
- devattach(ga_dvname, ga_offset, ga_mask);
- } else if (detach) {
- devdetach(ga_dvname);
- } else if (argc == 0 && !do_ctl) {
+ if (argc == 1) {
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 = strtonum(argv[1], INT_MIN, INT_MAX, &errstr);
- if (errstr)
- errx(1, "%s: invalid value", argv[1]);
- pinwrite(pin, value);
- }
+ return 0;
+ }
+
+ if (!strcmp(argv[1], "attach")) {
+ char *driver, *offset, *mask;
+
+ if (argc != 5)
+ usage();
+
+ driver = argv[2];
+ offset = argv[3];
+ mask = argv[4];
+
+ ga_offset = strtonum(offset, 0, INT_MAX, &errstr);
+ if (errstr)
+ errx(1, "offset is %s: %s", errstr, offset);
+
+ lval = strtol(mask, &ep, 0);
+ if (*mask == '\0' || *ep != '\0')
+ errx(1, "invalid mask (not a number)");
+ if ((errno == ERANGE && (lval == LONG_MAX
+ || lval == LONG_MIN)) || lval > UINT_MAX)
+ errx(1, "mask out of range");
+ ga_mask = lval;
+ devattach(driver, ga_offset, ga_mask);
+ return 0;
+ } else if (!strcmp(argv[1], "detach")) {
+ if (argc != 3)
+ usage();
+ devdetach(argv[2]);
} else {
- usage();
- /* NOTREACHED */
+ char *nm = NULL;
+
+ /* expecting a pin number or name */
+ pin = strtonum(argv[1], 0, INT_MAX, &errstr);
+ if (errstr)
+ nm = argv[1]; /* try named pin */
+ if (argc > 2) {
+ if (!strcmp(argv[2], "set")) {
+ for (n = 3; n < argc; n++) {
+ for (bs = pinflags; bs->string != NULL;
+ bs++) {
+ if (!strcmp(argv[n],
+ bs->string)) {
+ fl |= bs->mask;
+ break;
+ }
+ }
+ if (bs->string == NULL)
+ nam = argv[n];
+ }
+ pinset(pin, nm, fl, nam);
+ } else if (!strcmp(argv[2], "unset")) {
+ unset(pin, nm);
+ } else {
+ value = strtonum(argv[2], INT_MIN, INT_MAX,
+ &errstr);
+ if (errstr)
+ errx(1, "%s: invalid value", argv[2]);
+ pinwrite(pin, nm, value);
+ }
+ } else
+ pinread(pin, nm);
}
return (0);
@@ -170,27 +186,34 @@ getinfo(void)
if (quiet)
return;
- printf("%s: %d pins\n", device, info.gpio_npins);
+ printf("%s: %d pins\n", dev, info.gpio_npins);
}
void
-pinread(int pin)
+pinread(int pin, char *gp_name)
{
struct gpio_pin_op op;
bzero(&op, sizeof(op));
- op.gp_pin = pin;
+ if (gp_name != NULL)
+ strlcpy(op.gp_name, gp_name, sizeof(op.gp_name));
+ else
+ 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);
+ if (gp_name)
+ printf("pin %s: state %d\n", gp_name, op.gp_value);
+ else
+ printf("pin %d: state %d\n", pin, op.gp_value);
}
void
-pinwrite(int pin, int value)
+pinwrite(int pin, char *gp_name, int value)
{
struct gpio_pin_op op;
@@ -198,11 +221,14 @@ pinwrite(int pin, int value)
errx(1, "%d: invalid value", value);
bzero(&op, sizeof(op));
- op.gp_pin = pin;
+ if (gp_name != NULL)
+ strlcpy(op.gp_name, gp_name, sizeof(op.gp_name));
+ else
+ 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");
+ err(1, "GPIOPINWR");
} else {
if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1)
err(1, "GPIOPINTOGGLE");
@@ -211,42 +237,46 @@ pinwrite(int pin, int value)
if (quiet)
return;
- printf("pin %d: state %d -> %d\n", pin, op.gp_value,
- (value < 2 ? value : 1 - op.gp_value));
+ if (gp_name)
+ printf("pin %s: state %d -> %d\n", gp_name, op.gp_value,
+ (value < 2 ? value : 1 - op.gp_value));
+ else
+ 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)
+pinset(int pin, char *name, int fl, char *alias)
{
- struct gpio_pin_ctl ctl;
- int fl = 0;
+ struct gpio_pin_set set;
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");
+
+ bzero(&set, sizeof(set));
+ if (name != NULL)
+ strlcpy(set.gp_name, name, sizeof(set.gp_name));
+ else
+ set.gp_pin = pin;
+ set.gp_flags = fl;
+
+ if (alias != NULL)
+ strlcpy(set.gp_name2, alias, sizeof(set.gp_name2));
+
+ if (ioctl(devfd, GPIOPINSET, &set) == -1)
+ err(1, "GPIOPINSET");
if (quiet)
return;
- printf("pin %d: caps:", pin);
+ if (name != NULL)
+ printf("pin %s: caps:", name);
+ else
+ printf("pin %d: caps:", pin);
for (bs = pinflags; bs->string != NULL; bs++)
- if (ctl.gp_caps & bs->mask)
+ if (set.gp_caps & bs->mask)
printf(" %s", bs->string);
printf(", flags:");
for (bs = pinflags; bs->string != NULL; bs++)
- if (ctl.gp_flags & bs->mask)
+ if (set.gp_flags & bs->mask)
printf(" %s", bs->string);
if (fl > 0) {
printf(" ->");
@@ -258,6 +288,21 @@ pinctl(int pin, char *flags[], int nflags)
}
void
+unset(int pin, char *name)
+{
+ struct gpio_pin_set set;
+
+ bzero(&set, sizeof(set));
+ if (name != NULL)
+ strlcpy(set.gp_name, name, sizeof(set.gp_name));
+ else
+ set.gp_pin = pin;
+
+ if (ioctl(devfd, GPIOPINUNSET, &set) == -1)
+ err(1, "GPIOPINUNSET");
+}
+
+void
devattach(char *dvname, int offset, u_int32_t mask)
{
struct gpio_attach attach;
@@ -285,13 +330,14 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr, "usage: %s [-q] [-d device] [pin] [0 | 1 | 2]\n",
+ fprintf(stderr, "usage: %s [-q] device [pin] [0 | 1 | 2]\n",
__progname);
- fprintf(stderr, " %s [-q] [-d device] -c pin [flags]\n",
+ fprintf(stderr, " %s [-q] device pin set [flags] [name]\n",
__progname);
- fprintf(stderr, " %s -A device -o offset -m mask\n",
+ fprintf(stderr, " %s [-q] device pin unset\n", __progname);
+ fprintf(stderr, " %s [-q] device attach device offset mask\n",
__progname);
- fprintf(stderr, " %s -D device\n", __progname);
+ fprintf(stderr, " %s [-q] device detach device\n", __progname);
exit(1);
}