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 38gpio_handle_t 39gpio_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 48gpio_handle_t 49gpio_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 70void 71gpio_close(gpio_handle_t handle) 72{ 73 close(handle); 74} 75 76int 77gpio_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 102int 103gpio_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 119int 120gpio_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 135int 136gpio_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 150gpio_value_t 151gpio_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 163int 164gpio_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 179int 180gpio_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 192int 193gpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 194{ 195 return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 196} 197 198int 199gpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 200{ 201 return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 202} 203 204static int 205gpio_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 218int 219gpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 220{ 221 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 222} 223 224int 225gpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 226{ 227 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 228} 229 230int 231gpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 232{ 233 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 234} 235 236int 237gpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 238{ 239 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 240} 241 242int 243gpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 244{ 245 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 246} 247 248int 249gpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 250{ 251 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 252} 253 254int 255gpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 256{ 257 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 258} 259 260int 261gpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 262{ 263 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 264} 265 266int 267gpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 268{ 269 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 270} 271 272int 273gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 274{ 275 return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 276} 277