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