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 #include <stdio.h> 27 #include <fcntl.h> 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <errno.h> 32 33 #include <sys/ioctl.h> 34 #include <sys/types.h> 35 36 #include <libgpio.h> 37 38 gpio_handle_t 39 gpio_open(unsigned int unit) 40 { 41 char device[16]; 42 43 snprintf(device, sizeof(device), "/dev/gpioc%u", unit); 44 45 return (gpio_open_device(device)); 46 } 47 48 gpio_handle_t 49 gpio_open_device(const char *device) 50 { 51 int fd, maxpins; 52 int serr; 53 54 fd = open(device, O_RDONLY); 55 if (fd < 0) 56 return (GPIO_INVALID_HANDLE); 57 /* 58 * Check whether a simple ioctl works. 59 */ 60 if (ioctl(fd, GPIOMAXPIN, &maxpins) < 0) { 61 serr = errno; 62 close(fd); 63 errno = serr; 64 return (GPIO_INVALID_HANDLE); 65 } 66 67 return (fd); 68 } 69 70 void 71 gpio_close(gpio_handle_t handle) 72 { 73 close(handle); 74 } 75 76 int 77 gpio_pin_list(gpio_handle_t handle, gpio_config_t **pcfgs) 78 { 79 int maxpins, i; 80 gpio_config_t *cfgs; 81 82 *pcfgs = NULL; 83 if (ioctl(handle, GPIOMAXPIN, &maxpins) < 0) 84 return (-1); 85 /* Reasonable values. */ 86 if (maxpins < 0 || maxpins > 4096) { 87 errno = EINVAL; 88 return (-1); 89 } 90 cfgs = calloc(maxpins + 1, sizeof(*cfgs)); 91 if (cfgs == NULL) 92 return (-1); 93 for (i = 0; i <= maxpins; i++) { 94 cfgs[i].g_pin = i; 95 gpio_pin_config(handle, &cfgs[i]); 96 } 97 *pcfgs = cfgs; 98 99 return (maxpins); 100 } 101 102 int 103 gpio_pin_config(gpio_handle_t handle, gpio_config_t *cfg) 104 { 105 struct gpio_pin gppin; 106 107 if (cfg == NULL) 108 return (-1); 109 gppin.gp_pin = cfg->g_pin; 110 if (ioctl(handle, GPIOGETCONFIG, &gppin) < 0) 111 return (-1); 112 strlcpy(cfg->g_name, gppin.gp_name, GPIOMAXNAME); 113 cfg->g_caps = gppin.gp_caps; 114 cfg->g_flags = gppin.gp_flags; 115 116 return (0); 117 } 118 119 int 120 gpio_pin_set_name(gpio_handle_t handle, gpio_pin_t pin, char *name) 121 { 122 struct gpio_pin gppin; 123 124 if (name == NULL) 125 return (-1); 126 bzero(&gppin, sizeof(gppin)); 127 gppin.gp_pin = pin; 128 strlcpy(gppin.gp_name, name, GPIOMAXNAME); 129 if (ioctl(handle, GPIOSETNAME, &gppin) < 0) 130 return (-1); 131 132 return (0); 133 } 134 135 int 136 gpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) 137 { 138 struct gpio_pin gppin; 139 140 if (cfg == NULL) 141 return (-1); 142 gppin.gp_pin = cfg->g_pin; 143 gppin.gp_flags = cfg->g_flags; 144 if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 145 return (-1); 146 147 return (0); 148 } 149 150 gpio_value_t 151 gpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 152 { 153 struct gpio_req gpreq; 154 155 bzero(&gpreq, sizeof(gpreq)); 156 gpreq.gp_pin = pin; 157 if (ioctl(handle, GPIOGET, &gpreq) < 0) 158 return (GPIO_VALUE_INVALID); 159 160 return (gpreq.gp_value); 161 } 162 163 int 164 gpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 165 { 166 struct gpio_req gpreq; 167 168 if (value == GPIO_VALUE_INVALID) 169 return (-1); 170 bzero(&gpreq, sizeof(gpreq)); 171 gpreq.gp_pin = pin; 172 gpreq.gp_value = value; 173 if (ioctl(handle, GPIOSET, &gpreq) < 0) 174 return (-1); 175 176 return (0); 177 } 178 179 int 180 gpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 181 { 182 struct gpio_req gpreq; 183 184 bzero(&gpreq, sizeof(gpreq)); 185 gpreq.gp_pin = pin; 186 if (ioctl(handle, GPIOTOGGLE, &gpreq) < 0) 187 return (-1); 188 189 return (0); 190 } 191 192 int 193 gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 194 { 195 return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 196 } 197 198 int 199 gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 200 { 201 return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 202 } 203 204 static int 205 gpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 206 { 207 gpio_config_t cfg; 208 209 bzero(&cfg, sizeof(cfg)); 210 cfg.g_pin = pin; 211 if (gpio_pin_config(handle, &cfg) < 0) 212 return (-1); 213 cfg.g_flags = flag; 214 215 return (gpio_pin_set_flags(handle, &cfg)); 216 } 217 218 int 219 gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 220 { 221 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 222 } 223 224 int 225 gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 226 { 227 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 228 } 229 230 int 231 gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 232 { 233 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 234 } 235 236 int 237 gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 238 { 239 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 240 } 241 242 int 243 gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 244 { 245 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 246 } 247 248 int 249 gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 250 { 251 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 252 } 253 254 int 255 gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 256 { 257 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 258 } 259 260 int 261 gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 262 { 263 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 264 } 265 266 int 267 gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 268 { 269 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 270 } 271 272 int 273 gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 274 { 275 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 276 } 277