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