1 /* $NetBSD: gpioctl.c,v 1.1 2005/09/27 02:54:27 jmcneill 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 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 { 0, NULL }, 59 }; 60 61 int 62 main(int argc, char *argv[]) 63 { 64 int ch; 65 char *ep; 66 int do_ctl = 0; 67 int pin = 0, value = 0; 68 69 while ((ch = getopt(argc, argv, "cd:hq")) != -1) 70 switch (ch) { 71 case 'c': 72 do_ctl = 1; 73 break; 74 case 'd': 75 device = optarg; 76 break; 77 case 'q': 78 quiet = 1; 79 break; 80 case 'h': 81 case '?': 82 default: 83 usage(); 84 /* NOTREACHED */ 85 } 86 argc -= optind; 87 argv += optind; 88 89 if (argc > 0) { 90 pin = strtol(argv[0], &ep, 10); 91 if (*argv[0] == '\0' || *ep != '\0' || pin < 0) 92 errx(1, "%s: invalid pin", argv[0]); 93 } 94 95 if ((devfd = open(device, O_RDWR)) == -1) 96 err(1, "%s", device); 97 98 if (argc == 0 && !do_ctl) { 99 getinfo(); 100 } else if (argc == 1) { 101 if (do_ctl) 102 pinctl(pin, NULL, 0); 103 else 104 pinread(pin); 105 } else if (argc > 1) { 106 if (do_ctl) { 107 pinctl(pin, argv + 1, argc - 1); 108 } else { 109 value = strtol(argv[1], &ep, 10); 110 if (*argv[1] == '\0' || *ep != '\0') 111 errx(1, "%s: invalid value", argv[1]); 112 pinwrite(pin, value); 113 } 114 } else { 115 usage(); 116 /* NOTREACHED */ 117 } 118 119 return (0); 120 } 121 122 void 123 getinfo(void) 124 { 125 struct gpio_info info; 126 127 bzero(&info, sizeof(info)); 128 if (ioctl(devfd, GPIOINFO, &info) == -1) 129 err(1, "GPIOINFO"); 130 131 if (quiet) 132 return; 133 134 printf("%s: %d pins\n", device, info.gpio_npins); 135 } 136 137 void 138 pinread(int pin) 139 { 140 struct gpio_pin_op op; 141 142 bzero(&op, sizeof(op)); 143 op.gp_pin = pin; 144 if (ioctl(devfd, GPIOPINREAD, &op) == -1) 145 err(1, "GPIOPINREAD"); 146 147 if (quiet) 148 return; 149 150 printf("pin %d: state %d\n", pin, op.gp_value); 151 } 152 153 void 154 pinwrite(int pin, int value) 155 { 156 struct gpio_pin_op op; 157 158 if (value < 0 || value > 2) 159 errx(1, "%d: invalid value", value); 160 161 bzero(&op, sizeof(op)); 162 op.gp_pin = pin; 163 op.gp_value = (value == 0 ? GPIO_PIN_LOW : GPIO_PIN_HIGH); 164 if (value < 2) { 165 if (ioctl(devfd, GPIOPINWRITE, &op) == -1) 166 err(1, "GPIOPINWRITE"); 167 } else { 168 if (ioctl(devfd, GPIOPINTOGGLE, &op) == -1) 169 err(1, "GPIOPINTOGGLE"); 170 } 171 172 if (quiet) 173 return; 174 175 printf("pin %d: state %d -> %d\n", pin, op.gp_value, 176 (value < 2 ? value : 1 - op.gp_value)); 177 } 178 179 void 180 pinctl(int pin, char *flags[], int nflags) 181 { 182 struct gpio_pin_ctl ctl; 183 int fl = 0; 184 const struct bitstr *bs; 185 int i; 186 187 bzero(&ctl, sizeof(ctl)); 188 ctl.gp_pin = pin; 189 if (flags != NULL) { 190 for (i = 0; i < nflags; i++) 191 for (bs = pinflags; bs->string != NULL; bs++) 192 if (strcmp(flags[i], bs->string) == 0) { 193 fl |= bs->mask; 194 break; 195 } 196 } 197 ctl.gp_flags = fl; 198 if (ioctl(devfd, GPIOPINCTL, &ctl) == -1) 199 err(1, "GPIOPINCTL"); 200 201 if (quiet) 202 return; 203 204 printf("pin %d: caps:", pin); 205 for (bs = pinflags; bs->string != NULL; bs++) 206 if (ctl.gp_caps & bs->mask) 207 printf(" %s", bs->string); 208 printf(", flags:"); 209 for (bs = pinflags; bs->string != NULL; bs++) 210 if (ctl.gp_flags & bs->mask) 211 printf(" %s", bs->string); 212 if (fl > 0) { 213 printf(" ->"); 214 for (bs = pinflags; bs->string != NULL; bs++) 215 if (fl & bs->mask) 216 printf(" %s", bs->string); 217 } 218 printf("\n"); 219 } 220 221 void 222 usage(void) 223 { 224 extern char *__progname; 225 226 fprintf(stderr, "usage: %s [-hq] [-d device] [pin] [0 | 1 | 2]\n", 227 __progname); 228 fprintf(stderr, " %s [-hq] [-d device] -c pin [flags]\n", 229 __progname); 230 231 exit(1); 232 } 233