1 /* $NetBSD: gpioctl.c,v 1.7 2009/09/25 19:37:03 mbalmer Exp $ */
4 * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org>
5 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Program to control GPIO devices.
24 #include <sys/types.h>
26 #include <sys/ioctl.h>
44 void gpioread(int, char *);
45 void gpiowrite(int, char *, int);
46 void gpioset(int pin
, char *name
, int flags
, char *alias
);
47 void gpiounset(int pin
, char *name
);
48 void devattach(char *, int, u_int32_t
);
49 void devdetach(char *);
51 __dead
void usage(void);
53 extern long long strtonum(const char *numstr
, long long minval
,
54 long long maxval
, const char **errstrp
);
60 { GPIO_PIN_INPUT
, "in" },
61 { GPIO_PIN_OUTPUT
, "out" },
62 { GPIO_PIN_INOUT
, "inout" },
63 { GPIO_PIN_OPENDRAIN
, "od" },
64 { GPIO_PIN_PUSHPULL
, "pp" },
65 { GPIO_PIN_TRISTATE
, "tri" },
66 { GPIO_PIN_PULLUP
, "pu" },
67 { GPIO_PIN_PULLDOWN
, "pd" },
68 { GPIO_PIN_INVIN
, "iin" },
69 { GPIO_PIN_INVOUT
, "iout" },
70 { GPIO_PIN_PULSATE
, "pulsate" },
75 main(int argc
, char *argv
[])
77 const struct bitstr
*bs
;
78 int pin
, ch
, n
, fl
= 0, value
= 0;
82 u_int32_t ga_mask
= 0;
87 while ((ch
= getopt(argc
, argv
, "q")) != -1)
103 if (strncmp(_PATH_DEV
, dev
, sizeof(_PATH_DEV
) - 1)) {
104 (void)snprintf(devn
, sizeof(devn
), "%s%s", _PATH_DEV
, dev
);
108 if ((devfd
= open(dev
, O_RDWR
)) == -1)
109 err(EXIT_FAILURE
, "%s", dev
);
116 if (!strcmp(argv
[1], "attach")) {
117 char *driver
, *offset
, *mask
;
126 ga_offset
= strtonum(offset
, 0, INT_MAX
, &errstr
);
128 errx(EXIT_FAILURE
, "offset is %s: %s", errstr
, offset
);
129 lval
= strtol(mask
, &ep
, 0);
130 if (*mask
== '\0' || *ep
!= '\0')
131 errx(EXIT_FAILURE
, "invalid mask (not a number)");
132 if ((errno
== ERANGE
&& (lval
== LONG_MAX
133 || lval
== LONG_MIN
)) || (unsigned long)lval
> UINT_MAX
)
134 errx(EXIT_FAILURE
, "mask out of range");
136 devattach(driver
, ga_offset
, ga_mask
);
138 } else if (!strcmp(argv
[1], "detach")) {
145 /* expecting a pin number or name */
146 pin
= strtonum(argv
[1], 0, INT_MAX
, &errstr
);
148 nm
= argv
[1]; /* try named pin */
150 if (!strcmp(argv
[2], "set")) {
151 for (n
= 3; n
< argc
; n
++) {
152 for (bs
= pinflags
; bs
->string
!= NULL
;
160 if (bs
->string
== NULL
)
163 gpioset(pin
, nm
, fl
, nam
);
164 } else if (!strcmp(argv
[2], "unset")) {
167 value
= strtonum(argv
[2], INT_MIN
, INT_MAX
,
170 if (!strcmp(argv
[2], "on"))
172 else if (!strcmp(argv
[2], "off"))
174 else if (!strcmp(argv
[2], "toggle"))
181 gpiowrite(pin
, nm
, value
);
193 struct gpio_info info
;
195 if (ioctl(devfd
, GPIOINFO
, &info
) == -1)
196 err(EXIT_FAILURE
, "GPIOINFO");
201 printf("%s: %d pins\n", dev
, info
.gpio_npins
);
205 gpioread(int pin
, char *gp_name
)
209 memset(&req
, 0, sizeof(req
));
211 strlcpy(req
.gp_name
, gp_name
, sizeof(req
.gp_name
));
215 if (ioctl(devfd
, GPIOREAD
, &req
) == -1)
216 err(EXIT_FAILURE
, "GPIOREAD");
222 printf("pin %s: state %d\n", gp_name
, req
.gp_value
);
224 printf("pin %d: state %d\n", pin
, req
.gp_value
);
228 gpiowrite(int pin
, char *gp_name
, int value
)
232 if (value
< 0 || value
> 2)
233 errx(EXIT_FAILURE
, "%d: invalid value", value
);
235 memset(&req
, 0, sizeof(req
));
237 strlcpy(req
.gp_name
, gp_name
, sizeof(req
.gp_name
));
240 req
.gp_value
= (value
== 0 ? GPIO_PIN_LOW
: GPIO_PIN_HIGH
);
242 if (ioctl(devfd
, GPIOWRITE
, &req
) == -1)
243 err(EXIT_FAILURE
, "GPIOWRITE");
245 if (ioctl(devfd
, GPIOTOGGLE
, &req
) == -1)
246 err(EXIT_FAILURE
, "GPIOTOGGLE");
253 printf("pin %s: state %d -> %d\n", gp_name
, req
.gp_value
,
254 (value
< 2 ? value
: 1 - req
.gp_value
));
256 printf("pin %d: state %d -> %d\n", pin
, req
.gp_value
,
257 (value
< 2 ? value
: 1 - req
.gp_value
));
261 gpioset(int pin
, char *name
, int fl
, char *alias
)
264 const struct bitstr
*bs
;
266 memset(&set
, 0, sizeof(set
));
268 strlcpy(set
.gp_name
, name
, sizeof(set
.gp_name
));
274 strlcpy(set
.gp_name2
, alias
, sizeof(set
.gp_name2
));
276 if (ioctl(devfd
, GPIOSET
, &set
) == -1)
277 err(EXIT_FAILURE
, "GPIOSET");
283 printf("pin %s: caps:", name
);
285 printf("pin %d: caps:", pin
);
286 for (bs
= pinflags
; bs
->string
!= NULL
; bs
++)
287 if (set
.gp_caps
& bs
->mask
)
288 printf(" %s", bs
->string
);
290 for (bs
= pinflags
; bs
->string
!= NULL
; bs
++)
291 if (set
.gp_flags
& bs
->mask
)
292 printf(" %s", bs
->string
);
295 for (bs
= pinflags
; bs
->string
!= NULL
; bs
++)
297 printf(" %s", bs
->string
);
303 gpiounset(int pin
, char *name
)
307 memset(&set
, 0, sizeof(set
));
309 strlcpy(set
.gp_name
, name
, sizeof(set
.gp_name
));
313 if (ioctl(devfd
, GPIOUNSET
, &set
) == -1)
314 err(EXIT_FAILURE
, "GPIOUNSET");
318 devattach(char *dvname
, int offset
, u_int32_t mask
)
320 struct gpio_attach attach
;
322 memset(&attach
, 0, sizeof(attach
));
323 strlcpy(attach
.ga_dvname
, dvname
, sizeof(attach
.ga_dvname
));
324 attach
.ga_offset
= offset
;
325 attach
.ga_mask
= mask
;
326 if (ioctl(devfd
, GPIOATTACH
, &attach
) == -1)
327 err(EXIT_FAILURE
, "GPIOATTACH");
331 devdetach(char *dvname
)
333 struct gpio_attach attach
;
335 memset(&attach
, 0, sizeof(attach
));
336 strlcpy(attach
.ga_dvname
, dvname
, sizeof(attach
.ga_dvname
));
337 if (ioctl(devfd
, GPIODETACH
, &attach
) == -1)
338 err(EXIT_FAILURE
, "GPIODETACH");
344 extern char *__progname
;
346 fprintf(stderr
, "usage: %s [-q] device [pin] [0 | 1 | 2 | "
347 "on | off | toggle]\n", __progname
);
348 fprintf(stderr
, " %s [-q] device pin set [flags] [name]\n",
350 fprintf(stderr
, " %s [-q] device pin unset\n", __progname
);
351 fprintf(stderr
, " %s [-q] device attach device offset mask\n",
353 fprintf(stderr
, " %s [-q] device detach device\n", __progname
);