core: merge chip.c and line.c
authorBartosz Golaszewski <bartekgola@gmail.com>
Wed, 12 Jul 2017 15:47:07 +0000 (17:47 +0200)
committerBartosz Golaszewski <bartekgola@gmail.com>
Wed, 12 Jul 2017 15:47:07 +0000 (17:47 +0200)
Splitting the line and chip functionality led to unnecessary bloat.
Just put the code together into a single file.

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
src/lib/Makefile.am
src/lib/chip.c [deleted file]
src/lib/core.c [new file with mode: 0644]
src/lib/line.c [deleted file]
src/lib/line.h [deleted file]

index 574447806c6038e48315822e83ab59ccea2b4d36..6cf3e9ad74aaf9239ac881c6bfc44823c8ccd1bc 100644 (file)
@@ -7,7 +7,7 @@
 #
 
 lib_LTLIBRARIES = libgpiod.la
-libgpiod_la_SOURCES = chip.c iter.c line.c line.h misc.c simple.c
+libgpiod_la_SOURCES = core.c iter.c misc.c simple.c
 libgpiod_la_CFLAGS = -Wall -Wextra -g
 libgpiod_la_CFLAGS += -fvisibility=hidden -I$(top_srcdir)/include/
 libgpiod_la_CFLAGS += -include $(top_builddir)/config.h
diff --git a/src/lib/chip.c b/src/lib/chip.c
deleted file mode 100644 (file)
index 83daa91..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2017 Bartosz Golaszewski <bartekgola@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- */
-
-#include "line.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <linux/gpio.h>
-
-struct gpiod_chip {
-       int fd;
-       struct gpiochip_info cinfo;
-       struct gpiod_line **lines;
-       struct line_chip_ctx *chip_ctx;
-};
-
-static bool isuint(const char *str)
-{
-       for (; *str && isdigit(*str); str++);
-
-       return *str == '\0';
-}
-
-struct gpiod_chip * gpiod_chip_open(const char *path)
-{
-       struct gpiod_chip *chip;
-       int status, fd;
-
-       fd = open(path, O_RDWR | O_CLOEXEC);
-       if (fd < 0)
-               return NULL;
-
-       chip = malloc(sizeof(*chip));
-       if (!chip) {
-               close(fd);
-               return NULL;
-       }
-
-       memset(chip, 0, sizeof(*chip));
-       chip->fd = fd;
-
-       status = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip->cinfo);
-       if (status < 0) {
-               close(chip->fd);
-               free(chip);
-               return NULL;
-       }
-
-       return chip;
-}
-
-struct gpiod_chip * gpiod_chip_open_by_name(const char *name)
-{
-       struct gpiod_chip *chip;
-       char *path;
-       int status;
-
-       status = asprintf(&path, "/dev/%s", name);
-       if (status < 0)
-               return NULL;
-
-       chip = gpiod_chip_open(path);
-       free(path);
-
-       return chip;
-}
-
-struct gpiod_chip * gpiod_chip_open_by_number(unsigned int num)
-{
-       struct gpiod_chip *chip;
-       char *path;
-       int status;
-
-       status = asprintf(&path, "/dev/gpiochip%u", num);
-       if (!status)
-               return NULL;
-
-       chip = gpiod_chip_open(path);
-       free(path);
-
-       return chip;
-}
-
-struct gpiod_chip * gpiod_chip_open_by_label(const char *label)
-{
-       struct gpiod_chip_iter *iter;
-       struct gpiod_chip *chip;
-
-       iter = gpiod_chip_iter_new();
-       if (!iter)
-               return NULL;
-
-       gpiod_foreach_chip(iter, chip) {
-               if (gpiod_chip_iter_err(iter))
-                       goto out;
-
-               if (strcmp(label, gpiod_chip_label(chip)) == 0) {
-                       gpiod_chip_iter_free_noclose(iter);
-                       return chip;
-               }
-       }
-
-out:
-       gpiod_chip_iter_free(iter);
-       return  NULL;
-}
-
-struct gpiod_chip * gpiod_chip_open_lookup(const char *descr)
-{
-       struct gpiod_chip *chip;
-
-       if (isuint(descr)) {
-               chip = gpiod_chip_open_by_number(strtoul(descr, NULL, 10));
-       } else {
-               chip = gpiod_chip_open_by_label(descr);
-               if (!chip) {
-                       if (strncmp(descr, "/dev/", 5))
-                               chip = gpiod_chip_open_by_name(descr);
-                       else
-                               chip = gpiod_chip_open(descr);
-               }
-       }
-
-       return chip;
-}
-
-void gpiod_chip_close(struct gpiod_chip *chip)
-{
-       struct gpiod_line *line;
-       unsigned int i;
-
-       if (chip->lines) {
-               for (i = 0; i < chip->cinfo.lines; i++) {
-                       line = chip->lines[i];
-
-                       if (line) {
-                               gpiod_line_release(line);
-                               line_free(line);
-                       }
-               }
-
-               free(chip->lines);
-       }
-
-       if (chip->chip_ctx)
-               line_chip_ctx_free(chip->chip_ctx);
-
-       close(chip->fd);
-       free(chip);
-}
-
-const char * gpiod_chip_name(struct gpiod_chip *chip)
-{
-       return chip->cinfo.name[0] == '\0' ? NULL : chip->cinfo.name;
-}
-
-const char * gpiod_chip_label(struct gpiod_chip *chip)
-{
-       return chip->cinfo.label[0] == '\0' ? NULL : chip->cinfo.label;
-}
-
-unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip)
-{
-       return (unsigned int)chip->cinfo.lines;
-}
-
-struct gpiod_line *
-gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset)
-{
-       struct gpiod_line *line;
-       int status;
-
-       if (offset >= chip->cinfo.lines) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (!chip->lines) {
-               chip->lines = calloc(chip->cinfo.lines,
-                                    sizeof(struct gpiod_line *));
-               if (!chip->lines)
-                       return NULL;
-       }
-
-       if (!chip->chip_ctx) {
-               chip->chip_ctx = line_chip_ctx_new(chip, chip->fd);
-               if (!chip->chip_ctx)
-                       return NULL;
-       }
-
-       if (!chip->lines[offset]) {
-               line = line_new(offset, chip->chip_ctx);
-               if (!line)
-                       return NULL;
-
-               chip->lines[offset] = line;
-       } else {
-               line = chip->lines[offset];
-       }
-
-       status = gpiod_line_update(line);
-       if (status < 0)
-               return NULL;
-
-       return line;
-}
-
diff --git a/src/lib/core.c b/src/lib/core.c
new file mode 100644 (file)
index 0000000..8b00b18
--- /dev/null
@@ -0,0 +1,900 @@
+/*
+ * This file is part of libgpiod.
+ *
+ * Copyright (C) 2017 Bartosz Golaszewski <bartekgola@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <gpiod.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <poll.h>
+#include <errno.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/gpio.h>
+
+enum {
+       LINE_FREE = 0,
+       LINE_REQUESTED_VALUES,
+       LINE_REQUESTED_EVENTS,
+};
+
+struct handle_data {
+       struct gpiohandle_request request;
+       int refcount;
+};
+
+struct gpiod_line {
+       int state;
+       bool up_to_date;
+       struct gpiod_chip *chip;
+       struct gpioline_info info;
+       union {
+               struct handle_data *handle;
+               struct gpioevent_request event;
+       };
+};
+
+struct gpiod_chip {
+       int fd;
+       struct gpiochip_info cinfo;
+       struct gpiod_line **lines;
+};
+
+static bool isuint(const char *str)
+{
+       for (; *str && isdigit(*str); str++);
+
+       return *str == '\0';
+}
+
+static int line_get_state(struct gpiod_line *line)
+{
+       return line->state;
+}
+
+static void line_set_state(struct gpiod_line *line, int state)
+{
+       line->state = state;
+}
+
+static int line_get_handle_fd(struct gpiod_line *line)
+{
+       int state = line_get_state(line);
+
+       return state == LINE_REQUESTED_VALUES ? line->handle->request.fd : -1;
+}
+
+static int line_get_event_fd(struct gpiod_line *line)
+{
+       return line_get_state(line) == LINE_REQUESTED_EVENTS
+                                               ? line->event.fd : -1;
+}
+
+static void line_set_handle(struct gpiod_line *line,
+                           struct handle_data *handle)
+{
+       line->handle = handle;
+       handle->refcount++;
+}
+
+static void line_remove_handle(struct gpiod_line *line)
+{
+       struct handle_data *handle;
+
+       if (!line->handle)
+               return;
+
+       handle = line->handle;
+       line->handle = NULL;
+       handle->refcount--;
+       if (handle->refcount <= 0) {
+               close(handle->request.fd);
+               free(handle);
+       }
+}
+
+void line_set_offset(struct gpiod_line *line, unsigned int offset)
+{
+       line->info.line_offset = offset;
+}
+
+struct gpiod_chip * gpiod_line_get_chip(struct gpiod_line *line)
+{
+       return line->chip;
+}
+
+unsigned int gpiod_line_offset(struct gpiod_line *line)
+{
+       return (unsigned int)line->info.line_offset;
+}
+
+const char * gpiod_line_name(struct gpiod_line *line)
+{
+       return line->info.name[0] == '\0' ? NULL : line->info.name;
+}
+
+const char * gpiod_line_consumer(struct gpiod_line *line)
+{
+       return line->info.consumer[0] == '\0' ? NULL : line->info.consumer;
+}
+
+int gpiod_line_direction(struct gpiod_line *line)
+{
+       return line->info.flags & GPIOLINE_FLAG_IS_OUT ? GPIOD_DIRECTION_OUTPUT
+                                                      : GPIOD_DIRECTION_INPUT;
+}
+
+int gpiod_line_active_state(struct gpiod_line *line)
+{
+       return line->info.flags & GPIOLINE_FLAG_ACTIVE_LOW
+                                       ? GPIOD_ACTIVE_STATE_LOW
+                                       : GPIOD_ACTIVE_STATE_HIGH;
+}
+
+bool gpiod_line_is_used_by_kernel(struct gpiod_line *line)
+{
+       return line->info.flags & GPIOLINE_FLAG_KERNEL;
+}
+
+bool gpiod_line_is_open_drain(struct gpiod_line *line)
+{
+       return line->info.flags & GPIOLINE_FLAG_OPEN_DRAIN;
+}
+
+bool gpiod_line_is_open_source(struct gpiod_line *line)
+{
+       return line->info.flags & GPIOLINE_FLAG_OPEN_SOURCE;
+}
+
+static void line_set_updated(struct gpiod_line *line)
+{
+       line->up_to_date = true;
+}
+
+static void line_set_needs_update(struct gpiod_line *line)
+{
+       line->up_to_date = false;
+}
+
+static void line_maybe_update(struct gpiod_line *line)
+{
+       int status;
+
+       status = gpiod_line_update(line);
+       if (status < 0)
+               line_set_needs_update(line);
+}
+
+static bool line_bulk_is_requested(struct gpiod_line_bulk *bulk)
+{
+       unsigned int i;
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               if (!gpiod_line_is_requested(bulk->lines[i]))
+                       return false;
+       }
+
+       return true;
+}
+
+bool gpiod_line_needs_update(struct gpiod_line *line)
+{
+       return !line->up_to_date;
+}
+
+int gpiod_line_update(struct gpiod_line *line)
+{
+       int rv;
+
+       memset(line->info.name, 0, sizeof(line->info.name));
+       memset(line->info.consumer, 0, sizeof(line->info.consumer));
+       line->info.flags = 0;
+
+       rv = ioctl(line->chip->fd, GPIO_GET_LINEINFO_IOCTL, &line->info);
+       if (rv < 0)
+               return -1;
+
+       line_set_updated(line);
+
+       return 0;
+}
+
+int gpiod_line_request(struct gpiod_line *line,
+                      const struct gpiod_line_request_config *config,
+                      int default_val)
+{
+       struct gpiod_line_bulk bulk;
+
+       gpiod_line_bulk_init(&bulk);
+       gpiod_line_bulk_add(&bulk, line);
+
+       return gpiod_line_request_bulk(&bulk, config, &default_val);
+}
+
+int gpiod_line_request_input(struct gpiod_line *line,
+                            const char *consumer, bool active_low)
+{
+       struct gpiod_line_request_config config = {
+               .consumer = consumer,
+               .request_type = GPIOD_REQUEST_DIRECTION_INPUT,
+               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
+                                          : GPIOD_REQUEST_ACTIVE_HIGH,
+       };
+
+       return gpiod_line_request(line, &config, 0);
+}
+
+int gpiod_line_request_output(struct gpiod_line *line, const char *consumer,
+                             bool active_low, int default_val)
+{
+       struct gpiod_line_request_config config = {
+               .consumer = consumer,
+               .request_type = GPIOD_REQUEST_DIRECTION_OUTPUT,
+               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
+                                          : GPIOD_REQUEST_ACTIVE_HIGH,
+       };
+
+       return gpiod_line_request(line, &config, default_val);
+}
+
+static bool verify_line_bulk(struct gpiod_line_bulk *bulk)
+{
+       struct gpiod_line *line;
+       struct gpiod_chip *chip;
+       unsigned int i;
+
+       chip = gpiod_line_get_chip(bulk->lines[0]);
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               line = bulk->lines[i];
+
+               if (i > 0 && chip != gpiod_line_get_chip(line)) {
+                       errno = EINVAL;
+                       return false;
+               }
+
+               if (!gpiod_line_is_free(line)) {
+                       errno = EBUSY;
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static int line_request_values(struct gpiod_line_bulk *bulk,
+                              const struct gpiod_line_request_config *config,
+                              const int *default_vals)
+{
+       struct gpiohandle_request *req;
+       struct handle_data *handle;
+       struct gpiod_line *line;
+       unsigned int i;
+       int rv, fd;
+
+       handle = malloc(sizeof(*handle));
+       if (!handle)
+               return -1;
+
+       memset(handle, 0, sizeof(*handle));
+
+       req = &handle->request;
+
+       if (config->flags & GPIOD_REQUEST_OPEN_DRAIN)
+               req->flags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
+       if (config->flags & GPIOD_REQUEST_OPEN_SOURCE)
+               req->flags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
+
+       if (config->request_type == GPIOD_REQUEST_DIRECTION_INPUT)
+               req->flags |= GPIOHANDLE_REQUEST_INPUT;
+       else if (config->request_type == GPIOD_REQUEST_DIRECTION_OUTPUT)
+               req->flags |= GPIOHANDLE_REQUEST_OUTPUT;
+
+       if (config->active_state == GPIOD_REQUEST_ACTIVE_LOW) {
+               req->flags |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
+       } else if (config->active_state != GPIOD_REQUEST_ACTIVE_HIGH) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       req->lines = bulk->num_lines;
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               req->lineoffsets[i] = gpiod_line_offset(bulk->lines[i]);
+               if (config->request_type == GPIOD_REQUEST_DIRECTION_OUTPUT)
+                       req->default_values[i] = !!default_vals[i];
+       }
+
+       strncpy(req->consumer_label, config->consumer,
+               sizeof(req->consumer_label) - 1);
+
+       fd = bulk->lines[0]->chip->fd;
+
+       rv = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, req);
+       if (rv < 0)
+               return -1;
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               line = bulk->lines[i];
+
+               line_set_handle(line, handle);
+               line_set_state(line, LINE_REQUESTED_VALUES);
+               line_maybe_update(line);
+       }
+
+       return 0;
+}
+
+static int line_request_event_single(struct gpiod_line *line,
+                       const struct gpiod_line_request_config *config)
+{
+       struct gpioevent_request *req;
+       int rv;
+
+       req = &line->event;
+
+       memset(req, 0, sizeof(*req));
+       strncpy(req->consumer_label, config->consumer,
+               sizeof(req->consumer_label) - 1);
+       req->lineoffset = gpiod_line_offset(line);
+       req->handleflags |= GPIOHANDLE_REQUEST_INPUT;
+
+       if (config->flags & GPIOD_REQUEST_OPEN_DRAIN)
+               req->handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
+       if (config->flags & GPIOD_REQUEST_OPEN_SOURCE)
+               req->handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
+
+       if (config->active_state == GPIOD_REQUEST_ACTIVE_LOW) {
+               req->handleflags |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
+       } else if (config->active_state != GPIOD_REQUEST_ACTIVE_HIGH) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (config->request_type == GPIOD_REQUEST_EVENT_RISING_EDGE)
+               req->eventflags |= GPIOEVENT_REQUEST_RISING_EDGE;
+       else if (config->request_type == GPIOD_REQUEST_EVENT_FALLING_EDGE)
+               req->eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE;
+       else if (config->request_type == GPIOD_REQUEST_EVENT_BOTH_EDGES)
+               req->eventflags |= GPIOEVENT_REQUEST_BOTH_EDGES;
+
+       rv = ioctl(line->chip->fd, GPIO_GET_LINEEVENT_IOCTL, req);
+       if (rv < 0)
+               return -1;
+
+       line_set_state(line, LINE_REQUESTED_EVENTS);
+
+       return 0;
+}
+
+static int line_request_events(struct gpiod_line_bulk *bulk,
+                              const struct gpiod_line_request_config *config)
+{
+       unsigned int i, j;
+       int rv;
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               rv = line_request_event_single(bulk->lines[i], config);
+               if (rv) {
+                       for (j = i - 1; i > 0; i--)
+                               gpiod_line_release(bulk->lines[j]);
+
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk,
+                           const struct gpiod_line_request_config *config,
+                           const int *default_vals)
+{
+       if (!verify_line_bulk(bulk))
+               return -1;
+
+       if (config->request_type == GPIOD_REQUEST_DIRECTION_AS_IS
+           || config->request_type == GPIOD_REQUEST_DIRECTION_INPUT
+           || config->request_type == GPIOD_REQUEST_DIRECTION_OUTPUT) {
+               return line_request_values(bulk, config, default_vals);
+       } else if (config->request_type == GPIOD_REQUEST_EVENT_FALLING_EDGE
+                || config->request_type == GPIOD_REQUEST_EVENT_RISING_EDGE
+                || config->request_type == GPIOD_REQUEST_EVENT_BOTH_EDGES) {
+               return line_request_events(bulk, config);
+       } else {
+               errno = EINVAL;
+               return -1;
+       }
+}
+
+int gpiod_line_request_bulk_input(struct gpiod_line_bulk *bulk,
+                                 const char *consumer, bool active_low)
+{
+       struct gpiod_line_request_config config = {
+               .consumer = consumer,
+               .request_type = GPIOD_REQUEST_DIRECTION_INPUT,
+               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
+                                          : GPIOD_REQUEST_ACTIVE_HIGH,
+       };
+
+       return gpiod_line_request_bulk(bulk, &config, 0);
+}
+
+int gpiod_line_request_bulk_output(struct gpiod_line_bulk *bulk,
+                                  const char *consumer, bool active_low,
+                                  const int *default_vals)
+{
+       struct gpiod_line_request_config config = {
+               .consumer = consumer,
+               .request_type = GPIOD_REQUEST_DIRECTION_OUTPUT,
+               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
+                                          : GPIOD_REQUEST_ACTIVE_HIGH,
+       };
+
+       return gpiod_line_request_bulk(bulk, &config, default_vals);
+}
+
+void gpiod_line_release(struct gpiod_line *line)
+{
+       struct gpiod_line_bulk bulk;
+
+       gpiod_line_bulk_init(&bulk);
+       gpiod_line_bulk_add(&bulk, line);
+
+       gpiod_line_release_bulk(&bulk);
+}
+
+void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk)
+{
+       struct gpiod_line *line;
+       unsigned int i;
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               line = bulk->lines[i];
+
+               if (line_get_state(line) == LINE_REQUESTED_VALUES)
+                       line_remove_handle(line);
+               else if (line_get_state(line) == LINE_REQUESTED_EVENTS)
+                       close(line_get_event_fd(line));
+
+               line_set_state(line, LINE_FREE);
+       }
+}
+
+bool gpiod_line_is_requested(struct gpiod_line *line)
+{
+       return (line_get_state(line) == LINE_REQUESTED_VALUES
+               || line_get_state(line) == LINE_REQUESTED_EVENTS);
+}
+
+bool gpiod_line_is_free(struct gpiod_line *line)
+{
+       return line_get_state(line) == LINE_FREE;
+}
+
+int gpiod_line_get_value(struct gpiod_line *line)
+{
+       struct gpiod_line_bulk bulk;
+       int status, value;
+
+       gpiod_line_bulk_init(&bulk);
+       gpiod_line_bulk_add(&bulk, line);
+
+       status = gpiod_line_get_value_bulk(&bulk, &value);
+       if (status < 0)
+               return -1;
+
+       return value;
+}
+
+int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, int *values)
+{
+       struct gpiohandle_data data;
+       struct gpiod_line *first;
+       unsigned int i;
+       int status, fd;
+
+       first = bulk->lines[0];
+
+       if (!line_bulk_is_requested(bulk)) {
+               errno = EPERM;
+               return -1;
+       }
+
+       memset(&data, 0, sizeof(data));
+
+       if (line_get_state(first) == LINE_REQUESTED_VALUES)
+               fd = line_get_handle_fd(first);
+       else
+               fd = line_get_event_fd(first);
+
+       status = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+       if (status < 0)
+               return -1;
+
+       for (i = 0; i < bulk->num_lines; i++)
+               values[i] = data.values[i];
+
+       return 0;
+}
+
+int gpiod_line_set_value(struct gpiod_line *line, int value)
+{
+       struct gpiod_line_bulk bulk;
+
+       gpiod_line_bulk_init(&bulk);
+       gpiod_line_bulk_add(&bulk, line);
+
+       return gpiod_line_set_value_bulk(&bulk, &value);
+}
+
+int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, int *values)
+{
+       struct gpiohandle_data data;
+       unsigned int i;
+       int status;
+
+       if (!line_bulk_is_requested(bulk)) {
+               errno = EPERM;
+               return -1;
+       }
+
+       memset(&data, 0, sizeof(data));
+
+       for (i = 0; i < bulk->num_lines; i++)
+               data.values[i] = (uint8_t)!!values[i];
+
+       status = ioctl(line_get_handle_fd(bulk->lines[0]),
+                      GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
+       if (status < 0)
+               return -1;
+
+       return 0;
+}
+
+struct gpiod_line * gpiod_line_find_by_name(const char *name)
+{
+       struct gpiod_chip_iter *chip_iter;
+       struct gpiod_line_iter line_iter;
+       struct gpiod_chip *chip;
+       struct gpiod_line *line;
+       const char *line_name;
+
+       chip_iter = gpiod_chip_iter_new();
+       if (!chip_iter)
+               return NULL;
+
+       gpiod_foreach_chip(chip_iter, chip) {
+               if (gpiod_chip_iter_err(chip_iter))
+                       continue;
+
+               gpiod_line_iter_init(&line_iter, chip);
+               gpiod_foreach_line(&line_iter, line) {
+                       if (gpiod_line_iter_err(&line_iter))
+                               continue;
+
+                       line_name = gpiod_line_name(line);
+                       if (!line_name)
+                               continue;
+
+                       if (strcmp(line_name, name) == 0) {
+                               gpiod_chip_iter_free_noclose(chip_iter);
+                               return line;
+                       }
+               }
+       }
+
+       gpiod_chip_iter_free(chip_iter);
+
+       return NULL;
+}
+
+static int line_event_request_type(struct gpiod_line *line,
+                                  const char *consumer,
+                                  bool active_low, int type)
+{
+       struct gpiod_line_request_config config = {
+               .consumer = consumer,
+               .request_type = type,
+               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
+                                          : GPIOD_REQUEST_ACTIVE_HIGH,
+       };
+
+       return gpiod_line_request(line, &config, 0);
+}
+
+int gpiod_line_request_rising_edge_events(struct gpiod_line *line,
+                                         const char *consumer,
+                                         bool active_low)
+{
+       return line_event_request_type(line, consumer, active_low,
+                                      GPIOD_REQUEST_EVENT_RISING_EDGE);
+}
+
+int gpiod_line_request_falling_edge_events(struct gpiod_line *line,
+                                          const char *consumer,
+                                          bool active_low)
+{
+       return line_event_request_type(line, consumer, active_low,
+                                      GPIOD_REQUEST_EVENT_FALLING_EDGE);
+}
+
+int gpiod_line_request_both_edges_events(struct gpiod_line *line,
+                                        const char *consumer, bool active_low)
+{
+       return line_event_request_type(line, consumer, active_low,
+                                      GPIOD_REQUEST_EVENT_BOTH_EDGES);
+}
+
+int gpiod_line_event_wait(struct gpiod_line *line,
+                         const struct timespec *timeout)
+{
+       struct gpiod_line_bulk bulk;
+
+       gpiod_line_bulk_init(&bulk);
+       gpiod_line_bulk_add(&bulk, line);
+
+       return gpiod_line_event_wait_bulk(&bulk, timeout, NULL);
+}
+
+int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
+                              const struct timespec *timeout,
+                              struct gpiod_line **line)
+{
+       struct pollfd fds[GPIOD_REQUEST_MAX_LINES];
+       struct gpiod_line *linetmp;
+       unsigned int i;
+       int status;
+
+       memset(fds, 0, sizeof(fds));
+
+       for (i = 0; i < bulk->num_lines; i++) {
+               linetmp = bulk->lines[i];
+
+               fds[i].fd = line_get_event_fd(linetmp);
+               fds[i].events = POLLIN | POLLPRI;
+       }
+
+       status = ppoll(fds, bulk->num_lines, timeout, NULL);
+       if (status < 0)
+               return -1;
+       else if (status == 0)
+               return 0;
+
+       for (i = 0; !fds[i].revents; i++);
+       if (line)
+               *line = bulk->lines[i];
+
+       return 1;
+}
+
+int gpiod_line_event_read(struct gpiod_line *line,
+                         struct gpiod_line_event *event)
+{
+       int fd;
+
+       fd = line_get_event_fd(line);
+
+       return gpiod_line_event_read_fd(fd, event);
+}
+
+int gpiod_line_event_get_fd(struct gpiod_line *line)
+{
+       return line_get_state(line) == LINE_REQUESTED_EVENTS
+                               ? line_get_event_fd(line) : -1;
+}
+
+int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event)
+{
+       struct gpioevent_data evdata;
+       ssize_t rd;
+
+       memset(&evdata, 0, sizeof(evdata));
+
+       rd = read(fd, &evdata, sizeof(evdata));
+       if (rd < 0) {
+               return -1;
+       } else if (rd != sizeof(evdata)) {
+               errno = EIO;
+               return -1;
+       }
+
+       event->event_type = evdata.id == GPIOEVENT_EVENT_RISING_EDGE
+                                               ? GPIOD_EVENT_RISING_EDGE
+                                               : GPIOD_EVENT_FALLING_EDGE;
+
+       event->ts.tv_sec = evdata.timestamp / 1000000000ULL;
+       event->ts.tv_nsec = evdata.timestamp % 1000000000ULL;
+
+       return 0;
+}
+
+struct gpiod_chip * gpiod_chip_open(const char *path)
+{
+       struct gpiod_chip *chip;
+       int status, fd;
+
+       fd = open(path, O_RDWR | O_CLOEXEC);
+       if (fd < 0)
+               return NULL;
+
+       chip = malloc(sizeof(*chip));
+       if (!chip) {
+               close(fd);
+               return NULL;
+       }
+
+       memset(chip, 0, sizeof(*chip));
+       chip->fd = fd;
+
+       status = ioctl(fd, GPIO_GET_CHIPINFO_IOCTL, &chip->cinfo);
+       if (status < 0) {
+               close(chip->fd);
+               free(chip);
+               return NULL;
+       }
+
+       return chip;
+}
+
+struct gpiod_chip * gpiod_chip_open_by_name(const char *name)
+{
+       struct gpiod_chip *chip;
+       char *path;
+       int status;
+
+       status = asprintf(&path, "/dev/%s", name);
+       if (status < 0)
+               return NULL;
+
+       chip = gpiod_chip_open(path);
+       free(path);
+
+       return chip;
+}
+
+struct gpiod_chip * gpiod_chip_open_by_number(unsigned int num)
+{
+       struct gpiod_chip *chip;
+       char *path;
+       int status;
+
+       status = asprintf(&path, "/dev/gpiochip%u", num);
+       if (!status)
+               return NULL;
+
+       chip = gpiod_chip_open(path);
+       free(path);
+
+       return chip;
+}
+
+struct gpiod_chip * gpiod_chip_open_by_label(const char *label)
+{
+       struct gpiod_chip_iter *iter;
+       struct gpiod_chip *chip;
+
+       iter = gpiod_chip_iter_new();
+       if (!iter)
+               return NULL;
+
+       gpiod_foreach_chip(iter, chip) {
+               if (gpiod_chip_iter_err(iter))
+                       goto out;
+
+               if (strcmp(label, gpiod_chip_label(chip)) == 0) {
+                       gpiod_chip_iter_free_noclose(iter);
+                       return chip;
+               }
+       }
+
+out:
+       gpiod_chip_iter_free(iter);
+       return  NULL;
+}
+
+struct gpiod_chip * gpiod_chip_open_lookup(const char *descr)
+{
+       struct gpiod_chip *chip;
+
+       if (isuint(descr)) {
+               chip = gpiod_chip_open_by_number(strtoul(descr, NULL, 10));
+       } else {
+               chip = gpiod_chip_open_by_label(descr);
+               if (!chip) {
+                       if (strncmp(descr, "/dev/", 5))
+                               chip = gpiod_chip_open_by_name(descr);
+                       else
+                               chip = gpiod_chip_open(descr);
+               }
+       }
+
+       return chip;
+}
+
+void gpiod_chip_close(struct gpiod_chip *chip)
+{
+       struct gpiod_line *line;
+       unsigned int i;
+
+       if (chip->lines) {
+               for (i = 0; i < chip->cinfo.lines; i++) {
+                       line = chip->lines[i];
+                       if (line) {
+                               gpiod_line_release(line);
+                               free(line);
+                       }
+               }
+
+               free(chip->lines);
+       }
+
+       close(chip->fd);
+       free(chip);
+}
+
+const char * gpiod_chip_name(struct gpiod_chip *chip)
+{
+       return chip->cinfo.name[0] == '\0' ? NULL : chip->cinfo.name;
+}
+
+const char * gpiod_chip_label(struct gpiod_chip *chip)
+{
+       return chip->cinfo.label[0] == '\0' ? NULL : chip->cinfo.label;
+}
+
+unsigned int gpiod_chip_num_lines(struct gpiod_chip *chip)
+{
+       return (unsigned int)chip->cinfo.lines;
+}
+
+struct gpiod_line *
+gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset)
+{
+       struct gpiod_line *line;
+       int status;
+
+       if (offset >= chip->cinfo.lines) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       if (!chip->lines) {
+               chip->lines = calloc(chip->cinfo.lines,
+                                    sizeof(struct gpiod_line *));
+               if (!chip->lines)
+                       return NULL;
+       }
+
+       if (!chip->lines[offset]) {
+               line = malloc(sizeof(*line));
+               if (!line)
+                       return NULL;
+
+               memset(line, 0, sizeof(*line));
+
+               line->info.line_offset = offset;
+               line->chip = chip;
+
+               chip->lines[offset] = line;
+       } else {
+               line = chip->lines[offset];
+       }
+
+       status = gpiod_line_update(line);
+       if (status < 0)
+               return NULL;
+
+       return line;
+}
diff --git a/src/lib/line.c b/src/lib/line.c
deleted file mode 100644 (file)
index f078017..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2017 Bartosz Golaszewski <bartekgola@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- */
-
-#include <gpiod.h>
-
-#include <string.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <poll.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <linux/gpio.h>
-
-enum {
-       LINE_FREE = 0,
-       LINE_REQUESTED_VALUES,
-       LINE_REQUESTED_EVENTS,
-};
-
-struct handle_data {
-       struct gpiohandle_request request;
-       int refcount;
-};
-
-struct line_chip_ctx {
-       int fd;
-       struct gpiod_chip *chip;
-};
-
-struct gpiod_line {
-       int state;
-       bool up_to_date;
-       struct line_chip_ctx *chip_ctx;
-       struct gpioline_info info;
-       union {
-               struct handle_data *handle;
-               struct gpioevent_request event;
-       };
-};
-
-static int line_get_state(struct gpiod_line *line)
-{
-       return line->state;
-}
-
-static void line_set_state(struct gpiod_line *line, int state)
-{
-       line->state = state;
-}
-
-static int line_get_handle_fd(struct gpiod_line *line)
-{
-       int state = line_get_state(line);
-
-       return state == LINE_REQUESTED_VALUES ? line->handle->request.fd : -1;
-}
-
-static int line_get_event_fd(struct gpiod_line *line)
-{
-       return line_get_state(line) == LINE_REQUESTED_EVENTS
-                                               ? line->event.fd : -1;
-}
-
-static void line_set_handle(struct gpiod_line *line,
-                           struct handle_data *handle)
-{
-       line->handle = handle;
-       handle->refcount++;
-}
-
-static void line_remove_handle(struct gpiod_line *line)
-{
-       struct handle_data *handle;
-
-       if (!line->handle)
-               return;
-
-       handle = line->handle;
-       line->handle = NULL;
-       handle->refcount--;
-       if (handle->refcount <= 0) {
-               close(handle->request.fd);
-               free(handle);
-       }
-}
-
-struct line_chip_ctx * line_chip_ctx_new(struct gpiod_chip *chip, int fd)
-{
-       struct line_chip_ctx *chip_ctx;
-
-       chip_ctx = malloc(sizeof(*chip_ctx));
-       if (!chip_ctx)
-               return NULL;
-
-       chip_ctx->chip = chip;
-       chip_ctx->fd = fd;
-
-       return chip_ctx;
-}
-
-void line_chip_ctx_free(struct line_chip_ctx *chip_ctx)
-{
-       free(chip_ctx);
-}
-
-struct gpiod_line * line_new(unsigned int offset,
-                            struct line_chip_ctx *chip_ctx)
-{
-       struct gpiod_line *line;
-
-       line = malloc(sizeof(*line));
-       if (!line)
-               return NULL;
-
-       memset(line, 0, sizeof(*line));
-
-       line->info.line_offset = offset;
-       line->chip_ctx = chip_ctx;
-
-       return line;
-}
-
-void line_free(struct gpiod_line *line)
-{
-       free(line);
-}
-
-void line_set_offset(struct gpiod_line *line, unsigned int offset)
-{
-       line->info.line_offset = offset;
-}
-
-struct gpiod_chip * gpiod_line_get_chip(struct gpiod_line *line)
-{
-       return line->chip_ctx->chip;
-}
-
-unsigned int gpiod_line_offset(struct gpiod_line *line)
-{
-       return (unsigned int)line->info.line_offset;
-}
-
-const char * gpiod_line_name(struct gpiod_line *line)
-{
-       return line->info.name[0] == '\0' ? NULL : line->info.name;
-}
-
-const char * gpiod_line_consumer(struct gpiod_line *line)
-{
-       return line->info.consumer[0] == '\0' ? NULL : line->info.consumer;
-}
-
-int gpiod_line_direction(struct gpiod_line *line)
-{
-       return line->info.flags & GPIOLINE_FLAG_IS_OUT ? GPIOD_DIRECTION_OUTPUT
-                                                      : GPIOD_DIRECTION_INPUT;
-}
-
-int gpiod_line_active_state(struct gpiod_line *line)
-{
-       return line->info.flags & GPIOLINE_FLAG_ACTIVE_LOW
-                                       ? GPIOD_ACTIVE_STATE_LOW
-                                       : GPIOD_ACTIVE_STATE_HIGH;
-}
-
-bool gpiod_line_is_used_by_kernel(struct gpiod_line *line)
-{
-       return line->info.flags & GPIOLINE_FLAG_KERNEL;
-}
-
-bool gpiod_line_is_open_drain(struct gpiod_line *line)
-{
-       return line->info.flags & GPIOLINE_FLAG_OPEN_DRAIN;
-}
-
-bool gpiod_line_is_open_source(struct gpiod_line *line)
-{
-       return line->info.flags & GPIOLINE_FLAG_OPEN_SOURCE;
-}
-
-static void line_set_updated(struct gpiod_line *line)
-{
-       line->up_to_date = true;
-}
-
-static void line_set_needs_update(struct gpiod_line *line)
-{
-       line->up_to_date = false;
-}
-
-static void line_maybe_update(struct gpiod_line *line)
-{
-       int status;
-
-       status = gpiod_line_update(line);
-       if (status < 0)
-               line_set_needs_update(line);
-}
-
-static bool line_bulk_is_requested(struct gpiod_line_bulk *bulk)
-{
-       unsigned int i;
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               if (!gpiod_line_is_requested(bulk->lines[i]))
-                       return false;
-       }
-
-       return true;
-}
-
-bool gpiod_line_needs_update(struct gpiod_line *line)
-{
-       return !line->up_to_date;
-}
-
-int gpiod_line_update(struct gpiod_line *line)
-{
-       int rv;
-
-       memset(line->info.name, 0, sizeof(line->info.name));
-       memset(line->info.consumer, 0, sizeof(line->info.consumer));
-       line->info.flags = 0;
-
-       rv = ioctl(line->chip_ctx->fd, GPIO_GET_LINEINFO_IOCTL, &line->info);
-       if (rv < 0)
-               return -1;
-
-       line_set_updated(line);
-
-       return 0;
-}
-
-int gpiod_line_request(struct gpiod_line *line,
-                      const struct gpiod_line_request_config *config,
-                      int default_val)
-{
-       struct gpiod_line_bulk bulk;
-
-       gpiod_line_bulk_init(&bulk);
-       gpiod_line_bulk_add(&bulk, line);
-
-       return gpiod_line_request_bulk(&bulk, config, &default_val);
-}
-
-int gpiod_line_request_input(struct gpiod_line *line,
-                            const char *consumer, bool active_low)
-{
-       struct gpiod_line_request_config config = {
-               .consumer = consumer,
-               .request_type = GPIOD_REQUEST_DIRECTION_INPUT,
-               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
-                                          : GPIOD_REQUEST_ACTIVE_HIGH,
-       };
-
-       return gpiod_line_request(line, &config, 0);
-}
-
-int gpiod_line_request_output(struct gpiod_line *line, const char *consumer,
-                             bool active_low, int default_val)
-{
-       struct gpiod_line_request_config config = {
-               .consumer = consumer,
-               .request_type = GPIOD_REQUEST_DIRECTION_OUTPUT,
-               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
-                                          : GPIOD_REQUEST_ACTIVE_HIGH,
-       };
-
-       return gpiod_line_request(line, &config, default_val);
-}
-
-static bool verify_line_bulk(struct gpiod_line_bulk *bulk)
-{
-       struct gpiod_line *line;
-       struct gpiod_chip *chip;
-       unsigned int i;
-
-       chip = gpiod_line_get_chip(bulk->lines[0]);
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               line = bulk->lines[i];
-
-               if (i > 0 && chip != gpiod_line_get_chip(line)) {
-                       errno = EINVAL;
-                       return false;
-               }
-
-               if (!gpiod_line_is_free(line)) {
-                       errno = EBUSY;
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-static int line_request_values(struct gpiod_line_bulk *bulk,
-                              const struct gpiod_line_request_config *config,
-                              const int *default_vals)
-{
-       struct gpiohandle_request *req;
-       struct handle_data *handle;
-       struct gpiod_line *line;
-       unsigned int i;
-       int rv, fd;
-
-       handle = malloc(sizeof(*handle));
-       if (!handle)
-               return -1;
-
-       memset(handle, 0, sizeof(*handle));
-
-       req = &handle->request;
-
-       if (config->flags & GPIOD_REQUEST_OPEN_DRAIN)
-               req->flags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
-       if (config->flags & GPIOD_REQUEST_OPEN_SOURCE)
-               req->flags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
-
-       if (config->request_type == GPIOD_REQUEST_DIRECTION_INPUT)
-               req->flags |= GPIOHANDLE_REQUEST_INPUT;
-       else if (config->request_type == GPIOD_REQUEST_DIRECTION_OUTPUT)
-               req->flags |= GPIOHANDLE_REQUEST_OUTPUT;
-
-       if (config->active_state == GPIOD_REQUEST_ACTIVE_LOW) {
-               req->flags |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
-       } else if (config->active_state != GPIOD_REQUEST_ACTIVE_HIGH) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       req->lines = bulk->num_lines;
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               req->lineoffsets[i] = gpiod_line_offset(bulk->lines[i]);
-               if (config->request_type == GPIOD_REQUEST_DIRECTION_OUTPUT)
-                       req->default_values[i] = !!default_vals[i];
-       }
-
-       strncpy(req->consumer_label, config->consumer,
-               sizeof(req->consumer_label) - 1);
-
-       fd = bulk->lines[0]->chip_ctx->fd;
-
-       rv = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, req);
-       if (rv < 0)
-               return -1;
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               line = bulk->lines[i];
-
-               line_set_handle(line, handle);
-               line_set_state(line, LINE_REQUESTED_VALUES);
-               line_maybe_update(line);
-       }
-
-       return 0;
-}
-
-static int line_request_event_single(struct gpiod_line *line,
-                       const struct gpiod_line_request_config *config)
-{
-       struct gpioevent_request *req;
-       int rv;
-
-       req = &line->event;
-
-       memset(req, 0, sizeof(*req));
-       strncpy(req->consumer_label, config->consumer,
-               sizeof(req->consumer_label) - 1);
-       req->lineoffset = gpiod_line_offset(line);
-       req->handleflags |= GPIOHANDLE_REQUEST_INPUT;
-
-       if (config->flags & GPIOD_REQUEST_OPEN_DRAIN)
-               req->handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
-       if (config->flags & GPIOD_REQUEST_OPEN_SOURCE)
-               req->handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
-
-       if (config->active_state == GPIOD_REQUEST_ACTIVE_LOW) {
-               req->handleflags |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
-       } else if (config->active_state != GPIOD_REQUEST_ACTIVE_HIGH) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       if (config->request_type == GPIOD_REQUEST_EVENT_RISING_EDGE)
-               req->eventflags |= GPIOEVENT_REQUEST_RISING_EDGE;
-       else if (config->request_type == GPIOD_REQUEST_EVENT_FALLING_EDGE)
-               req->eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE;
-       else if (config->request_type == GPIOD_REQUEST_EVENT_BOTH_EDGES)
-               req->eventflags |= GPIOEVENT_REQUEST_BOTH_EDGES;
-
-       rv = ioctl(line->chip_ctx->fd, GPIO_GET_LINEEVENT_IOCTL, req);
-       if (rv < 0)
-               return -1;
-
-       line_set_state(line, LINE_REQUESTED_EVENTS);
-
-       return 0;
-}
-
-static int line_request_events(struct gpiod_line_bulk *bulk,
-                              const struct gpiod_line_request_config *config)
-{
-       unsigned int i, j;
-       int rv;
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               rv = line_request_event_single(bulk->lines[i], config);
-               if (rv) {
-                       for (j = i - 1; i > 0; i--)
-                               gpiod_line_release(bulk->lines[j]);
-
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk,
-                           const struct gpiod_line_request_config *config,
-                           const int *default_vals)
-{
-       if (!verify_line_bulk(bulk))
-               return -1;
-
-       if (config->request_type == GPIOD_REQUEST_DIRECTION_AS_IS
-           || config->request_type == GPIOD_REQUEST_DIRECTION_INPUT
-           || config->request_type == GPIOD_REQUEST_DIRECTION_OUTPUT) {
-               return line_request_values(bulk, config, default_vals);
-       } else if (config->request_type == GPIOD_REQUEST_EVENT_FALLING_EDGE
-                || config->request_type == GPIOD_REQUEST_EVENT_RISING_EDGE
-                || config->request_type == GPIOD_REQUEST_EVENT_BOTH_EDGES) {
-               return line_request_events(bulk, config);
-       } else {
-               errno = EINVAL;
-               return -1;
-       }
-}
-
-int gpiod_line_request_bulk_input(struct gpiod_line_bulk *bulk,
-                                 const char *consumer, bool active_low)
-{
-       struct gpiod_line_request_config config = {
-               .consumer = consumer,
-               .request_type = GPIOD_REQUEST_DIRECTION_INPUT,
-               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
-                                          : GPIOD_REQUEST_ACTIVE_HIGH,
-       };
-
-       return gpiod_line_request_bulk(bulk, &config, 0);
-}
-
-int gpiod_line_request_bulk_output(struct gpiod_line_bulk *bulk,
-                                  const char *consumer, bool active_low,
-                                  const int *default_vals)
-{
-       struct gpiod_line_request_config config = {
-               .consumer = consumer,
-               .request_type = GPIOD_REQUEST_DIRECTION_OUTPUT,
-               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
-                                          : GPIOD_REQUEST_ACTIVE_HIGH,
-       };
-
-       return gpiod_line_request_bulk(bulk, &config, default_vals);
-}
-
-void gpiod_line_release(struct gpiod_line *line)
-{
-       struct gpiod_line_bulk bulk;
-
-       gpiod_line_bulk_init(&bulk);
-       gpiod_line_bulk_add(&bulk, line);
-
-       gpiod_line_release_bulk(&bulk);
-}
-
-void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk)
-{
-       struct gpiod_line *line;
-       unsigned int i;
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               line = bulk->lines[i];
-
-               if (line_get_state(line) == LINE_REQUESTED_VALUES)
-                       line_remove_handle(line);
-               else if (line_get_state(line) == LINE_REQUESTED_EVENTS)
-                       close(line_get_event_fd(line));
-
-               line_set_state(line, LINE_FREE);
-       }
-}
-
-bool gpiod_line_is_requested(struct gpiod_line *line)
-{
-       return (line_get_state(line) == LINE_REQUESTED_VALUES
-               || line_get_state(line) == LINE_REQUESTED_EVENTS);
-}
-
-bool gpiod_line_is_free(struct gpiod_line *line)
-{
-       return line_get_state(line) == LINE_FREE;
-}
-
-int gpiod_line_get_value(struct gpiod_line *line)
-{
-       struct gpiod_line_bulk bulk;
-       int status, value;
-
-       gpiod_line_bulk_init(&bulk);
-       gpiod_line_bulk_add(&bulk, line);
-
-       status = gpiod_line_get_value_bulk(&bulk, &value);
-       if (status < 0)
-               return -1;
-
-       return value;
-}
-
-int gpiod_line_get_value_bulk(struct gpiod_line_bulk *bulk, int *values)
-{
-       struct gpiohandle_data data;
-       struct gpiod_line *first;
-       unsigned int i;
-       int status, fd;
-
-       first = bulk->lines[0];
-
-       if (!line_bulk_is_requested(bulk)) {
-               errno = EPERM;
-               return -1;
-       }
-
-       memset(&data, 0, sizeof(data));
-
-       if (line_get_state(first) == LINE_REQUESTED_VALUES)
-               fd = line_get_handle_fd(first);
-       else
-               fd = line_get_event_fd(first);
-
-       status = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
-       if (status < 0)
-               return -1;
-
-       for (i = 0; i < bulk->num_lines; i++)
-               values[i] = data.values[i];
-
-       return 0;
-}
-
-int gpiod_line_set_value(struct gpiod_line *line, int value)
-{
-       struct gpiod_line_bulk bulk;
-
-       gpiod_line_bulk_init(&bulk);
-       gpiod_line_bulk_add(&bulk, line);
-
-       return gpiod_line_set_value_bulk(&bulk, &value);
-}
-
-int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, int *values)
-{
-       struct gpiohandle_data data;
-       unsigned int i;
-       int status;
-
-       if (!line_bulk_is_requested(bulk)) {
-               errno = EPERM;
-               return -1;
-       }
-
-       memset(&data, 0, sizeof(data));
-
-       for (i = 0; i < bulk->num_lines; i++)
-               data.values[i] = (uint8_t)!!values[i];
-
-       status = ioctl(line_get_handle_fd(bulk->lines[0]),
-                      GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
-       if (status < 0)
-               return -1;
-
-       return 0;
-}
-
-struct gpiod_line * gpiod_line_find_by_name(const char *name)
-{
-       struct gpiod_chip_iter *chip_iter;
-       struct gpiod_line_iter line_iter;
-       struct gpiod_chip *chip;
-       struct gpiod_line *line;
-       const char *line_name;
-
-       chip_iter = gpiod_chip_iter_new();
-       if (!chip_iter)
-               return NULL;
-
-       gpiod_foreach_chip(chip_iter, chip) {
-               if (gpiod_chip_iter_err(chip_iter))
-                       continue;
-
-               gpiod_line_iter_init(&line_iter, chip);
-               gpiod_foreach_line(&line_iter, line) {
-                       if (gpiod_line_iter_err(&line_iter))
-                               continue;
-
-                       line_name = gpiod_line_name(line);
-                       if (!line_name)
-                               continue;
-
-                       if (strcmp(line_name, name) == 0) {
-                               gpiod_chip_iter_free_noclose(chip_iter);
-                               return line;
-                       }
-               }
-       }
-
-       gpiod_chip_iter_free(chip_iter);
-
-       return NULL;
-}
-
-static int line_event_request_type(struct gpiod_line *line,
-                                  const char *consumer,
-                                  bool active_low, int type)
-{
-       struct gpiod_line_request_config config = {
-               .consumer = consumer,
-               .request_type = type,
-               .active_state = active_low ? GPIOD_REQUEST_ACTIVE_LOW
-                                          : GPIOD_REQUEST_ACTIVE_HIGH,
-       };
-
-       return gpiod_line_request(line, &config, 0);
-}
-
-int gpiod_line_request_rising_edge_events(struct gpiod_line *line,
-                                         const char *consumer,
-                                         bool active_low)
-{
-       return line_event_request_type(line, consumer, active_low,
-                                      GPIOD_REQUEST_EVENT_RISING_EDGE);
-}
-
-int gpiod_line_request_falling_edge_events(struct gpiod_line *line,
-                                          const char *consumer,
-                                          bool active_low)
-{
-       return line_event_request_type(line, consumer, active_low,
-                                      GPIOD_REQUEST_EVENT_FALLING_EDGE);
-}
-
-int gpiod_line_request_both_edges_events(struct gpiod_line *line,
-                                        const char *consumer, bool active_low)
-{
-       return line_event_request_type(line, consumer, active_low,
-                                      GPIOD_REQUEST_EVENT_BOTH_EDGES);
-}
-
-int gpiod_line_event_wait(struct gpiod_line *line,
-                         const struct timespec *timeout)
-{
-       struct gpiod_line_bulk bulk;
-
-       gpiod_line_bulk_init(&bulk);
-       gpiod_line_bulk_add(&bulk, line);
-
-       return gpiod_line_event_wait_bulk(&bulk, timeout, NULL);
-}
-
-int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
-                              const struct timespec *timeout,
-                              struct gpiod_line **line)
-{
-       struct pollfd fds[GPIOD_REQUEST_MAX_LINES];
-       struct gpiod_line *linetmp;
-       unsigned int i;
-       int status;
-
-       memset(fds, 0, sizeof(fds));
-
-       for (i = 0; i < bulk->num_lines; i++) {
-               linetmp = bulk->lines[i];
-
-               fds[i].fd = line_get_event_fd(linetmp);
-               fds[i].events = POLLIN | POLLPRI;
-       }
-
-       status = ppoll(fds, bulk->num_lines, timeout, NULL);
-       if (status < 0)
-               return -1;
-       else if (status == 0)
-               return 0;
-
-       for (i = 0; !fds[i].revents; i++);
-       if (line)
-               *line = bulk->lines[i];
-
-       return 1;
-}
-
-int gpiod_line_event_read(struct gpiod_line *line,
-                         struct gpiod_line_event *event)
-{
-       int fd;
-
-       fd = line_get_event_fd(line);
-
-       return gpiod_line_event_read_fd(fd, event);
-}
-
-int gpiod_line_event_get_fd(struct gpiod_line *line)
-{
-       return line_get_state(line) == LINE_REQUESTED_EVENTS
-                               ? line_get_event_fd(line) : -1;
-}
-
-int gpiod_line_event_read_fd(int fd, struct gpiod_line_event *event)
-{
-       struct gpioevent_data evdata;
-       ssize_t rd;
-
-       memset(&evdata, 0, sizeof(evdata));
-
-       rd = read(fd, &evdata, sizeof(evdata));
-       if (rd < 0) {
-               return -1;
-       } else if (rd != sizeof(evdata)) {
-               errno = EIO;
-               return -1;
-       }
-
-       event->event_type = evdata.id == GPIOEVENT_EVENT_RISING_EDGE
-                                               ? GPIOD_EVENT_RISING_EDGE
-                                               : GPIOD_EVENT_FALLING_EDGE;
-
-       event->ts.tv_sec = evdata.timestamp / 1000000000ULL;
-       event->ts.tv_nsec = evdata.timestamp % 1000000000ULL;
-
-       return 0;
-}
diff --git a/src/lib/line.h b/src/lib/line.h
deleted file mode 100644 (file)
index c87d139..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is part of libgpiod.
- *
- * Copyright (C) 2017 Bartosz Golaszewski <bartekgola@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2.1 of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- */
-
-#ifndef __GPIOD_INTERNAL_LINE_H__
-#define __GPIOD_INTERNAL_LINE_H__
-
-#include <gpiod.h>
-
-struct line_chip_ctx;
-
-struct line_chip_ctx * line_chip_ctx_new(struct gpiod_chip *chip, int fd);
-void line_chip_ctx_free(struct line_chip_ctx *chip_ctx);
-
-struct gpiod_line * line_new(unsigned int offset,
-                            struct line_chip_ctx *chip_ctx);
-void line_free(struct gpiod_line *line);
-
-#endif /* __GPIOD_INTERNAL_LINE_H__ */