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 } 374