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