2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
46 struct flag_desc gpio_flags[] = {
47 { "IN", GPIO_PIN_INPUT },
48 { "OUT", GPIO_PIN_OUTPUT },
49 { "OD", GPIO_PIN_OPENDRAIN },
50 { "PP", GPIO_PIN_PUSHPULL },
51 { "TS", GPIO_PIN_TRISTATE },
52 { "PU", GPIO_PIN_PULLUP },
53 { "PD", GPIO_PIN_PULLDOWN },
54 { "II", GPIO_PIN_INVIN },
55 { "IO", GPIO_PIN_INVOUT },
56 { "PULSE", GPIO_PIN_PULSATE },
60 int str2cap(const char *str);
65 fprintf(stderr, "Usage:\n");
66 fprintf(stderr, "\tgpioctl -f ctldev -l [-v]\n");
67 fprintf(stderr, "\tgpioctl -f ctldev -t pin\n");
68 fprintf(stderr, "\tgpioctl -f ctldev -c pin flag ...\n");
69 fprintf(stderr, "\tgpioctl -f ctldev pin [0|1]\n");
76 struct flag_desc * pdesc = gpio_flags;
78 if (pdesc->flag == cap)
87 str2cap(const char *str)
89 struct flag_desc * pdesc = gpio_flags;
91 if (strcasecmp(str, pdesc->name) == 0)
100 * Our handmade function for converting string to number
103 str2int(const char *s, int *ok)
106 int res = strtod(s, &endptr);
107 if (endptr != s + strlen(s) )
122 for (i = 0; i < 32; i++) {
123 if (caps & (1 << i)) {
126 printf("%s", cap2str(1 << i));
134 dump_pins(int fd, int verbose)
140 if (ioctl(fd, GPIOMAXPIN, &maxpin) < 0) {
141 perror("ioctl(GPIOMAXPIN)");
145 for (i = 0; i <= maxpin; i++) {
147 if (ioctl(fd, GPIOGETCONFIG, &pin) < 0)
148 /* For some reason this pin is inaccessible */
152 if (ioctl(fd, GPIOGET, &req) < 0) {
153 /* Now, that's wrong */
154 perror("ioctl(GPIOGET)");
158 printf("pin %02d:\t%d\t%s", pin.gp_pin, req.gp_value,
161 print_caps(pin.gp_flags);
165 print_caps(pin.gp_caps);
172 fail(const char *fmt, ...)
177 vfprintf(stderr, fmt, ap);
183 main(int argc, char **argv)
188 char *ctlfile = NULL;
189 int pinn, pinv, fd, ch;
191 int config, toggle, verbose, list;
193 config = toggle = verbose = list = pinn = 0;
195 while ((ch = getopt(argc, argv, "c:f:lt:v")) != -1) {
199 pinn = str2int(optarg, &ok);
201 fail("Invalid pin number: %s\n", optarg);
211 pinn = str2int(optarg, &ok);
213 fail("Invalid pin number: %s\n", optarg);
225 for (i = 0; i < argc; i++)
226 printf("%d/%s\n", i, argv[i]);
229 fail("No gpioctl device provided\n");
231 fd = open(ctlfile, O_RDONLY);
238 dump_pins(fd, verbose);
245 * -t pin assumes no additional arguments
253 if (ioctl(fd, GPIOTOGGLE, &req) < 0) {
254 perror("ioctl(GPIOTOGGLE)");
264 for (i = 0; i < argc; i++) {
265 flag = str2cap(argv[i]);
267 fail("Invalid flag: %s\n", argv[i]);
272 pin.gp_flags = flags;
273 if (ioctl(fd, GPIOSETCONFIG, &pin) < 0) {
274 perror("ioctl(GPIOSETCONFIG)");
282 * Last two cases - set value or print value
284 if ((argc == 0) || (argc > 2)) {
289 pinn = str2int(argv[0], &ok);
291 fail("Invalid pin number: %s\n", argv[0]);
298 if (ioctl(fd, GPIOGET, &req) < 0) {
299 perror("ioctl(GPIOGET)");
302 printf("%d\n", req.gp_value);
306 /* Is it valid number (0 or 1) ? */
307 pinv = str2int(argv[1], &ok);
308 if (!ok || ((pinv != 0) && (pinv != 1)))
309 fail("Invalid pin value: %s\n", argv[1]);
316 if (ioctl(fd, GPIOSET, &req) < 0) {
317 perror("ioctl(GPIOSET)");