1 /* $OpenBSD: gpioctl.c,v 1.7 2007/11/17 16:55:05 mbalmer Exp $ */ 2 /* 3 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * Program to control GPIO devices. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/gpio.h> 24 #include <sys/ioctl.h> 25 #include <sys/limits.h> 26 27 #include <err.h> 28 #include <fcntl.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 34 #define _PATH_DEV_GPIO "/dev/gpio0" 35 36 char *device = _PATH_DEV_GPIO; 37 int devfd = -1; 38 int quiet = 0; 39 40 void getinfo(void); 41 void pinread(int); 42 void pinwrite(int, int); 43 void pinctl(int, char *[], int); 44 45 __dead void usage(void); 46 47 const struct bitstr { 48 unsigned int mask; 49 const char *string; 50 } pinflags[] = { 51 { GPIO_PIN_INPUT, "in" }, 52 { GPIO_PIN_OUTPUT, "out" }, 53 { GPIO_PIN_INOUT, "inout" }, 54 { GPIO_PIN_OPENDRAIN, "od" }, 55 { GPIO_PIN_PUSHPULL, "pp" }, 56 { GPIO_PIN_TRISTATE, "tri" }, 57 { GPIO_PIN_PULLUP, "pu" }, 58 { GPIO_PIN_PULLDOWN, "pd" }, 59 { GPIO_PIN_INVIN, "iin" }, 60 { GPIO_PIN_INVOUT, "iout" }, 61 { 0, NULL }, 62 }; 63 64 int 65 main(int argc, char *argv[]) 66 { 67 int ch; 68 const char *errstr; 69 int do_ctl = 0; 70 int pin = 0, value = 0; 71 72 while ((ch = getopt(argc, argv, "cd:q")) != -1) 73 switch (ch) { 74 case 'c': 75 do_ctl = 1; 76 break; 77 case 'd': 78 device = optarg; 79 break; 80 case 'q': 81 quiet = 1; 82 break; 83 default: 84 usage(); 85 /* NOTREACHED */ 86 } 87 argc -= optind; 88 argv += optind; 89 90 if (argc > 0) { 91 pin = strtonum(argv[0], 0, INT_MAX, &errstr); 92 if (errstr) 93 errx(1, "%s: invalid pin", argv[0]); 94 } 95 96 if ((devfd = open(device, O_RDWR)) == -1) 97 err(1, "%s", device); 98 99 if (argc == 0 && !do_ctl) { 100 getinfo(); 101 } else if (argc == 1) { 102 if (do_ctl) 103 pinctl(pin, NULL, 0); 104 else 105 pinread(pin); 106 } else if (argc > 1) { 107 if (do_ctl) { 108 pinctl(pin, argv + 1, argc - 1); 109 } else { 110 value = strtonum(argv[1], INT_MIN, INT_MAX, &errstr); 111 if (errstr) 112 errx(1, "%s: invalid value", argv[1]); 113 pinwrite(pin, value); 114 } 115 } else { 116 usage(); 117 /* NOTREACHED */ 118 } 119 120 return (0); 121 } 122 123 void 124 getinfo(void) 125 { 126 struct gpio_info info; 127 128 bzero(&info, sizeof(info)); 129 if (ioctl(devfd, GPIOINFO, &info) == -1) 130 err(1, "GPIOINFO"); 131 132 if (quiet) 133 return; 134 135 printf("%s: %d pins\n", device, info.gpio_npins); 136 } 137 138 void 139 pinread(int pin) 140 { 141 struct gpio_pin_op op; 142 143 bzero(&op, sizeof(op)); 144 op.gp_pin = pin; 145 if (ioctl(devfd, GPIOPINREAD, &op) == -1) 146 err(1, "GPIOPINREAD"); 147 148 if (quiet) 149 return; 150 151 printf("pin %d: state %d\n", pin, op.gp_value); 152 } 153 154 void 155 pinwrite(int pin, int value) 156 { 157 struct gpio_pin_op op; 158 159 if (value < 0 || value > 2) 160 errx(1, "%d: invalid value", value); 161 162 bzero(&op, sizeof(op)); 163 op.gp_pin = pin; 164 op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH); 165 if (value < 2) { 166 if (ioctl(devfd, GPIOPINWRITE, &op) == -1) 167 err(1, "GPIOPINWRITE"); 168 } else { 169 if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1) 170 err(1, "GPIOPINTOGGLE"); 171 } 172 173 if (quiet) 174 return; 175 176 printf("pin %d: state %d -> %d\n", pin, op.gp_value, 177 (value < 2 ? value : 1 - op.gp_value)); 178 } 179 180 void 181 pinctl(int pin, char *flags[], int nflags) 182 { 183 struct gpio_pin_ctl ctl; 184 int fl = 0; 185 const struct bitstr *bs; 186 int i; 187 188 bzero(&ctl, sizeof(ctl)); 189 ctl.gp_pin = pin; 190 if (flags != NULL) { 191 for (i = 0; i < nflags; i++) 192 for (bs = pinflags; bs->string != NULL; bs++) 193 if (strcmp(flags[i], bs->string) == 0) { 194 fl |= bs->mask; 195 break; 196 } 197 } 198 ctl.gp_flags = fl; 199 if (ioctl(devfd, GPIOPINCTL, &ctl) == -1) 200 err(1, "GPIOPINCTL"); 201 202 if (quiet) 203 return; 204 205 printf("pin %d: caps:", pin); 206 for (bs = pinflags; bs->string != NULL; bs++) 207 if (ctl.gp_caps & bs->mask) 208 printf(" %s", bs->string); 209 printf(", flags:"); 210 for (bs = pinflags; bs->string != NULL; bs++) 211 if (ctl.gp_flags & bs->mask) 212 printf(" %s", bs->string); 213 if (fl > 0) { 214 printf(" ->"); 215 for (bs = pinflags; bs->string != NULL; bs++) 216 if (fl & bs->mask) 217 printf(" %s", bs->string); 218 } 219 printf("\n"); 220 } 221 222 void 223 usage(void) 224 { 225 extern char *__progname; 226 227 fprintf(stderr, "usage: %s [-q] [-d device] [pin] [0 | 1 | 2]\n", 228 __progname); 229 fprintf(stderr, " %s [-q] [-d device] -c pin [flags]\n", 230 __progname); 231 232 exit(1); 233 } 234