From 296c6aacaa7f2473e203ceee5c1fd2e5cff8f2b2 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 4 Jan 2017 17:09:28 +0100 Subject: [PATCH] core: implement public line update routines Line info is retrieved from the kernel for the first time automatically when gpiod_chip_get_line() is called. Then the line is updated automatically on request/release. If the ioctl fails in the latter case, the up_to_date flag is set to false. Expose an interface allowing users to check if a line is up-to-date and manually update it if needed. Signed-off-by: Bartosz Golaszewski --- core.c | 59 ++++++++++++++++++++++++++++++++++++--------------------- gpiod.h | 4 ++++ 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/core.c b/core.c index f830189..f582dde 100644 --- a/core.c +++ b/core.c @@ -125,26 +125,15 @@ int gpiod_simple_get_value(const char *device, unsigned int offset) struct gpiod_line { bool requested; + bool up_to_date; struct gpiod_chip *chip; struct gpioline_info info; struct gpiohandle_request *req; }; -static int update_line_info(struct gpiod_line *line, - struct gpiod_chip *chip, unsigned int offset) +static void line_set_offset(struct gpiod_line *line, unsigned int offset) { - int status, fd; - - memset(&line->info, 0, sizeof(line->info)); line->info.line_offset = offset; - - fd = gpiod_chip_get_fd(chip); - - status = gpio_ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &line->info); - if (status < 0) - return -1; - - return 0; } unsigned int gpiod_line_offset(struct gpiod_line *line) @@ -190,6 +179,30 @@ bool gpiod_line_is_open_source(struct gpiod_line *line) return line->info.flags & GPIOLINE_FLAG_OPEN_SOURCE; } +bool gpiod_line_needs_update(struct gpiod_line *line) +{ + return !line->up_to_date; +} + +int gpiod_line_update(struct gpiod_line *line) +{ + struct gpiod_chip *chip; + int status, fd; + + memset(&line->info, 0, sizeof(line->info)); + + chip = gpiod_line_get_chip(line); + fd = gpiod_chip_get_fd(chip); + + status = gpio_ioctl(fd, GPIO_GET_LINEINFO_IOCTL, &line->info); + if (status < 0) + return -1; + + line->up_to_date = true; + + return 0; +} + int gpiod_line_request(struct gpiod_line *line, const char *consumer, int default_val, int flags) { @@ -221,7 +234,7 @@ int gpiod_line_request_bulk(struct gpiod_line_bulk *line_bulk, { struct gpiohandle_request *req; struct gpiod_chip *chip; - unsigned int i, j; + unsigned int i; int status, fd; /* Paranoia: verify that all lines are from the same gpiochip. */ @@ -283,13 +296,9 @@ int gpiod_line_request_bulk(struct gpiod_line_bulk *line_bulk, * Update line info to include the changes after the * request. */ - status = update_line_info(line_bulk->lines[i], chip, - gpiod_line_offset(line_bulk->lines[i])); - if (status < 0) { - for (j = 0; j < i; j++) - gpiod_line_release(line_bulk->lines[i]); - return -1; - } + status = gpiod_line_update(line_bulk->lines[i]); + if (status < 0) + line_bulk->lines[i]->up_to_date = false; } return 0; @@ -308,6 +317,7 @@ void gpiod_line_release(struct gpiod_line *line) void gpiod_line_release_bulk(struct gpiod_line_bulk *line_bulk) { unsigned int i; + int status; close(line_bulk->lines[0]->req->fd); free(line_bulk->lines[0]->req); @@ -315,6 +325,10 @@ void gpiod_line_release_bulk(struct gpiod_line_bulk *line_bulk) for (i = 0; i < line_bulk->num_lines; i++) { line_bulk->lines[i]->req = NULL; line_bulk->lines[i]->requested = false; + + status = gpiod_line_update(line_bulk->lines[i]); + if (status < 0) + line_bulk->lines[i]->up_to_date = false; } } @@ -539,9 +553,10 @@ gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset) } line = &chip->lines[offset]; + line_set_offset(line, offset); line->chip = chip; - status = update_line_info(line, chip, offset); + status = gpiod_line_update(line); if (status < 0) return NULL; diff --git a/gpiod.h b/gpiod.h index 51b81dd..6104cce 100644 --- a/gpiod.h +++ b/gpiod.h @@ -86,6 +86,10 @@ bool gpiod_line_is_open_drain(struct gpiod_line *line) GPIOD_API; bool gpiod_line_is_open_source(struct gpiod_line *line) GPIOD_API; +bool gpiod_line_needs_update(struct gpiod_line *line) GPIOD_API; + +int gpiod_line_update(struct gpiod_line *line) GPIOD_API; + int gpiod_line_request(struct gpiod_line *line, const char *consumer, int default_val, int flags) GPIOD_API; -- 2.30.2