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, 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_flags(gpio_handle_t handle, gpio_config_t *cfg) 123 { 124 struct gpio_pin gppin; 125 126 if (cfg == NULL) 127 return (-1); 128 gppin.gp_pin = cfg->g_pin; 129 gppin.gp_flags = cfg->g_flags; 130 if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 131 return (-1); 132 133 return (0); 134 } 135 136 gpio_value_t 137 gpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 138 { 139 struct gpio_req gpreq; 140 141 bzero(&gpreq, sizeof(gpreq)); 142 gpreq.gp_pin = pin; 143 if (ioctl(handle, GPIOGET, &gpreq) < 0) 144 return (GPIO_VALUE_INVALID); 145 146 return (gpreq.gp_value); 147 } 148 149 int 150 gpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 151 { 152 struct gpio_req gpreq; 153 154 if (value == GPIO_VALUE_INVALID) 155 return (-1); 156 bzero(&gpreq, sizeof(gpreq)); 157 gpreq.gp_pin = pin; 158 gpreq.gp_value = value; 159 if (ioctl(handle, GPIOSET, &gpreq) < 0) 160 return (-1); 161 162 return (0); 163 } 164 165 int 166 gpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 167 { 168 gpio_value_t value; 169 170 value = gpio_pin_get(handle, pin); 171 if (value == GPIO_VALUE_INVALID) 172 return (-1); 173 value = !value; 174 175 return (gpio_pin_set(handle, pin, value)); 176 } 177 178 int 179 gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 180 { 181 return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 182 } 183 184 int 185 gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 186 { 187 return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 188 } 189 190 static int 191 gpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 192 { 193 gpio_config_t cfg; 194 195 bzero(&cfg, sizeof(cfg)); 196 cfg.g_pin = pin; 197 if (gpio_pin_config(handle, &cfg) < 0) 198 return (-1); 199 cfg.g_flags = flag; 200 201 return (gpio_pin_set_flags(handle, &cfg)); 202 } 203 204 int 205 gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 206 { 207 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 208 } 209 210 int 211 gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 212 { 213 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 214 } 215 216 int 217 gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 218 { 219 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 220 } 221 222 int 223 gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 224 { 225 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 226 } 227 228 int 229 gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 230 { 231 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 232 } 233 234 int 235 gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 236 { 237 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 238 } 239 240 int 241 gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 242 { 243 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 244 } 245 246 int 247 gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 248 { 249 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 250 } 251 252 int 253 gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 254 { 255 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 256 } 257 258 int 259 gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 260 { 261 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 262 } 263