1 /*- 2 * Copyright (c) 2013-2014 Rui Paulo <rpaulo@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 #include <stdio.h> 29 #include <fcntl.h> 30 #include <unistd.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <errno.h> 34 35 #include <sys/ioctl.h> 36 #include <sys/types.h> 37 38 #include <libgpio.h> 39 40 gpio_handle_t 41 gpio_open(unsigned int unit) 42 { 43 char device[16]; 44 45 snprintf(device, sizeof(device), "/dev/gpioc%u", unit); 46 47 return (gpio_open_device(device)); 48 } 49 50 gpio_handle_t 51 gpio_open_device(const char *device) 52 { 53 int fd, maxpins; 54 int serr; 55 56 fd = open(device, O_RDONLY); 57 if (fd < 0) 58 return (GPIO_INVALID_HANDLE); 59 /* 60 * Check whether a simple ioctl works. 61 */ 62 if (ioctl(fd, GPIOMAXPIN, &maxpins) < 0) { 63 serr = errno; 64 close(fd); 65 errno = serr; 66 return (GPIO_INVALID_HANDLE); 67 } 68 69 return (fd); 70 } 71 72 void 73 gpio_close(gpio_handle_t handle) 74 { 75 close(handle); 76 } 77 78 int 79 gpio_pin_list(gpio_handle_t handle, gpio_config_t **pcfgs) 80 { 81 int maxpins, i; 82 gpio_config_t *cfgs; 83 84 *pcfgs = NULL; 85 if (ioctl(handle, GPIOMAXPIN, &maxpins) < 0) 86 return (-1); 87 /* Reasonable values. */ 88 if (maxpins < 0 || maxpins > 4096) { 89 errno = EINVAL; 90 return (-1); 91 } 92 cfgs = calloc(maxpins + 1, sizeof(*cfgs)); 93 if (cfgs == NULL) 94 return (-1); 95 for (i = 0; i <= maxpins; i++) { 96 cfgs[i].g_pin = i; 97 gpio_pin_config(handle, &cfgs[i]); 98 } 99 *pcfgs = cfgs; 100 101 return (maxpins); 102 } 103 104 int 105 gpio_pin_config(gpio_handle_t handle, gpio_config_t *cfg) 106 { 107 struct gpio_pin gppin; 108 109 if (cfg == NULL) 110 return (-1); 111 gppin.gp_pin = cfg->g_pin; 112 if (ioctl(handle, GPIOGETCONFIG, &gppin) < 0) 113 return (-1); 114 strlcpy(cfg->g_name, gppin.gp_name, GPIOMAXNAME); 115 cfg->g_caps = gppin.gp_caps; 116 cfg->g_flags = gppin.gp_flags; 117 118 return (0); 119 } 120 121 int 122 gpio_pin_set_name(gpio_handle_t handle, gpio_pin_t pin, char *name) 123 { 124 struct gpio_pin gppin; 125 126 if (name == NULL) 127 return (-1); 128 bzero(&gppin, sizeof(gppin)); 129 gppin.gp_pin = pin; 130 strlcpy(gppin.gp_name, name, GPIOMAXNAME); 131 if (ioctl(handle, GPIOSETNAME, &gppin) < 0) 132 return (-1); 133 134 return (0); 135 } 136 137 int 138 gpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) 139 { 140 struct gpio_pin gppin; 141 142 if (cfg == NULL) 143 return (-1); 144 gppin.gp_pin = cfg->g_pin; 145 gppin.gp_flags = cfg->g_flags; 146 if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 147 return (-1); 148 149 return (0); 150 } 151 152 gpio_value_t 153 gpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 154 { 155 struct gpio_req gpreq; 156 157 bzero(&gpreq, sizeof(gpreq)); 158 gpreq.gp_pin = pin; 159 if (ioctl(handle, GPIOGET, &gpreq) < 0) 160 return (GPIO_VALUE_INVALID); 161 162 return (gpreq.gp_value); 163 } 164 165 int 166 gpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 167 { 168 struct gpio_req gpreq; 169 170 if (value == GPIO_VALUE_INVALID) 171 return (-1); 172 bzero(&gpreq, sizeof(gpreq)); 173 gpreq.gp_pin = pin; 174 gpreq.gp_value = value; 175 if (ioctl(handle, GPIOSET, &gpreq) < 0) 176 return (-1); 177 178 return (0); 179 } 180 181 int 182 gpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 183 { 184 gpio_value_t value; 185 186 value = gpio_pin_get(handle, pin); 187 if (value == GPIO_VALUE_INVALID) 188 return (-1); 189 value = !value; 190 191 return (gpio_pin_set(handle, pin, value)); 192 } 193 194 int 195 gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 196 { 197 return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 198 } 199 200 int 201 gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 202 { 203 return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 204 } 205 206 static int 207 gpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 208 { 209 gpio_config_t cfg; 210 211 bzero(&cfg, sizeof(cfg)); 212 cfg.g_pin = pin; 213 if (gpio_pin_config(handle, &cfg) < 0) 214 return (-1); 215 cfg.g_flags = flag; 216 217 return (gpio_pin_set_flags(handle, &cfg)); 218 } 219 220 int 221 gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 222 { 223 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 224 } 225 226 int 227 gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 228 { 229 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 230 } 231 232 int 233 gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 234 { 235 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 236 } 237 238 int 239 gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 240 { 241 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 242 } 243 244 int 245 gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 246 { 247 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 248 } 249 250 int 251 gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 252 { 253 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 254 } 255 256 int 257 gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 258 { 259 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 260 } 261 262 int 263 gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 264 { 265 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 266 } 267 268 int 269 gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 270 { 271 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 272 } 273 274 int 275 gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 276 { 277 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 278 } 279