/* GPIO handler routines */ /* (C) 2016 by sysmocom s.f.m.c. GmbH * All Rights Reserved * * Author: Philipp Maier * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include "gpio.h" #define SYSFS_EXPORT "/sys/class/gpio/export" #define SYSFS_UNEXPORT "/sys/class/gpio/unexport" #define SYSFS_DIRECTION "/sys/class/gpio/gpio%d/direction" #define SYSFS_VALUE "/sys/class/gpio/gpio%d/value" /* Open sysfs endpoints and initalize GPIOs */ struct gpio_descr *gpio_open(void *ctx, unsigned int *gpios, unsigned int gpios_len) { int i; char buf[255]; FILE *fd_export = NULL; FILE *fd_direction[MAX_GPIOS]; FILE *fd_value[MAX_GPIOS]; struct gpio_descr *gd; OSMO_ASSERT(gpios); OSMO_ASSERT(gpios_len <= MAX_GPIOS); /* Export requested GPIOs to userspace */ fd_export = fopen(SYSFS_EXPORT, "w"); if (!fd_export) { printf("Error: Could not open: %s\n", SYSFS_EXPORT); return NULL; } else { for (i = 0; i < gpios_len; i++) { sprintf(buf, "%d", gpios[i]); rewind(fd_export); fputs(buf, fd_export); } fclose(fd_export); fd_export = NULL; } /* Open GPIO file descriptors */ for (i = 0; i < gpios_len; i++) { sprintf(buf, SYSFS_DIRECTION, gpios[i]); fd_direction[i] = fopen(buf, "w"); if (!fd_direction[i]) { printf("Error: Could not open: %s\n", buf); return NULL; } sprintf(buf, SYSFS_VALUE, gpios[i]); fd_value[i] = fopen(buf, "w"); if (!fd_value[i]) { printf("Error: Could not open: %s\n", buf); return NULL; } } /* Configure GPIOs as outputs */ for (i = 0; i < gpios_len; i++) { rewind(fd_direction[i]); fputs("out", fd_direction[i]); fflush(fd_direction[i]); } /* Generate descriptor struct */ gd = talloc_zero(ctx, struct gpio_descr); memcpy(gd->gpios, gpios, sizeof(gd->gpios)); gd->gpios_len = gpios_len; memcpy(gd->fd_direction, fd_direction, sizeof(gd->fd_direction)); memcpy(gd->fd_value, fd_value, sizeof(gd->fd_value)); return gd; } /* Close sysfs endpoints and unintialize GPIOs */ void gpio_close(struct gpio_descr *gd) { int i; char buf[255]; FILE *fd_unexport = NULL; OSMO_ASSERT(gd); /* Close GPIOs file descriptors */ for (i = 0; i < gd->gpios_len; i++) { if (gd->fd_direction[i]) fclose(gd->fd_direction[i]); if (gd->fd_value[i]) fclose(gd->fd_value[i]); } /* Remove requested GPIOs from userspace */ fd_unexport = fopen(SYSFS_UNEXPORT, "w"); if (fd_unexport) { for (i = 0; i < gd->gpios_len; i++) { sprintf(buf, "%d", gd->gpios[i]); rewind(fd_unexport); fputs(buf, fd_unexport); } fclose(fd_unexport); } /* Free descriptor struct */ talloc_free(gd); } /* Set GPIO pin status */ void gpio_set(struct gpio_descr *gd, unsigned int gpio, unsigned int state) { OSMO_ASSERT(gd); OSMO_ASSERT(gpio < gd->gpios_len); rewind(gd->fd_value[gpio]); if (state) fputs("1", gd->fd_value[gpio]); else fputs("0", gd->fd_value[gpio]); fflush(gd->fd_value[gpio]); }