gpio.c revision 274987
1274987Srpaulo/*- 2274987Srpaulo * Copyright (c) 2013-2014 Rui Paulo <rpaulo@FreeBSD.org> 3274987Srpaulo * All rights reserved. 4274987Srpaulo * 5274987Srpaulo * Redistribution and use in source and binary forms, with or without 6274987Srpaulo * modification, are permitted provided that the following conditions 7274987Srpaulo * are met: 8274987Srpaulo * 1. Redistributions of source code must retain the above copyright 9274987Srpaulo * notice, this list of conditions and the following disclaimer. 10274987Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 11274987Srpaulo * notice, this list of conditions and the following disclaimer in the 12274987Srpaulo * documentation and/or other materials provided with the distribution. 13274987Srpaulo * 14274987Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15274987Srpaulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16274987Srpaulo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17274987Srpaulo * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 18274987Srpaulo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19274987Srpaulo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20274987Srpaulo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21274987Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22274987Srpaulo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 23274987Srpaulo * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24274987Srpaulo * POSSIBILITY OF SUCH DAMAGE. 25274987Srpaulo * 26274987Srpaulo * $FreeBSD: head/lib/libgpio/gpio.c 274987 2014-11-24 21:49:40Z rpaulo $ 27274987Srpaulo */ 28274987Srpaulo#include <stdio.h> 29274987Srpaulo#include <fcntl.h> 30274987Srpaulo#include <unistd.h> 31274987Srpaulo#include <stdlib.h> 32274987Srpaulo#include <string.h> 33274987Srpaulo#include <errno.h> 34274987Srpaulo 35274987Srpaulo#include <sys/ioctl.h> 36274987Srpaulo#include <sys/types.h> 37274987Srpaulo 38274987Srpaulo#include <libgpio.h> 39274987Srpaulo 40274987Srpaulogpio_handle_t 41274987Srpaulogpio_open(unsigned int unit) 42274987Srpaulo{ 43274987Srpaulo char device[16]; 44274987Srpaulo 45274987Srpaulo snprintf(device, sizeof(device), "/dev/gpioc%u", unit); 46274987Srpaulo 47274987Srpaulo return (gpio_open_device(device)); 48274987Srpaulo} 49274987Srpaulo 50274987Srpaulogpio_handle_t 51274987Srpaulogpio_open_device(const char *device) 52274987Srpaulo{ 53274987Srpaulo int fd, maxpins; 54274987Srpaulo int serr; 55274987Srpaulo 56274987Srpaulo fd = open(device, O_RDONLY); 57274987Srpaulo if (fd < 0) 58274987Srpaulo return (GPIO_INVALID_HANDLE); 59274987Srpaulo /* 60274987Srpaulo * Check whether a simple ioctl works. 61274987Srpaulo */ 62274987Srpaulo if (ioctl(fd, GPIOMAXPIN, &maxpins) < 0) { 63274987Srpaulo serr = errno; 64274987Srpaulo close(fd); 65274987Srpaulo errno = serr; 66274987Srpaulo return (GPIO_INVALID_HANDLE); 67274987Srpaulo } 68274987Srpaulo 69274987Srpaulo return (fd); 70274987Srpaulo} 71274987Srpaulo 72274987Srpaulovoid 73274987Srpaulogpio_close(gpio_handle_t handle) 74274987Srpaulo{ 75274987Srpaulo close(handle); 76274987Srpaulo} 77274987Srpaulo 78274987Srpauloint 79274987Srpaulogpio_pin_list(gpio_handle_t handle, gpio_config_t **pcfgs) 80274987Srpaulo{ 81274987Srpaulo int maxpins, i; 82274987Srpaulo gpio_config_t *cfgs; 83274987Srpaulo 84274987Srpaulo *pcfgs = NULL; 85274987Srpaulo if (ioctl(handle, GPIOMAXPIN, &maxpins) < 0) 86274987Srpaulo return (-1); 87274987Srpaulo /* Reasonable values. */ 88274987Srpaulo if (maxpins < 0 || maxpins > 4096) { 89274987Srpaulo errno = EINVAL; 90274987Srpaulo return (-1); 91274987Srpaulo } 92274987Srpaulo cfgs = calloc(maxpins, sizeof(*cfgs)); 93274987Srpaulo if (cfgs == NULL) 94274987Srpaulo return (-1); 95274987Srpaulo for (i = 0; i <= maxpins; i++) { 96274987Srpaulo cfgs[i].g_pin = i; 97274987Srpaulo gpio_pin_config(handle, &cfgs[i]); 98274987Srpaulo } 99274987Srpaulo *pcfgs = cfgs; 100274987Srpaulo 101274987Srpaulo return (maxpins); 102274987Srpaulo} 103274987Srpaulo 104274987Srpauloint 105274987Srpaulogpio_pin_config(gpio_handle_t handle, gpio_config_t *cfg) 106274987Srpaulo{ 107274987Srpaulo struct gpio_pin gppin; 108274987Srpaulo 109274987Srpaulo if (cfg == NULL) 110274987Srpaulo return (-1); 111274987Srpaulo gppin.gp_pin = cfg->g_pin; 112274987Srpaulo if (ioctl(handle, GPIOGETCONFIG, &gppin) < 0) 113274987Srpaulo return (-1); 114274987Srpaulo strlcpy(cfg->g_name, gppin.gp_name, GPIOMAXNAME); 115274987Srpaulo cfg->g_caps = gppin.gp_caps; 116274987Srpaulo cfg->g_flags = gppin.gp_flags; 117274987Srpaulo 118274987Srpaulo return (0); 119274987Srpaulo} 120274987Srpaulo 121274987Srpauloint 122274987Srpaulogpio_pin_set_flags(gpio_handle_t handle, gpio_config_t *cfg) 123274987Srpaulo{ 124274987Srpaulo struct gpio_pin gppin; 125274987Srpaulo 126274987Srpaulo if (cfg == NULL) 127274987Srpaulo return (-1); 128274987Srpaulo gppin.gp_pin = cfg->g_pin; 129274987Srpaulo gppin.gp_flags = cfg->g_flags; 130274987Srpaulo if (ioctl(handle, GPIOSETCONFIG, &gppin) < 0) 131274987Srpaulo return (-1); 132274987Srpaulo 133274987Srpaulo return (0); 134274987Srpaulo} 135274987Srpaulo 136274987Srpaulogpio_value_t 137274987Srpaulogpio_pin_get(gpio_handle_t handle, gpio_pin_t pin) 138274987Srpaulo{ 139274987Srpaulo struct gpio_req gpreq; 140274987Srpaulo 141274987Srpaulo bzero(&gpreq, sizeof(gpreq)); 142274987Srpaulo gpreq.gp_pin = pin; 143274987Srpaulo if (ioctl(handle, GPIOGET, &gpreq) < 0) 144274987Srpaulo return (GPIO_VALUE_INVALID); 145274987Srpaulo 146274987Srpaulo return (gpreq.gp_value); 147274987Srpaulo} 148274987Srpaulo 149274987Srpauloint 150274987Srpaulogpio_pin_set(gpio_handle_t handle, gpio_pin_t pin, gpio_value_t value) 151274987Srpaulo{ 152274987Srpaulo struct gpio_req gpreq; 153274987Srpaulo 154274987Srpaulo if (value == GPIO_VALUE_INVALID) 155274987Srpaulo return (-1); 156274987Srpaulo bzero(&gpreq, sizeof(gpreq)); 157274987Srpaulo gpreq.gp_pin = pin; 158274987Srpaulo gpreq.gp_value = value; 159274987Srpaulo if (ioctl(handle, GPIOSET, &gpreq) < 0) 160274987Srpaulo return (-1); 161274987Srpaulo 162274987Srpaulo return (0); 163274987Srpaulo} 164274987Srpaulo 165274987Srpauloint 166274987Srpaulogpio_pin_toggle(gpio_handle_t handle, gpio_pin_t pin) 167274987Srpaulo{ 168274987Srpaulo gpio_value_t value; 169274987Srpaulo 170274987Srpaulo value = gpio_pin_get(handle, pin); 171274987Srpaulo if (value == GPIO_VALUE_INVALID) 172274987Srpaulo return (-1); 173274987Srpaulo value = !value; 174274987Srpaulo 175274987Srpaulo return (gpio_pin_set(handle, pin, value)); 176274987Srpaulo} 177274987Srpaulo 178274987Srpauloint 179274987Srpaulogpio_pin_low(gpio_handle_t handle, gpio_pin_t pin) 180274987Srpaulo{ 181274987Srpaulo return (gpio_pin_set(handle, pin, GPIO_VALUE_LOW)); 182274987Srpaulo} 183274987Srpaulo 184274987Srpauloint 185274987Srpaulogpio_pin_high(gpio_handle_t handle, gpio_pin_t pin) 186274987Srpaulo{ 187274987Srpaulo return (gpio_pin_set(handle, pin, GPIO_VALUE_HIGH)); 188274987Srpaulo} 189274987Srpaulo 190274987Srpaulostatic int 191274987Srpaulogpio_pin_set_flag(gpio_handle_t handle, gpio_pin_t pin, uint32_t flag) 192274987Srpaulo{ 193274987Srpaulo gpio_config_t cfg; 194274987Srpaulo 195274987Srpaulo bzero(&cfg, sizeof(cfg)); 196274987Srpaulo cfg.g_pin = pin; 197274987Srpaulo if (gpio_pin_config(handle, &cfg) < 0) 198274987Srpaulo return (-1); 199274987Srpaulo cfg.g_flags = flag; 200274987Srpaulo 201274987Srpaulo return (gpio_pin_set_flags(handle, &cfg)); 202274987Srpaulo} 203274987Srpaulo 204274987Srpauloint 205274987Srpaulogpio_pin_input(gpio_handle_t handle, gpio_pin_t pin) 206274987Srpaulo{ 207274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INPUT)); 208274987Srpaulo} 209274987Srpaulo 210274987Srpauloint 211274987Srpaulogpio_pin_output(gpio_handle_t handle, gpio_pin_t pin) 212274987Srpaulo{ 213274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OUTPUT)); 214274987Srpaulo} 215274987Srpaulo 216274987Srpauloint 217274987Srpaulogpio_pin_opendrain(gpio_handle_t handle, gpio_pin_t pin) 218274987Srpaulo{ 219274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_OPENDRAIN)); 220274987Srpaulo} 221274987Srpaulo 222274987Srpauloint 223274987Srpaulogpio_pin_pushpull(gpio_handle_t handle, gpio_pin_t pin) 224274987Srpaulo{ 225274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PUSHPULL)); 226274987Srpaulo} 227274987Srpaulo 228274987Srpauloint 229274987Srpaulogpio_pin_tristate(gpio_handle_t handle, gpio_pin_t pin) 230274987Srpaulo{ 231274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_TRISTATE)); 232274987Srpaulo} 233274987Srpaulo 234274987Srpauloint 235274987Srpaulogpio_pin_pullup(gpio_handle_t handle, gpio_pin_t pin) 236274987Srpaulo{ 237274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLUP)); 238274987Srpaulo} 239274987Srpaulo 240274987Srpauloint 241274987Srpaulogpio_pin_pulldown(gpio_handle_t handle, gpio_pin_t pin) 242274987Srpaulo{ 243274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULLDOWN)); 244274987Srpaulo} 245274987Srpaulo 246274987Srpauloint 247274987Srpaulogpio_pin_invin(gpio_handle_t handle, gpio_pin_t pin) 248274987Srpaulo{ 249274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVIN)); 250274987Srpaulo} 251274987Srpaulo 252274987Srpauloint 253274987Srpaulogpio_pin_invout(gpio_handle_t handle, gpio_pin_t pin) 254274987Srpaulo{ 255274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_INVOUT)); 256274987Srpaulo} 257274987Srpaulo 258274987Srpauloint 259274987Srpaulogpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) 260274987Srpaulo{ 261274987Srpaulo return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); 262274987Srpaulo} 263