core: allow to read values of lines configured for events
authorBartosz Golaszewski <bartekgola@gmail.com>
Mon, 23 Jan 2017 15:01:28 +0000 (16:01 +0100)
committerBartosz Golaszewski <bartekgola@gmail.com>
Mon, 23 Jan 2017 15:01:28 +0000 (16:01 +0100)
The kernel allows us to read values of lines on which we're listening
for events, but libgpiod bails out if the user tries to do it.

Modify gpiod_line_get_value_bulk() to select the correct file
descriptor, depending on how the line object is configured and
allow reading values for both normally exported and monitored lines.

Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com>
src/lib/core.c

index e4ca720b7156d1e75c544cb98debf4fdfb449185..2d45e357694fbc5d2e58c32af96dabc473e3e021 100644 (file)
@@ -426,6 +426,30 @@ static void line_update(struct gpiod_line *line)
                line_set_needs_update(line);
 }
 
+static bool line_bulk_is_reserved(struct gpiod_line_bulk *line_bulk)
+{
+       unsigned int i;
+
+       for (i = 0; i < line_bulk->num_lines; i++) {
+               if (!gpiod_line_is_reserved(line_bulk->lines[i]))
+                       return false;
+       }
+
+       return true;
+}
+
+static bool line_bulk_is_event_configured(struct gpiod_line_bulk *line_bulk)
+{
+       unsigned int i;
+
+       for (i = 0; i < line_bulk->num_lines; i++) {
+               if (!gpiod_line_event_configured(line_bulk->lines[i]))
+                       return false;
+       }
+
+       return true;
+}
+
 bool gpiod_line_needs_update(struct gpiod_line *line)
 {
        return !line->up_to_date;
@@ -582,18 +606,6 @@ bool gpiod_line_is_free(struct gpiod_line *line)
        return line_get_state(line) == LINE_FREE;
 }
 
-static bool line_bulk_is_reserved(struct gpiod_line_bulk *line_bulk)
-{
-       unsigned int i;
-
-       for (i = 0; i < line_bulk->num_lines; i++) {
-               if (!gpiod_line_is_reserved(line_bulk->lines[i]))
-                       return false;
-       }
-
-       return true;
-}
-
 int gpiod_line_get_value(struct gpiod_line *line)
 {
        struct gpiod_line_bulk bulk;
@@ -612,18 +624,26 @@ int gpiod_line_get_value(struct gpiod_line *line)
 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;
+       int status, fd;
 
-       if (!line_bulk_is_reserved(bulk)) {
+       first = bulk->lines[0];
+
+       if (!line_bulk_is_reserved(bulk) &&
+           !line_bulk_is_event_configured(bulk)) {
                set_last_error(GPIOD_EREQUEST);
                return -1;
        }
 
        memset(&data, 0, sizeof(data));
 
-       status = gpio_ioctl(line_get_handle_fd(bulk->lines[0]),
-                           GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
+       if (gpiod_line_is_reserved(first))
+               fd = line_get_handle_fd(first);
+       else
+               fd = line_get_event_fd(first);
+
+       status = gpio_ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
        if (status < 0)
                return -1;
 
@@ -773,18 +793,6 @@ int gpiod_line_event_wait(struct gpiod_line *line,
        return gpiod_line_event_wait_bulk(&bulk, timeout, NULL);
 }
 
-static bool line_bulk_is_event_configured(struct gpiod_line_bulk *line_bulk)
-{
-       unsigned int i;
-
-       for (i = 0; i < line_bulk->num_lines; i++) {
-               if (!gpiod_line_event_configured(line_bulk->lines[i]))
-                       return false;
-       }
-
-       return true;
-}
-
 int gpiod_line_event_wait_bulk(struct gpiod_line_bulk *bulk,
                               const struct timespec *timeout,
                               struct gpiod_line **line)