]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/gpioctl/gpioctl.c
Update Makefiles and other build glue for llvm/clang 3.7.0, as of trunk
[FreeBSD/FreeBSD.git] / usr.sbin / gpioctl / gpioctl.c
1 /*-
2  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
3  * Copyright (c) 2014, Rui Paulo <rpaulo@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <fcntl.h>
33 #include <getopt.h>
34 #include <paths.h>
35 #include <stdio.h>
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include <libgpio.h>
42
43 struct flag_desc {
44         const char *name;
45         uint32_t flag;
46 };
47
48 static struct flag_desc gpio_flags[] = {
49         { "IN", GPIO_PIN_INPUT },
50         { "OUT", GPIO_PIN_OUTPUT },
51         { "OD", GPIO_PIN_OPENDRAIN },
52         { "PP", GPIO_PIN_PUSHPULL },
53         { "TS", GPIO_PIN_TRISTATE },
54         { "PU", GPIO_PIN_PULLUP },
55         { "PD", GPIO_PIN_PULLDOWN },
56         { "II", GPIO_PIN_INVIN },
57         { "IO", GPIO_PIN_INVOUT },
58         { "PULSE", GPIO_PIN_PULSATE },
59         { NULL, 0 },
60 };
61
62 int str2cap(const char *str);
63
64 static void
65 usage(void)
66 {
67         fprintf(stderr, "Usage:\n");
68         fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n");
69         fprintf(stderr, "\tgpioctl [-f ctldev] -t pin\n");
70         fprintf(stderr, "\tgpioctl [-f ctldev] -c pin flag ...\n");
71         fprintf(stderr, "\tgpioctl [-f ctldev] -n pin pin-name\n");
72         fprintf(stderr, "\tgpioctl [-f ctldev] pin [0|1]\n");
73         exit(1);
74 }
75
76 static const char *
77 cap2str(uint32_t cap)
78 {
79         struct flag_desc * pdesc = gpio_flags;
80         while (pdesc->name) {
81                 if (pdesc->flag == cap)
82                         return pdesc->name;
83                 pdesc++;
84         }
85
86         return "UNKNOWN";
87 }
88
89 int
90 str2cap(const char *str)
91 {
92         struct flag_desc * pdesc = gpio_flags;
93         while (pdesc->name) {
94                 if (strcasecmp(str, pdesc->name) == 0)
95                         return pdesc->flag;
96                 pdesc++;
97         }
98
99         return (-1);
100 }
101
102 /*
103  * Our handmade function for converting string to number
104  */
105 static int
106 str2int(const char *s, int *ok)
107 {
108         char *endptr;
109         int res = strtod(s, &endptr);
110         if (endptr != s + strlen(s) )
111                 *ok = 0;
112         else
113                 *ok = 1;
114
115         return res;
116 }
117
118 static void
119 print_caps(int caps)
120 {
121         int i, need_coma;
122
123         need_coma = 0;
124         printf("<");
125         for (i = 0; i < 32; i++) {
126                 if (caps & (1 << i)) {
127                         if (need_coma)
128                                 printf(",");
129                         printf("%s", cap2str(1 << i));
130                         need_coma = 1;
131                 }
132         }
133         printf(">");
134 }
135
136 static void
137 dump_pins(gpio_handle_t handle, int verbose)
138 {
139         int i, maxpin, pinv;
140         gpio_config_t *cfgs;
141         gpio_config_t *pin;
142
143         maxpin = gpio_pin_list(handle, &cfgs);
144         if (maxpin < 0) {
145                 perror("gpio_pin_list");
146                 exit(1);
147         }
148
149         for (i = 0; i <= maxpin; i++) {
150                 pin = cfgs + i;
151                 pinv = gpio_pin_get(handle, pin->g_pin);
152                 printf("pin %02d:\t%d\t%s", pin->g_pin, pinv,
153                     pin->g_name);
154
155                 print_caps(pin->g_flags);
156
157                 if (verbose) {
158                         printf(", caps:");
159                         print_caps(pin->g_caps);
160                 }
161                 printf("\n");
162         }
163         free(cfgs);
164 }
165
166 static void
167 fail(const char *fmt, ...)
168 {
169         va_list ap;
170
171         va_start(ap, fmt);
172         vfprintf(stderr, fmt, ap);
173         va_end(ap);
174         exit(1);
175 }
176
177 int
178 main(int argc, char **argv)
179 {
180         int i;
181         gpio_config_t pin;
182         gpio_handle_t handle;
183         char *ctlfile = NULL;
184         int pinn, pinv, ch;
185         int flags, flag, ok;
186         int config, list, name, toggle, verbose;
187
188         config = toggle = verbose = list = name = pinn = 0;
189
190         while ((ch = getopt(argc, argv, "c:f:ln:t:v")) != -1) {
191                 switch (ch) {
192                 case 'c':
193                         config = 1;
194                         pinn = str2int(optarg, &ok);
195                         if (!ok)
196                                 fail("Invalid pin number: %s\n", optarg);
197                         break;
198                 case 'f':
199                         ctlfile = optarg;
200                         break;
201                 case 'l':
202                         list = 1;
203                         break;
204                 case 'n':
205                         name = 1;
206                         pinn = str2int(optarg, &ok);
207                         if (!ok)
208                                 fail("Invalid pin number: %s\n", optarg);
209                         break;
210                 case 't':
211                         toggle = 1;
212                         pinn = str2int(optarg, &ok);
213                         if (!ok)
214                                 fail("Invalid pin number: %s\n", optarg);
215                         break;
216                 case 'v':
217                         verbose = 1;
218                         break;
219                 default:
220                         usage();
221                         break;
222                 }
223         }
224         argv += optind;
225         argc -= optind;
226         if (ctlfile == NULL)
227                 handle = gpio_open(0);
228         else
229                 handle = gpio_open_device(ctlfile);
230         if (handle == GPIO_INVALID_HANDLE) {
231                 perror("gpio_open");
232                 exit(1);
233         }
234
235         /* Set the pin name. */
236         if (name) {
237                 if (argc == 0) {
238                         usage();
239                         exit(1);
240                 }
241                 if (gpio_pin_set_name(handle, pinn, argv[0]) < 0) {
242                         perror("gpio_pin_set_name");
243                         exit(1);
244                 }
245                 exit(0);
246         }
247
248         if (list) {
249                 dump_pins(handle, verbose);
250                 gpio_close(handle);
251                 exit(0);
252         }
253
254         if (toggle) {
255                 /*
256                  * -t pin assumes no additional arguments
257                  */
258                 if (argc > 0) {
259                         usage();
260                         exit(1);
261                 }
262                 if (gpio_pin_toggle(handle, pinn) < 0) {
263                         perror("gpio_pin_toggle");
264                         exit(1);
265                 }
266                 gpio_close(handle);
267                 exit(0);
268         }
269
270         if (config) {
271                 flags = 0;
272                 for (i = 0; i < argc; i++) {
273                         flag =  str2cap(argv[i]);
274                         if (flag < 0)
275                                 fail("Invalid flag: %s\n", argv[i]);
276                         flags |= flag;
277                 }
278                 pin.g_pin = pinn;
279                 pin.g_flags = flags;
280                 if (gpio_pin_set_flags(handle, &pin) < 0) {
281                         perror("gpio_pin_set_flags");
282                         exit(1);
283                 }
284                 exit(0);
285         }
286
287         /*
288          * Last two cases - set value or print value
289          */
290         if ((argc == 0) || (argc > 2)) {
291                 usage();
292                 exit(1);
293         }
294
295         pinn = str2int(argv[0], &ok);
296         if (!ok)
297                 fail("Invalid pin number: %s\n", argv[0]);
298
299         /*
300          * Read pin value
301          */
302         if (argc == 1) {
303                 pinv = gpio_pin_get(handle, pinn);
304                 if (pinv < 0) {
305                         perror("gpio_pin_get");
306                         exit(1);
307                 }
308                 printf("%d\n", pinv);
309                 exit(0);
310         }
311
312         /* Is it valid number (0 or 1) ? */
313         pinv = str2int(argv[1], &ok);
314         if (!ok || ((pinv != 0) && (pinv != 1)))
315                 fail("Invalid pin value: %s\n", argv[1]);
316
317         /*
318          * Set pin value
319          */
320         if (gpio_pin_set(handle, pinn, pinv) < 0) {
321                 perror("gpio_pin_set");
322                 exit(1);
323         }
324
325         gpio_close(handle);
326         exit(0);
327 }