1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #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 { "INTRLL", GPIO_INTR_LEVEL_LOW}, 64 { "INTRLH", GPIO_INTR_LEVEL_HIGH}, 65 { "INTRER", GPIO_INTR_EDGE_RISING}, 66 { "INTREF", GPIO_INTR_EDGE_FALLING}, 67 { "INTREB", GPIO_INTR_EDGE_BOTH}, 68 { NULL, 0 }, 69 }; 70 71 int str2cap(const char *str); 72 73 static void 74 usage(void) 75 { 76 fprintf(stderr, "Usage:\n"); 77 fprintf(stderr, "\tgpioctl [-f ctldev] -l [-v]\n"); 78 fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -t pin\n"); 79 fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -c pin flag ...\n"); 80 fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] -n pin pin-name\n"); 81 fprintf(stderr, "\tgpioctl [-f ctldev] [-pN] pin [0|1]\n"); 82 exit(1); 83 } 84 85 static const char * 86 cap2str(uint32_t cap) 87 { 88 struct flag_desc * pdesc = gpio_flags; 89 while (pdesc->name) { 90 if (pdesc->flag == cap) 91 return pdesc->name; 92 pdesc++; 93 } 94 95 return "UNKNOWN"; 96 } 97 98 int 99 str2cap(const char *str) 100 { 101 struct flag_desc * pdesc = gpio_flags; 102 while (pdesc->name) { 103 if (strcasecmp(str, pdesc->name) == 0) 104 return pdesc->flag; 105 pdesc++; 106 } 107 108 return (-1); 109 } 110 111 /* 112 * Our handmade function for converting string to number 113 */ 114 static int 115 str2int(const char *s, int *ok) 116 { 117 char *endptr; 118 int res = strtod(s, &endptr); 119 if (endptr != s + strlen(s) ) 120 *ok = 0; 121 else 122 *ok = 1; 123 124 return res; 125 } 126 127 static void 128 print_caps(int caps) 129 { 130 int i, need_coma; 131 132 need_coma = 0; 133 printf("<"); 134 for (i = 0; i < 32; i++) { 135 if (caps & (1 << i)) { 136 if (need_coma) 137 printf(","); 138 printf("%s", cap2str(1 << i)); 139 need_coma = 1; 140 } 141 } 142 printf(">"); 143 } 144 145 static void 146 dump_pins(gpio_handle_t handle, int verbose) 147 { 148 int i, maxpin, pinv; 149 gpio_config_t *cfgs; 150 gpio_config_t *pin; 151 152 maxpin = gpio_pin_list(handle, &cfgs); 153 if (maxpin < 0) { 154 perror("gpio_pin_list"); 155 exit(1); 156 } 157 158 for (i = 0; i <= maxpin; i++) { 159 pin = cfgs + i; 160 pinv = gpio_pin_get(handle, pin->g_pin); 161 printf("pin %02d:\t%d\t%s", pin->g_pin, pinv, 162 pin->g_name); 163 164 print_caps(pin->g_flags); 165 166 if (verbose) { 167 printf(", caps:"); 168 print_caps(pin->g_caps); 169 } 170 printf("\n"); 171 } 172 free(cfgs); 173 } 174 175 static int 176 get_pinnum_by_name(gpio_handle_t handle, const char *name) { 177 int i, maxpin, pinn; 178 gpio_config_t *cfgs; 179 gpio_config_t *pin; 180 181 pinn = -1; 182 maxpin = gpio_pin_list(handle, &cfgs); 183 if (maxpin < 0) { 184 perror("gpio_pin_list"); 185 exit(1); 186 } 187 188 for (i = 0; i <= maxpin; i++) { 189 pin = cfgs + i; 190 gpio_pin_get(handle, pin->g_pin); 191 if (!strcmp(name, pin->g_name)) { 192 pinn = i; 193 break; 194 } 195 } 196 free(cfgs); 197 198 return pinn; 199 } 200 201 static void 202 fail(const char *fmt, ...) 203 { 204 va_list ap; 205 206 va_start(ap, fmt); 207 vfprintf(stderr, fmt, ap); 208 va_end(ap); 209 exit(1); 210 } 211 212 int 213 main(int argc, char **argv) 214 { 215 int i; 216 gpio_config_t pin; 217 gpio_handle_t handle; 218 char *ctlfile = NULL; 219 int pinn, pinv, pin_type, ch; 220 int flags, flag, ok; 221 int config, list, name, toggle, verbose; 222 223 config = toggle = verbose = list = name = pin_type = 0; 224 225 while ((ch = getopt(argc, argv, "cf:lntvNp")) != -1) { 226 switch (ch) { 227 case 'c': 228 config = 1; 229 break; 230 case 'f': 231 ctlfile = optarg; 232 break; 233 case 'l': 234 list = 1; 235 break; 236 case 'n': 237 name = 1; 238 break; 239 case 'N': 240 pin_type = PIN_TYPE_NAME; 241 break; 242 case'p': 243 pin_type = PIN_TYPE_NUMBER; 244 break; 245 case 't': 246 toggle = 1; 247 break; 248 case 'v': 249 verbose = 1; 250 break; 251 default: 252 usage(); 253 break; 254 } 255 } 256 argv += optind; 257 argc -= optind; 258 if (ctlfile == NULL) 259 handle = gpio_open(0); 260 else 261 handle = gpio_open_device(ctlfile); 262 if (handle == GPIO_INVALID_HANDLE) { 263 perror("gpio_open"); 264 exit(1); 265 } 266 267 if (list) { 268 dump_pins(handle, verbose); 269 gpio_close(handle); 270 exit(0); 271 } 272 273 if (argc == 0) 274 usage(); 275 276 /* Find the pin number by the name */ 277 switch (pin_type) { 278 default: 279 /* First test if it is a pin number */ 280 pinn = str2int(argv[0], &ok); 281 if (ok) { 282 /* Test if we have any pin named by this number and tell the user */ 283 if (get_pinnum_by_name(handle, argv[0]) != -1) 284 fail("%s is also a pin name, use -p or -N\n", argv[0]); 285 } else { 286 /* Test if it is a name */ 287 if ((pinn = get_pinnum_by_name(handle, argv[0])) == -1) 288 fail("Can't find pin named \"%s\"\n", argv[0]); 289 } 290 break; 291 case PIN_TYPE_NUMBER: 292 pinn = str2int(argv[0], &ok); 293 if (!ok) 294 fail("Invalid pin number: %s\n", argv[0]); 295 break; 296 case PIN_TYPE_NAME: 297 if ((pinn = get_pinnum_by_name(handle, argv[0])) == -1) 298 fail("Can't find pin named \"%s\"\n", argv[0]); 299 break; 300 } 301 302 /* Set the pin name. */ 303 if (name) { 304 if (argc != 2) 305 usage(); 306 if (gpio_pin_set_name(handle, pinn, argv[1]) < 0) { 307 perror("gpio_pin_set_name"); 308 exit(1); 309 } 310 exit(0); 311 } 312 313 if (toggle) { 314 /* 315 * -t pin assumes no additional arguments 316 */ 317 if (argc > 1) 318 usage(); 319 if (gpio_pin_toggle(handle, pinn) < 0) { 320 perror("gpio_pin_toggle"); 321 exit(1); 322 } 323 gpio_close(handle); 324 exit(0); 325 } 326 327 if (config) { 328 flags = 0; 329 for (i = 1; i < argc; i++) { 330 flag = str2cap(argv[i]); 331 if (flag < 0) 332 fail("Invalid flag: %s\n", argv[i]); 333 else if ((flag & GPIO_INTR_MASK) != 0) 334 fail("Interrupt capability %s cannot be set as configuration flag\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