Sat Jul 25 16:18:09 2009 UTC ()
Reworked gpioctl(8) command to reflect recent gpio(4) changes.


(mbalmer)
diff -r1.3 -r1.4 src/usr.sbin/gpioctl/Makefile
diff -r1.4 -r1.5 src/usr.sbin/gpioctl/gpioctl.8
diff -r1.5 -r1.6 src/usr.sbin/gpioctl/gpioctl.c
diff -r0 -r1.1 src/usr.sbin/gpioctl/strtonum.c

cvs diff -r1.3 -r1.4 src/usr.sbin/gpioctl/Makefile (expand / switch to unified diff)

--- src/usr.sbin/gpioctl/Makefile 2009/04/22 15:23:03 1.3
+++ src/usr.sbin/gpioctl/Makefile 2009/07/25 16:18:09 1.4
@@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
1# $NetBSD: Makefile,v 1.3 2009/04/22 15:23:03 lukem Exp $ 1# $NetBSD: Makefile,v 1.4 2009/07/25 16:18:09 mbalmer Exp $
2 2
3PROG= gpioctl 3PROG= gpioctl
4SRCS= gpioctl.c 4SRCS= gpioctl.c strtonum.c
5 5
6MAN= gpioctl.8 6MAN= gpioctl.8
7 7
8.include <bsd.prog.mk> 8.include <bsd.prog.mk>

cvs diff -r1.4 -r1.5 src/usr.sbin/gpioctl/gpioctl.8 (expand / switch to unified diff)

--- src/usr.sbin/gpioctl/gpioctl.8 2008/01/09 15:56:27 1.4
+++ src/usr.sbin/gpioctl/gpioctl.8 2009/07/25 16:18:09 1.5
@@ -1,183 +1,209 @@ @@ -1,183 +1,209 @@
1.\" $NetBSD: gpioctl.8,v 1.4 2008/01/09 15:56:27 xtraeme Exp $ 1.\" $NetBSD: gpioctl.8,v 1.5 2009/07/25 16:18:09 mbalmer Exp $
2.\" $OpenBSD: gpioctl.8,v 1.5 2004/12/02 05:11:40 grange Exp $ 
3.\" 2.\"
 3.\" Copyright (c) 2009 Marc Balmer <marc@msys.ch>
4.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 4.\" Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
5.\" 5.\"
6.\" Permission to use, copy, modify, and distribute this software for any 6.\" Permission to use, copy, modify, and distribute this software for any
7.\" purpose with or without fee is hereby granted, provided that the above 7.\" purpose with or without fee is hereby granted, provided that the above
8.\" copyright notice and this permission notice appear in all copies. 8.\" copyright notice and this permission notice appear in all copies.
9.\" 9.\"
10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17.\" 17.\"
18.Dd January 9, 2008 18.Dd July 15, 2009
19.Dt GPIOCTL 8 19.Dt GPIOCTL 8
20.Os 20.Os
21.Sh NAME 21.Sh NAME
22.Nm gpioctl 22.Nm gpioctl
23.Nd control GPIO devices 23.Nd control GPIO devices
24.Sh SYNOPSIS 24.Sh SYNOPSIS
25.Nm 25.Nm gpioctl
26.Op Fl hq 26.Op Fl q
27.Op Fl d Ar device 27.Ar device
28.Op Ar pin 28attach
 29.Ar device
 30.Ar offset
 31.Ar mask
 32.Nm gpioctl
 33.Op Fl q
 34.Ar device
 35detach
 36.Ar device
 37.Nm gpioctl
 38.Op Fl q
 39.Ar device
 40.Ar pin
29.Op Ar 0 | 1 | 2 41.Op Ar 0 | 1 | 2
30.Nm 42.Nm gpioctl
31.Op Fl hq 43.Op Fl q
32.Op Fl d Ar device 44.Ar device
33.Fl c 
34.Ar pin 45.Ar pin
 46.Op Ar on | off | toggle
 47.Nm gpioctl
 48.Op Fl q
 49.Ar device
 50.Ar pin
 51set
35.Op Ar flags 52.Op Ar flags
 53.Op Ar name
 54.Nm gpioctl
 55.Op Fl q
 56.Ar device
 57.Ar pin
 58unset
36.Sh DESCRIPTION 59.Sh DESCRIPTION
37The 60The
38.Nm 61.Nm
39program allows manipulation of 62program allows manipulation of GPIO
40.Tn GPIO 
41(General Purpose Input/Output) device pins. 63(General Purpose Input/Output) device pins.
42Such devices can be either part of the chipset or embedded 64Such devices can be either part of the chipset or embedded CPU,
43.Tn CPU , 
44or a separate chip. 65or a separate chip.
45The usual way of using 66The usual way of using GPIO
46.Tn GPIO 67is to connect some simple devices such as LEDs and 1-wire thermal sensors
47is to connect some simple devices such as LEDs, 1-wire thermal sensors, 68to its pins.
48etc., to its pins. 
49.Pp 69.Pp
50Each 70Each GPIO device has an associated device file in the
51.Tn GPIO 
52device has an associated device file in the 
53.Pa /dev 71.Pa /dev
54directory. 72directory.
55By default 73.Ar device
56.Nm 74can be specified with or without the
57uses 75.Pa /dev
58.Pa /dev/gpio0 , 76prefix.
59which corresponds to the first found 77For example,
60.Tn GPIO 78.Pa /dev/gpio0
61device in the system. 79or
62If more than one 80.Pa gpio0 .
63.Tn GPIO 
64device is present, an alternative device file can be specified with the 
65.Fl d 
66option in order to access a particular 
67.Tn GPIO 
68device. 
69.Pp 
70When executed without any arguments, 
71.Nm 
72reads information about the 
73.Tn GPIO 
74device and displays it. 
75.Pp 81.Pp
76.Tn GPIO 82GPIO pins can be either
77pins can be either 
78.Dq read 83.Dq read
79or 84or
80.Dq written 85.Dq written
81with the values of logical 0 or 1. 86with the values of logical 0 or 1.
82If only a 87If only a
83.Ar pin 88.Ar pin
84number is specified on the command line, the pin state will be read 89number is specified on the command line, the pin state will be read
85from the 90from the GPIO controller and displayed.
86.Tn GPIO 
87controller and displayed. 
88To write to a pin, a value must be specified after the 91To write to a pin, a value must be specified after the
89.Ar pin 92.Ar pin
90number. 93number.
91Values can be either 0 or 1. 94Values can be either 0 or 1.
92A value of 2 has a special meaning: it 95A value of 2 has a special meaning: it
93.Dq toggles 96.Dq toggles
94the pin, i.e. changes its state to the opposite. 97the pin, i.e. changes its state to the opposite.
 98Instead of the numerical values, the word
 99.Ar on ,
 100.Ar off ,
 101or
 102.Ar toggle
 103can be used.
95.Pp 104.Pp
96Each pin can be configured with different flags with the 105Only pins that have been configured at securelevel 0, typically during system
97.Fl c 106startup, are accessible once the securelevel has been raised.
98option. 107Pins can be given symbolic names for easier use.
99The following configuration flags are supported by the 108Besides using individual pins, device drivers that use GPIO pins can be
100.Tn GPIO 109attached to a
101framework: 110.Xr gpio 4
 111device using the
 112.Nm
 113command.
 114.Pp
 115The following configuration
 116.Ar flags
 117are supported by the GPIO framework:
102.Pp 118.Pp
103.Bl -tag -width XXXXXXX -offset indent -compact 119.Bl -tag -width Ds -offset indent -compact
104.It in 120.It in
105input direction 121input direction
106.It out 122.It out
107output direction 123output direction
108.It inout 124.It inout
109bi-directional 125bi-directional
110.It od 126.It od
111open-drain output 127open-drain output
112.It pp 128.It pp
113push-pull output 129push-pull output
114.It tri 130.It tri
115tri-state (output disabled) 131tri-state (output disabled)
116.It pu 132.It pu
117internal pull-up enabled 133internal pull-up enabled
118.It pd 134.It pd
119internal pull-down enabled 135internal pull-down enabled
120.It iin 136.It iin
121invert input 137invert input
122.It iout 138.It iout
123invert output 139invert output
124.El 140.El
125.Pp 141.Pp
126Note that not all the flags can be supported by the particular 142Note that not all the flags may be supported by the particular GPIO controller.
127.Tn GPIO 
128controller. 
129The list of supported flags is always displayed when executing 
130.Nm 
131with the 
132.Fl c 
133option. 
134If only a 
135.Ar pin 
136number is specified on the command line, the current pin flags will be 
137displayed. 
138To change pin flags, a new flags set separated by spaces must be 
139specified after the 
140.Ar pin 
141number. 
142.Pp 143.Pp
143The 144When executed with only the
144.Fl q 145.Xr gpio 4
145option causes 146device name as argument,
146.Nm 147.Nm
147to operate quietly i.e. nothing is printed to stdout. 148reads information about the
148The 149.Tn GPIO
149.Fl h 150device and displays it.
150option displays a usage summary. 151At securelevel 0 the number of physically available pins is displayed,
 152at higher securelevels the number of configured (set) pins is displayed.
 153.Pp
 154The options are as follows:
 155.Bl -tag -width Ds
 156.It Fl q
 157Operate quietly i.e. nothing is printed to stdout.
 158.El
151.Sh FILES 159.Sh FILES
152.Bl -tag -width "/dev/gpiou" -compact 160.Bl -tag -width "/dev/gpiou" -compact
153.It /dev/gpio Ns Ar u 161.It /dev/gpio Ns Ar u
154GPIO device unit 162GPIO device unit
155.Ar u 163.Ar u
156file. 164file.
157.El 165.El
158.Sh EXAMPLES 166.Sh EXAMPLES
159Configure pin 20 to have push-pull output: 167Configure pin 20 to have push-pull output:
160.Pp 168.Pp
161.Dl # gpioctl -c 20 out pp 169.Dl # gpioctl gpio0 20 set out pp
162.Pp 170.Pp
163Write logical 1 to pin 20: 171Write logical 1 to pin 20:
164.Pp 172.Pp
165.Dl # gpioctl 20 1 173.Dl # gpioctl gpio0 20 1
 174.Pp
 175Attach a
 176.Xr onewire 4
 177bus on a
 178.Xr gpioow 4
 179device on pin 4:
 180.Pp
 181.Dl # gpioctl gpio0 attach gpioow 4 0x01
 182.Pp
 183Detach the gpioow0 device:
 184.Pp
 185.Dl # gpioctl gpio0 detach gpioow0
 186.Pp
 187Configure pin 5 as output and name it error_led:
 188.Pp
 189.Dl # gpioctl gpio0 5 set out error_led
 190.Pp
 191Toggle the error_led:
 192.Pp
 193.Dl # gpioctl gpio0 error_led 2
166.Sh SEE ALSO 194.Sh SEE ALSO
167.Xr elansc 4 , 195.Xr gpio 4
168.Xr gcscpcib 4 , 
169.Xr gpio 4 , 
170.Xr gscpcib 4 , 
171.Xr nsclpcsio 4 
172.Sh HISTORY 196.Sh HISTORY
173The 197The
174.Nm 198.Nm
175command first appeared in 199command first appeared in
176.Ox 3.6 200.Ox 3.6
177and 201and
178.Nx 4.0 . 202.Nx 4.0 .
179.Sh AUTHORS 203.Sh AUTHORS
180The 204The
181.Nm 205.Nm
182program was written by 206program was written by
183.An Alexander Yurchenko Aq grange@openbsd.org . 207.An Alexander Yurchenko Aq grange@openbsd.org .
 208Device attachment was added by
 209.An Marc Balmer Aq marc@msys.ch .

cvs diff -r1.5 -r1.6 src/usr.sbin/gpioctl/gpioctl.c (expand / switch to unified diff)

--- src/usr.sbin/gpioctl/gpioctl.c 2008/01/09 16:08:33 1.5
+++ src/usr.sbin/gpioctl/gpioctl.c 2009/07/25 16:18:09 1.6
@@ -1,235 +1,355 @@ @@ -1,235 +1,355 @@
1/* $NetBSD: gpioctl.c,v 1.5 2008/01/09 16:08:33 xtraeme Exp $ */ 1/* $NetBSD: gpioctl.c,v 1.6 2009/07/25 16:18:09 mbalmer Exp $ */
2/* $OpenBSD: gpioctl.c,v 1.2 2004/08/08 00:05:09 deraadt Exp $ */ 2
3/* 3/*
 4 * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org>
4 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 5 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
5 * 6 *
6 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
9 * 10 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 18 */
18 19
19/* 20/*
20 * Program to control GPIO devices. 21 * Program to control GPIO devices.
21 */ 22 */
22 23
23#include <sys/types.h> 24#include <sys/types.h>
24#include <sys/gpio.h> 25#include <sys/gpio.h>
25#include <sys/ioctl.h> 26#include <sys/ioctl.h>
26 27
27#include <err.h> 28#include <err.h>
 29#include <errno.h>
28#include <fcntl.h> 30#include <fcntl.h>
 31#include <limits.h>
 32#include <paths.h>
29#include <stdio.h> 33#include <stdio.h>
30#include <stdlib.h> 34#include <stdlib.h>
31#include <string.h> 35#include <string.h>
32#include <unistd.h> 36#include <unistd.h>
33 37
34#define _PATH_DEV_GPIO "/dev/gpio0" 
35 38
36static const char *device = _PATH_DEV_GPIO; 39char *dev;
37static int devfd = -1; 40int devfd = -1;
38static int quiet = 0; 41int quiet = 0;
39 42
40static void getinfo(void); 43void getinfo(void);
41static void pinread(int); 44void gpioread(int, char *);
42static void pinwrite(int, int); 45void gpiowrite(int, char *, int);
43static void pinctl(int, char *[], int); 46void gpioset(int pin, char *name, int flags, char *alias);
44static void usage(void); 47void gpiounset(int pin, char *name);
 48void devattach(char *, int, u_int32_t);
 49void devdetach(char *);
 50
 51__dead void usage(void);
 52
 53extern long long strtonum(const char *numstr, long long minval,
 54 long long maxval, const char **errstrp);
45 55
46static const struct bitstr { 56const struct bitstr {
47 unsigned int mask; 57 unsigned int mask;
48 const char *string; 58 const char *string;
49} pinflags[] = { 59} pinflags[] = {
50 { GPIO_PIN_INPUT, "in" }, 60 { GPIO_PIN_INPUT, "in" },
51 { GPIO_PIN_OUTPUT, "out" }, 61 { GPIO_PIN_OUTPUT, "out" },
52 { GPIO_PIN_INOUT, "inout" }, 62 { GPIO_PIN_INOUT, "inout" },
53 { GPIO_PIN_OPENDRAIN, "od" }, 63 { GPIO_PIN_OPENDRAIN, "od" },
54 { GPIO_PIN_PUSHPULL, "pp" }, 64 { GPIO_PIN_PUSHPULL, "pp" },
55 { GPIO_PIN_TRISTATE, "tri" }, 65 { GPIO_PIN_TRISTATE, "tri" },
56 { GPIO_PIN_PULLUP, "pu" }, 66 { GPIO_PIN_PULLUP, "pu" },
57 { GPIO_PIN_PULLDOWN, "pd" }, 67 { GPIO_PIN_PULLDOWN, "pd" },
58 { GPIO_PIN_INVIN, "iin" }, 68 { GPIO_PIN_INVIN, "iin" },
59 { GPIO_PIN_INVOUT, "iiout" }, 69 { GPIO_PIN_INVOUT, "iout" },
60 { 0, NULL }, 70 { 0, NULL },
61}; 71};
62 72
63int 73int
64main(int argc, char *argv[]) 74main(int argc, char *argv[])
65{ 75{
66 int ch; 76 const struct bitstr *bs;
 77 int pin, ch, n, fl = 0, value = 0;
 78 const char *errstr;
67 char *ep; 79 char *ep;
68 int do_ctl = 0; 80 int ga_offset = -1;
69 int pin = 0, value = 0; 81 u_int32_t ga_mask = 0;
70 82 long lval;
71 setprogname(argv[0]); 83 char *nam = NULL;
 84 char devn[32];
72 85
73 while ((ch = getopt(argc, argv, "cd:hq")) != -1) 86 while ((ch = getopt(argc, argv, "q")) != -1)
74 switch (ch) { 87 switch (ch) {
75 case 'c': 
76 do_ctl = 1; 
77 break; 
78 case 'd': 
79 device = optarg; 
80 break; 
81 case 'q': 88 case 'q':
82 quiet = 1; 89 quiet = 1;
83 break; 90 break;
84 case 'h': 
85 case '?': 
86 default: 91 default:
87 usage(); 92 usage();
88 /* NOTREACHED */ 93 /* NOTREACHED */
89 } 94 }
90 argc -= optind; 95 argc -= optind;
91 argv += optind; 96 argv += optind;
92 97
93 if (argc > 0) { 98 if (argc < 1)
94 pin = strtol(argv[0], &ep, 10); 99 usage();
95 if (*argv[0] == '\0' || *ep != '\0' || pin < 0) 100 dev = argv[0];
96 errx(EXIT_FAILURE, "%s: invalid pin", argv[0]); 101
 102 if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
 103 (void)snprintf(devn, sizeof(devn), "%s%s", _PATH_DEV, dev);
 104 dev = devn;
97 } 105 }
98 106
99 if ((devfd = open(device, O_RDWR)) == -1) 107 if ((devfd = open(dev, O_RDWR)) == -1)
100 err(EXIT_FAILURE, "%s", device); 108 err(EXIT_FAILURE, "%s", dev);
101 109
102 if (argc == 0 && !do_ctl) { 110 if (argc == 1) {
103 getinfo(); 111 getinfo();
104 } else if (argc == 1) { 112 return EXIT_SUCCESS;
105 if (do_ctl) 113 }
106 pinctl(pin, NULL, 0); 114
107 else 115 if (!strcmp(argv[1], "attach")) {
108 pinread(pin); 116 char *driver, *offset, *mask;
109 } else if (argc > 1) { 117
110 if (do_ctl) { 118 if (argc != 5)
111 pinctl(pin, argv + 1, argc - 1); 119 usage();
112 } else { 120
113 value = strtol(argv[1], &ep, 10); 121 driver = argv[2];
114 if (*argv[1] == '\0' || *ep != '\0') 122 offset = argv[3];
115 errx(EXIT_FAILURE, "%s: invalid value", 123 mask = argv[4];
116 argv[1]); 124
117 pinwrite(pin, value); 125 ga_offset = strtonum(offset, 0, INT_MAX, &errstr);
118 } 126 if (errstr)
 127 errx(EXIT_FAILURE, "offset is %s: %s", errstr, offset);
 128 lval = strtol(mask, &ep, 0);
 129 if (*mask == '\0' || *ep != '\0')
 130 errx(EXIT_FAILURE, "invalid mask (not a number)");
 131 if ((errno == ERANGE && (lval == LONG_MAX
 132 || lval == LONG_MIN)) || (unsigned long)lval > UINT_MAX)
 133 errx(EXIT_FAILURE, "mask out of range");
 134 ga_mask = lval;
 135 devattach(driver, ga_offset, ga_mask);
 136 return EXIT_SUCCESS;
 137 } else if (!strcmp(argv[1], "detach")) {
 138 if (argc != 3)
 139 usage();
 140 devdetach(argv[2]);
119 } else { 141 } else {
120 usage(); 142 char *nm = NULL;
121 /* NOTREACHED */ 143
 144 /* expecting a pin number or name */
 145 pin = strtonum(argv[1], 0, INT_MAX, &errstr);
 146 if (errstr)
 147 nm = argv[1]; /* try named pin */
 148 if (argc > 2) {
 149 if (!strcmp(argv[2], "set")) {
 150 for (n = 3; n < argc; n++) {
 151 for (bs = pinflags; bs->string != NULL;
 152 bs++) {
 153 if (!strcmp(argv[n],
 154 bs->string)) {
 155 fl |= bs->mask;
 156 break;
 157 }
 158 }
 159 if (bs->string == NULL)
 160 nam = argv[n];
 161 }
 162 gpioset(pin, nm, fl, nam);
 163 } else if (!strcmp(argv[2], "unset")) {
 164 gpiounset(pin, nm);
 165 } else {
 166 value = strtonum(argv[2], INT_MIN, INT_MAX,
 167 &errstr);
 168 if (errstr) {
 169 if (!strcmp(argv[2], "on"))
 170 value = 1;
 171 else if (!strcmp(argv[2], "off"))
 172 value = 0;
 173 else if (!strcmp(argv[2], "toggle"))
 174 value = 2;
 175 else
 176 errx(EXIT_FAILURE,
 177 "%s: invalid value",
 178 argv[2]);
 179 }
 180 gpiowrite(pin, nm, value);
 181 }
 182 } else
 183 gpioread(pin, nm);
122 } 184 }
123 185
124 return EXIT_SUCCESS; 186 return EXIT_SUCCESS;
125} 187}
126 188
127static void 189void
128getinfo(void) 190getinfo(void)
129{ 191{
130 struct gpio_info info; 192 struct gpio_info info;
131 193
132 memset(&info, 0, sizeof(info)); 
133 if (ioctl(devfd, GPIOINFO, &info) == -1) 194 if (ioctl(devfd, GPIOINFO, &info) == -1)
134 err(EXIT_FAILURE, "GPIOINFO"); 195 err(EXIT_FAILURE, "GPIOINFO");
135 196
136 if (quiet) 197 if (quiet)
137 return; 198 return;
138 199
139 printf("%s: %d pins\n", device, info.gpio_npins); 200 printf("%s: %d pins\n", dev, info.gpio_npins);
140} 201}
141 202
142static void 203void
143pinread(int pin) 204gpioread(int pin, char *gp_name)
144{ 205{
145 struct gpio_pin_op op; 206 struct gpio_req req;
146 207
147 memset(&op, 0, sizeof(op)); 208 memset(&req, 0, sizeof(req));
148 op.gp_pin = pin; 209 if (gp_name != NULL)
149 if (ioctl(devfd, GPIOPINREAD, &op) == -1) 210 strlcpy(req.gp_name, gp_name, sizeof(req.gp_name));
150 err(EXIT_FAILURE, "GPIOPINREAD"); 211 else
 212 req.gp_pin = pin;
 213
 214 if (ioctl(devfd, GPIOREAD, &req) == -1)
 215 err(EXIT_FAILURE, "GPIOREAD");
151 216
152 if (quiet) 217 if (quiet)
153 return; 218 return;
154 219
155 printf("pin %d: state %d\n", pin, op.gp_value); 220 if (gp_name)
 221 printf("pin %s: state %d\n", gp_name, req.gp_value);
 222 else
 223 printf("pin %d: state %d\n", pin, req.gp_value);
156} 224}
157 225
158static void 226void
159pinwrite(int pin, int value) 227gpiowrite(int pin, char *gp_name, int value)
160{ 228{
161 struct gpio_pin_op op; 229 struct gpio_req req;
162 230
163 if (value < 0 || value > 2) 231 if (value < 0 || value > 2)
164 errx(EXIT_FAILURE, "%d: invalid value", value); 232 errx(EXIT_FAILURE, "%d: invalid value", value);
165 233
166 memset(&op, 0, sizeof(op)); 234 memset(&req, 0, sizeof(req));
167 op.gp_pin = pin; 235 if (gp_name != NULL)
168 op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH); 236 strlcpy(req.gp_name, gp_name, sizeof(req.gp_name));
 237 else
 238 req.gp_pin = pin;
 239 req.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH);
169 if (value < 2) { 240 if (value < 2) {
170 if (ioctl(devfd, GPIOPINWRITE, &op) == -1) 241 if (ioctl(devfd, GPIOWRITE, &req) == -1)
171 err(EXIT_FAILURE, "GPIOPINWRITE"); 242 err(EXIT_FAILURE, "GPIOWRITE");
172 } else { 243 } else {
173 if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1) 244 if (ioctl(devfd, GPIOTOGGLE, &req) == -1)
174 err(EXIT_FAILURE, "GPIOPINTOGGLE"); 245 err(EXIT_FAILURE, "GPIOTOGGLE");
175 } 246 }
176 247
177 if (quiet) 248 if (quiet)
178 return; 249 return;
179 250
180 printf("pin %d: state %d -> %d\n", pin, op.gp_value, 251 if (gp_name)
181 (value < 2 ? value : 1 - op.gp_value)); 252 printf("pin %s: state %d -> %d\n", gp_name, req.gp_value,
 253 (value < 2 ? value : 1 - req.gp_value));
 254 else
 255 printf("pin %d: state %d -> %d\n", pin, req.gp_value,
 256 (value < 2 ? value : 1 - req.gp_value));
182} 257}
183 258
184static void 259void
185pinctl(int pin, char *flags[], int nflags) 260gpioset(int pin, char *name, int fl, char *alias)
186{ 261{
187 struct gpio_pin_ctl ctl; 262 struct gpio_set set;
188 int fl = 0; 
189 const struct bitstr *bs; 263 const struct bitstr *bs;
190 int i; 
191 264
192 memset(&ctl, 0, sizeof(ctl)); 265 memset(&set, 0, sizeof(set));
193 ctl.gp_pin = pin; 266 if (name != NULL)
194 if (flags != NULL) { 267 strlcpy(set.gp_name, name, sizeof(set.gp_name));
195 for (i = 0; i < nflags; i++) 268 else
196 for (bs = pinflags; bs->string != NULL; bs++) 269 set.gp_pin = pin;
197 if (strcmp(flags[i], bs->string) == 0) { 270 set.gp_flags = fl;
198 fl |= bs->mask; 271
199 break; 272 if (alias != NULL)
200 } 273 strlcpy(set.gp_name2, alias, sizeof(set.gp_name2));
201 } 274
202 ctl.gp_flags = fl; 275 if (ioctl(devfd, GPIOSET, &set) == -1)
203 if (ioctl(devfd, GPIOPINCTL, &ctl) == -1) 276 err(EXIT_FAILURE, "GPIOSET");
204 err(EXIT_FAILURE, "GPIOPINCTL"); 
205 277
206 if (quiet) 278 if (quiet)
207 return; 279 return;
208 280
209 printf("pin %d: caps:", pin); 281 if (name != NULL)
 282 printf("pin %s: caps:", name);
 283 else
 284 printf("pin %d: caps:", pin);
210 for (bs = pinflags; bs->string != NULL; bs++) 285 for (bs = pinflags; bs->string != NULL; bs++)
211 if (ctl.gp_caps & bs->mask) 286 if (set.gp_caps & bs->mask)
212 printf(" %s", bs->string); 287 printf(" %s", bs->string);
213 printf(", flags:"); 288 printf(", flags:");
214 for (bs = pinflags; bs->string != NULL; bs++) 289 for (bs = pinflags; bs->string != NULL; bs++)
215 if (ctl.gp_flags & bs->mask) 290 if (set.gp_flags & bs->mask)
216 printf(" %s", bs->string); 291 printf(" %s", bs->string);
217 if (fl > 0) { 292 if (fl > 0) {
218 printf(" ->"); 293 printf(" ->");
219 for (bs = pinflags; bs->string != NULL; bs++) 294 for (bs = pinflags; bs->string != NULL; bs++)
220 if (fl & bs->mask) 295 if (fl & bs->mask)
221 printf(" %s", bs->string); 296 printf(" %s", bs->string);
222 } 297 }
223 printf("\n"); 298 printf("\n");
224} 299}
225 300
226static void 301void
 302gpiounset(int pin, char *name)
 303{
 304 struct gpio_set set;
 305
 306 memset(&set, 0, sizeof(set));
 307 if (name != NULL)
 308 strlcpy(set.gp_name, name, sizeof(set.gp_name));
 309 else
 310 set.gp_pin = pin;
 311
 312 if (ioctl(devfd, GPIOUNSET, &set) == -1)
 313 err(EXIT_FAILURE, "GPIOUNSET");
 314}
 315
 316void
 317devattach(char *dvname, int offset, u_int32_t mask)
 318{
 319 struct gpio_attach attach;
 320
 321 memset(&attach, 0, sizeof(attach));
 322 strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname));
 323 attach.ga_offset = offset;
 324 attach.ga_mask = mask;
 325 if (ioctl(devfd, GPIOATTACH, &attach) == -1)
 326 err(EXIT_FAILURE, "GPIOATTACH");
 327}
 328
 329void
 330devdetach(char *dvname)
 331{
 332 struct gpio_attach attach;
 333
 334 memset(&attach, 0, sizeof(attach));
 335 strlcpy(attach.ga_dvname, dvname, sizeof(attach.ga_dvname));
 336 if (ioctl(devfd, GPIODETACH, &attach) == -1)
 337 err(EXIT_FAILURE, "GPIODETACH");
 338}
 339
 340void
227usage(void) 341usage(void)
228{ 342{
229 fprintf(stderr, "usage: %s [-hq] [-d device] [pin] [0 | 1 | 2]\n", 343 extern char *__progname;
230 getprogname()); 344
231 fprintf(stderr, " %s [-hq] [-d device] -c pin [flags]\n", 345 fprintf(stderr, "usage: %s [-q] device [pin] [0 | 1 | 2 | "
232 getprogname()); 346 "on | off | toggle]\n", __progname);
 347 fprintf(stderr, " %s [-q] device pin set [flags] [name]\n",
 348 __progname);
 349 fprintf(stderr, " %s [-q] device pin unset\n", __progname);
 350 fprintf(stderr, " %s [-q] device attach device offset mask\n",
 351 __progname);
 352 fprintf(stderr, " %s [-q] device detach device\n", __progname);
233 353
234 exit(EXIT_FAILURE); 354 exit(EXIT_FAILURE);
235} 355}

File Added: src/usr.sbin/gpioctl/Attic/strtonum.c
/* $NetBSD: strtonum.c,v 1.1 2009/07/25 16:18:09 mbalmer Exp $ */
/*	$OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $	*/

/*
 * Copyright (c) 2004 Ted Unangst and Todd Miller
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <errno.h>
#include <limits.h>
#include <stdlib.h>

#define INVALID 	1
#define TOOSMALL 	2
#define TOOLARGE 	3

long long strtonum(const char *numstr, long long minval, long long maxval,
    const char **errstrp);

long long
strtonum(const char *numstr, long long minval, long long maxval,
    const char **errstrp)
{
	long long ll = 0;
	char *ep;
	int error = 0;
	struct errval {
		const char *errstr;
		int err;
	} ev[4] = {
		{ NULL,		0 },
		{ "invalid",	EINVAL },
		{ "too small",	ERANGE },
		{ "too large",	ERANGE },
	};

	ev[0].err = errno;
	errno = 0;
	if (minval > maxval)
		error = INVALID;
	else {
		ll = strtoll(numstr, &ep, 10);
		if (numstr == ep || *ep != '\0')
			error = INVALID;
		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
			error = TOOSMALL;
		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
			error = TOOLARGE;
	}
	if (errstrp != NULL)
		*errstrp = ev[error].errstr;
	errno = ev[error].err;
	if (error)
		ll = 0;

	return (ll);
}