diff options
author | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-11-26 14:56:11 +0000 |
---|---|---|
committer | Marc Balmer <mbalmer@cvs.openbsd.org> | 2008-11-26 14:56:11 +0000 |
commit | 4c3ec141e9ae7be32359c7fe2c68c03354ba2a64 (patch) | |
tree | e4856b14405d321c75633447b86e71a0ea325b64 /usr.sbin | |
parent | 8b05f52c66040516db238de1c834b93ee6487452 (diff) |
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')
-rw-r--r-- | usr.sbin/gpioctl/gpioctl.8 | 114 | ||||
-rw-r--r-- | usr.sbin/gpioctl/gpioctl.c | 256 |
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); } |