From ffe1776244e10c137def5df85da0349d4381d701 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 30 Jun 2017 12:55:36 +0200 Subject: [PATCH] core: separate the chip and line logic 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 --- src/lib/Makefile.am | 2 +- src/lib/chip.c | 36 ++++++++++++++------------- src/lib/gpiod-internal.h | 25 ------------------- src/lib/line.c | 53 ++++++++++++++++++++-------------------- src/lib/line.h | 20 +++++++++++++++ 5 files changed, 66 insertions(+), 70 deletions(-) delete mode 100644 src/lib/gpiod-internal.h create mode 100644 src/lib/line.h diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 693b8cd..5744478 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -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 diff --git a/src/lib/chip.c b/src/lib/chip.c index 58d02c2..51e64cc 100644 --- a/src/lib/chip.c +++ b/src/lib/chip.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation. */ -#include "gpiod-internal.h" +#include "line.h" #include #include @@ -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 index 6bf6be5..0000000 --- a/src/lib/gpiod-internal.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Internal routines for libgpiod. - * - * Copyright (C) 2017 Bartosz Golaszewski - * - * 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 - -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__ */ diff --git a/src/lib/line.c b/src/lib/line.c index ea0aef0..aae6cff 100644 --- a/src/lib/line.c +++ b/src/lib/line.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation. */ -#include "gpiod-internal.h" +#include #include #include @@ -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 index 0000000..3ffb088 --- /dev/null +++ b/src/lib/line.h @@ -0,0 +1,20 @@ +/* + * Internal GPIO line-related prototypes. + * + * Copyright (C) 2017 Bartosz Golaszewski + * + * 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 + +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__ */ -- 2.30.2