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