From ce0841ecfaca463c93dd5551bc5f45cd9365a938 Mon Sep 17 00:00:00 2001 From: Gediminas Jakutis Date: Mon, 31 Oct 2016 14:53:40 +0200 Subject: gpio: add initial implementation. --- configure.ac | 5 +- include/rin/gpio.h | 37 +++++++++++ src/Makefile.am | 8 ++- src/gpio/Makefile.am | 26 ++++++++ src/gpio/gpio.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gpio/gpio_private.h | 44 +++++++++++++ 6 files changed, 287 insertions(+), 5 deletions(-) create mode 100644 include/rin/gpio.h create mode 100644 src/gpio/Makefile.am create mode 100644 src/gpio/gpio.c create mode 100644 src/gpio/gpio_private.h diff --git a/configure.ac b/configure.ac index 8241db8..588049b 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ([2.13]) m4_define(LIBRIN_VERSION, m4_normalize(m4_include(VERSION))) AC_INIT([librin], [LIBRIN_VERSION], [gediminas@varciai.lt]) -AC_CONFIG_SRCDIR([src/float/float.c]) +AC_CONFIG_SRCDIR([src/dummy.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([m4]) @@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE LT_INIT # Checks for header files. -AC_CHECK_HEADERS([inttypes.h stdio.h stdint.h stdlib.h string.h]) +AC_CHECK_HEADERS([fcntl.h inttypes.h stdio.h stdint.h stdlib.h string.h sys/types.h sys/stat.h time,h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_INT32_T @@ -46,5 +46,6 @@ AC_CONFIG_FILES([Makefile src/Makefile src/diagnostic/Makefile src/float/Makefile + src/gpio/Makefile test/Makefile]) AC_OUTPUT diff --git a/include/rin/gpio.h b/include/rin/gpio.h new file mode 100644 index 0000000..83ca934 --- /dev/null +++ b/include/rin/gpio.h @@ -0,0 +1,37 @@ +/* + * The Rin Library – gpio module + * + * Copyright (C) 2016 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef LIBRIN_GPIO_INCLUDED +#define LIBRIN_GPIO_INCLUDED + +enum rin_gpiotype { + rin_gpio_in, + rin_gpio_out, + rin_gpio_closed +}; + +unsigned int rin_gpio_open(const unsigned int num, const enum rin_gpiotype type); +unsigned int rin_gpio_close(const unsigned int num); +unsigned int rin_gpio_setval(const unsigned int num, const unsigned int val); +unsigned int rin_gpio_readval(const unsigned int num, unsigned int * const val); +unsigned int rin_gpio_pin_exists(const unsigned int pin); +unsigned int rin_gpio_get_pincount(void); + +#endif /* LIBRIN_GPIO_INCLUDED */ diff --git a/src/Makefile.am b/src/Makefile.am index de86e4c..1717659 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA -SUBDIRS = float diagnostic +SUBDIRS = float diagnostic gpio AM_CFLAGS = \ -I$(top_srcdir)/include/ \ @@ -33,11 +33,13 @@ librin_la_SOURCES = dummy.c librin_la_LIBADD = \ float/librin_float.la \ - diagnostic/librin_diagnostic.la + diagnostic/librin_diagnostic.la \ + gpio/librin_gpio.la librin_includedir = $(includedir)/rin librin_include_HEADERS = \ $(top_srcdir)/include/rin/float.h \ $(top_srcdir)/include/rin/float_types.h \ $(top_srcdir)/include/rin/definitions.h \ - $(top_srcdir)/include/rin/diagnostic.h + $(top_srcdir)/include/rin/diagnostic.h \ + $(top_srcdir)/include/rin/gpio.h diff --git a/src/gpio/Makefile.am b/src/gpio/Makefile.am new file mode 100644 index 0000000..e009cab --- /dev/null +++ b/src/gpio/Makefile.am @@ -0,0 +1,26 @@ +# Copyright (C) 2016 Gediminas Jakutis +# +# This Makefile.am is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; version 2.1 +# of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +AM_CFLAGS = \ + -I$(top_srcdir)/include/ \ + -Wall \ + -Wextra + +noinst_LTLIBRARIES = librin_gpio.la + +librin_gpio_la_SOURCES = \ + gpio.c \ + gpio_private.h diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c new file mode 100644 index 0000000..45639a3 --- /dev/null +++ b/src/gpio/gpio.c @@ -0,0 +1,172 @@ +/* + * The Rin Library – gpio module + * + * Copyright (C) 2016 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "rin/gpio.h" +#include "gpio_private.h" + +unsigned int rin_gpio_open(const unsigned int num, const enum rin_gpiotype type) +{ + struct stat st; + struct timespec grace = { 0, 1 * 1000 * 1000 }; /* 1 ms */ + char buf[48] = { 0 }; + int fd; + unsigned int timeout; + + init(); + + if (type == rin_gpio_closed || !rin_gpio_pin_exists(num) || gpio[num].type != rin_gpio_closed) { + return 1; + } + + fd = open("/sys/class/gpio/export", O_WRONLY | O_DSYNC); + sprintf(buf, "%u", num); + write(fd, buf, strlen(buf)); + close(fd); + sprintf(buf, "/sys/class/gpio/gpio%u/direction", num); + timeout = 500; /* 500 ms, if it takes longer, something ain't right. */ + while (stat(buf, &st)) { + nanosleep(&grace, NULL); + if (!(--timeout)) { + return 1; + } + } + fd = open(buf, O_WRONLY | O_DSYNC); + if (type == rin_gpio_in) { + write(fd, "in", 2); + } else { + write(fd, "out", 3); + } + close(fd); + gpio[num].type = type; + sprintf(buf, "/sys/class/gpio/gpio%u/value", num); + if (type == rin_gpio_in) { + gpio[num].fd = open(buf, O_RDONLY); + } else { + gpio[num].fd = open(buf, O_WRONLY); + } + + return 0; +} + +unsigned int rin_gpio_close(const unsigned int num) +{ + char buf[32] = { 0 }; + struct stat st; + int fd; + + init(); + sprintf(buf, "/sys/class/gpio/gpio%u", num); + if (stat(buf, &st)) { + return 0; + } + close(gpio[num].fd); + gpio[num].fd = -1; + fd = open("/sys/class/gpio/unexport", O_WRONLY); + sprintf(buf, "%u", num); + write(fd, buf, strlen(buf)); + close(fd); + gpio[num].type = rin_gpio_closed; + return 0; +} + +unsigned int rin_gpio_setval(const unsigned int num, const unsigned int val) +{ + char buf[8] = { 0 }; + + init(); + if (!rin_gpio_pin_exists(num) || gpio[num].type != rin_gpio_out) { + return 1; + } + sprintf(buf, "%u", val); + lseek(gpio[num].fd, 0, SEEK_SET); + write(gpio[num].fd, buf, strlen(buf)); + return 0; +} + +unsigned int rin_gpio_readval(const unsigned int num, unsigned int * const val) +{ + init(); + + if (!rin_gpio_pin_exists(num) || gpio[num].type != rin_gpio_in) { + exit(EXIT_FAILURE); + } + + lseek(gpio[num].fd, 0, SEEK_SET); + read(gpio[num].fd, val, 1); + + if (*val >= '0') { + *val -= '0'; + } + + return 0; +} + +/* + * right now is rpi V1 specific, should be rewritten when/if we support + * other platforms. + */ +unsigned int rin_gpio_pin_exists(const unsigned int pin) +{ + switch (pin) { + case 2: + case 3: + case 4: + case 7: + case 8: + case 9: + case 10: + case 11: + case 14: + case 15: + case 17: + case 18: + case 22: + case 23: + case 24: + case 25: + return 1; + default: + return 0; + } +} + +/* + * in case we ever support hardware other than the V1 Raspberry, + * we need this to get the pin usable pin count + */ +unsigned int rin_gpio_get_pincount(void) +{ + return 16; +} + +static void init(void) +{ + size_t i; + static unsigned int firstrun = 1; + + if (firstrun) { + firstrun = 0; + for (i = 0; i < gpio_count; ++i) { + gpio[i].num = i; + gpio[i].type = rin_gpio_closed; + gpio[i].fd = -1; + } + } +} diff --git a/src/gpio/gpio_private.h b/src/gpio/gpio_private.h new file mode 100644 index 0000000..4a22570 --- /dev/null +++ b/src/gpio/gpio_private.h @@ -0,0 +1,44 @@ +/* + * The Rin Library – gpio module + * + * Copyright (C) 2016 Gediminas Jakutis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef GPIO_PRIVATE_H_INCLUDED +#define GPIO_PRIVATE_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +/* TODO: make this platform-dependent */ +#define gpio_count 32 + +static struct gpio { + unsigned int num; + enum rin_gpiotype type; + int fd; +} gpio[gpio_count]; + +static void init(void); + +#endif /* GPIO_PRIVATE_H_INCLUDED */ -- cgit v1.2.3