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