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