core: separate the chip and line logic
authorBartosz Golaszewski <bartekgola@gmail.com>
Fri, 30 Jun 2017 10:55:36 +0000 (12:55 +0200)
committerBartosz Golaszewski <bartekgola@gmail.com>
Thu, 6 Jul 2017 09:11:36 +0000 (11:11 +0200)
Lazily allocate memory for line objects in chip.c. This eliminates the
need for chip routines to know the size of a line object.

Line objects now contain the chip file descriptor as well, so that we
don't need to access the chip object in any way from line.c.

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

index 693b8cdbcb6c3e00788bde13c2cd1e9fa436df7a..574447806c6038e48315822e83ab59ccea2b4d36 100644 (file)
@@ -7,7 +7,7 @@
 #
 
 lib_LTLIBRARIES = libgpiod.la
-libgpiod_la_SOURCES = chip.c iter.c line.c misc.c simple.c
+libgpiod_la_SOURCES = chip.c iter.c line.c line.h 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
index 58d02c2aeebd5cca36754a500e88740edba0b135..51e64cccf5004bb83b8617701951d883d413ab87 100644 (file)
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation.
  */
 
-#include "gpiod-internal.h"
+#include "line.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -22,7 +22,7 @@
 struct gpiod_chip {
        int fd;
        struct gpiochip_info cinfo;
-       struct gpiod_line *lines;
+       struct gpiod_line **lines;
 };
 
 static bool isuint(const char *str)
@@ -32,11 +32,6 @@ static bool isuint(const char *str)
        return *str == '\0';
 }
 
-int chip_get_fd(struct gpiod_chip *chip)
-{
-       return chip->fd;
-}
-
 struct gpiod_chip * gpiod_chip_open(const char *path)
 {
        struct gpiod_chip *chip;
@@ -62,7 +57,7 @@ struct gpiod_chip * gpiod_chip_open(const char *path)
                return NULL;
        }
 
-       chip->lines = line_array_alloc(chip->cinfo.lines);
+       chip->lines = calloc(chip->cinfo.lines, sizeof(struct gpiod_line *));
        if (!chip->lines) {
                close(chip->fd);
                free(chip);
@@ -149,16 +144,17 @@ struct gpiod_chip * gpiod_chip_open_lookup(const char *descr)
 
 void gpiod_chip_close(struct gpiod_chip *chip)
 {
-       struct gpiod_line_bulk bulk;
        unsigned int i;
 
-       gpiod_line_bulk_init(&bulk);
-       for (i = 0; i < chip->cinfo.lines; i++)
-               gpiod_line_bulk_add(&bulk, line_array_member(chip->lines, i));
-       gpiod_line_release_bulk(&bulk);
+       for (i = 0; i < chip->cinfo.lines; i++) {
+               if (chip->lines[i]) {
+                       gpiod_line_release(chip->lines[i]);
+                       line_free(chip->lines[i]);
+               }
+       }
 
        close(chip->fd);
-       line_array_free(chip->lines);
+       free(chip->lines);
        free(chip);
 }
 
@@ -188,9 +184,15 @@ gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset)
                return NULL;
        }
 
-       line = line_array_member(chip->lines, offset);
-       line_set_offset(line, offset);
-       line_set_chip(line, chip);
+       if (!chip->lines[offset]) {
+               line = line_new(offset, chip, chip->fd);
+               if (!line)
+                       return NULL;
+
+               chip->lines[offset] = line;
+       } else {
+               line = chip->lines[offset];
+       }
 
        status = gpiod_line_update(line);
        if (status < 0)
diff --git a/src/lib/gpiod-internal.h b/src/lib/gpiod-internal.h
deleted file mode 100644 (file)
index 6bf6be5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Internal routines for 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_H__
-#define __GPIOD_INTERNAL_H__
-
-#include <gpiod.h>
-
-struct gpiod_line * line_array_alloc(size_t numlines);
-void line_array_free(struct gpiod_line *lines);
-struct gpiod_line * line_array_member(struct gpiod_line *lines, size_t index);
-
-void line_set_chip(struct gpiod_line *line, struct gpiod_chip *chip);
-void line_set_offset(struct gpiod_line *line, unsigned int offset);
-
-int chip_get_fd(struct gpiod_chip *chip);
-
-#endif /* __GPIOD_INTERNAL_H__ */
index ea0aef041269f77e2a6c0b43901b182bcaade51d..aae6cffc2a116948720350bdb6ff8bb19beb44e9 100644 (file)
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation.
  */
 
-#include "gpiod-internal.h"
+#include <gpiod.h>
 
 #include <string.h>
 #include <stdint.h>
@@ -33,6 +33,7 @@ struct gpiod_line {
        int state;
        bool up_to_date;
        struct gpiod_chip *chip;
+       int fd;
        struct gpioline_info info;
        union {
                struct handle_data *handle;
@@ -85,29 +86,37 @@ static void line_remove_handle(struct gpiod_line *line)
        }
 }
 
-void line_set_offset(struct gpiod_line *line, unsigned int offset)
+struct gpiod_line *
+line_new(unsigned int offset, struct gpiod_chip *chip, int info_fd)
 {
+       struct gpiod_line *line;
+
+       line = malloc(sizeof(*line));
+       if (!line)
+               return NULL;
+
+       memset(line, 0, sizeof(*line));
+
        line->info.line_offset = offset;
-}
+       line->chip = chip;
+       line->fd = info_fd;
 
-struct gpiod_chip * gpiod_line_get_chip(struct gpiod_line *line)
-{
-       return line->chip;
+       return line;
 }
 
-struct gpiod_line * line_array_alloc(size_t numlines)
+void line_free(struct gpiod_line *line)
 {
-       return calloc(numlines, sizeof(struct gpiod_line));
+       free(line);
 }
 
-void line_array_free(struct gpiod_line *lines)
+void line_set_offset(struct gpiod_line *line, unsigned int offset)
 {
-       free(lines);
+       line->info.line_offset = offset;
 }
 
-struct gpiod_line * line_array_member(struct gpiod_line *lines, size_t index)
+struct gpiod_chip * gpiod_line_get_chip(struct gpiod_line *line)
 {
-       return &lines[index];
+       return line->chip;
 }
 
 void line_set_chip(struct gpiod_line *line, struct gpiod_chip *chip)
@@ -208,17 +217,13 @@ bool gpiod_line_needs_update(struct gpiod_line *line)
 
 int gpiod_line_update(struct gpiod_line *line)
 {
-       struct gpiod_chip *chip;
-       int status, fd;
+       int status;
 
        memset(line->info.name, 0, sizeof(line->info.name));
        memset(line->info.consumer, 0, sizeof(line->info.consumer));
        line->info.flags = 0;
 
-       chip = gpiod_line_get_chip(line);
-       fd = chip_get_fd(chip);
-
-       status = ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &line->info);
+       status = ioctl(line->fd, GPIO_GET_LINEINFO_IOCTL, &line->info);
        if (status < 0)
                return -1;
 
@@ -296,7 +301,6 @@ int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk,
 {
        struct gpiohandle_request *req;
        struct handle_data *handle;
-       struct gpiod_chip *chip;
        struct gpiod_line *line;
        int status, fd;
        unsigned int i;
@@ -336,8 +340,7 @@ int gpiod_line_request_bulk(struct gpiod_line_bulk *bulk,
        strncpy(req->consumer_label, config->consumer,
                sizeof(req->consumer_label) - 1);
 
-       chip = gpiod_line_get_chip(bulk->lines[0]);
-       fd = chip_get_fd(chip);
+       fd = bulk->lines[0]->fd;
 
        status = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, req);
        if (status < 0)
@@ -546,8 +549,7 @@ int gpiod_line_event_request(struct gpiod_line *line,
                             struct gpiod_line_evreq_config *config)
 {
        struct gpioevent_request *req;
-       struct gpiod_chip *chip;
-       int status, fd;
+       int status;
 
        if (!gpiod_line_is_free(line)) {
                errno = EBUSY;
@@ -577,10 +579,7 @@ int gpiod_line_event_request(struct gpiod_line *line,
        else if (config->event_type == GPIOD_EVENT_BOTH_EDGES)
                req->eventflags |= GPIOEVENT_REQUEST_BOTH_EDGES;
 
-       chip = gpiod_line_get_chip(line);
-       fd = chip_get_fd(chip);
-
-       status = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, req);
+       status = ioctl(line->fd, GPIO_GET_LINEEVENT_IOCTL, req);
        if (status < 0)
                return -1;
 
diff --git a/src/lib/line.h b/src/lib/line.h
new file mode 100644 (file)
index 0000000..3ffb088
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Internal GPIO line-related prototypes.
+ *
+ * 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 gpiod_line *
+line_new(unsigned int offset, struct gpiod_chip *chip, int info_fd);
+void line_free(struct gpiod_line *line);
+
+#endif /* __GPIOD_INTERNAL_LINE_H__ */