xref: /freebsd-src/usr.sbin/gpioctl/gpioctl.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
1968ec6a6SOleksandr Tymoshenko /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4968ec6a6SOleksandr Tymoshenko  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
5244c371dSRui Paulo  * Copyright (c) 2014, Rui Paulo <rpaulo@FreeBSD.org>
63b2bb133SOleksandr Tymoshenko  * Copyright (c) 2015, Emmanuel Vadot <manu@bidouilliste.com>
7968ec6a6SOleksandr Tymoshenko  * All rights reserved.
8968ec6a6SOleksandr Tymoshenko  *
9968ec6a6SOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
10968ec6a6SOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
11968ec6a6SOleksandr Tymoshenko  * are met:
12968ec6a6SOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
13968ec6a6SOleksandr Tymoshenko  *    notice unmodified, this list of conditions, and the following
14968ec6a6SOleksandr Tymoshenko  *    disclaimer.
15968ec6a6SOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
16968ec6a6SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
17968ec6a6SOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
18968ec6a6SOleksandr Tymoshenko  *
19968ec6a6SOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20968ec6a6SOleksandr Tymoshenko  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21968ec6a6SOleksandr Tymoshenko  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22968ec6a6SOleksandr Tymoshenko  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23968ec6a6SOleksandr Tymoshenko  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24968ec6a6SOleksandr Tymoshenko  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25968ec6a6SOleksandr Tymoshenko  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26968ec6a6SOleksandr Tymoshenko  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27968ec6a6SOleksandr Tymoshenko  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28968ec6a6SOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29968ec6a6SOleksandr Tymoshenko  * SUCH DAMAGE.
30968ec6a6SOleksandr Tymoshenko  */
31968ec6a6SOleksandr Tymoshenko 
32968ec6a6SOleksandr Tymoshenko #include <sys/cdefs.h>
33968ec6a6SOleksandr Tymoshenko #include <fcntl.h>
34968ec6a6SOleksandr Tymoshenko #include <getopt.h>
3522e3858cSSean Bruno #include <paths.h>
36968ec6a6SOleksandr Tymoshenko #include <stdio.h>
37968ec6a6SOleksandr Tymoshenko #include <stdarg.h>
38968ec6a6SOleksandr Tymoshenko #include <stdlib.h>
39968ec6a6SOleksandr Tymoshenko #include <string.h>
40968ec6a6SOleksandr Tymoshenko #include <unistd.h>
41968ec6a6SOleksandr Tymoshenko 
42244c371dSRui Paulo #include <libgpio.h>
43968ec6a6SOleksandr Tymoshenko 
443b2bb133SOleksandr Tymoshenko #define PIN_TYPE_NUMBER		1
453b2bb133SOleksandr Tymoshenko #define PIN_TYPE_NAME		2
463b2bb133SOleksandr Tymoshenko 
47968ec6a6SOleksandr Tymoshenko struct flag_desc {
48968ec6a6SOleksandr Tymoshenko 	const char *name;
49968ec6a6SOleksandr Tymoshenko 	uint32_t flag;
50968ec6a6SOleksandr Tymoshenko };
51968ec6a6SOleksandr Tymoshenko 
52bf70beceSEd Schouten static struct flag_desc gpio_flags[] = {
53968ec6a6SOleksandr Tymoshenko 	{ "IN", GPIO_PIN_INPUT },
54968ec6a6SOleksandr Tymoshenko 	{ "OUT", GPIO_PIN_OUTPUT },
55968ec6a6SOleksandr Tymoshenko 	{ "OD", GPIO_PIN_OPENDRAIN },
56968ec6a6SOleksandr Tymoshenko 	{ "PP", GPIO_PIN_PUSHPULL },
57968ec6a6SOleksandr Tymoshenko 	{ "TS", GPIO_PIN_TRISTATE },
58968ec6a6SOleksandr Tymoshenko 	{ "PU", GPIO_PIN_PULLUP },
59968ec6a6SOleksandr Tymoshenko 	{ "PD", GPIO_PIN_PULLDOWN },
60968ec6a6SOleksandr Tymoshenko 	{ "II", GPIO_PIN_INVIN },
61968ec6a6SOleksandr Tymoshenko 	{ "IO", GPIO_PIN_INVOUT },
62968ec6a6SOleksandr Tymoshenko 	{ "PULSE", GPIO_PIN_PULSATE },
6319602a38SEmmanuel Vadot 	{ "INTRLL", GPIO_INTR_LEVEL_LOW},
6419602a38SEmmanuel Vadot 	{ "INTRLH", GPIO_INTR_LEVEL_HIGH},
6519602a38SEmmanuel Vadot 	{ "INTRER", GPIO_INTR_EDGE_RISING},
6619602a38SEmmanuel Vadot 	{ "INTREF", GPIO_INTR_EDGE_FALLING},
6719602a38SEmmanuel Vadot 	{ "INTREB", GPIO_INTR_EDGE_BOTH},
68968ec6a6SOleksandr Tymoshenko 	{ NULL, 0 },
69968ec6a6SOleksandr Tymoshenko };
70968ec6a6SOleksandr Tymoshenko 
71968ec6a6SOleksandr Tymoshenko int str2cap(const char *str);
72968ec6a6SOleksandr Tymoshenko 
73968ec6a6SOleksandr Tymoshenko static void
usage(void)74968ec6a6SOleksandr Tymoshenko usage(void)
75968ec6a6SOleksandr Tymoshenko {
76968ec6a6SOleksandr Tymoshenko 	fprintf(stderr, "Usage:\n");
7722e3858cSSean Bruno 	fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n");
783b2bb133SOleksandr Tymoshenko 	fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -t pin\n");
793b2bb133SOleksandr Tymoshenko 	fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -c pin flag ...\n");
803b2bb133SOleksandr Tymoshenko 	fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -n pin pin-name\n");
813b2bb133SOleksandr Tymoshenko 	fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] pin [0|1]\n");
82968ec6a6SOleksandr Tymoshenko 	exit(1);
83968ec6a6SOleksandr Tymoshenko }
84968ec6a6SOleksandr Tymoshenko 
85968ec6a6SOleksandr Tymoshenko static const char *
cap2str(uint32_t cap)86968ec6a6SOleksandr Tymoshenko cap2str(uint32_t cap)
87968ec6a6SOleksandr Tymoshenko {
88968ec6a6SOleksandr Tymoshenko 	struct flag_desc * pdesc = gpio_flags;
89968ec6a6SOleksandr Tymoshenko 	while (pdesc->name) {
90968ec6a6SOleksandr Tymoshenko 		if (pdesc->flag == cap)
91968ec6a6SOleksandr Tymoshenko 			return pdesc->name;
92968ec6a6SOleksandr Tymoshenko 		pdesc++;
93968ec6a6SOleksandr Tymoshenko 	}
94968ec6a6SOleksandr Tymoshenko 
95968ec6a6SOleksandr Tymoshenko 	return "UNKNOWN";
96968ec6a6SOleksandr Tymoshenko }
97968ec6a6SOleksandr Tymoshenko 
98968ec6a6SOleksandr Tymoshenko int
str2cap(const char * str)99968ec6a6SOleksandr Tymoshenko str2cap(const char *str)
100968ec6a6SOleksandr Tymoshenko {
101968ec6a6SOleksandr Tymoshenko 	struct flag_desc * pdesc = gpio_flags;
102968ec6a6SOleksandr Tymoshenko 	while (pdesc->name) {
103968ec6a6SOleksandr Tymoshenko 		if (strcasecmp(str, pdesc->name) == 0)
104968ec6a6SOleksandr Tymoshenko 			return pdesc->flag;
105968ec6a6SOleksandr Tymoshenko 		pdesc++;
106968ec6a6SOleksandr Tymoshenko 	}
107968ec6a6SOleksandr Tymoshenko 
108968ec6a6SOleksandr Tymoshenko 	return (-1);
109968ec6a6SOleksandr Tymoshenko }
110968ec6a6SOleksandr Tymoshenko 
111968ec6a6SOleksandr Tymoshenko /*
112968ec6a6SOleksandr Tymoshenko  * Our handmade function for converting string to number
113968ec6a6SOleksandr Tymoshenko  */
114968ec6a6SOleksandr Tymoshenko static int
str2int(const char * s,int * ok)115968ec6a6SOleksandr Tymoshenko str2int(const char *s, int *ok)
116968ec6a6SOleksandr Tymoshenko {
117968ec6a6SOleksandr Tymoshenko 	char *endptr;
118968ec6a6SOleksandr Tymoshenko 	int res = strtod(s, &endptr);
119968ec6a6SOleksandr Tymoshenko 	if (endptr != s + strlen(s) )
120968ec6a6SOleksandr Tymoshenko 		*ok = 0;
121968ec6a6SOleksandr Tymoshenko 	else
122968ec6a6SOleksandr Tymoshenko 		*ok = 1;
123968ec6a6SOleksandr Tymoshenko 
124968ec6a6SOleksandr Tymoshenko 	return res;
125968ec6a6SOleksandr Tymoshenko }
126968ec6a6SOleksandr Tymoshenko 
127968ec6a6SOleksandr Tymoshenko static void
print_caps(int caps)128968ec6a6SOleksandr Tymoshenko print_caps(int caps)
129968ec6a6SOleksandr Tymoshenko {
130968ec6a6SOleksandr Tymoshenko 	int i, need_coma;
131968ec6a6SOleksandr Tymoshenko 
132968ec6a6SOleksandr Tymoshenko 	need_coma = 0;
133968ec6a6SOleksandr Tymoshenko 	printf("<");
134968ec6a6SOleksandr Tymoshenko 	for (i = 0; i < 32; i++) {
135968ec6a6SOleksandr Tymoshenko 		if (caps & (1 << i)) {
136968ec6a6SOleksandr Tymoshenko 			if (need_coma)
137968ec6a6SOleksandr Tymoshenko 				printf(",");
138968ec6a6SOleksandr Tymoshenko 			printf("%s", cap2str(1 << i));
139968ec6a6SOleksandr Tymoshenko 			need_coma = 1;
140968ec6a6SOleksandr Tymoshenko 		}
141968ec6a6SOleksandr Tymoshenko 	}
142968ec6a6SOleksandr Tymoshenko 	printf(">");
143968ec6a6SOleksandr Tymoshenko }
144968ec6a6SOleksandr Tymoshenko 
145968ec6a6SOleksandr Tymoshenko static void
dump_pins(gpio_handle_t handle,int verbose)146244c371dSRui Paulo dump_pins(gpio_handle_t handle, int verbose)
147968ec6a6SOleksandr Tymoshenko {
148244c371dSRui Paulo 	int i, maxpin, pinv;
149244c371dSRui Paulo 	gpio_config_t *cfgs;
150244c371dSRui Paulo 	gpio_config_t *pin;
151968ec6a6SOleksandr Tymoshenko 
152244c371dSRui Paulo 	maxpin = gpio_pin_list(handle, &cfgs);
153244c371dSRui Paulo 	if (maxpin < 0) {
154244c371dSRui Paulo 		perror("gpio_pin_list");
155968ec6a6SOleksandr Tymoshenko 		exit(1);
156968ec6a6SOleksandr Tymoshenko 	}
157968ec6a6SOleksandr Tymoshenko 
158968ec6a6SOleksandr Tymoshenko 	for (i = 0; i <= maxpin; i++) {
159244c371dSRui Paulo 		pin = cfgs + i;
160244c371dSRui Paulo 		pinv = gpio_pin_get(handle, pin->g_pin);
161244c371dSRui Paulo 		printf("pin %02d:\t%d\t%s", pin->g_pin, pinv,
162244c371dSRui Paulo 		    pin->g_name);
163968ec6a6SOleksandr Tymoshenko 
164244c371dSRui Paulo 		print_caps(pin->g_flags);
165968ec6a6SOleksandr Tymoshenko 
166968ec6a6SOleksandr Tymoshenko 		if (verbose) {
167968ec6a6SOleksandr Tymoshenko 			printf(", caps:");
168244c371dSRui Paulo 			print_caps(pin->g_caps);
169968ec6a6SOleksandr Tymoshenko 		}
170968ec6a6SOleksandr Tymoshenko 		printf("\n");
171968ec6a6SOleksandr Tymoshenko 	}
17221bc384aSLuiz Otavio O Souza 	free(cfgs);
173968ec6a6SOleksandr Tymoshenko }
174968ec6a6SOleksandr Tymoshenko 
1753b2bb133SOleksandr Tymoshenko static int
get_pinnum_by_name(gpio_handle_t handle,const char * name)1763b2bb133SOleksandr Tymoshenko get_pinnum_by_name(gpio_handle_t handle, const char *name) {
1773b2bb133SOleksandr Tymoshenko 	int i, maxpin, pinn;
1783b2bb133SOleksandr Tymoshenko 	gpio_config_t *cfgs;
1793b2bb133SOleksandr Tymoshenko 	gpio_config_t *pin;
1803b2bb133SOleksandr Tymoshenko 
1813b2bb133SOleksandr Tymoshenko 	pinn = -1;
1823b2bb133SOleksandr Tymoshenko 	maxpin = gpio_pin_list(handle, &cfgs);
1833b2bb133SOleksandr Tymoshenko 	if (maxpin < 0) {
1843b2bb133SOleksandr Tymoshenko 		perror("gpio_pin_list");
1853b2bb133SOleksandr Tymoshenko 		exit(1);
1863b2bb133SOleksandr Tymoshenko 	}
1873b2bb133SOleksandr Tymoshenko 
1883b2bb133SOleksandr Tymoshenko 	for (i = 0; i <= maxpin; i++) {
1893b2bb133SOleksandr Tymoshenko 		pin = cfgs + i;
1903b2bb133SOleksandr Tymoshenko 		gpio_pin_get(handle, pin->g_pin);
1913b2bb133SOleksandr Tymoshenko 		if (!strcmp(name, pin->g_name)) {
1923b2bb133SOleksandr Tymoshenko 			pinn = i;
1933b2bb133SOleksandr Tymoshenko 			break;
1943b2bb133SOleksandr Tymoshenko 		}
1953b2bb133SOleksandr Tymoshenko 	}
1963b2bb133SOleksandr Tymoshenko 	free(cfgs);
1973b2bb133SOleksandr Tymoshenko 
1983b2bb133SOleksandr Tymoshenko 	return pinn;
1993b2bb133SOleksandr Tymoshenko }
2003b2bb133SOleksandr Tymoshenko 
201968ec6a6SOleksandr Tymoshenko static void
fail(const char * fmt,...)202968ec6a6SOleksandr Tymoshenko fail(const char *fmt, ...)
203968ec6a6SOleksandr Tymoshenko {
204968ec6a6SOleksandr Tymoshenko 	va_list ap;
205968ec6a6SOleksandr Tymoshenko 
206968ec6a6SOleksandr Tymoshenko 	va_start(ap, fmt);
207968ec6a6SOleksandr Tymoshenko 	vfprintf(stderr, fmt, ap);
208968ec6a6SOleksandr Tymoshenko 	va_end(ap);
209968ec6a6SOleksandr Tymoshenko 	exit(1);
210968ec6a6SOleksandr Tymoshenko }
211968ec6a6SOleksandr Tymoshenko 
212968ec6a6SOleksandr Tymoshenko int
main(int argc,char ** argv)213968ec6a6SOleksandr Tymoshenko main(int argc, char **argv)
214968ec6a6SOleksandr Tymoshenko {
215968ec6a6SOleksandr Tymoshenko 	int i;
216244c371dSRui Paulo 	gpio_config_t pin;
217244c371dSRui Paulo 	gpio_handle_t handle;
218968ec6a6SOleksandr Tymoshenko 	char *ctlfile = NULL;
2193b2bb133SOleksandr Tymoshenko 	int pinn, pinv, pin_type, ch;
220968ec6a6SOleksandr Tymoshenko 	int flags, flag, ok;
221d752f0f6SLuiz Otavio O Souza 	int config, list, name, toggle, verbose;
222968ec6a6SOleksandr Tymoshenko 
2233b2bb133SOleksandr Tymoshenko 	config = toggle = verbose = list = name = pin_type = 0;
224968ec6a6SOleksandr Tymoshenko 
2253b2bb133SOleksandr Tymoshenko 	while ((ch = getopt(argc, argv, "cf:lntvNp")) != -1) {
226968ec6a6SOleksandr Tymoshenko 		switch (ch) {
227968ec6a6SOleksandr Tymoshenko 		case 'c':
228968ec6a6SOleksandr Tymoshenko 			config = 1;
229968ec6a6SOleksandr Tymoshenko 			break;
230968ec6a6SOleksandr Tymoshenko 		case 'f':
231968ec6a6SOleksandr Tymoshenko 			ctlfile = optarg;
232968ec6a6SOleksandr Tymoshenko 			break;
233968ec6a6SOleksandr Tymoshenko 		case 'l':
234968ec6a6SOleksandr Tymoshenko 			list = 1;
235968ec6a6SOleksandr Tymoshenko 			break;
236d752f0f6SLuiz Otavio O Souza 		case 'n':
237d752f0f6SLuiz Otavio O Souza 			name = 1;
2383b2bb133SOleksandr Tymoshenko 			break;
2393b2bb133SOleksandr Tymoshenko 		case 'N':
2403b2bb133SOleksandr Tymoshenko 			pin_type = PIN_TYPE_NAME;
2413b2bb133SOleksandr Tymoshenko 			break;
2423b2bb133SOleksandr Tymoshenko 		case'p':
2433b2bb133SOleksandr Tymoshenko 			pin_type = PIN_TYPE_NUMBER;
244d752f0f6SLuiz Otavio O Souza 			break;
245968ec6a6SOleksandr Tymoshenko 		case 't':
246968ec6a6SOleksandr Tymoshenko 			toggle = 1;
247968ec6a6SOleksandr Tymoshenko 			break;
248968ec6a6SOleksandr Tymoshenko 		case 'v':
249968ec6a6SOleksandr Tymoshenko 			verbose = 1;
250968ec6a6SOleksandr Tymoshenko 			break;
251968ec6a6SOleksandr Tymoshenko 		default:
252968ec6a6SOleksandr Tymoshenko 			usage();
253968ec6a6SOleksandr Tymoshenko 			break;
254968ec6a6SOleksandr Tymoshenko 		}
255968ec6a6SOleksandr Tymoshenko 	}
256968ec6a6SOleksandr Tymoshenko 	argv += optind;
257968ec6a6SOleksandr Tymoshenko 	argc -= optind;
258968ec6a6SOleksandr Tymoshenko 	if (ctlfile == NULL)
259244c371dSRui Paulo 		handle = gpio_open(0);
260244c371dSRui Paulo 	else
261244c371dSRui Paulo 		handle = gpio_open_device(ctlfile);
262244c371dSRui Paulo 	if (handle == GPIO_INVALID_HANDLE) {
263244c371dSRui Paulo 		perror("gpio_open");
264968ec6a6SOleksandr Tymoshenko 		exit(1);
265968ec6a6SOleksandr Tymoshenko 	}
266968ec6a6SOleksandr Tymoshenko 
267968ec6a6SOleksandr Tymoshenko 	if (list) {
268244c371dSRui Paulo 		dump_pins(handle, verbose);
269244c371dSRui Paulo 		gpio_close(handle);
270968ec6a6SOleksandr Tymoshenko 		exit(0);
271968ec6a6SOleksandr Tymoshenko 	}
272968ec6a6SOleksandr Tymoshenko 
2733b2bb133SOleksandr Tymoshenko 	if (argc == 0)
2743b2bb133SOleksandr Tymoshenko 		usage();
2753b2bb133SOleksandr Tymoshenko 
2763b2bb133SOleksandr Tymoshenko 	/* Find the pin number by the name */
2773b2bb133SOleksandr Tymoshenko 	switch (pin_type) {
278e74d991dSDimitry Andric 	default:
2793b2bb133SOleksandr Tymoshenko 		/* First test if it is a pin number */
2803b2bb133SOleksandr Tymoshenko 		pinn = str2int(argv[0], &ok);
2813b2bb133SOleksandr Tymoshenko 		if (ok) {
2823b2bb133SOleksandr Tymoshenko 			/* Test if we have any pin named by this number and tell the user */
2833b2bb133SOleksandr Tymoshenko 			if (get_pinnum_by_name(handle, argv[0]) != -1)
2843b2bb133SOleksandr Tymoshenko 				fail("%s is also a pin name, use -p or -N\n", argv[0]);
2853b2bb133SOleksandr Tymoshenko 		} else {
2863b2bb133SOleksandr Tymoshenko 			/* Test if it is a name */
2873b2bb133SOleksandr Tymoshenko 			if ((pinn = get_pinnum_by_name(handle, argv[0])) == -1)
2883b2bb133SOleksandr Tymoshenko 				fail("Can't find pin named \"%s\"\n", argv[0]);
2893b2bb133SOleksandr Tymoshenko 		}
2903b2bb133SOleksandr Tymoshenko 		break;
2913b2bb133SOleksandr Tymoshenko 	case PIN_TYPE_NUMBER:
2923b2bb133SOleksandr Tymoshenko 		pinn = str2int(argv[0], &ok);
2933b2bb133SOleksandr Tymoshenko 		if (!ok)
2943b2bb133SOleksandr Tymoshenko 			fail("Invalid pin number: %s\n", argv[0]);
2953b2bb133SOleksandr Tymoshenko 		break;
2963b2bb133SOleksandr Tymoshenko 	case PIN_TYPE_NAME:
2973b2bb133SOleksandr Tymoshenko 		if ((pinn = get_pinnum_by_name(handle, argv[0])) == -1)
2983b2bb133SOleksandr Tymoshenko 			fail("Can't find pin named \"%s\"\n", argv[0]);
2993b2bb133SOleksandr Tymoshenko 		break;
3003b2bb133SOleksandr Tymoshenko 	}
3013b2bb133SOleksandr Tymoshenko 
3023b2bb133SOleksandr Tymoshenko 	/* Set the pin name. */
3033b2bb133SOleksandr Tymoshenko 	if (name) {
3043b2bb133SOleksandr Tymoshenko 		if (argc != 2)
3053b2bb133SOleksandr Tymoshenko 			usage();
3063b2bb133SOleksandr Tymoshenko 		if (gpio_pin_set_name(handle, pinn, argv[1]) < 0) {
3073b2bb133SOleksandr Tymoshenko 			perror("gpio_pin_set_name");
3083b2bb133SOleksandr Tymoshenko 			exit(1);
3093b2bb133SOleksandr Tymoshenko 		}
3103b2bb133SOleksandr Tymoshenko 		exit(0);
3113b2bb133SOleksandr Tymoshenko 	}
3123b2bb133SOleksandr Tymoshenko 
313968ec6a6SOleksandr Tymoshenko 	if (toggle) {
314968ec6a6SOleksandr Tymoshenko 		/*
315968ec6a6SOleksandr Tymoshenko                 * -t pin assumes no additional arguments
316968ec6a6SOleksandr Tymoshenko                 */
3173b2bb133SOleksandr Tymoshenko 		if (argc > 1)
318968ec6a6SOleksandr Tymoshenko 			usage();
319244c371dSRui Paulo 		if (gpio_pin_toggle(handle, pinn) < 0) {
320244c371dSRui Paulo 			perror("gpio_pin_toggle");
321968ec6a6SOleksandr Tymoshenko 			exit(1);
322968ec6a6SOleksandr Tymoshenko 		}
323244c371dSRui Paulo 		gpio_close(handle);
324968ec6a6SOleksandr Tymoshenko 		exit(0);
325968ec6a6SOleksandr Tymoshenko 	}
326968ec6a6SOleksandr Tymoshenko 
327968ec6a6SOleksandr Tymoshenko 	if (config) {
328968ec6a6SOleksandr Tymoshenko 		flags = 0;
3293b2bb133SOleksandr Tymoshenko 		for (i = 1; i < argc; i++) {
330968ec6a6SOleksandr Tymoshenko 			flag = 	str2cap(argv[i]);
331968ec6a6SOleksandr Tymoshenko 			if (flag < 0)
332968ec6a6SOleksandr Tymoshenko 				fail("Invalid flag: %s\n", argv[i]);
333ff3468acSIan Lepore 			else if ((flag & GPIO_INTR_MASK) != 0)
334ff3468acSIan Lepore 				fail("Interrupt capability %s cannot be set as configuration flag\n", argv[i]);
335968ec6a6SOleksandr Tymoshenko 			flags |= flag;
336968ec6a6SOleksandr Tymoshenko 		}
337244c371dSRui Paulo 		pin.g_pin = pinn;
338244c371dSRui Paulo 		pin.g_flags = flags;
339244c371dSRui Paulo 		if (gpio_pin_set_flags(handle, &pin) < 0) {
340244c371dSRui Paulo 			perror("gpio_pin_set_flags");
341968ec6a6SOleksandr Tymoshenko 			exit(1);
342968ec6a6SOleksandr Tymoshenko 		}
343968ec6a6SOleksandr Tymoshenko 		exit(0);
344968ec6a6SOleksandr Tymoshenko 	}
345968ec6a6SOleksandr Tymoshenko 
346968ec6a6SOleksandr Tymoshenko 	/*
347968ec6a6SOleksandr Tymoshenko 	 * Last two cases - set value or print value
348968ec6a6SOleksandr Tymoshenko 	 */
3493b2bb133SOleksandr Tymoshenko 	if ((argc == 0) || (argc > 2))
350968ec6a6SOleksandr Tymoshenko 		usage();
351968ec6a6SOleksandr Tymoshenko 
352968ec6a6SOleksandr Tymoshenko 	/*
353968ec6a6SOleksandr Tymoshenko 	 * Read pin value
354968ec6a6SOleksandr Tymoshenko 	 */
355968ec6a6SOleksandr Tymoshenko 	if (argc == 1) {
356244c371dSRui Paulo 		pinv = gpio_pin_get(handle, pinn);
357244c371dSRui Paulo 		if (pinv < 0) {
358244c371dSRui Paulo 			perror("gpio_pin_get");
359968ec6a6SOleksandr Tymoshenko 			exit(1);
360968ec6a6SOleksandr Tymoshenko 		}
361244c371dSRui Paulo 		printf("%d\n", pinv);
362968ec6a6SOleksandr Tymoshenko 		exit(0);
363968ec6a6SOleksandr Tymoshenko 	}
364968ec6a6SOleksandr Tymoshenko 
365968ec6a6SOleksandr Tymoshenko 	/* Is it valid number (0 or 1) ? */
366968ec6a6SOleksandr Tymoshenko 	pinv = str2int(argv[1], &ok);
3673b2bb133SOleksandr Tymoshenko 	if (ok == 0 || ((pinv != 0) && (pinv != 1)))
368968ec6a6SOleksandr Tymoshenko 		fail("Invalid pin value: %s\n", argv[1]);
369968ec6a6SOleksandr Tymoshenko 
370968ec6a6SOleksandr Tymoshenko 	/*
371968ec6a6SOleksandr Tymoshenko 	 * Set pin value
372968ec6a6SOleksandr Tymoshenko 	 */
373244c371dSRui Paulo 	if (gpio_pin_set(handle, pinn, pinv) < 0) {
374244c371dSRui Paulo 		perror("gpio_pin_set");
375968ec6a6SOleksandr Tymoshenko 		exit(1);
376968ec6a6SOleksandr Tymoshenko 	}
377968ec6a6SOleksandr Tymoshenko 
378244c371dSRui Paulo 	gpio_close(handle);
379968ec6a6SOleksandr Tymoshenko 	exit(0);
380968ec6a6SOleksandr Tymoshenko }
381