Add support for bias flags and SET_CONFIG
Subsystems (2)
cover Add support for bias flags and SET_CONFIG
This patch series adds support for changes to the GPIO uAPI that are on track to be included in the v5.5 kernel. There are two components to the uAPI changes - the addition of bias flags and a new SET_CONFIG ioctl. This series adds support to the libgpiod API, and to both C++ and Python bindings, for both of those components.
The libgpiod tools are also updated, where appropriate, to support the bias flags.
There are a few additional patches that serve to restructure the code to simplify subsequent patches, or to fix minor problems discovered during development. These patches are generally adjacent to the main patch most relevant to that patch.
The series is based on the current libgpiod master@9ed02fc.
Kent Gibson (19):
core: move request flag to handle flag conversion into a separate
function
API: add support for bias flags
core: fix misspelling of parameter
tests: add tests for bias flags
bindings: cxx: drop noexcept from direction and active_state
bindings: cxx: initialise bitset with integer instead of string
bindings: cxx: add support for bias flags
bindings: cxx: tests: add tests for bias flags
bindings: python: add support for bias flags
bindings: python: tests: add tests for bias flags
API: add support for SET_CONFIG
tests: add tests for SET_CONFIG
core: allow gpiod_line_set_value_bulk to accept null values
bindings: cxx: add support for SET_CONFIG
bindings: cxx: tests: add tests for SET_CONFIG methods
bindings: python: add support for SET_CONFIG
bindings: python: tests: add tests for SET_CONFIG methods
tools: add support for bias flags
treewide: change "correspond with" to "correspond to"
bindings/cxx/gpiod.hpp | 85 +++- bindings/cxx/line.cpp | 60 ++- bindings/cxx/line_bulk.cpp | 95 ++++- bindings/cxx/tests/tests-line.cpp | 215 ++++++++++ bindings/python/gpiodmodule.c | 469 +++++++++++++++++++++- bindings/python/tests/gpiod_py_test.py | 254 ++++++++++++ include/gpiod.h | 303 +++++++++++++- lib/core.c | 250 ++++++++++-- lib/ctxless.c | 115 +++++- tests/mockup/gpio-mockup.c | 2 +- tests/tests-ctxless.c | 64 ++- tests/tests-event.c | 120 ++++++ tests/tests-line.c | 522 ++++++++++++++++++++++++- tools/gpioget.c | 24 +- tools/gpiomon.c | 28 +- tools/gpioset.c | 26 +- 16 files changed, 2561 insertions(+), 71 deletions(-)
Signature · 1 line
2.24.0
PATCH 1/19 core: move request flag to handle flag conversion into a separate function
Move common conversion code from line_request_values and line_request_event_single into a separate function to simplify adding additional flags.
--- lib/core.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-)
lib/core.c +17 -14
@@ -463,6 +463,20 @@ static bool line_bulk_all_free(struct gpiod_line_bulk *bulk)return true; } +static __u32 line_request_flag_to_gpio_handleflag (int flags) +{ +int hflags =0 ; + +if (flags &GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN ) + hflags |=GPIOHANDLE_REQUEST_OPEN_DRAIN ; +if (flags &GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ) + hflags |=GPIOHANDLE_REQUEST_OPEN_SOURCE ; +if (flags &GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ) + hflags |=GPIOHANDLE_REQUEST_ACTIVE_LOW ; + +return hflags; +} +static int line_request_values (struct gpiod_line_bulk *bulk,const struct gpiod_line_request_config *config,const int *default_vals)
@@ -488,19 +502,14 @@ static int line_request_values(struct gpiod_line_bulk *bulk,memset (&req,0 ,sizeof (req)); -if (config->flags &GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN ) - req.flags |=GPIOHANDLE_REQUEST_OPEN_DRAIN ; -if (config->flags &GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ) - req.flags |=GPIOHANDLE_REQUEST_OPEN_SOURCE ; -if (config->flags &GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ) - req.flags |=GPIOHANDLE_REQUEST_ACTIVE_LOW ; + req.lines =gpiod_line_bulk_num_lines (bulk); + req.flags =line_request_flag_to_gpio_handleflag (config->flags);if (config->request_type ==GPIOD_LINE_REQUEST_DIRECTION_INPUT ) req.flags |=GPIOHANDLE_REQUEST_INPUT ;else if (config->request_type ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) req.flags |=GPIOHANDLE_REQUEST_OUTPUT ; - req.lines =gpiod_line_bulk_num_lines (bulk); gpiod_line_bulk_foreach_line_off(bulk, line, i) { req.lineoffsets[i] =gpiod_line_offset (line);
@@ -548,15 +557,9 @@ static int line_request_event_single(struct gpiod_line *line, sizeof(req.consumer_label) - 1); req.lineoffset =gpiod_line_offset (line); + req.handleflags =line_request_flag_to_gpio_handleflag (config->flags); req.handleflags |=GPIOHANDLE_REQUEST_INPUT ; -if (config->flags &GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN ) - req.handleflags |=GPIOHANDLE_REQUEST_OPEN_DRAIN ; -if (config->flags &GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ) - req.handleflags |=GPIOHANDLE_REQUEST_OPEN_SOURCE ; -if (config->flags &GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ) - req.handleflags |=GPIOHANDLE_REQUEST_ACTIVE_LOW ; -if (config->request_type ==GPIOD_LINE_REQUEST_EVENT_RISING_EDGE ) req.eventflags |=GPIOEVENT_REQUEST_RISING_EDGE ;else if (config->request_type ==GPIOD_LINE_REQUEST_EVENT_FALLING_EDGE )
Signature · 1 line
2.24.0
PATCH 2/19 API: add support for bias flags
In reply to Kent GibsonExtend the libgpiod API to support the bias flags recently added to the kernel GPIO uAPI. The core change is the addition of GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE, GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP and GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN flags to be passed into line_request functions, and the addition of gpiod_line_bias to return the bias state of lines.
Extended variants of the ctxless functions that accept an active_low flag are added to also accept other flags. The variant names add a "_ext" suffix to the name of the original function.
Based on initial work by Drew Fustini <[email protected]>.
--- include/gpiod.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/core.c | 32 ++++++--- lib/ctxless.c | 115 +++++++++++++++++++++++++++--- 3 files changed, 313 insertions(+), 18 deletions(-)
include/gpiod.h +184 -0
@@ -84,6 +84,22 @@ struct gpiod_line_bulk;* the need to use the gpiod_* structures or to keep track of resources. */ +/** +* @brief Miscellaneous GPIO flags. +*/ +enum { +GPIOD_CTXLESS_FLAG_OPEN_DRAIN =GPIOD_BIT (0 ), +/**< The line is an open-drain port. */ +GPIOD_CTXLESS_FLAG_OPEN_SOURCE =GPIOD_BIT (1 ), +/**< The line is an open-source port. */ +GPIOD_CTXLESS_FLAG_BIAS_DISABLE =GPIOD_BIT (2 ), +/**< The line has neither either pull-up nor pull-down resistor */ +GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN =GPIOD_BIT (3 ), +/**< The line has pull-down resistor enabled */ +GPIOD_CTXLESS_FLAG_BIAS_PULL_UP =GPIOD_BIT (4 ), +/**< The line has pull-up resistor enabled */ +}; +/** * @brief Read current value from a single GPIO line. * @param device Name, path, number or label of the gpiochip.
@@ -95,6 +111,19 @@ struct gpiod_line_bulk; int gpiod_ctxless_get_value(const char *device, unsigned int offset, bool active_low, const char *consumer) GPIOD_API; +/** +* @brief Read current value from a single GPIO line. +* @param device Name, path, number or label of the gpiochip. +* @param offset Offset of the GPIO line. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the line. +* @param consumer Name of the consumer. +* @return 0 or 1 (GPIO value) if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_get_value_ext(const char *device, unsigned int offset, + bool active_low, int flags, + const char *consumer) GPIOD_API; +/** * @brief Read current values from a set of GPIO lines. * @param device Name, path, number or label of the gpiochip.
@@ -110,6 +139,24 @@ int gpiod_ctxless_get_value_multiple(const char *device, unsigned int num_lines, bool active_low, const char *consumer) GPIOD_API; +/** +* @brief Read current values from a set of GPIO lines. +* @param device Name, path, number or label of the gpiochip. +* @param offsets Array of offsets of lines whose values should be read. +* @param values Buffer in which the values will be stored. +* @param num_lines Number of lines, must be > 0. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the lines. +* @param consumer Name of the consumer. +* @return 0 if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_get_value_multiple_ext(const char *device, + const unsigned int *offsets, + int *values, + unsigned int num_lines, + bool active_low, int flags, + const char *consumer) GPIOD_API; +/** * @brief Simple set value callback signature. */
@@ -133,6 +180,26 @@ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,gpiod_ctxless_set_value_cb cb, void *data) GPIOD_API; +/** +* @brief Set value of a single GPIO line. +* @param device Name, path, number or label of the gpiochip. +* @param offset The offset of the GPIO line. +* @param value New value (0 or 1). +* @param active_low The active state of this line - true if low. +* @param flags The flags for the line. +* @param consumer Name of the consumer. +* @param cb Optional callback function that will be called right after setting +* the value. Users can use this, for example, to pause the execution +* after toggling a GPIO. +* @param data Optional user data that will be passed to the callback function. +* @return 0 if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_set_value_ext(const char *device, unsigned int offset, + int value, bool active_low, int flags, + const char *consumer, + gpiod_ctxless_set_value_cb cb, + void *data) GPIOD_API; +/** * @brief Set values of multiple GPIO lines. * @param device Name, path, number or label of the gpiochip.
@@ -153,6 +220,29 @@ int gpiod_ctxless_set_value_multiple(const char *device,gpiod_ctxless_set_value_cb cb, void *data) GPIOD_API; +/** +* @brief Set values of multiple GPIO lines. +* @param device Name, path, number or label of the gpiochip. +* @param offsets Array of offsets of lines the values of which should be set. +* @param values Array of integers containing new values. +* @param num_lines Number of lines, must be > 0. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the lines. +* @param consumer Name of the consumer. +* @param cb Optional callback function that will be called right after setting +* all values. Works the same as in ::gpiod_ctxless_set_value. +* @param data Optional user data that will be passed to the callback function. +* @return 0 if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_set_value_multiple_ext(const char *device, + const unsigned int *offsets, + const int *values, + unsigned int num_lines, + bool active_low, int flags, + const char *consumer, + gpiod_ctxless_set_value_cb cb, + void *data) GPIOD_API; +/** * @brief Event types that the ctxless event monitor can wait for. */
@@ -327,6 +417,31 @@ int gpiod_ctxless_event_monitor(const char *device, int event_type,gpiod_ctxless_event_handle_cb event_cb, void *data) GPIOD_API; +/** +* @brief Wait for events on a single GPIO line. +* @param device Name, path, number or label of the gpiochip. +* @param event_type Type of events to listen for. +* @param offset GPIO line offset to monitor. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the line. +* @param consumer Name of the consumer. +* @param timeout Maximum wait time for each iteration. +* @param poll_cb Callback function to call when waiting for events. +* @param event_cb Callback function to call for each line event. +* @param data User data passed to the callback. +* @return 0 if no errors were encountered, -1 if an error occurred. +* @note The way the ctxless event loop works is described in detail in +* ::gpiod_ctxless_event_monitor_multiple - this is just a wrapper aound +* this routine which calls it for a single GPIO line. +*/ +int gpiod_ctxless_event_monitor_ext(const char *device, int event_type, + unsigned int offset, bool active_low, + int flags, const char *consumer, + const struct timespec *timeout, + gpiod_ctxless_event_poll_cb poll_cb, + gpiod_ctxless_event_handle_cb event_cb, + void *data) GPIOD_API; +/** * @brief Wait for events on multiple GPIO lines. * @param device Name, path, number or label of the gpiochip.
@@ -366,6 +481,47 @@ int gpiod_ctxless_event_monitor_multiple(gpiod_ctxless_event_handle_cb event_cb, void *data) GPIOD_API; +/** +* @brief Wait for events on multiple GPIO lines. +* @param device Name, path, number or label of the gpiochip. +* @param event_type Type of events to listen for. +* @param offsets Array of GPIO line offsets to monitor. +* @param num_lines Number of lines to monitor. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the lines. +* @param consumer Name of the consumer. +* @param timeout Maximum wait time for each iteration. +* @param poll_cb Callback function to call when waiting for events. Can +* be NULL. +* @param event_cb Callback function to call on event occurrence. +* @param data User data passed to the callback. +* @return 0 no errors were encountered, -1 if an error occurred. +* @note The poll callback can be NULL in which case the routine will fall +* back to a basic, ppoll() based callback. +* +* Internally this routine opens the GPIO chip, requests the set of lines for +* the type of events specified in the event_type parameter and calls the +* polling callback in a loop. The role of the polling callback is to detect +* input events on a set of file descriptors and notify the caller about the +* fds ready for reading. +* +* The ctxless event loop then reads each queued event from marked descriptors +* and calls the event callback. Both callbacks can stop the loop at any +* point. +* +* The poll_cb argument can be NULL in which case the function falls back to +* a default, ppoll() based callback. +*/ +int gpiod_ctxless_event_monitor_multiple_ext( + const char *device, int event_type, + const unsigned int *offsets, + unsigned int num_lines, bool active_low, int flags, + const char *consumer, const struct timespec *timeout, + gpiod_ctxless_event_poll_cb poll_cb, + gpiod_ctxless_event_handle_cb event_cb, + void *data) GPIOD_API; + +/** * @brief Determine the chip name and line offset of a line with given name. * @param name The name of the GPIO line to lookup.
@@ -658,6 +814,20 @@ enum {/**< The active state of a GPIO is active-low. */ }; +/** +* @brief Possible internal bias settings. +*/ +enum { +GPIOD_LINE_BIAS_AS_IS =1 , +/**< The internal bias state is unknown. */ +GPIOD_LINE_BIAS_DISABLE , +/**< The internal bias is disabled. */ +GPIOD_LINE_BIAS_PULL_UP , +/**< The internal pull-up bias is enabled. */ +GPIOD_LINE_BIAS_PULL_DOWN , +/**< The internal pull-down bias is enabled. */ +}; +/** * @brief Read the GPIO line offset. * @param line GPIO line object.
@@ -697,6 +867,14 @@ int gpiod_line_direction(struct gpiod_line *line) GPIOD_API;*/ int gpiod_line_active_state(struct gpiod_line *line) GPIOD_API; +/** +* @brief Read the GPIO line bias setting. +* @param line GPIO line object. +* @return Returns GPIOD_LINE_BIAS_PULL_UP, GPIOD_LINE_BIAS_PULL_DOWN, +* GPIOD_LINE_BIAS_DISABLE or GPIOD_LINE_BIAS_AS_IS. +*/ +int gpiod_line_bias(struct gpiod_line *line) GPIOD_API; +/** * @brief Check if the line is currently in use. * @param line GPIO line object.
@@ -792,6 +970,12 @@ enum {/**< The line is an open-source port. */ GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW =GPIOD_BIT (2 ),/**< The active state of the line is low (high is the default). */ +GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE =GPIOD_BIT (3 ), +/**< The line has neither either pull-up nor pull-down resistor */ +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN =GPIOD_BIT (4 ), +/**< The line has pull-down resistor enabled */ + GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP = GPIOD_BIT(5), + /**< The line has pull-up resistor enabled */ };/**
lib/core.c +23 -9
@@ -36,9 +36,7 @@ struct gpiod_line {unsigned int offset;int direction;int active_state; -bool used; -bool open_source; -bool open_drain; +__u32 flags;int state;bool needs_update;
@@ -359,19 +357,31 @@ int gpiod_line_active_state(struct gpiod_line *line)return line->active_state; } +int gpiod_line_bias (struct gpiod_line *line) +{ +if (line->flags &GPIOLINE_FLAG_BIAS_DISABLE ) +return GPIOD_LINE_BIAS_DISABLE ; +if (line->flags &GPIOLINE_FLAG_BIAS_PULL_UP ) +return GPIOD_LINE_BIAS_PULL_UP ; +if (line->flags &GPIOLINE_FLAG_BIAS_PULL_DOWN ) +return GPIOD_LINE_BIAS_PULL_DOWN ; + +return GPIOD_LINE_BIAS_AS_IS ; +} +bool gpiod_line_is_used (struct gpiod_line *line) { -return line->used; +return line->flags &GPIOLINE_FLAG_KERNEL ; }bool gpiod_line_is_open_drain (struct gpiod_line *line) { -return line->open_drain; +return line->flags &GPIOLINE_FLAG_OPEN_DRAIN ; }bool gpiod_line_is_open_source (struct gpiod_line *line) { -return line->open_source; +return line->flags &GPIOLINE_FLAG_OPEN_SOURCE ; }bool gpiod_line_needs_update (struct gpiod_line *line)
@@ -398,9 +408,7 @@ int gpiod_line_update(struct gpiod_line *line) ? GPIOD_LINE_ACTIVE_STATE_LOW :GPIOD_LINE_ACTIVE_STATE_HIGH ; - line->used = info.flags &GPIOLINE_FLAG_KERNEL ; - line->open_drain = info.flags &GPIOLINE_FLAG_OPEN_DRAIN ; - line->open_source = info.flags &GPIOLINE_FLAG_OPEN_SOURCE ; + line->flags = info.flags;strncpy (line->name, info.name,sizeof (line->name));strncpy (line->consumer, info.consumer,sizeof (line->consumer));
@@ -473,6 +481,12 @@ static __u32 line_request_flag_to_gpio_handleflag(int flags) hflags |=GPIOHANDLE_REQUEST_OPEN_SOURCE ;if (flags &GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ) hflags |=GPIOHANDLE_REQUEST_ACTIVE_LOW ; +if (flags &GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ) + hflags |=GPIOHANDLE_REQUEST_BIAS_DISABLE ; +if (flags &GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ) + hflags |=GPIOHANDLE_REQUEST_BIAS_PULL_DOWN ; +if (flags &GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ) + hflags |=GPIOHANDLE_REQUEST_BIAS_PULL_UP ;return hflags; }
lib/ctxless.c +106 -9
183 lines not on this page · raw message
Signature · 1 line
2.24.0
Re: [libgpiod] [PATCH 02/19] API: add support for bias flags
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 8 lines
Extend the libgpiod API to support the bias flags recently added to the kernel GPIO uAPI. The core change is the addition of
GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE,GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UPandGPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWNflags to be passed intoline_requestfunctions, and the addition ofgpiod_line_biasto return the bias state of lines.
Quoted 7 lines
Extended variants of the ctxless functions that accept an
active_lowflag are added to also accept other flags. The variant names add a "_ext" suffix to the name of the original function.Based on initial work by Drew Fustini <[email protected]>.
Signed-off-by Kent Gibson <[email protected]>
Hi Kent,
this looks good, just a couple nits. I'd change the subject line to "core: add support for bias flags". Also: how about moving the flags argument to the last position in all the ctxless extended variants, so that they keep the same signature *except* for the appended new argument?
Bart
Quoted 536 lines
--- include/gpiod.h | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/core.c | 32 ++++++--- lib/ctxless.c | 115 +++++++++++++++++++++++++++--- 3 files changed, 313 insertions(+), 18 deletions(-)include/gpiod.h +184
-0@@ -84,6 +84,22 @@ struct gpiod_line_bulk;* the need to use the gpiod_* structures or to keep track of resources. */ +/** +* @brief Miscellaneous GPIO flags. +*/ +enum { +GPIOD_CTXLESS_FLAG_OPEN_DRAIN =GPIOD_BIT (0 ), +/**< The line is an open-drain port. */ +GPIOD_CTXLESS_FLAG_OPEN_SOURCE =GPIOD_BIT (1 ), +/**< The line is an open-source port. */ +GPIOD_CTXLESS_FLAG_BIAS_DISABLE =GPIOD_BIT (2 ), +/**< The line has neither either pull-up nor pull-down resistor */ +GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN =GPIOD_BIT (3 ), +/**< The line has pull-down resistor enabled */ +GPIOD_CTXLESS_FLAG_BIAS_PULL_UP =GPIOD_BIT (4 ), +/**< The line has pull-up resistor enabled */ +}; +/** * @brief Read current value from a single GPIO line. * @param device Name, path, number or label of the gpiochip. @@ -95,6 +111,19 @@ struct gpiod_line_bulk; int gpiod_ctxless_get_value(const char *device, unsigned int offset, bool active_low, const char *consumer) GPIOD_API; +/** +* @brief Read current value from a single GPIO line. +* @param device Name, path, number or label of the gpiochip. +* @param offset Offset of the GPIO line. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the line. +* @param consumer Name of the consumer. +* @return 0 or 1 (GPIO value) if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_get_value_ext(const char *device, unsigned int offset, + bool active_low, int flags, + const char *consumer) GPIOD_API; +/** * @brief Read current values from a set of GPIO lines. * @param device Name, path, number or label of the gpiochip. @@ -110,6 +139,24 @@ int gpiod_ctxless_get_value_multiple(const char *device, unsigned int num_lines, bool active_low, const char *consumer) GPIOD_API; +/** +* @brief Read current values from a set of GPIO lines. +* @param device Name, path, number or label of the gpiochip. +* @param offsets Array of offsets of lines whose values should be read. +* @param values Buffer in which the values will be stored. +* @param num_lines Number of lines, must be > 0. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the lines. +* @param consumer Name of the consumer. +* @return 0 if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_get_value_multiple_ext(const char *device, + const unsigned int *offsets, + int *values, + unsigned int num_lines, + bool active_low, int flags, + const char *consumer) GPIOD_API; +/** * @brief Simple set value callback signature. */ @@ -133,6 +180,26 @@ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value,gpiod_ctxless_set_value_cb cb, void *data) GPIOD_API; +/** +* @brief Set value of a single GPIO line. +* @param device Name, path, number or label of the gpiochip. +* @param offset The offset of the GPIO line. +* @param value New value (0 or 1). +* @param active_low The active state of this line - true if low. +* @param flags The flags for the line. +* @param consumer Name of the consumer. +* @param cb Optional callback function that will be called right after setting +* the value. Users can use this, for example, to pause the execution +* after toggling a GPIO. +* @param data Optional user data that will be passed to the callback function. +* @return 0 if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_set_value_ext(const char *device, unsigned int offset, + int value, bool active_low, int flags, + const char *consumer, + gpiod_ctxless_set_value_cb cb, + void *data) GPIOD_API; +/** * @brief Set values of multiple GPIO lines. * @param device Name, path, number or label of the gpiochip. @@ -153,6 +220,29 @@ int gpiod_ctxless_set_value_multiple(const char *device,gpiod_ctxless_set_value_cb cb, void *data) GPIOD_API; +/** +* @brief Set values of multiple GPIO lines. +* @param device Name, path, number or label of the gpiochip. +* @param offsets Array of offsets of lines the values of which should be set. +* @param values Array of integers containing new values. +* @param num_lines Number of lines, must be > 0. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the lines. +* @param consumer Name of the consumer. +* @param cb Optional callback function that will be called right after setting +* all values. Works the same as in ::gpiod_ctxless_set_value. +* @param data Optional user data that will be passed to the callback function. +* @return 0 if the operation succeeds, -1 on error. +*/ +int gpiod_ctxless_set_value_multiple_ext(const char *device, + const unsigned int *offsets, + const int *values, + unsigned int num_lines, + bool active_low, int flags, + const char *consumer, + gpiod_ctxless_set_value_cb cb, + void *data) GPIOD_API; +/** * @brief Event types that the ctxless event monitor can wait for. */ @@ -327,6 +417,31 @@ int gpiod_ctxless_event_monitor(const char *device, int event_type,gpiod_ctxless_event_handle_cb event_cb, void *data) GPIOD_API; +/** +* @brief Wait for events on a single GPIO line. +* @param device Name, path, number or label of the gpiochip. +* @param event_type Type of events to listen for. +* @param offset GPIO line offset to monitor. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the line. +* @param consumer Name of the consumer. +* @param timeout Maximum wait time for each iteration. +* @param poll_cb Callback function to call when waiting for events. +* @param event_cb Callback function to call for each line event. +* @param data User data passed to the callback. +* @return 0 if no errors were encountered, -1 if an error occurred. +* @note The way the ctxless event loop works is described in detail in +* ::gpiod_ctxless_event_monitor_multiple - this is just a wrapper aound +* this routine which calls it for a single GPIO line. +*/ +int gpiod_ctxless_event_monitor_ext(const char *device, int event_type, + unsigned int offset, bool active_low, + int flags, const char *consumer, + const struct timespec *timeout, + gpiod_ctxless_event_poll_cb poll_cb, + gpiod_ctxless_event_handle_cb event_cb, + void *data) GPIOD_API; +/** * @brief Wait for events on multiple GPIO lines. * @param device Name, path, number or label of the gpiochip. @@ -366,6 +481,47 @@ int gpiod_ctxless_event_monitor_multiple(gpiod_ctxless_event_handle_cb event_cb, void *data) GPIOD_API; +/** +* @brief Wait for events on multiple GPIO lines. +* @param device Name, path, number or label of the gpiochip. +* @param event_type Type of events to listen for. +* @param offsets Array of GPIO line offsets to monitor. +* @param num_lines Number of lines to monitor. +* @param active_low The active state of this line - true if low. +* @param flags The flags for the lines. +* @param consumer Name of the consumer. +* @param timeout Maximum wait time for each iteration. +* @param poll_cb Callback function to call when waiting for events. Can +* be NULL. +* @param event_cb Callback function to call on event occurrence. +* @param data User data passed to the callback. +* @return 0 no errors were encountered, -1 if an error occurred. +* @note The poll callback can be NULL in which case the routine will fall +* back to a basic, ppoll() based callback. +* +* Internally this routine opens the GPIO chip, requests the set of lines for +* the type of events specified in the event_type parameter and calls the +* polling callback in a loop. The role of the polling callback is to detect +* input events on a set of file descriptors and notify the caller about the +* fds ready for reading. +* +* The ctxless event loop then reads each queued event from marked descriptors +* and calls the event callback. Both callbacks can stop the loop at any +* point. +* +* The poll_cb argument can be NULL in which case the function falls back to +* a default, ppoll() based callback. +*/ +int gpiod_ctxless_event_monitor_multiple_ext( + const char *device, int event_type, + const unsigned int *offsets, + unsigned int num_lines, bool active_low, int flags, + const char *consumer, const struct timespec *timeout, + gpiod_ctxless_event_poll_cb poll_cb, + gpiod_ctxless_event_handle_cb event_cb, + void *data) GPIOD_API; + +/** * @brief Determine the chip name and line offset of a line with given name. * @param name The name of the GPIO line to lookup. @@ -658,6 +814,20 @@ enum {/**< The active state of a GPIO is active-low. */ }; +/** +* @brief Possible internal bias settings. +*/ +enum { +GPIOD_LINE_BIAS_AS_IS =1 , +/**< The internal bias state is unknown. */ +GPIOD_LINE_BIAS_DISABLE , +/**< The internal bias is disabled. */ +GPIOD_LINE_BIAS_PULL_UP , +/**< The internal pull-up bias is enabled. */ +GPIOD_LINE_BIAS_PULL_DOWN , +/**< The internal pull-down bias is enabled. */ +}; +/** * @brief Read the GPIO line offset. * @param line GPIO line object. @@ -697,6 +867,14 @@ int gpiod_line_direction(struct gpiod_line *line) GPIOD_API;*/ int gpiod_line_active_state(struct gpiod_line *line) GPIOD_API; +/** +* @brief Read the GPIO line bias setting. +* @param line GPIO line object. +* @return Returns GPIOD_LINE_BIAS_PULL_UP, GPIOD_LINE_BIAS_PULL_DOWN, +* GPIOD_LINE_BIAS_DISABLE or GPIOD_LINE_BIAS_AS_IS. +*/ +int gpiod_line_bias(struct gpiod_line *line) GPIOD_API; +/** * @brief Check if the line is currently in use. * @param line GPIO line object. @@ -792,6 +970,12 @@ enum {/**< The line is an open-source port. */ GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW =GPIOD_BIT (2 ),/**< The active state of the line is low (high is the default). */ +GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE =GPIOD_BIT (3 ), +/**< The line has neither either pull-up nor pull-down resistor */ +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN =GPIOD_BIT (4 ), +/**< The line has pull-down resistor enabled */ + GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP = GPIOD_BIT(5), + /**< The line has pull-up resistor enabled */ };/** lib/core.c +23
-9@@ -36,9 +36,7 @@ struct gpiod_line {unsigned int offset;int direction;int active_state; -bool used; -bool open_source; -bool open_drain; +__u32 flags;int state;bool needs_update;@@ -359,19 +357,31 @@ int gpiod_line_active_state(struct gpiod_line *line)return line->active_state; } +int gpiod_line_bias (struct gpiod_line *line) +{ +if (line->flags &GPIOLINE_FLAG_BIAS_DISABLE ) +return GPIOD_LINE_BIAS_DISABLE ; +if (line->flags &GPIOLINE_FLAG_BIAS_PULL_UP ) +return GPIOD_LINE_BIAS_PULL_UP ; +if (line->flags &GPIOLINE_FLAG_BIAS_PULL_DOWN ) +return GPIOD_LINE_BIAS_PULL_DOWN ; + +return GPIOD_LINE_BIAS_AS_IS ; +} +bool gpiod_line_is_used (struct gpiod_line *line) { -return line->used; +return line->flags &GPIOLINE_FLAG_KERNEL ; }bool gpiod_line_is_open_drain (struct gpiod_line *line) { -return line->open_drain; +return line->flags &GPIOLINE_FLAG_OPEN_DRAIN ; }bool gpiod_line_is_open_source (struct gpiod_line *line) { -return line->open_source; +return line->flags &GPIOLINE_FLAG_OPEN_SOURCE ; }bool gpiod_line_needs_update (struct gpiod_line *line)@@ -398,9 +408,7 @@ int gpiod_line_update(struct gpiod_line *line) ? GPIOD_LINE_ACTIVE_STATE_LOW :GPIOD_LINE_ACTIVE_STATE_HIGH ; - line->used = info.flags &GPIOLINE_FLAG_KERNEL ; - line->open_drain = info.flags &GPIOLINE_FLAG_OPEN_DRAIN ; - line->open_source = info.flags &GPIOLINE_FLAG_OPEN_SOURCE ; + line->flags = info.flags;strncpy (line->name, info.name,sizeof (line->name));strncpy (line->consumer, info.consumer,sizeof (line->consumer));@@ -473,6 +481,12 @@ static __u32 line_request_flag_to_gpio_handleflag(int flags) hflags |=GPIOHANDLE_REQUEST_OPEN_SOURCE ;if (flags &GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ) hflags |=GPIOHANDLE_REQUEST_ACTIVE_LOW ; +if (flags &GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ) + hflags |=GPIOHANDLE_REQUEST_BIAS_DISABLE ; +if (flags &GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ) + hflags |=GPIOHANDLE_REQUEST_BIAS_PULL_DOWN ; +if (flags &GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ) + hflags |=GPIOHANDLE_REQUEST_BIAS_PULL_UP ;return hflags; }lib/ctxless.c +106
-10@@ -14,6 +14,26 @@#include <stdio.h> #include <string.h> +static int ctxless_flags_to_line_request_flags (bool active_low,int flags) +{ +int lflags =0 ; + +if (active_low) + lflags |=GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ; +if (flags &GPIOD_CTXLESS_FLAG_OPEN_DRAIN ) + lflags |=GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN ; +if (flags &GPIOD_CTXLESS_FLAG_OPEN_SOURCE ) + lflags |=GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ; +if (flags &GPIOD_CTXLESS_FLAG_BIAS_DISABLE ) + lflags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +if (flags &GPIOD_CTXLESS_FLAG_BIAS_PULL_UP ) + lflags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +if (flags &GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN ) + lflags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; + +return lflags; +} +int gpiod_ctxless_get_value (const char *device,unsigned int offset,bool active_low,const char *consumer) {@@ -27,16 +47,45 @@ int gpiod_ctxless_get_value(const char *device, unsigned int offset,return value; } +int gpiod_ctxless_get_value_ext (const char *device,unsigned int offset, +bool active_low,int flags, +const char *consumer) +{ +int value, rv; + + rv =gpiod_ctxless_get_value_multiple_ext (device, &offset, &value,1 , + active_low, flags, consumer); +if (rv <0 ) +return rv; + +return value; +} +int gpiod_ctxless_get_value_multiple (const char *device,const unsigned int *offsets,int *values,unsigned int num_lines,bool active_low,const char *consumer) +{ +int rv; + + rv =gpiod_ctxless_get_value_multiple_ext (device, offsets, values, + num_lines, active_low,0 , + consumer); +return rv; +} + +int gpiod_ctxless_get_value_multiple_ext (const char *device, +const unsigned int *offsets, +int *values, +unsigned int num_lines, +bool active_low,int flags, +const char *consumer) {struct gpiod_line_bulk bulk;struct gpiod_chip *chip;struct gpiod_line *line;unsigned int i; -int rv, flags; +int rv, lflags;if (!num_lines || num_lines >GPIOD_LINE_BULK_MAX_LINES ) { errno =EINVAL ;@@ -59,9 +108,8 @@ int gpiod_ctxless_get_value_multiple(const char *device,gpiod_line_bulk_add (&bulk, line); } - flags = active_low ?GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW :0 ; - - rv =gpiod_line_request_bulk_input_flags (&bulk, consumer, flags); + lflags =ctxless_flags_to_line_request_flags (active_low, flags); + rv =gpiod_line_request_bulk_input_flags (&bulk, consumer, lflags);if (rv <0 ) {gpiod_chip_close (chip);return -1 ;@@ -83,17 +131,39 @@ int gpiod_ctxless_set_value(const char *device, unsigned int offset, int value, active_low, consumer, cb, data); } +int gpiod_ctxless_set_value_ext (const char *device,unsigned int offset, +int value,bool active_low,int flags, +const char *consumer, +gpiod_ctxless_set_value_cb cb,void *data) +{ +return gpiod_ctxless_set_value_multiple_ext (device, &offset, &value, +1 , active_low, flags, + consumer, cb, data); +} +int gpiod_ctxless_set_value_multiple (const char *device,const unsigned int *offsets,const int *values,unsigned int num_lines,bool active_low,const char *consumer,gpiod_ctxless_set_value_cb cb,void *data) +{ +return gpiod_ctxless_set_value_multiple_ext (device, offsets, values, + num_lines, active_low, +0 , consumer, cb, data); +} + +int gpiod_ctxless_set_value_multiple_ext ( +const char *device, +const unsigned int *offsets, +const int *values,unsigned int num_lines, +bool active_low,int flags,const char *consumer, +gpiod_ctxless_set_value_cb cb,void *data) {struct gpiod_line_bulk bulk;struct gpiod_chip *chip;struct gpiod_line *line;unsigned int i; -int rv, flags; +int rv, lflags;if (!num_lines || num_lines >GPIOD_LINE_BULK_MAX_LINES ) { errno =EINVAL ;@@ -116,10 +186,9 @@ int gpiod_ctxless_set_value_multiple(const char *device,gpiod_line_bulk_add (&bulk, line); } - flags = active_low ?GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW :0 ; - + lflags =ctxless_flags_to_line_request_flags (active_low, flags); rv =gpiod_line_request_bulk_output_flags (&bulk, consumer, - flags, values); + lflags, values);if (rv <0 ) {gpiod_chip_close (chip);return -1 ;@@ -216,6 +285,19 @@ int gpiod_ctxless_event_monitor(const char *device, int event_type, poll_cb, event_cb, data); } +int gpiod_ctxless_event_monitor_ext (const char *device,int event_type, +unsigned int offset,bool active_low, +int flags,const char *consumer, +const struct timespec *timeout, +gpiod_ctxless_event_poll_cb poll_cb, +gpiod_ctxless_event_handle_cb event_cb, +void *data) +{ +return gpiod_ctxless_event_monitor_multiple_ext ( + device, event_type, &offset,1 , active_low, + flags, consumer, timeout, poll_cb, event_cb, data); +} + int gpiod_ctxless_event_monitor_multiple( const char *device, int event_type, const unsigned int *offsets,@@ -225,6 +307,21 @@ int gpiod_ctxless_event_monitor_multiple(gpiod_ctxless_event_poll_cb poll_cb, gpiod_ctxless_event_handle_cb event_cb, void *data) +{ + return gpiod_ctxless_event_monitor_multiple_ext( +device ,event_type ,offsets , + num_lines, active_low, 0, consumer, timeout, +poll_cb ,event_cb ,data ); +} + +int gpiod_ctxless_event_monitor_multiple_ext ( +const char *device,int event_type, +const unsigned int *offsets, +unsigned int num_lines,bool active_low,int flags, +const char *consumer,const struct timespec *timeout, +gpiod_ctxless_event_poll_cb poll_cb, +gpiod_ctxless_event_handle_cb event_cb, +void *data) {struct gpiod_ctxless_event_poll_fd fds[GPIOD_LINE_BULK_MAX_LINES ];struct gpiod_line_request_config conf;@@ -259,7 +356,7 @@ int gpiod_ctxless_event_monitor_multiple(gpiod_line_bulk_add (&bulk, line); } - conf.flags = active_low ?GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW :0 ; + conf.flags =ctxless_flags_to_line_request_flags (active_low, flags); conf.consumer = consumer;if (event_type ==GPIOD_CTXLESS_EVENT_RISING_EDGE ) { --2.24.0
Re: [libgpiod] [PATCH 02/19] API: add support for bias flags
Quoted 17 lines · Bartosz Golaszewski
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 8 lines
Extend the libgpiod API to support the bias flags recently added to the kernel GPIO uAPI. The core change is the addition of
GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE,GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UPandGPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWNflags to be passed intoline_requestfunctions, and the addition ofgpiod_line_biasto return the bias state of lines.Quoted 7 lines
Extended variants of the ctxless functions that accept an
active_lowflag are added to also accept other flags. The variant names add a "_ext" suffix to the name of the original function.Based on initial work by Drew Fustini <[email protected]>.
Signed-off-by Kent Gibson <[email protected]>
Quoted 8 lines
Hi Kent,
this looks good, just a couple nits. I'd change the subject line to "core: add support for bias flags". Also: how about moving the flags argument to the last position in all the ctxless extended variants, so that they keep the same signature *except* for the appended new argument?
Will do.
Kent.
PATCH 3/19 core: fix misspelling of parameter
In reply to Kent GibsonTrivial fix to bring gpiod_ctxless_event_monitor_multiple documentation into line with gpiod_ctxless_event_monitor_multiple_ext.
--- include/gpiod.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/gpiod.h +1 -1
@@ -460,7 +460,7 @@ int gpiod_ctxless_event_monitor_ext(const char *device, int event_type,* back to a basic, ppoll() based callback. * * Internally this routine opens the GPIO chip, requests the set of lines for -* the type of events specified in the event_type paramter and calls the +* the type of events specified in the event_type parameter and calls the * polling callback in a loop. The role of the polling callback is to detect * input events on a set of file descriptors and notify the caller about the * fds ready for reading.
Signature · 1 line
2.24.0
PATCH 4/19 tests: add tests for bias flags
In reply to Kent GibsonExtend test coverage over the bias flags, gpiod_line_bias and the extended ctxless functions.
Also update existing tests to check bias flags where line state is checked.
--- tests/tests-ctxless.c | 64 +++++++++++++++++++++- tests/tests-event.c | 120 ++++++++++++++++++++++++++++++++++++++++++ tests/tests-line.c | 98 ++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 2 deletions(-)
tests/tests-ctxless.c +62 -2
@@ -26,11 +26,41 @@ GPIOD_TEST_CASE(get_value, 0, { 8 }) g_assert_cmpint(ret, ==, 1); } -static void set_value_check(gpointer data G_GNUC_UNUSED) +GPIOD_TEST_CASE(get_value_ext, 0, { 8 }) +{ +gint ret; + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + false,GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + false,GPIOD_CTXLESS_FLAG_BIAS_PULL_UP , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + true,GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + true,GPIOD_CTXLESS_FLAG_BIAS_PULL_UP , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); +} + +static void set_value_check_hi(gpointer data G_GNUC_UNUSED) { g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 1); } +static void set_value_check_lo(gpointer data G_GNUC_UNUSED) +{ + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); +} + GPIOD_TEST_CASE(set_value, 0, { 8 }) {gint ret;
@@ -39,13 +69,43 @@ GPIOD_TEST_CASE(set_value, 0, { 8 }) ret =gpiod_ctxless_set_value (gpiod_test_chip_name (0 ),3 ,1 , false,GPIOD_TEST_CONSUMER , - set_value_check,NULL ); + set_value_check_hi,NULL );gpiod_test_return_if_failed (); g_assert_cmpint(ret, ==, 0); g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); } +GPIOD_TEST_CASE(set_value_ext, 0, { 8 }) +{ +gint ret; + +gpiod_test_chip_set_pull (0 ,3 ,0 ); + + ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,1 , + false,0 ,GPIOD_TEST_CONSUMER , + set_value_check_hi,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); + +// test drive flags by checking that sets are caught by emulation + ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,1 , + false,GPIOD_CTXLESS_FLAG_OPEN_DRAIN , +GPIOD_TEST_CONSUMER , set_value_check_lo,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); + +gpiod_test_chip_set_pull (0 ,3 ,1 ); + ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,0 , + false,GPIOD_CTXLESS_FLAG_OPEN_SOURCE , +GPIOD_TEST_CONSUMER , set_value_check_hi,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 1); +} +static const guint get_value_multiple_offsets[] = {1 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,13 ,14 };
tests/tests-event.c +120 -0
126 lines not on this page · raw message
tests/tests-line.c +98 -0
138 lines not on this page · raw message
Signature · 1 line
2.24.0
Re: [libgpiod] [PATCH 04/19] tests: add tests for bias flags
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 76 lines
Extend test coverage over the bias flags,
gpiod_line_biasand the extended ctxless functions.Also update existing tests to check bias flags where line state is checked.
Signed-off-by Kent Gibson <[email protected]>--- tests/tests-ctxless.c | 64 +++++++++++++++++++++- tests/tests-event.c | 120 ++++++++++++++++++++++++++++++++++++++++++ tests/tests-line.c | 98 ++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 2 deletions(-)tests/tests-ctxless.c +36
-2@@ -26,11 +26,41 @@ GPIOD_TEST_CASE(get_value, 0, { 8 }) g_assert_cmpint(ret, ==, 1); } -static void set_value_check(gpointer data G_GNUC_UNUSED) +GPIOD_TEST_CASE(get_value_ext, 0, { 8 }) +{ +gint ret; + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + false,GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + false,GPIOD_CTXLESS_FLAG_BIAS_PULL_UP , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + true,GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + true,GPIOD_CTXLESS_FLAG_BIAS_PULL_UP , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); +} + +static void set_value_check_hi(gpointer data G_GNUC_UNUSED) { g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 1); } +static void set_value_check_lo(gpointer data G_GNUC_UNUSED) +{ + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); +} + GPIOD_TEST_CASE(set_value, 0, { 8 }) {gint ret;@@ -39,13 +69,43 @@ GPIOD_TEST_CASE(set_value, 0, { 8 }) ret =gpiod_ctxless_set_value (gpiod_test_chip_name (0 ),3 ,1 , false,GPIOD_TEST_CONSUMER , - set_value_check,NULL ); + set_value_check_hi,NULL );gpiod_test_return_if_failed (); g_assert_cmpint(ret, ==, 0); g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); } +GPIOD_TEST_CASE(set_value_ext, 0, { 8 }) +{ +gint ret; +
tests/tests-ctxless.c GPIOD_TEST_CASE(set_value, 0, { 8 }) · line 92
Quoted 10 lines
tests/tests-ctxless.c +10
-0+gpiod_test_chip_set_pull (0 ,3 ,0 ); + + ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,1 , + false,0 ,GPIOD_TEST_CONSUMER , + set_value_check_hi,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); + +// test drive flags by checking that sets are caught by emulation
Nit: don't use C++ comments in libgpiod.
Bart
Quoted 301 lines
tests/tests-ctxless.c +16
-0+ ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,1 , + false,GPIOD_CTXLESS_FLAG_OPEN_DRAIN , +GPIOD_TEST_CONSUMER , set_value_check_lo,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); + +gpiod_test_chip_set_pull (0 ,3 ,1 ); + ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,0 , + false,GPIOD_CTXLESS_FLAG_OPEN_SOURCE , +GPIOD_TEST_CONSUMER , set_value_check_hi,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 1); +} +static const guint get_value_multiple_offsets[] = {1 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,13 ,14 };tests/tests-event.c +120
-0@@ -196,6 +196,126 @@ GPIOD_TEST_CASE(both_edges_active_low, 0, { 8 }) g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE); } +GPIOD_TEST_CASE(both_edges_bias_disable, 0, { 8 }) +{ +g_autoptr (GpiodTestEventThread) ev_thread =NULL ; +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct timespec ts = {1 ,0 }; +struct gpiod_line_event ev; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,7 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_both_edges_events_flags (line, +GPIOD_TEST_CONSUMER ,GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ); + g_assert_cmpint(ret, ==, 0); + + ev_thread =gpiod_test_start_event_thread (0 ,7 ,100 ); + + ret =gpiod_line_event_wait (line, &ts); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_line_event_read (line, &ev); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE); + + ret =gpiod_line_event_wait (line, &ts); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_line_event_read (line, &ev); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE); +} + +GPIOD_TEST_CASE(both_edges_bias_pull_down, 0, { 8 }) +{ +g_autoptr (GpiodTestEventThread) ev_thread =NULL ; +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct timespec ts = {1 ,0 }; +struct gpiod_line_event ev; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,7 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_both_edges_events_flags (line, +GPIOD_TEST_CONSUMER ,GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ); + g_assert_cmpint(ret, ==, 0); + + ev_thread =gpiod_test_start_event_thread (0 ,7 ,100 ); + + ret =gpiod_line_event_wait (line, &ts); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_line_event_read (line, &ev); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE); + + ret =gpiod_line_event_wait (line, &ts); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_line_event_read (line, &ev); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE); +} + +GPIOD_TEST_CASE(both_edges_bias_pull_up, 0, { 8 }) +{ +g_autoptr (GpiodTestEventThread) ev_thread =NULL ; +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct timespec ts = {1 ,0 }; +struct gpiod_line_event ev; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,7 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_both_edges_events_flags (line, +GPIOD_TEST_CONSUMER ,GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ); + g_assert_cmpint(ret, ==, 0); + + ev_thread =gpiod_test_start_event_thread (0 ,7 ,100 ); + + ret =gpiod_line_event_wait (line, &ts); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_line_event_read (line, &ev); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_FALLING_EDGE); + + ret =gpiod_line_event_wait (line, &ts); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_line_event_read (line, &ev); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(ev.event_type, ==, GPIOD_LINE_EVENT_RISING_EDGE); +} + GPIOD_TEST_CASE(falling_edge_active_low, 0, { 8 }) {g_autoptr (GpiodTestEventThread) ev_thread =NULL ;tests/tests-line.c +98
-1@@ -451,6 +451,7 @@ GPIOD_TEST_CASE(misc_flags, 0, { 8 })g_assert_false (gpiod_line_is_used (line));g_assert_false (gpiod_line_is_open_drain (line));g_assert_false (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_AS_IS); config.request_type =GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ; config.consumer =GPIOD_TEST_CONSUMER ;@@ -462,6 +463,7 @@ GPIOD_TEST_CASE(misc_flags, 0, { 8 })g_assert_true (gpiod_line_is_used (line));g_assert_true (gpiod_line_is_open_drain (line));g_assert_false (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_AS_IS); g_assert_cmpint(gpiod_line_direction(line), ==,GPIOD_LINE_DIRECTION_OUTPUT );@@ -475,8 +477,11 @@ GPIOD_TEST_CASE(misc_flags, 0, { 8 })g_assert_true (gpiod_line_is_used (line));g_assert_false (gpiod_line_is_open_drain (line));g_assert_true (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_AS_IS); g_assert_cmpint(gpiod_line_direction(line), ==,GPIOD_LINE_DIRECTION_OUTPUT ); + +gpiod_line_release (line); } GPIOD_TEST_CASE(misc_flags_work_together, 0, { 8 })@@ -510,6 +515,7 @@ GPIOD_TEST_CASE(misc_flags_work_together, 0, { 8 })g_assert_true (gpiod_line_is_used (line));g_assert_true (gpiod_line_is_open_drain (line));g_assert_false (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_AS_IS); g_assert_cmpint(gpiod_line_active_state(line), ==,GPIOD_LINE_ACTIVE_STATE_LOW ); g_assert_cmpint(gpiod_line_direction(line), ==,@@ -526,8 +532,59 @@ GPIOD_TEST_CASE(misc_flags_work_together, 0, { 8 })g_assert_true (gpiod_line_is_used (line));g_assert_false (gpiod_line_is_open_drain (line));g_assert_true (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_AS_IS); g_assert_cmpint(gpiod_line_active_state(line), ==,GPIOD_LINE_ACTIVE_STATE_LOW ); + +gpiod_line_release (line); + +/* +* Verify that pull-up/down flags work together +* with active_low. +*/ + + config.request_type =GPIOD_LINE_REQUEST_DIRECTION_INPUT ; + config.flags =GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN | +GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ; + + ret =gpiod_line_request (line, &config,0 ); + g_assert_cmpint(ret, ==, 0); + +g_assert_true (gpiod_line_is_used (line)); +g_assert_false (gpiod_line_is_open_drain (line)); +g_assert_false (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_PULL_DOWN); + g_assert_cmpint(gpiod_line_active_state(line), ==, +GPIOD_LINE_ACTIVE_STATE_LOW ); + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_INPUT ); + + ret =gpiod_line_get_value (line); + g_assert_cmpint(ret, ==, 1); + g_assert_cmpint(errno, ==, 0); + +gpiod_line_release (line); + + config.flags =GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP | +GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ; + + ret =gpiod_line_request (line, &config,0 ); + g_assert_cmpint(ret, ==, 0); + +g_assert_true (gpiod_line_is_used (line)); +g_assert_false (gpiod_line_is_open_drain (line)); +g_assert_false (gpiod_line_is_open_source (line)); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_PULL_UP); + g_assert_cmpint(gpiod_line_active_state(line), ==, +GPIOD_LINE_ACTIVE_STATE_LOW ); + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_INPUT ); + + ret =gpiod_line_get_value (line); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(errno, ==, 0); + +gpiod_line_release (line); } GPIOD_TEST_CASE(open_source_open_drain_input_mode, 0, { 8 })@@ -576,6 +633,47 @@ GPIOD_TEST_CASE(open_source_open_drain_simultaneously, 0, { 8 }) g_assert_cmpint(errno, ==, EINVAL); } +GPIOD_TEST_CASE(multiple_bias_flags, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,2 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_input_flags (line,GPIOD_TEST_CONSUMER , +GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE | +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ); + g_assert_cmpint(ret, ==, -1); + g_assert_cmpint(errno, ==, EINVAL); + + ret =gpiod_line_request_input_flags (line,GPIOD_TEST_CONSUMER , +GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE | +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ); + g_assert_cmpint(ret, ==, -1); + g_assert_cmpint(errno, ==, EINVAL); + + ret =gpiod_line_request_input_flags (line,GPIOD_TEST_CONSUMER , +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN | +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ); + g_assert_cmpint(ret, ==, -1); + g_assert_cmpint(errno, ==, EINVAL); + + ret =gpiod_line_request_input_flags (line,GPIOD_TEST_CONSUMER , +GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE | +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN | +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ); + g_assert_cmpint(ret, ==, -1); + g_assert_cmpint(errno, ==, EINVAL); +} + +/* Verify that the reference counting of the line fd handle works correctly. */ GPIOD_TEST_CASE(release_one_use_another, 0, { 8 }) { --2.24.0
Re: [libgpiod] [PATCH 04/19] tests: add tests for bias flags
Quoted 73 lines · Bartosz Golaszewski
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 72 lines
Extend test coverage over the bias flags,
gpiod_line_biasand the extended ctxless functions.Also update existing tests to check bias flags where line state is checked.
Signed-off-by Kent Gibson <[email protected]>--- tests/tests-ctxless.c | 64 +++++++++++++++++++++- tests/tests-event.c | 120 ++++++++++++++++++++++++++++++++++++++++++ tests/tests-line.c | 98 ++++++++++++++++++++++++++++++++++ 3 files changed, 280 insertions(+), 2 deletions(-)tests/tests-ctxless.c +32
-2@@ -26,11 +26,41 @@ GPIOD_TEST_CASE(get_value, 0, { 8 }) g_assert_cmpint(ret, ==, 1); } -static void set_value_check(gpointer data G_GNUC_UNUSED) +GPIOD_TEST_CASE(get_value_ext, 0, { 8 }) +{ +gint ret; + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + false,GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + false,GPIOD_CTXLESS_FLAG_BIAS_PULL_UP , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + true,GPIOD_CTXLESS_FLAG_BIAS_PULL_DOWN , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 1); + + ret =gpiod_ctxless_get_value_ext (gpiod_test_chip_name (0 ),3 , + true,GPIOD_CTXLESS_FLAG_BIAS_PULL_UP , +GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); +} + +static void set_value_check_hi(gpointer data G_GNUC_UNUSED) { g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 1); } +static void set_value_check_lo(gpointer data G_GNUC_UNUSED) +{ + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); +} + GPIOD_TEST_CASE(set_value, 0, { 8 }) {gint ret;@@ -39,13 +69,43 @@ GPIOD_TEST_CASE(set_value, 0, { 8 }) ret =gpiod_ctxless_set_value (gpiod_test_chip_name (0 ),3 ,1 , false,GPIOD_TEST_CONSUMER , - set_value_check,NULL ); + set_value_check_hi,NULL );gpiod_test_return_if_failed (); g_assert_cmpint(ret, ==, 0); g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); }
Quoted 17 lines
Quoted 4 lines
tests/tests-ctxless.c +4
-0+GPIOD_TEST_CASE(set_value_ext, 0, { 8 }) +{ +gint ret; +tests/tests-ctxless.c GPIOD_TEST_CASE(set_value, 0, { 8 }) · line 92
Quoted 10 lines
tests/tests-ctxless.c +10
-0+gpiod_test_chip_set_pull (0 ,3 ,0 ); + + ret =gpiod_ctxless_set_value_ext (gpiod_test_chip_name (0 ),3 ,1 , + false,0 ,GPIOD_TEST_CONSUMER , + set_value_check_hi,NULL ); +gpiod_test_return_if_failed (); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 3), ==, 0); + +// test drive flags by checking that sets are caught by emulation Nit: don't use C++ comments in libgpiod.
Sorry - old habits.
Kent.
PATCH 5/19 bindings: cxx: drop noexcept from direction and active_state
In reply to Kent GibsonBoth direction and active_state methods can throw and so should not be declared as noexcept.
--- bindings/cxx/gpiod.hpp | 4 ++-- bindings/cxx/line.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
bindings/cxx/gpiod.hpp +2 -2
@@ -312,13 +312,13 @@ public: * @brief Get current direction of this line. * @return Current direction setting. */ - GPIOD_API int direction(void) const noexcept; + GPIOD_API int direction(void) const; /** * @brief Get current active state of this line. * @return Current active state setting. */ - GPIOD_API int active_state(void) const noexcept; + GPIOD_API int active_state(void) const; /** * @brief Check if this line is used by the kernel or other user space
bindings/cxx/line.cpp +2 -2
@@ -49,7 +49,7 @@ unsigned int line::offset(void) const return consumer ? ::std::string(consumer) : ::std::string(); } -int line::direction(void) const noexcept +int line::direction(void) const { this->throw_if_null();
@@ -58,7 +58,7 @@ int line::direction(void) const noexcept return dir == GPIOD_LINE_DIRECTION_INPUT ? DIRECTION_INPUT : DIRECTION_OUTPUT; } -int line::active_state(void) const noexcept +int line::active_state(void) const { this->throw_if_null();
Signature · 1 line
2.24.0
PATCH 6/19 bindings: cxx: initialise bitset with integer instead of string
In reply to Kent GibsonInitialising bitsets with string is inefficient and confusing. Initialise them with the corresponding int instead.
--- bindings/cxx/line_bulk.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
bindings/cxx/line_bulk.cpp +3 -3
@@ -11,9 +11,9 @@ namespace gpiod { -const ::std::bitset<32> line_request::FLAG_ACTIVE_LOW("001"); -const ::std::bitset<32> line_request::FLAG_OPEN_SOURCE("010"); -const ::std::bitset<32> line_request::FLAG_OPEN_DRAIN("100"); +const ::std::bitset<32> line_request::FLAG_ACTIVE_LOW(GPIOD_BIT(0)); +const ::std::bitset<32> line_request::FLAG_OPEN_SOURCE(GPIOD_BIT(1)); +const ::std::bitset<32> line_request::FLAG_OPEN_DRAIN(GPIOD_BIT(2)); namespace {
Signature · 1 line
2.24.0
Re: [libgpiod] [PATCH 06/19] bindings: cxx: initialise bitset with integer instead of string
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 4 lines
Initialising bitsets with string is inefficient and confusing. Initialise them with the corresponding int instead.
I'm not a native English speaker, of course, so correcting you on spelling may be risky but I generally try to stick to American spelling so "initialise" looks somehow wrong to me. :) Anyway, this is just the commit message, so never mind that.
Quoted 25 lines
Signed-off-by Kent Gibson <[email protected]>--- bindings/cxx/line_bulk.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)bindings/cxx/line_bulk.cpp +3
-4@@ -11,9 +11,9 @@ namespace gpiod { -const ::std::bitset<32> line_request::FLAG_ACTIVE_LOW("001"); -const ::std::bitset<32> line_request::FLAG_OPEN_SOURCE("010"); -const ::std::bitset<32> line_request::FLAG_OPEN_DRAIN("100"); +const ::std::bitset<32> line_request::FLAG_ACTIVE_LOW(GPIOD_BIT(0)); +const ::std::bitset<32> line_request::FLAG_OPEN_SOURCE(GPIOD_BIT(1)); +const ::std::bitset<32> line_request::FLAG_OPEN_DRAIN(GPIOD_BIT(2)); namespace { --2.24.0
Re: [libgpiod] [PATCH 06/19] bindings: cxx: initialise bitset with integer instead of string
Quoted 11 lines · Bartosz Golaszewski
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 4 lines
Initialising bitsets with string is inefficient and confusing. Initialise them with the corresponding int instead.
I'm not a native English speaker, of course, so correcting you on spelling may be risky but I generally try to stick to American spelling so "initialise" looks somehow wrong to me. :) Anyway, this is just the commit message, so never mind that.
And I speak English, not American, so I didn't even notice. I will try to keep that in mind though.
Kent.
PATCH 7/19 bindings: cxx: add support for bias flags
In reply to Kent GibsonAdd support for bias flags in line requests and returning the line bias setting via a bias accessor.
Based on initial work by Drew Fustini <[email protected]>.
--- bindings/cxx/gpiod.hpp | 26 ++++++++++++++++++++++++++ bindings/cxx/line.cpp | 19 +++++++++++++++++++ bindings/cxx/line_bulk.cpp | 6 ++++++ 3 files changed, 51 insertions(+)
bindings/cxx/gpiod.hpp +26 -0
@@ -233,6 +233,12 @@ struct line_request /**< The line is an open-source port. */ GPIOD_API static const ::std::bitset<32> FLAG_OPEN_DRAIN; /**< The line is an open-drain port. */ + GPIOD_API static const ::std::bitset<32> FLAG_BIAS_DISABLE; + /**< The line has neither pull-up nor pull-down resistor enabled */ + GPIOD_API static const ::std::bitset<32> FLAG_BIAS_PULL_DOWN; + /**< The line has a configurable pull-down resistor enabled */ + GPIOD_API static const ::std::bitset<32> FLAG_BIAS_PULL_UP; + /**< The line has a configurable pull-up resistor enabled */ ::std::string consumer; /**< Consumer name to pass to the request. */
@@ -320,6 +326,12 @@ public: */ GPIOD_API int active_state(void) const; + /** + * @brief Get current bias of this line. + * @return Current bias setting. + */ + GPIOD_API int bias(void) const; + /** * @brief Check if this line is used by the kernel or other user space * process.
@@ -456,6 +468,20 @@ public: /**< Line's active state is high. */ }; + /** + * @brief Possible bias settings. + */ + enum : int { + BIAS_AS_IS = 1, + /**< Line's bias state is unknown. */ + BIAS_DISABLE, + /**< Line's internal bias is disabled. */ + BIAS_PULL_UP, + /**< Line's internal pull-up bias is enabled. */ + BIAS_PULL_DOWN, + /**< Line's internal pull-down bias is enabled. */ + }; + private: line(::gpiod_line* line, const chip& owner);
bindings/cxx/line.cpp +19 -0
@@ -67,6 +67,25 @@ int line::active_state(void) const return active == GPIOD_LINE_ACTIVE_STATE_HIGH ? ACTIVE_HIGH : ACTIVE_LOW; } +int line::bias(void) const +{ + this->throw_if_null(); + + int bias = ::gpiod_line_bias(this->_m_line); + + switch (bias) { + case GPIOD_LINE_BIAS_PULL_UP: + return BIAS_PULL_UP; + case GPIOD_LINE_BIAS_PULL_DOWN: + return BIAS_PULL_DOWN; + case GPIOD_LINE_BIAS_DISABLE: + return BIAS_DISABLE; + case GPIOD_LINE_BIAS_AS_IS: + default: + return BIAS_AS_IS; + } +} + bool line::is_used(void) const { this->throw_if_null();
bindings/cxx/line_bulk.cpp +6 -0
@@ -14,6 +14,9 @@ namespace gpiod { const ::std::bitset<32> line_request::FLAG_ACTIVE_LOW(GPIOD_BIT(0)); const ::std::bitset<32> line_request::FLAG_OPEN_SOURCE(GPIOD_BIT(1)); const ::std::bitset<32> line_request::FLAG_OPEN_DRAIN(GPIOD_BIT(2)); +const ::std::bitset<32> line_request::FLAG_BIAS_DISABLE(GPIOD_BIT(3)); +const ::std::bitset<32> line_request::FLAG_BIAS_PULL_DOWN(GPIOD_BIT(4)); +const ::std::bitset<32> line_request::FLAG_BIAS_PULL_UP(GPIOD_BIT(5)); namespace {
@@ -38,6 +41,9 @@ const ::std::map<::std::bitset<32>, int, bitset_cmp> reqflag_mapping = { { line_request::FLAG_ACTIVE_LOW, GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW, }, { line_request::FLAG_OPEN_DRAIN, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN, }, { line_request::FLAG_OPEN_SOURCE, GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE, }, + { line_request::FLAG_BIAS_DISABLE, GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE, }, + { line_request::FLAG_BIAS_PULL_DOWN, GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN, }, + { line_request::FLAG_BIAS_PULL_UP, GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP, }, }; } /* namespace */
Signature · 1 line
2.24.0
PATCH 8/19 bindings: cxx: tests: add tests for bias flags
In reply to Kent GibsonExtend test coverage over the bias flags in requests and the bias setting returned by line.bias().
--- bindings/cxx/tests/tests-line.cpp | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
bindings/cxx/tests/tests-line.cpp +87 -0
@@ -52,6 +52,9 @@ TEST_CASE("Line information can be correctly retrieved", "[line]") REQUIRE(line.consumer().empty()); REQUIRE_FALSE(line.is_requested()); REQUIRE_FALSE(line.is_used()); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_AS_IS); } SECTION("exported line")
@@ -68,6 +71,9 @@ TEST_CASE("Line information can be correctly retrieved", "[line]") REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); REQUIRE(line.is_requested()); REQUIRE(line.is_used()); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_AS_IS); } SECTION("exported line with flags")
@@ -88,6 +94,87 @@ TEST_CASE("Line information can be correctly retrieved", "[line]") REQUIRE(line.is_used()); REQUIRE(line.is_open_drain()); REQUIRE_FALSE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_AS_IS); + } + + SECTION("exported open source line") + { + ::gpiod::line_request config; + + config.consumer = consumer.c_str(); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = ::gpiod::line_request::FLAG_OPEN_SOURCE; + line.request(config); + + REQUIRE(line.offset() == 4); + REQUIRE(line.name() == "gpio-mockup-A-4"); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + REQUIRE(line.is_requested()); + REQUIRE(line.is_used()); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_AS_IS); + } + + SECTION("exported bias disable line") + { + ::gpiod::line_request config; + + config.consumer = consumer.c_str(); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = ::gpiod::line_request::FLAG_BIAS_DISABLE; + line.request(config); + + REQUIRE(line.offset() == 4); + REQUIRE(line.name() == "gpio-mockup-A-4"); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + REQUIRE(line.is_requested()); + REQUIRE(line.is_used()); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_DISABLE); + } + + SECTION("exported pull-down line") + { + ::gpiod::line_request config; + + config.consumer = consumer.c_str(); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = ::gpiod::line_request::FLAG_BIAS_PULL_DOWN; + line.request(config); + + REQUIRE(line.offset() == 4); + REQUIRE(line.name() == "gpio-mockup-A-4"); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + REQUIRE(line.is_requested()); + REQUIRE(line.is_used()); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_PULL_DOWN); + } + + SECTION("exported pull-up line") + { + ::gpiod::line_request config; + + config.consumer = consumer.c_str(); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = ::gpiod::line_request::FLAG_BIAS_PULL_UP; + line.request(config); + + REQUIRE(line.offset() == 4); + REQUIRE(line.name() == "gpio-mockup-A-4"); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + REQUIRE(line.is_requested()); + REQUIRE(line.is_used()); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + REQUIRE(line.bias() == ::gpiod::line::BIAS_PULL_UP); } SECTION("update line info")
Signature · 1 line
2.24.0
PATCH 9/19 bindings: python: add support for bias flags
In reply to Kent GibsonAdd support for bias flags in line requests and returning the line bias setting via a bias accessor.
Based on initial work by Drew Fustini <[email protected]>.
--- bindings/python/gpiodmodule.c | 82 +++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
bindings/python/gpiodmodule.c +82 -0
@@ -60,6 +60,9 @@ enum { gpiod_LINE_REQ_FLAG_OPEN_DRAIN =GPIOD_BIT (0 ), gpiod_LINE_REQ_FLAG_OPEN_SOURCE =GPIOD_BIT (1 ), gpiod_LINE_REQ_FLAG_ACTIVE_LOW =GPIOD_BIT (2 ), + gpiod_LINE_REQ_FLAG_BIAS_DISABLE =GPIOD_BIT (3 ), + gpiod_LINE_REQ_FLAG_BIAS_PULL_DOWN =GPIOD_BIT (4 ), + gpiod_LINE_REQ_FLAG_BIAS_PULL_UP = GPIOD_BIT(5), }; enum {
@@ -72,6 +75,13 @@ enum { gpiod_ACTIVE_LOW, }; +enum { + gpiod_BIAS_AS_IS =1 , + gpiod_BIAS_DISABLE, + gpiod_BIAS_PULL_UP, + gpiod_BIAS_PULL_DOWN, +}; +enum { gpiod_RISING_EDGE =1 , gpiod_FALLING_EDGE,
@@ -358,6 +368,34 @@ static PyObject *gpiod_Line_active_state(gpiod_LineObject *self,return ret; } +PyDoc_STRVAR (gpiod_Line_bias_doc, +"bias() -> integer\n" +"\n" +"Get the bias setting of this GPIO line." ); + +static PyObject *gpiod_Line_bias (gpiod_LineObject *self, +PyObject *Py_UNUSED (ignored )) +{ +int bias; + +if (gpiod_ChipIsClosed (self->owner)) +return NULL ; + + bias =gpiod_line_bias (self->line); + +switch (bias) { +case GPIOD_LINE_BIAS_PULL_UP : +return Py_BuildValue ("I" , gpiod_BIAS_PULL_UP); +case GPIOD_LINE_BIAS_PULL_DOWN : +return Py_BuildValue ("I" , gpiod_BIAS_PULL_DOWN); +case GPIOD_LINE_BIAS_DISABLE : +return Py_BuildValue ("I" , gpiod_BIAS_DISABLE); +case GPIOD_LINE_BIAS_AS_IS : +default : +return Py_BuildValue ("I" , gpiod_BIAS_AS_IS); + } +} +PyDoc_STRVAR (gpiod_Line_is_used_doc,"is_used() -> boolean\n" "\n"
@@ -752,6 +790,12 @@ static PyMethodDef gpiod_Line_methods[] = { .ml_flags = METH_NOARGS, .ml_doc = gpiod_Line_active_state_doc, }, + { + .ml_name = "bias", + .ml_meth = (PyCFunction)gpiod_Line_bias, + .ml_flags = METH_NOARGS, + .ml_doc = gpiod_Line_bias_doc, + }, { .ml_name = "is_used", .ml_meth = (PyCFunction)gpiod_Line_is_used,
@@ -1030,6 +1074,12 @@ static void gpiod_MakeRequestConfig(struct gpiod_line_request_config *conf, conf->flags |=GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ;if (flags & gpiod_LINE_REQ_FLAG_ACTIVE_LOW) conf->flags |=GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ; +if (flags & gpiod_LINE_REQ_FLAG_BIAS_DISABLE) + conf->flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +if (flags & gpiod_LINE_REQ_FLAG_BIAS_PULL_DOWN) + conf->flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +if (flags & gpiod_LINE_REQ_FLAG_BIAS_PULL_UP) + conf->flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; } PyDoc_STRVAR(gpiod_LineBulk_request_doc,
@@ -2313,6 +2363,26 @@ static gpiod_ConstDescr gpiod_ConstList[] = { .name = "ACTIVE_LOW", .val = gpiod_ACTIVE_LOW, }, + { + .typeobj = &gpiod_LineType, + .name = "BIAS_AS_IS", + .val = gpiod_BIAS_AS_IS, + }, + { + .typeobj = &gpiod_LineType, + .name = "BIAS_DISABLE", + .val = gpiod_BIAS_DISABLE, + }, + { + .typeobj = &gpiod_LineType, + .name = "BIAS_PULL_UP", + .val = gpiod_BIAS_PULL_UP, + }, + { + .typeobj = &gpiod_LineType, + .name = "BIAS_PULL_DOWN", + .val = gpiod_BIAS_PULL_DOWN, + }, { .typeobj = &gpiod_LineEventType, .name = "RISING_EDGE",
@@ -2381,6 +2451,18 @@ static gpiod_ModuleConst gpiod_ModuleConsts[] = { .name = "LINE_REQ_FLAG_ACTIVE_LOW", .value = gpiod_LINE_REQ_FLAG_ACTIVE_LOW, }, + { + .name = "LINE_REQ_FLAG_BIAS_DISABLE", + .value = gpiod_LINE_REQ_FLAG_BIAS_DISABLE, + }, + { + .name = "LINE_REQ_FLAG_BIAS_PULL_DOWN", + .value = gpiod_LINE_REQ_FLAG_BIAS_PULL_DOWN, + }, + { + .name = "LINE_REQ_FLAG_BIAS_PULL_UP", + .value = gpiod_LINE_REQ_FLAG_BIAS_PULL_UP, + }, { } };
Signature · 1 line
2.24.0
PATCH 10/19 bindings: python: tests: add tests for bias flags
In reply to Kent GibsonExtend test coverage to cover the bias flags in requests and the bias setting returned by line.bias().
--- bindings/python/tests/gpiod_py_test.py | 91 ++++++++++++++++++++++++++ 1 file changed, 91 insertions(+)
bindings/python/tests/gpiod_py_test.py +91 -0
@@ -306,6 +306,97 @@ class LineInfo(MockupTestCase): self.assertTrue(line.is_requested()) self.assertTrue(line.is_open_drain()) self.assertFalse(line.is_open_source()) + self.assertEqual(line.bias(), gpiod.Line.BIAS_AS_IS) + + def test_exported_open_drain_line(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(4) + flags = gpiod.LINE_REQ_FLAG_OPEN_DRAIN + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + flags=flags) + self.assertEqual(line.offset(), 4) + self.assertEqual(line.name(), 'gpio-mockup-A-4') + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(line.active_state(), gpiod.Line.ACTIVE_HIGH) + self.assertEqual(line.consumer(), default_consumer) + self.assertTrue(line.is_used()) + self.assertTrue(line.is_requested()) + self.assertTrue(line.is_open_drain()) + self.assertFalse(line.is_open_source()) + self.assertEqual(line.bias(), gpiod.Line.BIAS_AS_IS) + + def test_exported_open_source_line(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(4) + flags = gpiod.LINE_REQ_FLAG_OPEN_SOURCE + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + flags=flags) + self.assertEqual(line.offset(), 4) + self.assertEqual(line.name(), 'gpio-mockup-A-4') + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(line.active_state(), gpiod.Line.ACTIVE_HIGH) + self.assertEqual(line.consumer(), default_consumer) + self.assertTrue(line.is_used()) + self.assertTrue(line.is_requested()) + self.assertFalse(line.is_open_drain()) + self.assertTrue(line.is_open_source()) + self.assertEqual(line.bias(), gpiod.Line.BIAS_AS_IS) + + def test_exported_bias_disable_line(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(4) + flags = gpiod.LINE_REQ_FLAG_BIAS_DISABLE + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + flags=flags) + self.assertEqual(line.offset(), 4) + self.assertEqual(line.name(), 'gpio-mockup-A-4') + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(line.active_state(), gpiod.Line.ACTIVE_HIGH) + self.assertEqual(line.consumer(), default_consumer) + self.assertTrue(line.is_used()) + self.assertTrue(line.is_requested()) + self.assertFalse(line.is_open_drain()) + self.assertFalse(line.is_open_source()) + self.assertEqual(line.bias(), gpiod.Line.BIAS_DISABLE) + + def test_exported_bias_pull_down_line(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(4) + flags = gpiod.LINE_REQ_FLAG_BIAS_PULL_DOWN + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + flags=flags) + self.assertEqual(line.offset(), 4) + self.assertEqual(line.name(), 'gpio-mockup-A-4') + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(line.active_state(), gpiod.Line.ACTIVE_HIGH) + self.assertEqual(line.consumer(), default_consumer) + self.assertTrue(line.is_used()) + self.assertTrue(line.is_requested()) + self.assertFalse(line.is_open_drain()) + self.assertFalse(line.is_open_source()) + self.assertEqual(line.bias(), gpiod.Line.BIAS_PULL_DOWN) + + def test_exported_bias_pull_up_line(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(4) + flags = gpiod.LINE_REQ_FLAG_BIAS_PULL_UP + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + flags=flags) + self.assertEqual(line.offset(), 4) + self.assertEqual(line.name(), 'gpio-mockup-A-4') + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(line.active_state(), gpiod.Line.ACTIVE_HIGH) + self.assertEqual(line.consumer(), default_consumer) + self.assertTrue(line.is_used()) + self.assertTrue(line.is_requested()) + self.assertFalse(line.is_open_drain()) + self.assertFalse(line.is_open_source()) + self.assertEqual(line.bias(), gpiod.Line.BIAS_PULL_UP) def test_update_line_info(self): with gpiod.Chip(mockup.chip_name(0)) as chip:
Signature · 1 line
2.24.0
PATCH 11/19 API: add support for SET_CONFIG
In reply to Kent GibsonExtend the libgpiod API to support the setting line configuration using the GPIO GPIOHANDLE_SET_CONFIG_IOCTL uAPI ioctl.
The core change is the addition of gpiod_line_set_config, which provides a low level wrapper around the ioctl.
Additionally, higher level helper functions, gpiod_line_set_flags, gpiod_line_set_direction_input, and gpiod_line_set_direction_output provide slightly simplified APIs for common use cases.
Bulk forms of all functions are also provided.
--- include/gpiod.h | 115 ++++++++++++++++++++++++++++ lib/core.c | 196 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 300 insertions(+), 11 deletions(-)
include/gpiod.h +115 -0
@@ -1252,6 +1252,14 @@ void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) GPIOD_API;*/ bool gpiod_line_is_requested(struct gpiod_line *line) GPIOD_API; +/** +* @brief Check if the calling user has ownership of this line for values, +* not events. +* @param line GPIO line object. +* @return True if given line was requested, false otherwise. +*/ +bool gpiod_line_is_requested_values(struct gpiod_line *line) GPIOD_API; +/** * @brief Check if the calling user has neither requested ownership of this * line nor configured any event notifications.
@@ -1311,6 +1319,113 @@ int gpiod_line_set_value(struct gpiod_line *line, int value) GPIOD_API; int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) GPIOD_API; +/** +* @} +* +* @defgroup __line_config__ Setting line configuration +* @{ +*/ + +/** +* @brief Update the configuration of a single GPIO line. +* @param line GPIO line object. +* @param direction Updated direction which may be one of +* GPIOD_LINE_REQUEST_DIRECTION_AS_IS, GPIOD_LINE_REQUEST_DIRECTION_INPUT, +* or GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @param flags Replacement flags. +* @param value The new output value for the line when direction is +* GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_config(struct gpiod_line *line, int direction, + int flags, int value) GPIOD_API; + +/** +* @brief Update the configuration of a set of GPIO lines. +* @param bulk Set of GPIO lines. +* @param direction Updated direction which may be one of +* GPIOD_LINE_REQUEST_DIRECTION_AS_IS, GPIOD_LINE_REQUEST_DIRECTION_INPUT, +* or GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @param flags Replacement flags. +* @param values An array holding line_bulk->num_lines new logical values +* for lines when direction is GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_config_bulk(struct gpiod_line_bulk *bulk, + int direction, int flags, + const int *values) GPIOD_API; + + +/** +* @brief Update the configuration flags of a single GPIO line. +* @param line GPIO line object. +* @param flags Replacement flags. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_flags(struct gpiod_line *line, int flags) GPIOD_API; + +/** +* @brief Update the configuration flags of a set of GPIO lines. +* @param bulk Set of GPIO lines. +* @param flags Replacement flags. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, + int flags) GPIOD_API; + +/** +* @brief Set the direction of a single GPIO line to input. +* @param line GPIO line object. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_direction_input(struct gpiod_line *line) GPIOD_API; + +/** +* @brief Set the direction of a set of GPIO lines to input. +* @param bulk Set of GPIO lines. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_direction_bulk_input(struct gpiod_line_bulk *bulk + ) GPIOD_API; + +/** +* @brief Set the direction of a single GPIO line to output. +* @param line GPIO line object. +* @param value The logical value output on the line. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_direction_output(struct gpiod_line *line, + int value) GPIOD_API; + +/** +* @brief Set the direction of a set of GPIO lines to output. +* @param bulk Set of GPIO lines. +* @values The logical value to output for each line. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_direction_bulk_output(struct gpiod_line_bulk *bulk, + const int *values) GPIOD_API; +/** * @} *
lib/core.c +185 -11
285 lines not on this page · raw message
Signature · 1 line
2.24.0
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
pt., 15 lis 2019 o 15:45 Kent Gibson <[email protected]> napisał(a):
Quoted 24 lines
Extend the libgpiod API to support the setting line configuration using the GPIO
GPIOHANDLE_SET_CONFIG_IOCTLuAPI ioctl.The core change is the addition of
gpiod_line_set_config, which provides a low level wrapper around the ioctl.Additionally, higher level helper functions,
gpiod_line_set_flags,gpiod_line_set_direction_input, andgpiod_line_set_direction_outputprovide slightly simplified APIs for common use cases.Bulk forms of all functions are also provided.
Signed-off-by Kent Gibson <[email protected]>--- include/gpiod.h | 115 ++++++++++++++++++++++++++++ lib/core.c | 196 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 300 insertions(+), 11 deletions(-)include/gpiod.h +0
-0
include/gpiod.h void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) GPIOD_API; · line 1259
Quoted 8 lines
include/gpiod.h +5
-0@@ -1252,6 +1252,14 @@ void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) GPIOD_API;*/ bool gpiod_line_is_requested(struct gpiod_line *line) GPIOD_API; +/** +* @brief Check if the calling user has ownership of this line for values, +* not events. +* @param line GPIO line object. +* @return True if given line was requested, false otherwise.
I'd clarify: "requested for reading/setting values".
Quoted 83 lines
include/gpiod.h +76
-0+*/ +bool gpiod_line_is_requested_values(struct gpiod_line *line) GPIOD_API; +/** * @brief Check if the calling user has neither requested ownership of this * line nor configured any event notifications. @@ -1311,6 +1319,113 @@ int gpiod_line_set_value(struct gpiod_line *line, int value) GPIOD_API; int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) GPIOD_API; +/** +* @} +* +* @defgroup __line_config__ Setting line configuration +* @{ +*/ + +/** +* @brief Update the configuration of a single GPIO line. +* @param line GPIO line object. +* @param direction Updated direction which may be one of +* GPIOD_LINE_REQUEST_DIRECTION_AS_IS, GPIOD_LINE_REQUEST_DIRECTION_INPUT, +* or GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @param flags Replacement flags. +* @param value The new output value for the line when direction is +* GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_config(struct gpiod_line *line, int direction, + int flags, int value) GPIOD_API; + +/** +* @brief Update the configuration of a set of GPIO lines. +* @param bulk Set of GPIO lines. +* @param direction Updated direction which may be one of +* GPIOD_LINE_REQUEST_DIRECTION_AS_IS, GPIOD_LINE_REQUEST_DIRECTION_INPUT, +* or GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @param flags Replacement flags. +* @param values An array holding line_bulk->num_lines new logical values +* for lines when direction is GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_config_bulk(struct gpiod_line_bulk *bulk, + int direction, int flags, + const int *values) GPIOD_API; + + +/** +* @brief Update the configuration flags of a single GPIO line. +* @param line GPIO line object. +* @param flags Replacement flags. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_flags(struct gpiod_line *line, int flags) GPIOD_API; + +/** +* @brief Update the configuration flags of a set of GPIO lines. +* @param bulk Set of GPIO lines. +* @param flags Replacement flags. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, + int flags) GPIOD_API; + +/** +* @brief Set the direction of a single GPIO line to input. +* @param line GPIO line object. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_direction_input(struct gpiod_line *line) GPIOD_API; + +/**
include/gpiod.h int gpiod_line_set_value(struct gpiod_line *line, int value) GPIOD_API; · line 1404
Quoted 10 lines
include/gpiod.h +10
-0+* @brief Set the direction of a set of GPIO lines to input. +* @param bulk Set of GPIO lines. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_direction_bulk_input(struct gpiod_line_bulk *bulk + ) GPIOD_API;
Please stick to the current convention of having "_bulk" at the end of the function name.
Quoted 32 lines
include/gpiod.h +24
-0+ +/** +* @brief Set the direction of a single GPIO line to output. +* @param line GPIO line object. +* @param value The logical value output on the line. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_direction_output(struct gpiod_line *line, + int value) GPIOD_API; + +/** +* @brief Set the direction of a set of GPIO lines to output. +* @param bulk Set of GPIO lines. +* @values The logical value to output for each line. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_direction_bulk_output(struct gpiod_line_bulk *bulk, + const int *values) GPIOD_API; +/** * @} * lib/core.c +0
-0
lib/core.c struct gpiod_line { · line 41
Quoted 7 lines
lib/core.c +3
-1@@ -36,10 +36,13 @@ struct gpiod_line {unsigned int offset;int direction;int active_state; -__u32 flags; +int output_value; +__u32 lflags; +__u32 cflags;
Ugh, these aren't very fortunate names - at first glance I have no idea what they mean. Either document those or change the names to something more obvious.
Quoted 228 lines
lib/core.c +124
-10int state;bool needs_update; +bool as_is;struct gpiod_chip *chip;struct line_fd_handle *fd_handle;@@ -359,11 +362,11 @@ int gpiod_line_active_state(struct gpiod_line *line)int gpiod_line_bias (struct gpiod_line *line) { -if (line->flags &GPIOLINE_FLAG_BIAS_DISABLE ) +if (line->lflags &GPIOLINE_FLAG_BIAS_DISABLE )return GPIOD_LINE_BIAS_DISABLE ; -if (line->flags &GPIOLINE_FLAG_BIAS_PULL_UP ) +if (line->lflags &GPIOLINE_FLAG_BIAS_PULL_UP )return GPIOD_LINE_BIAS_PULL_UP ; -if (line->flags &GPIOLINE_FLAG_BIAS_PULL_DOWN ) +if (line->lflags &GPIOLINE_FLAG_BIAS_PULL_DOWN )return GPIOD_LINE_BIAS_PULL_DOWN ;return GPIOD_LINE_BIAS_AS_IS ;@@ -371,17 +374,17 @@ int gpiod_line_bias(struct gpiod_line *line)bool gpiod_line_is_used (struct gpiod_line *line) { -return line->flags &GPIOLINE_FLAG_KERNEL ; +return line->lflags &GPIOLINE_FLAG_KERNEL ; }bool gpiod_line_is_open_drain (struct gpiod_line *line) { -return line->flags &GPIOLINE_FLAG_OPEN_DRAIN ; +return line->lflags &GPIOLINE_FLAG_OPEN_DRAIN ; }bool gpiod_line_is_open_source (struct gpiod_line *line) { -return line->flags &GPIOLINE_FLAG_OPEN_SOURCE ; +return line->lflags &GPIOLINE_FLAG_OPEN_SOURCE ; }bool gpiod_line_needs_update (struct gpiod_line *line)@@ -408,7 +411,7 @@ int gpiod_line_update(struct gpiod_line *line) ? GPIOD_LINE_ACTIVE_STATE_LOW :GPIOD_LINE_ACTIVE_STATE_HIGH ; - line->flags = info.flags; + line->lflags = info.flags;strncpy (line->name, info.name,sizeof (line->name));strncpy (line->consumer, info.consumer,sizeof (line->consumer));@@ -457,6 +460,20 @@ static bool line_bulk_all_requested(struct gpiod_line_bulk *bulk)return true; } +static bool line_bulk_all_requested_values (struct gpiod_line_bulk *bulk) +{ +struct gpiod_line *line, **lineptr; + + gpiod_line_bulk_foreach_line(bulk, line, lineptr) { +if (!gpiod_line_is_requested_values (line)) { + errno =EPERM ; +return false; + } + } + +return true; +} +static bool line_bulk_all_free (struct gpiod_line_bulk *bulk) {struct gpiod_line *line, **lineptr;@@ -471,6 +488,27 @@ static bool line_bulk_all_free(struct gpiod_line_bulk *bulk)return true; } +static bool line_request_direction_is_valid (int direction) +{ +if ((direction ==GPIOD_LINE_REQUEST_DIRECTION_AS_IS ) || + (direction ==GPIOD_LINE_REQUEST_DIRECTION_INPUT ) || + (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT )) +return true; + + errno =EINVAL ; +return false; +} + +static __u32 line_request_direction_to_gpio_handleflag (int direction) +{ +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_INPUT ) +return GPIOHANDLE_REQUEST_INPUT ; +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) +return GPIOHANDLE_REQUEST_OUTPUT ; + +return 0 ; +} +static __u32 line_request_flag_to_gpio_handleflag (int flags) {int hflags =0 ;@@ -495,7 +533,7 @@ static int line_request_values(struct gpiod_line_bulk *bulk,const struct gpiod_line_request_config *config, const int *default_vals) { - struct gpiod_line *line, **lineptr; + struct gpiod_line *line;struct line_fd_handle *line_fd;struct gpiohandle_request req;unsigned int i;@@ -524,7 +562,6 @@ static int line_request_values(struct gpiod_line_bulk *bulk,else if (config->request_type ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) req.flags |=GPIOHANDLE_REQUEST_OUTPUT ; - gpiod_line_bulk_foreach_line_off(bulk, line, i) { req.lineoffsets[i] =gpiod_line_offset (line); if (config->request_type ==@@ -548,8 +585,14 @@ static int line_request_values(struct gpiod_line_bulk *bulk,if (!line_fd)return -1 ; - gpiod_line_bulk_foreach_line(bulk, line, lineptr) { + gpiod_line_bulk_foreach_line_off(bulk, line, i) { line->state =LINE_REQUESTED_VALUES ; + line->cflags = config->flags; +if (config->request_type == +GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) + line->output_value = req.default_values[i]; +if (config->request_type ==GPIOD_LINE_REQUEST_DIRECTION_AS_IS ) + line->as_is = true;line_set_fd (line, line_fd);line_maybe_update (line); }@@ -590,6 +633,7 @@ static int line_request_event_single(struct gpiod_line *line,return -1 ; line->state =LINE_REQUESTED_EVENTS ; + line->cflags = config->flags;line_set_fd (line, line_fd);line_maybe_update (line);@@ -688,6 +732,11 @@ bool gpiod_line_is_requested(struct gpiod_line *line) line->state == LINE_REQUESTED_EVENTS); } +bool gpiod_line_is_requested_values (struct gpiod_line *line) +{ +return (line->state ==LINE_REQUESTED_VALUES ); +} +bool gpiod_line_is_free (struct gpiod_line *line) {return line->state ==LINE_FREE ;@@ -766,9 +815,134 @@ int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values)if (rv <0 )return -1 ; +gpiod_line_bulk_foreach_line_off (bulk, line, i) + line->output_value = data.values[i]; + +return 0 ; +} + +int gpiod_line_set_config (struct gpiod_line *line,int direction, +int flags,int value) +{ +struct gpiod_line_bulk bulk; + +gpiod_line_bulk_init (&bulk); +gpiod_line_bulk_add (&bulk, line); + +return gpiod_line_set_config_bulk (&bulk, direction, flags, &value); +} + +int gpiod_line_set_config_bulk (struct gpiod_line_bulk *bulk, +int direction,int flags, +const int *values) +{ +struct gpiohandle_config hcfg; +struct gpiod_line *line; +unsigned int i; +int rv, fd; +bool as_is; + +if (!line_bulk_same_chip (bulk) || + !line_bulk_all_requested_values (bulk)) +return -1 ; + +if (!line_request_direction_is_valid (direction)) +return -1 ; + +memset (&hcfg,0 ,sizeof (hcfg)); + + hcfg.flags =line_request_flag_to_gpio_handleflag (flags); + hcfg.flags |=line_request_direction_to_gpio_handleflag (direction); +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT && values) { +for (i =0 ; i <gpiod_line_bulk_num_lines (bulk); i++) + hcfg.default_values[i] = (uint8_t )!!values[i]; + } + + line =gpiod_line_bulk_get_line (bulk,0 ); + fd =line_get_fd (line); + + rv =ioctl (fd,GPIOHANDLE_SET_CONFIG_IOCTL , &hcfg); +if (rv <0 ) +return -1 ; + + as_is = line->as_is && direction ==GPIOD_LINE_REQUEST_DIRECTION_AS_IS ; + gpiod_line_bulk_foreach_line_off(bulk, line, i) { + line->cflags = flags; +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) + line->output_value = hcfg.default_values[i]; + line->as_is = as_is; +line_maybe_update (line); + }return 0 ; } +int gpiod_line_set_flags (struct gpiod_line *line,int flags) +{ +struct gpiod_line_bulk bulk; + +gpiod_line_bulk_init (&bulk); +gpiod_line_bulk_add (&bulk, line); + +return gpiod_line_set_flags_bulk (&bulk, flags); +}
lib/core.c int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) · line 897
Quoted 10 lines
lib/core.c +10
-0+ +int gpiod_line_set_flags_bulk (struct gpiod_line_bulk *bulk,int flags) +{ +struct gpiod_line *line; +int values[GPIOD_LINE_BULK_MAX_LINES ]; +unsigned int i; +int direction; + + line =gpiod_line_bulk_get_line (bulk,0 ); +if (line->as_is) {
Can you explain the purpose of this as_is field? I'm not sure this is really needed.
Bart
Quoted 54 lines
lib/core.c +48
-1+ errno =EPERM ; +return -1 ; + } +if (line->direction ==GPIOD_LINE_DIRECTION_OUTPUT ) { + gpiod_line_bulk_foreach_line_off(bulk, line, i) { + values[i] = line->output_value; + } + direction =GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ; + }else + direction =GPIOD_LINE_REQUEST_DIRECTION_INPUT ; + +return gpiod_line_set_config_bulk (bulk, direction, + flags, values); +} + +int gpiod_line_set_direction_input (struct gpiod_line *line) +{ +return gpiod_line_set_config (line,GPIOD_LINE_REQUEST_DIRECTION_INPUT , + line->cflags,0 ); +} + +int gpiod_line_set_direction_bulk_input (struct gpiod_line_bulk *bulk) +{ +struct gpiod_line *line; + + line =gpiod_line_bulk_get_line (bulk,0 ); +return gpiod_line_set_config_bulk (bulk, +GPIOD_LINE_REQUEST_DIRECTION_INPUT , + line->cflags,NULL ); +} + +int gpiod_line_set_direction_output (struct gpiod_line *line,int value) +{ +return gpiod_line_set_config (line,GPIOD_LINE_REQUEST_DIRECTION_OUTPUT , + line->cflags, value); +} + +int gpiod_line_set_direction_bulk_output (struct gpiod_line_bulk *bulk, +const int *values) +{ +struct gpiod_line *line; + + line =gpiod_line_bulk_get_line (bulk,0 ); +return gpiod_line_set_config_bulk (bulk, +GPIOD_LINE_REQUEST_DIRECTION_OUTPUT , + line->cflags, values); +} +int gpiod_line_event_wait (struct gpiod_line *line,const struct timespec *timeout) { --2.24.0
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 124 lines · Bartosz Golaszewski
pt., 15 lis 2019 o 15:45 Kent Gibson <[email protected]> napisał(a):
Quoted 24 lines
Extend the libgpiod API to support the setting line configuration using the GPIO
GPIOHANDLE_SET_CONFIG_IOCTLuAPI ioctl.The core change is the addition of
gpiod_line_set_config, which provides a low level wrapper around the ioctl.Additionally, higher level helper functions,
gpiod_line_set_flags,gpiod_line_set_direction_input, andgpiod_line_set_direction_outputprovide slightly simplified APIs for common use cases.Bulk forms of all functions are also provided.
Signed-off-by Kent Gibson <[email protected]>--- include/gpiod.h | 115 ++++++++++++++++++++++++++++ lib/core.c | 196 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 300 insertions(+), 11 deletions(-)include/gpiod.h +0
-0include/gpiod.h void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) GPIOD_API; · line 1259
Quoted 8 lines
include/gpiod.h +5
-0@@ -1252,6 +1252,14 @@ void gpiod_line_release_bulk(struct gpiod_line_bulk *bulk) GPIOD_API;*/ bool gpiod_line_is_requested(struct gpiod_line *line) GPIOD_API; +/** +* @brief Check if the calling user has ownership of this line for values, +* not events. +* @param line GPIO line object. +* @return True if given line was requested, false otherwise. I'd clarify: "requested for reading/setting values".
Quoted 88 lines
include/gpiod.h +81
-0+*/ +bool gpiod_line_is_requested_values(struct gpiod_line *line) GPIOD_API; +/** * @brief Check if the calling user has neither requested ownership of this * line nor configured any event notifications. @@ -1311,6 +1319,113 @@ int gpiod_line_set_value(struct gpiod_line *line, int value) GPIOD_API; int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) GPIOD_API; +/** +* @} +* +* @defgroup __line_config__ Setting line configuration +* @{ +*/ + +/** +* @brief Update the configuration of a single GPIO line. +* @param line GPIO line object. +* @param direction Updated direction which may be one of +* GPIOD_LINE_REQUEST_DIRECTION_AS_IS, GPIOD_LINE_REQUEST_DIRECTION_INPUT, +* or GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @param flags Replacement flags. +* @param value The new output value for the line when direction is +* GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_config(struct gpiod_line *line, int direction, + int flags, int value) GPIOD_API; + +/** +* @brief Update the configuration of a set of GPIO lines. +* @param bulk Set of GPIO lines. +* @param direction Updated direction which may be one of +* GPIOD_LINE_REQUEST_DIRECTION_AS_IS, GPIOD_LINE_REQUEST_DIRECTION_INPUT, +* or GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @param flags Replacement flags. +* @param values An array holding line_bulk->num_lines new logical values +* for lines when direction is GPIOD_LINE_REQUEST_DIRECTION_OUTPUT. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_config_bulk(struct gpiod_line_bulk *bulk, + int direction, int flags, + const int *values) GPIOD_API; + + +/** +* @brief Update the configuration flags of a single GPIO line. +* @param line GPIO line object. +* @param flags Replacement flags. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_flags(struct gpiod_line *line, int flags) GPIOD_API; + +/** +* @brief Update the configuration flags of a set of GPIO lines. +* @param bulk Set of GPIO lines. +* @param flags Replacement flags. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, + int flags) GPIOD_API; + +/** +* @brief Set the direction of a single GPIO line to input. +* @param line GPIO line object. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_direction_input(struct gpiod_line *line) GPIOD_API; + +/** +* @brief Set the direction of a set of GPIO lines to input. +* @param bulk Set of GPIO lines. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*
Quoted 9 lines
include/gpiod.h int gpiod_line_set_value(struct gpiod_line *line, int value) GPIOD_API; · line 1404
Quoted 5 lines
include/gpiod.h +5
-0+* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_direction_bulk_input(struct gpiod_line_bulk *bulk + ) GPIOD_API;Please stick to the current convention of having "
_bulk" at the end of the function name.
That would be clearer. Not sure why I went with those names - maybe taking the lead from gpiod_line_request_bulk_falling_edge_events_flags? Maybe I originally had a core set_direction function, and these were to be wrappers around that?
Anyway - will change it.
Quoted 35 lines
Quoted 35 lines
include/gpiod.h +24
-0+ +/** +* @brief Set the direction of a single GPIO line to output. +* @param line GPIO line object. +* @param value The logical value output on the line. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +*/ +int gpiod_line_set_direction_output(struct gpiod_line *line, + int value) GPIOD_API; + +/** +* @brief Set the direction of a set of GPIO lines to output. +* @param bulk Set of GPIO lines. +* @values The logical value to output for each line. +* @return 0 is the operation succeeds. In case of an error this routine +* returns -1 and sets the last error number. +* +* If the lines were not previously requested together, the behavior is +* undefined. +*/ +int gpiod_line_set_direction_bulk_output(struct gpiod_line_bulk *bulk, + const int *values) GPIOD_API; +/** * @} * lib/core.c +0
-0@@ -36,10 +36,13 @@ struct gpiod_line {unsigned int offset;int direction;int active_state;
Quoted 9 lines
lib/core.c struct gpiod_line { · line 41
Quoted 4 lines
lib/core.c +3
-1-__u32 flags; +int output_value; +__u32 lflags; +__u32 cflags;Ugh, these aren't very fortunate names - at first glance I have no idea what they mean. Either document those or change the names to something more obvious.
Yeah - not the best - lflags are line_flags (those returned by LINEINFO_IOCTL) and cflags is config_flags (those set in the initial line request). So maybe rename lflags to line_flags or info_flags, and rename cflags to handle_flags or req_flags?
And add some documentation as well.
Quoted 233 lines
Quoted 233 lines
lib/core.c +129
-10int state;bool needs_update; +bool as_is;struct gpiod_chip *chip;struct line_fd_handle *fd_handle;@@ -359,11 +362,11 @@ int gpiod_line_active_state(struct gpiod_line *line)int gpiod_line_bias (struct gpiod_line *line) { -if (line->flags &GPIOLINE_FLAG_BIAS_DISABLE ) +if (line->lflags &GPIOLINE_FLAG_BIAS_DISABLE )return GPIOD_LINE_BIAS_DISABLE ; -if (line->flags &GPIOLINE_FLAG_BIAS_PULL_UP ) +if (line->lflags &GPIOLINE_FLAG_BIAS_PULL_UP )return GPIOD_LINE_BIAS_PULL_UP ; -if (line->flags &GPIOLINE_FLAG_BIAS_PULL_DOWN ) +if (line->lflags &GPIOLINE_FLAG_BIAS_PULL_DOWN )return GPIOD_LINE_BIAS_PULL_DOWN ;return GPIOD_LINE_BIAS_AS_IS ;@@ -371,17 +374,17 @@ int gpiod_line_bias(struct gpiod_line *line)bool gpiod_line_is_used (struct gpiod_line *line) { -return line->flags &GPIOLINE_FLAG_KERNEL ; +return line->lflags &GPIOLINE_FLAG_KERNEL ; }bool gpiod_line_is_open_drain (struct gpiod_line *line) { -return line->flags &GPIOLINE_FLAG_OPEN_DRAIN ; +return line->lflags &GPIOLINE_FLAG_OPEN_DRAIN ; }bool gpiod_line_is_open_source (struct gpiod_line *line) { -return line->flags &GPIOLINE_FLAG_OPEN_SOURCE ; +return line->lflags &GPIOLINE_FLAG_OPEN_SOURCE ; }bool gpiod_line_needs_update (struct gpiod_line *line)@@ -408,7 +411,7 @@ int gpiod_line_update(struct gpiod_line *line) ? GPIOD_LINE_ACTIVE_STATE_LOW :GPIOD_LINE_ACTIVE_STATE_HIGH ; - line->flags = info.flags; + line->lflags = info.flags;strncpy (line->name, info.name,sizeof (line->name));strncpy (line->consumer, info.consumer,sizeof (line->consumer));@@ -457,6 +460,20 @@ static bool line_bulk_all_requested(struct gpiod_line_bulk *bulk)return true; } +static bool line_bulk_all_requested_values (struct gpiod_line_bulk *bulk) +{ +struct gpiod_line *line, **lineptr; + + gpiod_line_bulk_foreach_line(bulk, line, lineptr) { +if (!gpiod_line_is_requested_values (line)) { + errno =EPERM ; +return false; + } + } + +return true; +} +static bool line_bulk_all_free (struct gpiod_line_bulk *bulk) {struct gpiod_line *line, **lineptr;@@ -471,6 +488,27 @@ static bool line_bulk_all_free(struct gpiod_line_bulk *bulk)return true; } +static bool line_request_direction_is_valid (int direction) +{ +if ((direction ==GPIOD_LINE_REQUEST_DIRECTION_AS_IS ) || + (direction ==GPIOD_LINE_REQUEST_DIRECTION_INPUT ) || + (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT )) +return true; + + errno =EINVAL ; +return false; +} + +static __u32 line_request_direction_to_gpio_handleflag (int direction) +{ +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_INPUT ) +return GPIOHANDLE_REQUEST_INPUT ; +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) +return GPIOHANDLE_REQUEST_OUTPUT ; + +return 0 ; +} +static __u32 line_request_flag_to_gpio_handleflag (int flags) {int hflags =0 ;@@ -495,7 +533,7 @@ static int line_request_values(struct gpiod_line_bulk *bulk,const struct gpiod_line_request_config *config, const int *default_vals) { - struct gpiod_line *line, **lineptr; + struct gpiod_line *line;struct line_fd_handle *line_fd;struct gpiohandle_request req;unsigned int i;@@ -524,7 +562,6 @@ static int line_request_values(struct gpiod_line_bulk *bulk,else if (config->request_type ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) req.flags |=GPIOHANDLE_REQUEST_OUTPUT ; - gpiod_line_bulk_foreach_line_off(bulk, line, i) { req.lineoffsets[i] =gpiod_line_offset (line); if (config->request_type ==@@ -548,8 +585,14 @@ static int line_request_values(struct gpiod_line_bulk *bulk,if (!line_fd)return -1 ; - gpiod_line_bulk_foreach_line(bulk, line, lineptr) { + gpiod_line_bulk_foreach_line_off(bulk, line, i) { line->state =LINE_REQUESTED_VALUES ; + line->cflags = config->flags; +if (config->request_type == +GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) + line->output_value = req.default_values[i]; +if (config->request_type ==GPIOD_LINE_REQUEST_DIRECTION_AS_IS ) + line->as_is = true;line_set_fd (line, line_fd);line_maybe_update (line); }@@ -590,6 +633,7 @@ static int line_request_event_single(struct gpiod_line *line,return -1 ; line->state =LINE_REQUESTED_EVENTS ; + line->cflags = config->flags;line_set_fd (line, line_fd);line_maybe_update (line);@@ -688,6 +732,11 @@ bool gpiod_line_is_requested(struct gpiod_line *line) line->state == LINE_REQUESTED_EVENTS); } +bool gpiod_line_is_requested_values (struct gpiod_line *line) +{ +return (line->state ==LINE_REQUESTED_VALUES ); +} +bool gpiod_line_is_free (struct gpiod_line *line) {return line->state ==LINE_FREE ;@@ -766,9 +815,134 @@ int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values)if (rv <0 )return -1 ; +gpiod_line_bulk_foreach_line_off (bulk, line, i) + line->output_value = data.values[i]; + +return 0 ; +} + +int gpiod_line_set_config (struct gpiod_line *line,int direction, +int flags,int value) +{ +struct gpiod_line_bulk bulk; + +gpiod_line_bulk_init (&bulk); +gpiod_line_bulk_add (&bulk, line); + +return gpiod_line_set_config_bulk (&bulk, direction, flags, &value); +} + +int gpiod_line_set_config_bulk (struct gpiod_line_bulk *bulk, +int direction,int flags, +const int *values) +{ +struct gpiohandle_config hcfg; +struct gpiod_line *line; +unsigned int i; +int rv, fd; +bool as_is; + +if (!line_bulk_same_chip (bulk) || + !line_bulk_all_requested_values (bulk)) +return -1 ; + +if (!line_request_direction_is_valid (direction)) +return -1 ; + +memset (&hcfg,0 ,sizeof (hcfg)); + + hcfg.flags =line_request_flag_to_gpio_handleflag (flags); + hcfg.flags |=line_request_direction_to_gpio_handleflag (direction); +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT && values) { +for (i =0 ; i <gpiod_line_bulk_num_lines (bulk); i++) + hcfg.default_values[i] = (uint8_t )!!values[i]; + } + + line =gpiod_line_bulk_get_line (bulk,0 ); + fd =line_get_fd (line); + + rv =ioctl (fd,GPIOHANDLE_SET_CONFIG_IOCTL , &hcfg); +if (rv <0 ) +return -1 ; + + as_is = line->as_is && direction ==GPIOD_LINE_REQUEST_DIRECTION_AS_IS ; + gpiod_line_bulk_foreach_line_off(bulk, line, i) { + line->cflags = flags; +if (direction ==GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ) + line->output_value = hcfg.default_values[i]; + line->as_is = as_is; +line_maybe_update (line); + }return 0 ; } +int gpiod_line_set_flags (struct gpiod_line *line,int flags) +{ +struct gpiod_line_bulk bulk; + +gpiod_line_bulk_init (&bulk); +gpiod_line_bulk_add (&bulk, line); + +return gpiod_line_set_flags_bulk (&bulk, flags); +} + +int gpiod_line_set_flags_bulk (struct gpiod_line_bulk *bulk,int flags) +{ +struct gpiod_line *line; +int values[GPIOD_LINE_BULK_MAX_LINES ];
Quoted 9 lines
lib/core.c int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) · line 897
Quoted 5 lines
lib/core.c +5
-0+unsigned int i; +int direction; + + line =gpiod_line_bulk_get_line (bulk,0 ); +if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.
It is there for gpiod_set_flags, which has to populate the direction flags in the SET_CONFIG ioctl. The existing line->direction is either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.
Happy to entertain alternatives...
Cheers,
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 16 lines · Kent Gibson
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
lib/core.c +5
-0+ +int gpiod_line_set_flags_bulk (struct gpiod_line_bulk *bulk,int flags) +{ +struct gpiod_line *line; +int values[GPIOD_LINE_BULK_MAX_LINES ];Quoted 9 lines
lib/core.c int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) · line 897
Quoted 5 lines
lib/core.c +5
-0+unsigned int i; +int direction; + + line =gpiod_line_bulk_get_line (bulk,0 ); +if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.
Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.
Hmmm, I think I see what you were getting at - the line->direction is the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??
If that is the case then the line->as_is can be dropped throughout.
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
lib/core.c +5
-0+ +int gpiod_line_set_flags_bulk (struct gpiod_line_bulk *bulk,int flags) +{ +struct gpiod_line *line; +int values[GPIOD_LINE_BULK_MAX_LINES ];Quoted 9 lines
lib/core.c int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) · line 897
Quoted 5 lines
lib/core.c +5
-0+unsigned int i; +int direction; + + line =gpiod_line_bulk_get_line (bulk,0 ); +if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.
Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Bart
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 32 lines · Bartosz Golaszewski
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 31 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
lib/core.c +5
-0+ +int gpiod_line_set_flags_bulk (struct gpiod_line_bulk *bulk,int flags) +{ +struct gpiod_line *line; +int values[GPIOD_LINE_BULK_MAX_LINES ];Quoted 9 lines
lib/core.c int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) · line 897
Quoted 5 lines
lib/core.c +5
-0+unsigned int i; +int direction; + + line =gpiod_line_bulk_get_line (bulk,0 ); +if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??
Quoted 8 lines
Quoted 4 lines
If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
So fail if needs_update?
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 39 lines · Bartosz Golaszewski
Quoted 37 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 35 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
lib/core.c +5
-0+ +int gpiod_line_set_flags_bulk (struct gpiod_line_bulk *bulk,int flags) +{ +struct gpiod_line *line; +int values[GPIOD_LINE_BULK_MAX_LINES ];Quoted 9 lines
lib/core.c int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values) · line 897
Quoted 5 lines
lib/core.c +5
-0+unsigned int i; +int direction; + + line =gpiod_line_bulk_get_line (bulk,0 ); +if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Quoted 7 lines
Quoted 3 lines
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
Bart
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 44 lines · Bartosz Golaszewski
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags) +{ + struct gpiod_line *line; + int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ unsigned int i; + int direction; + + line = gpiod_line_bulk_get_line(bulk, 0); + if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So gpiod_line_update if needs_update, and fail if that fails?
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 48 lines · Bartosz Golaszewski
Quoted 46 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 45 lines · Bartosz Golaszewski
Quoted 32 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 31 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags) +{ + struct gpiod_line *line; + int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ unsigned int i; + int direction; + + line = gpiod_line_bulk_get_line(bulk, 0); + if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??Quoted 8 lines
Quoted 4 lines
If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
So fail if
needs_update?
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Without the if - needs_update is only set if an implicit update fails in line_maybe_update(). But in this case we need to be sure, so do it unconditionally.
Bart
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 54 lines · Bartosz Golaszewski
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 53 lines · Bartosz Golaszewski
Quoted 50 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 39 lines · Bartosz Golaszewski
Quoted 37 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 35 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags) +{ + struct gpiod_line *line; + int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ unsigned int i; + int direction; + + line = gpiod_line_bulk_get_line(bulk, 0); + if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Quoted 7 lines
Quoted 3 lines
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
Quoted 8 lines
Quoted 3 lines
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.
Given that line_maybe_update is called at the end of request creation, and whenever set_config is called, how can line->direction be inconsistent with the kernel state - as long as needs_update is false?
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags) +{ + struct gpiod_line *line; + int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ unsigned int i; + int direction; + + line = gpiod_line_bulk_get_line(bulk, 0); + if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?
I don't think we should call line_maybe_update() on set_config() - in this case we should call gpiod_line_update() and fail in set_config() if it fails.
I hope that's clearer.
Bart
Quoted 1 line
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 71 lines · Bartosz Golaszewski
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags) +{ + struct gpiod_line *line; + int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ unsigned int i; + int direction; + + line = gpiod_line_bulk_get_line(bulk, 0); + if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?
Quoted 6 lines
I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.I hope that's clearer.
Not really. I was already shaky on the needs_update and I'm getting more confused about the overall needs_update handling policy by the minute.
Perhaps it will be more productive to go to the code. I'll send out what I have as v2 and we can go from there.
Cheers,
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
(quoted diff) +5
-0+ +int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags) +{ + struct gpiod_line *line; + int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ unsigned int i; + int direction; + + line = gpiod_line_bulk_get_line(bulk, 0); + if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.
Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another ioctl() that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.
I then thought that nobody is requesting this yet and so it may be overkill.
Bart
Quoted 5 lines
Perhaps it will be more productive to go to the code. I'll send out what I have as v2 and we can go from there.
Cheers,
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 85 lines · Bartosz Golaszewski
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 5 lines
Quoted 5 lines
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];Quoted 9 lines
Quoted 5 lines
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this
as_isfield? I'm not sure this is really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.
Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Kent.
Quoted 9 lines
I then thought that nobody is requesting this yet and so it may be overkill.
Bart
Quoted 5 lines
Perhaps it will be more productive to go to the code. I'll send out what I have as v2 and we can go from there.
Cheers,
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 16 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
Quoted 14 lines
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.Quoted 8 lines
It is there for
gpiod_set_flags, which has to populate the direction flags in theSET_CONFIGioctl. The existingline->directionis either input or output. It is drawn fromGPIOLINE_FLAG_IS_OUT, so as-is is gets mapped to input.
I didn't want to change the existingline->direction, and adding the as-is seemed clearer than adding another flavour of direction that contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.
Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo ioctl() but returning an fd notifying about changes. Maybe we could even consider having lineinfo2 ioctl() which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.
Bart
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 103 lines · Bartosz Golaszewski
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 27 lines · Kent Gibson
Quoted 24 lines
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Quoted 8 lines
Hmmm, I think I see what you were getting at - the
line->directionis the direction from the kernel, so it doesn't hurt to use that value to set the corresponding request flags - even if the original request was as-is??If that is the case then the
line->as_iscan be dropped throughout.Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when needs_update gets set in line_maybe_update(). Hardware being unplugged?
Cheers,
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
Quoted 35 lines · Kent Gibson
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value from the kernel is up-to-date.
Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.
Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.
Quoted 4 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?
If the ioctl() can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.
Bart
Quoted 2 lines
Cheers,
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 123 lines · Bartosz Golaszewski
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
Quoted 40 lines
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.Quoted 6 lines
Quoted 3 lines
So fail if
needs_update?Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon. The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.
Quoted 10 lines
Quoted 4 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting needs_update? Or are there less catastrohpic failure modes?
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 11:18 Kent Gibson <[email protected]> napisał(a):
Quoted 133 lines · Bartosz Golaszewski
Quoted 123 lines
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 44 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
Quoted 43 lines · Bartosz Golaszewski
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):
On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.Quoted 6 lines
Quoted 3 lines
So fail if needs_update?
Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.
Quoted 3 lines
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon.
No, I don't think requesting the line should be obligatory. In my WiP dbus daemon, I expose line info for all lines in the system by reading LINEINFO for each one. Then - for unrequested lines - every time the client asks for any line info again - I call gpiod_line_update() before responding. This could be optimized by this lineinfo fd feature.
I don't want to force the user-space to choose between using a single central daemon or dealing with lines separately.
Quoted 5 lines
The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.
In other words: yes.
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.
Quoted 4 lines
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting
needs_update? Or are there less catastrohpic failure modes?
What if the disconnect happens after the request but before the update? It's super unlikely, but again: the lineinfo ioctl() can fail, so we need to check the return value. We also can't update line info before requesting the line as it's racy - someone can change the state between the update and the request.
(I hope I'm getting this right :))
Bart
Quoted 1 line
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 11:27 Bartosz Golaszewski <[email protected]> napisał(a):
Quoted 149 lines
czw., 21 lis 2019 o 11:18 Kent Gibson <[email protected]> napisał(a):
Quoted 133 lines · Bartosz Golaszewski
Quoted 123 lines
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 50 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
On Wed, Nov 20, 2019 at 12:00:45PM +0100, Bartosz Golaszewski wrote:
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.So fail if needs_update?
Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.Quoted 3 lines
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon.No, I don't think requesting the line should be obligatory. In my WiP dbus daemon, I expose line info for all lines in the system by reading LINEINFO for each one. Then - for unrequested lines - every time the client asks for any line info again - I call
gpiod_line_update()before responding. This could be optimized by this lineinfo fd feature.I don't want to force the user-space to choose between using a single central daemon or dealing with lines separately.
Quoted 8 lines
Quoted 5 lines
The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.In other words: yes.
Just to be clear: I mean line info - not values or events. By monitoring I mean: be notified about changes to the line properties without requesting it.
As for implementation: I imagine an ioctl() called LINEINFO_FD that would return an open file descriptor on which read events would arrive when the line properties change and then we could call regular line info ioctl() to actually re-read it. Does that make sense? I can try to prepare an example implementation.
Bart
Quoted 28 lines
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.Quoted 4 lines
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting
needs_update? Or are there less catastrohpic failure modes?What if the disconnect happens after the request but before the update? It's super unlikely, but again: the lineinfo
ioctl()can fail, so we need to check the return value. We also can't update line info before requesting the line as it's racy - someone can change the state between the update and the request.(I hope I'm getting this right :))
Bart
Quoted 1 line
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
Quoted 163 lines · Bartosz Golaszewski
czw., 21 lis 2019 o 11:27 Bartosz Golaszewski <[email protected]> napisał(a):
Quoted 149 lines
czw., 21 lis 2019 o 11:18 Kent Gibson <[email protected]> napisał(a):
Quoted 133 lines · Bartosz Golaszewski
Quoted 123 lines
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
On Wed, Nov 20, 2019 at 12:00:45PM +0100, Bartosz Golaszewski wrote:
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.So fail if needs_update?
Kent.
I'd say: do an implicit update before setting config.
So gpiod_line_update if needs_update, and fail if that fails?
Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.Quoted 3 lines
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon.No, I don't think requesting the line should be obligatory. In my WiP dbus daemon, I expose line info for all lines in the system by reading LINEINFO for each one. Then - for unrequested lines - every time the client asks for any line info again - I call
gpiod_line_update()before responding. This could be optimized by this lineinfo fd feature.I don't want to force the user-space to choose between using a single central daemon or dealing with lines separately.
Quoted 8 lines
Quoted 5 lines
The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.In other words: yes.
Just to be clear: I mean line info - not values or events. By monitoring I mean: be notified about changes to the line properties without requesting it.
Quoted 6 lines
As for implementation: I imagine an
ioctl()calledLINEINFO_FDthat would return an open file descriptor on which read events would arrive when the line properties change and then we could call regular line infoioctl()to actually re-read it. Does that make sense? I can try to prepare an example implementation.
Ah, ok. So you might want to send a dbus message when someone requests a line, or changes direction or whatever, but not have the monitoring daemon involved in the line control. And not have the daemon polling the LINEINFO ioctl.
Sounds reasonable.
Now, how did we get here?? ;-).
Kent.
Quoted 30 lines
Bart
Quoted 28 lines
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.Quoted 4 lines
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting
needs_update? Or are there less catastrohpic failure modes?What if the disconnect happens after the request but before the update? It's super unlikely, but again: the lineinfo
ioctl()can fail, so we need to check the return value. We also can't update line info before requesting the line as it's racy - someone can change the state between the update and the request.(I hope I'm getting this right :))
Bart
Quoted 1 line
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 12:07 Kent Gibson <[email protected]> napisał(a):
Quoted 172 lines · Bartosz Golaszewski
Quoted 163 lines
czw., 21 lis 2019 o 11:27 Bartosz Golaszewski <[email protected]> napisał(a):
Quoted 149 lines
czw., 21 lis 2019 o 11:18 Kent Gibson <[email protected]> napisał(a):
Quoted 133 lines · Bartosz Golaszewski
Quoted 123 lines
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
On Wed, Nov 20, 2019 at 03:08:57PM +0100, Bartosz Golaszewski wrote:
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):On Wed, Nov 20, 2019 at 12:00:45PM +0100, Bartosz Golaszewski wrote:
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.So fail if needs_update?
Kent.
I'd say: do an implicit update before setting config.
So gpiod_line_update if needs_update, and fail if that fails?
Kent.
Quoted 9 lines
Quoted 4 lines
Without the if - needs_update is only set if an implicit update fails
in line_maybe_update(). But in this case we need to be sure, so do it
unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.Quoted 3 lines
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon.No, I don't think requesting the line should be obligatory. In my WiP dbus daemon, I expose line info for all lines in the system by reading LINEINFO for each one. Then - for unrequested lines - every time the client asks for any line info again - I call
gpiod_line_update()before responding. This could be optimized by this lineinfo fd feature.I don't want to force the user-space to choose between using a single central daemon or dealing with lines separately.
Quoted 8 lines
Quoted 5 lines
The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.In other words: yes.
Just to be clear: I mean line info - not values or events. By monitoring I mean: be notified about changes to the line properties without requesting it.
Quoted 6 lines
As for implementation: I imagine an
ioctl()calledLINEINFO_FDthat would return an open file descriptor on which read events would arrive when the line properties change and then we could call regular line infoioctl()to actually re-read it. Does that make sense? I can try to prepare an example implementation.
Quoted 7 lines
Ah, ok. So you might want to send a dbus message when someone requests a line, or changes direction or whatever, but not have the monitoring daemon involved in the line control. And not have the daemon polling the LINEINFO ioctl.
Sounds reasonable.
That would be great, yes.
Quoted 2 lines
Now, how did we get here?? ;-).
I'm actually happy you're doing this. You're making me think about issues I never noticed. It's always great to have someone go through your code. Thanks!
Bart
Quoted 32 lines
Kent.
Quoted 30 lines
Bart
Quoted 28 lines
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.Quoted 4 lines
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting
needs_update? Or are there less catastrohpic failure modes?What if the disconnect happens after the request but before the update? It's super unlikely, but again: the lineinfo
ioctl()can fail, so we need to check the return value. We also can't update line info before requesting the line as it's racy - someone can change the state between the update and the request.(I hope I'm getting this right :))
Bart
Quoted 1 line
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
In reply to Bartosz GolaszewskiQuoted 173 lines · Bartosz Golaszewski
czw., 21 lis 2019 o 11:18 Kent Gibson <[email protected]> napisał(a):
Quoted 133 lines · Bartosz Golaszewski
Quoted 123 lines
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
Quoted 50 lines
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
On Wed, Nov 20, 2019 at 12:00:45PM +0100, Bartosz Golaszewski wrote:
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.So fail if needs_update?
Kent.
I'd say: do an implicit update before setting config.
So
gpiod_line_updateifneeds_update, and fail if that fails?Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.Quoted 3 lines
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon.No, I don't think requesting the line should be obligatory. In my WiP dbus daemon, I expose line info for all lines in the system by reading LINEINFO for each one. Then - for unrequested lines - every time the client asks for any line info again - I call
gpiod_line_update()before responding. This could be optimized by this lineinfo fd feature.I don't want to force the user-space to choose between using a single central daemon or dealing with lines separately.
Quoted 5 lines
The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.In other words: yes.
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.Quoted 4 lines
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting
needs_update? Or are there less catastrohpic failure modes?
Quoted 8 lines
What if the disconnect happens after the request but before the update? It's super unlikely, but again: the lineinfo
ioctl()can fail, so we need to check the return value. We also can't update line info before requesting the line as it's racy - someone can change the state between the update and the request.(I hope I'm getting this right :))
I understand that the disconnect can occur between the request ioctl and the info ioctl, but both of those are called within line_request_values(), which implements the core of gpiod_line_request_bulk(), so the opportunity exists to propagate the info failure back as part of the request, but instead the error is absorbed and needs_update is set. This puts the onus on the caller to always check gpiod_line_needs_update() between requesting a line and calling any of the state accessors - else they may be returning garbage.
Similarly the event case in line_request_event_single().
I was wondering what the reasoning was for this approach?
Kent.
Re: [libgpiod] [PATCH 11/19] API: add support for SET_CONFIG
czw., 21 lis 2019 o 11:59 Kent Gibson <[email protected]> napisał(a):
Quoted 193 lines · Bartosz Golaszewski
Quoted 173 lines
czw., 21 lis 2019 o 11:18 Kent Gibson <[email protected]> napisał(a):
Quoted 133 lines · Bartosz Golaszewski
Quoted 123 lines
czw., 21 lis 2019 o 10:30 Kent Gibson <[email protected]> napisał(a):
Quoted 113 lines · Bartosz Golaszewski
Quoted 103 lines
czw., 21 lis 2019 o 08:46 Kent Gibson <[email protected]> napisał(a):
Quoted 96 lines · Bartosz Golaszewski
Quoted 85 lines
czw., 21 lis 2019 o 01:34 Kent Gibson <[email protected]> napisał(a):
Quoted 77 lines · Bartosz Golaszewski
Quoted 75 lines
śr., 20 lis 2019 o 15:36 Kent Gibson <[email protected]> napisał(a):
Quoted 60 lines · Bartosz Golaszewski
Quoted 58 lines
śr., 20 lis 2019 o 15:13 Kent Gibson <[email protected]> napisał(a):
Quoted 56 lines · Bartosz Golaszewski
śr., 20 lis 2019 o 14:59 Kent Gibson <[email protected]> napisał(a):
On Wed, Nov 20, 2019 at 12:00:45PM +0100, Bartosz Golaszewski wrote:
wt., 19 lis 2019 o 16:53 Kent Gibson <[email protected]> napisał(a):On Mon, Nov 18, 2019 at 10:48:25PM +0800, Kent Gibson wrote:
On Mon, Nov 18, 2019 at 02:52:04PM +0100, Bartosz Golaszewski
+
+int gpiod_line_set_flags_bulk(struct gpiod_line_bulk *bulk, int flags)
+{
+ struct gpiod_line *line;
+ int values[GPIOD_LINE_BULK_MAX_LINES];
+ unsigned int i;
+ int direction;
+
+ line = gpiod_line_bulk_get_line(bulk, 0);
+ if (line->as_is) {Can you explain the purpose of this as_is field? I'm not sure this is
really needed.It is there for gpiod_set_flags, which has to populate the direction
flags in the SET_CONFIG ioctl. The existing line->direction is
either input or output. It is drawn from GPIOLINE_FLAG_IS_OUT, so
as-is is gets mapped to input.
I didn't want to change the existing line->direction, and adding the
as-is seemed clearer than adding another flavour of direction that
contained all three.Hmmm, I think I see what you were getting at - the line->direction is the
direction from the kernel, so it doesn't hurt to use that value to set the
corresponding request flags - even if the original request was as-is??If that is the case then the line->as_is can be dropped throughout.
Kent.
Yes, this is what I was thinking. Just need to make sure the value
from the kernel is up-to-date.So fail if needs_update?
Kent.
I'd say: do an implicit update before setting config.
So gpiod_line_update if needs_update, and fail if that fails?
Kent.
Quoted 9 lines
Quoted 4 lines
Without the if -
needs_updateis only set if an implicit update fails inline_maybe_update(). But in this case we need to be sure, so do it unconditionally.Given that
line_maybe_updateis called at the end of request creation, and wheneverset_configis called, how canline->directionbe inconsistent with the kernel state - as long asneeds_updateis false?I don't think we should call
line_maybe_update()onset_config()- in this case we should callgpiod_line_update()and fail inset_config()if it fails.Quoted 6 lines
Quoted 2 lines
I hope that's clearer.
Not really. I was already shaky on the
needs_updateand I'm getting more confused about the overallneeds_updatehandling policy by the minute.Quoted 8 lines
Yeah it's not optimal. If you have better ideas on how to handle the fact that the kernel can't really notify us about the changes in line's flags introduced by other processes - I'll be more than glad to give them a try. At some point I was thinking about another
ioctl()that - for a requested line - would return a file descriptor which would emit events when a line changes - for instance, it's requested by someone else or its direction is changed etc.Quoted 5 lines
I didn't realise it was possible for a requested line's flags to be changed by other processes. Quite the opposite - I thought that was one of the reasons for GPIOD was to allow the userspace to prevent other from processes messing with requested lines.
Quoted 7 lines
Ugh, sorry, was writing it before coffee. I was thinking about a non-requested line. Something like lineinfo
ioctl()but returning an fd notifying about changes. Maybe we could even consider having lineinfo2ioctl()which would be extended with this functionality - not only would it fill the relevant structure but also pass a new fd for notification about changes.Quoted 8 lines
Whew - that makes more sense. Had me worried there.
Not sure how useful an async info ioctl would be. Couldn't you build something equivalent in userspace with the existing API - as long as you don't mind the daemon holding the line, and so having to control the line via the daemon. You want to be able to monitor without requesting the line?
Quoted 7 lines
I'm not sure if I was expressing myself clearly enough: a hypothetical daemon calls LINEINFO
ioctl(). Now a different program or kernel driver requests this line. The daemon is not up-to-date on its state unless it polls the line all the time. If a user now asks the daemon about this line's state - it will be given outdated info. Listening on this fd would allow us to be informed about such changes immediately.Quoted 3 lines
I think I understand you - but you might not be getting my meaning... I was thinking the daemon would request the lines it wanted to monitor
- which is why you would then have to control the line via the daemon.No, I don't think requesting the line should be obligatory. In my WiP dbus daemon, I expose line info for all lines in the system by reading LINEINFO for each one. Then - for unrequested lines - every time the client asks for any line info again - I call
gpiod_line_update()before responding. This could be optimized by this lineinfo fd feature.I don't want to force the user-space to choose between using a single central daemon or dealing with lines separately.
Quoted 5 lines
The daemon then always knows the state of the line.
That obviously isn't the case if you want to monitor a line without requesting it, hence the "You want to be able to monitor without requesting the line?" question.In other words: yes.
Quoted 12 lines
Quoted 11 lines
Quoted 5 lines
I'm still puzzled as to when the existing info ioctl could fail on a requested line - which is when
needs_updategets set inline_maybe_update(). Hardware being unplugged?If the
ioctl()can fail, then we're obligated to check the return value. As you say: unplugging the device is a good example - it may be a GPIO expander on an HID device (e.g. Silicon Labs CP2112) that can be easily disconnected from USB.Quoted 4 lines
Fair enough. But for failures of that scale shouldn't the line request fail - rather than just setting
needs_update? Or are there less catastrohpic failure modes?Quoted 8 lines
What if the disconnect happens after the request but before the update? It's super unlikely, but again: the lineinfo
ioctl()can fail, so we need to check the return value. We also can't update line info before requesting the line as it's racy - someone can change the state between the update and the request.(I hope I'm getting this right :))
I understand that the disconnect can occur between the request ioctl and the info ioctl, but both of those are called within
line_request_values(), which implements the core ofgpiod_line_request_bulk(), so the opportunity exists to propagate the info failure back as part of the request, but instead the error is absorbed andneeds_updateis set. This puts the onus on the caller to always checkgpiod_line_needs_update()between requesting a line and calling any of the state accessors - else they may be returning garbage.
Quoted 4 lines
Similarly the event case in
line_request_event_single().I was wondering what the reasoning was for this approach?
So I've been thinking about why I decided to go with this - and while I can't remember any more (I didn't comment on it...) I think there must have been *some* reason to do this. Now it actually seems to me as if we could make the request function release all lines and return an error if updating fails (we'd also need to make gpiod_line_needs_update() deprecated and always return false for compatibility). I need to think about it some more...
Bart
Quoted 1 line
Kent.
PATCH 12/19 tests: add tests for SET_CONFIG
In reply to Kent GibsonExtend test coverage over the SET_CONFIG functions.
--- tests/tests-line.c | 371 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 370 insertions(+), 1 deletion(-)
tests/tests-line.c +370 -1
@@ -267,6 +267,7 @@ GPIOD_TEST_CASE(set_value, 0, { 8 }) ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,0 ); g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); ret =gpiod_line_set_value (line,1 ); g_assert_cmpint(ret, ==, 0);
@@ -276,6 +277,352 @@ GPIOD_TEST_CASE(set_value, 0, { 8 }) g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); } +GPIOD_TEST_CASE(set_config_bulk_null_values, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line_bulk bulk =GPIOD_LINE_BULK_INITIALIZER ; +struct gpiod_line *line0, *line1, *line2; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line0 =gpiod_chip_get_line (chip,0 ); + line1 =gpiod_chip_get_line (chip,1 ); + line2 =gpiod_chip_get_line (chip,2 ); + +g_assert_nonnull (line0); +g_assert_nonnull (line1); +g_assert_nonnull (line2); +gpiod_test_return_if_failed (); + +gpiod_line_bulk_add (&bulk, line0); +gpiod_line_bulk_add (&bulk, line1); +gpiod_line_bulk_add (&bulk, line2); + + ret =gpiod_line_request_bulk_output (&bulk,GPIOD_TEST_CONSUMER ,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_active_state(line0), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_line_active_state(line1), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_line_active_state(line2), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 0), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 1), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_config_bulk (&bulk, +GPIOD_LINE_REQUEST_DIRECTION_OUTPUT , +GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ,NULL ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_active_state(line0), ==, +GPIOD_LINE_ACTIVE_STATE_LOW ); + g_assert_cmpint(gpiod_line_active_state(line1), ==, +GPIOD_LINE_ACTIVE_STATE_LOW ); + g_assert_cmpint(gpiod_line_active_state(line2), ==, +GPIOD_LINE_ACTIVE_STATE_LOW ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 0), ==, 1); + g_assert_cmpint(gpiod_test_chip_get_value(0, 1), ==, 1); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + + ret =gpiod_line_set_config_bulk (&bulk, +GPIOD_LINE_REQUEST_DIRECTION_OUTPUT ,0 ,NULL ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_active_state(line0), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_line_active_state(line1), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_line_active_state(line2), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 0), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 1), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); +} + +GPIOD_TEST_CASE(set_flags_active_state, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,2 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,1 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_active_state(line), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + + ret =gpiod_line_set_flags (line,GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_active_state(line), ==, +GPIOD_LINE_ACTIVE_STATE_LOW ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_flags (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_active_state(line), ==, +GPIOD_LINE_ACTIVE_STATE_HIGH ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); +} + +GPIOD_TEST_CASE(set_flags_bias, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,2 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_input (line,GPIOD_TEST_CONSUMER ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_AS_IS); + + ret =gpiod_line_set_flags (line, +GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_DISABLE); + + ret =gpiod_line_set_flags (line, +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_PULL_UP); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + + ret =gpiod_line_set_flags (line, +GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_bias(line), ==, GPIOD_LINE_BIAS_PULL_DOWN); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); +} + +GPIOD_TEST_CASE(set_flags_drive, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,2 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_is_open_drain(line), ==, false); + g_assert_cmpint(gpiod_line_is_open_source(line), ==, false); + + ret =gpiod_line_set_flags (line, +GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_is_open_drain(line), ==, true); + g_assert_cmpint(gpiod_line_is_open_source(line), ==, false); + + ret =gpiod_line_set_flags (line, +GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_is_open_drain(line), ==, false); + g_assert_cmpint(gpiod_line_is_open_source(line), ==, true); +} + +GPIOD_TEST_CASE(set_direction, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line *line; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,2 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + + ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_direction_input (line); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_INPUT ); + + ret =gpiod_line_set_direction_output (line,1 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); +} + +GPIOD_TEST_CASE(set_direction_bulk, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line_bulk bulk =GPIOD_LINE_BULK_INITIALIZER ; +struct gpiod_line *line0, *line1, *line2; +int values[3 ]; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line0 =gpiod_chip_get_line (chip,0 ); + line1 =gpiod_chip_get_line (chip,1 ); + line2 =gpiod_chip_get_line (chip,2 ); + +g_assert_nonnull (line0); +g_assert_nonnull (line1); +g_assert_nonnull (line2); +gpiod_test_return_if_failed (); + +gpiod_line_bulk_add (&bulk, line0); +gpiod_line_bulk_add (&bulk, line1); +gpiod_line_bulk_add (&bulk, line2); + + values[0 ] =0 ; + values[1 ] =1 ; + values[2 ] =2 ; + + ret =gpiod_line_request_bulk_output (&bulk, +GPIOD_TEST_CONSUMER , values); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line0), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_line_direction(line1), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_line_direction(line2), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 0), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 1), ==, 1); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + + ret =gpiod_line_set_direction_bulk_input (&bulk); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line0), ==, +GPIOD_LINE_DIRECTION_INPUT ); + g_assert_cmpint(gpiod_line_direction(line1), ==, +GPIOD_LINE_DIRECTION_INPUT ); + g_assert_cmpint(gpiod_line_direction(line2), ==, +GPIOD_LINE_DIRECTION_INPUT ); + + values[0 ] =2 ; + values[1 ] =1 ; + values[2 ] =0 ; + + ret =gpiod_line_set_direction_bulk_output (&bulk, values); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line0), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_line_direction(line1), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_line_direction(line2), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 0), ==, 1); + g_assert_cmpint(gpiod_test_chip_get_value(0, 1), ==, 1); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_direction_bulk_output (&bulk,NULL ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_line_direction(line0), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_line_direction(line1), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_line_direction(line2), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 0), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 1), ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); +} + +GPIOD_TEST_CASE(output_value_caching, 0, { 8 }) +{ +g_autoptr (gpiod_chip_struct) chip =NULL ; +struct gpiod_line *line; +struct gpiod_line_bulk bulk; +gint ret; + + chip =gpiod_chip_open (gpiod_test_chip_path (0 )); +g_assert_nonnull (chip); +gpiod_test_return_if_failed (); + + line =gpiod_chip_get_line (chip,2 ); +g_assert_nonnull (line); +gpiod_test_return_if_failed (); + +// check cached by request... + ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,1 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + +// ...by checking cached value applied by set_flags + ret =gpiod_line_set_flags (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + +// check cached by set_value + ret =gpiod_line_set_value (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_flags (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_value (line,1 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + + ret =gpiod_line_set_flags (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + +// check cached by set_config + ret =gpiod_line_set_config (line,GPIOD_LINE_REQUEST_DIRECTION_OUTPUT , +0 ,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_flags (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + +// check cached by set_value_bulk default + ret =gpiod_line_set_value (line,1 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 1); + +gpiod_line_bulk_init (&bulk); +gpiod_line_bulk_add (&bulk, line); + ret =gpiod_line_set_value_bulk (&bulk,NULL ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); + + ret =gpiod_line_set_flags (line,0 ); + g_assert_cmpint(ret, ==, 0); + g_assert_cmpint(gpiod_test_chip_get_value(0, 2), ==, 0); +} + + GPIOD_TEST_CASE(get_value_different_chips, 0, { 8, 8 }) {g_autoptr (gpiod_chip_struct) chipA =NULL ;
@@ -390,10 +737,11 @@ GPIOD_TEST_CASE(direction, 0, { 8 })g_assert_nonnull (line);gpiod_test_return_if_failed (); - ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,0 ); + ret =gpiod_line_request_output (line,GPIOD_TEST_CONSUMER ,1 ); g_assert_cmpint(ret, ==, 0); g_assert_cmpint(gpiod_line_direction(line), ==,GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 5), ==, 1);gpiod_line_release (line);
@@ -431,6 +779,27 @@ GPIOD_TEST_CASE(active_state, 0, { 8 }) g_assert_cmpint(gpiod_line_direction(line), ==,GPIOD_LINE_DIRECTION_INPUT ); + +gpiod_line_release (line); + + ret =gpiod_line_request_output_flags (line,GPIOD_TEST_CONSUMER , +GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW ,0 ); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 5), ==, 1); + +gpiod_line_release (line); + + ret =gpiod_line_request_output_flags (line, +GPIOD_TEST_CONSUMER ,0 ,0 ); + g_assert_cmpint(ret, ==, 0); + + g_assert_cmpint(gpiod_line_direction(line), ==, +GPIOD_LINE_DIRECTION_OUTPUT ); + g_assert_cmpint(gpiod_test_chip_get_value(0, 5), ==, 0); + } GPIOD_TEST_CASE(misc_flags, 0, { 8 })
Signature · 1 line
2.24.0
PATCH 13/19 core: allow gpiod_line_set_value_bulk to accept null values
In reply to Kent GibsonChange gpiod_line_set_value_bulk to interpret a NULL values pointer as an array of zero, as per gpiod_line_request_bulk, gpiod_line_set_config_bulk, and gpiod_line_set_direction_bulk_output.
The old behaviour was to segfault.
--- lib/core.c | 5 +++-- tests/tests-line.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-)
lib/core.c +3 -2
@@ -805,8 +805,9 @@ int gpiod_line_set_value_bulk(struct gpiod_line_bulk *bulk, const int *values)memset (&data,0 ,sizeof (data)); -for (i =0 ; i <gpiod_line_bulk_num_lines (bulk); i++) - data.values[i] = (uint8_t )!!values[i]; +if (values) +for (i =0 ; i <gpiod_line_bulk_num_lines (bulk); i++) + data.values[i] = (uint8_t )!!values[i]; line =gpiod_line_bulk_get_line (bulk,0 ); fd =line_get_fd (line);
tests/tests-line.c +53 -0
59 lines not on this page · raw message
Signature · 1 line
2.24.0
PATCH 14/19 bindings: cxx: add support for SET_CONFIG
In reply to Kent GibsonAdd methods to support setting line configuration.
--- bindings/cxx/gpiod.hpp | 55 +++++++++++++++++++++++++ bindings/cxx/line.cpp | 37 +++++++++++++++++ bindings/cxx/line_bulk.cpp | 83 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+)
bindings/cxx/gpiod.hpp +55 -0
@@ -381,6 +381,32 @@ public: */ GPIOD_API void set_value(int val) const; + /** + * @brief Set configuration of this line. + * @param direction New direction. + * @param flags Replacement flags. + * @param value New value (0 or 1) - only matters for OUTPUT direction. + */ + GPIOD_API void set_config(int direction, ::std::bitset<32> flags, + int value = 0) const; + + /** + * @brief Set configuration flags of this line. + * @param flags Replacement flags. + */ + GPIOD_API void set_flags(::std::bitset<32> flags) const; + + /** + * @brief Change the direction this line to input. + */ + GPIOD_API void set_direction_input() const; + + /** + * @brief Change the direction this lines to output. + * @param value New value (0 or 1). + */ + GPIOD_API void set_direction_output(int value = 0) const; + /** * @brief Wait for an event on this line. * @param timeout Time to wait before returning if no event occurred.
@@ -648,6 +674,35 @@ public: */ GPIOD_API void set_values(const ::std::vector<int>& values) const; + /** + * @brief Set configuration of all lines held by this object. + * @param direction New direction. + * @param flags Replacement flags. + * @param values Vector of values to set. Must be the same size as the + * number of lines held by this line_bulk. + * Only relevant for output direction requests. + */ + GPIOD_API void set_config(int direction, ::std::bitset<32> flags, + const ::std::vector<int> values = std::vector<int>()) const; + + /** + * @brief Set configuration flags of all lines held by this object. + * @param flags Replacement flags. + */ + GPIOD_API void set_flags(::std::bitset<32> flags) const; + + /** + * @brief Change the direction all lines held by this object to input. + */ + GPIOD_API void set_direction_input() const; + + /** + * @brief Change the direction all lines held by this object to output. + * @param values Vector of values to set. Must be the same size as the + * number of lines held by this line_bulk. + */ + GPIOD_API void set_direction_output(const ::std::vector<int>& values) const; + /** * @brief Poll the set of lines for line events. * @param timeout Number of nanoseconds to wait before returning an
bindings/cxx/line.cpp +37 -0
@@ -158,6 +158,43 @@ void line::set_value(int val) const bulk.set_values({ val }); } +void line::set_config(int direction, ::std::bitset<32> flags, + int value) const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_config(direction, flags, { value }); +} + +void line::set_flags(::std::bitset<32> flags) const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_flags(flags); +} + +void line::set_direction_input() const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_direction_input(); +} + +void line::set_direction_output(int value) const +{ + this->throw_if_null(); + + line_bulk bulk({ *this }); + + bulk.set_direction_output({ value }); +} + bool line::event_wait(const ::std::chrono::nanoseconds& timeout) const { this->throw_if_null();
bindings/cxx/line_bulk.cpp +83 -0
89 lines not on this page · raw message
Signature · 1 line
2.24.0
PATCH 15/19 bindings: cxx: tests: add tests for SET_CONFIG methods
In reply to Kent GibsonExtend test coverage over set_config, set_flags, set_direction_input, and set_direction_output methods.
--- bindings/cxx/tests/tests-line.cpp | 128 ++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+)
bindings/cxx/tests/tests-line.cpp +128 -0
@@ -324,6 +324,134 @@ TEST_CASE("Line values can be set and read", "[line]") } } +TEST_CASE("Line can be reconfigured", "[line]") +{ + mockup::probe_guard mockup_chips({ 8 }); + ::gpiod::chip chip(mockup::instance().chip_name(0)); + ::gpiod::line_request config; + + config.consumer = consumer.c_str(); + + SECTION("set config (single line, active-state)") + { + auto line = chip.get_line(3); + config.request_type = ::gpiod::line_request::DIRECTION_INPUT; + config.flags = 0; + line.request(config); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + + line.set_config(::gpiod::line_request::DIRECTION_OUTPUT, + ::gpiod::line_request::FLAG_ACTIVE_LOW,1); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_LOW); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 0); + line.set_value(0); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 1); + + line.set_config(::gpiod::line_request::DIRECTION_OUTPUT, 0); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 0); + line.set_value(1); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 1); + } + + SECTION("set flags (single line, active-state)") + { + auto line = chip.get_line(3); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = 0; + line.request(config,1); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 1); + + line.set_flags(::gpiod::line_request::FLAG_ACTIVE_LOW); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_LOW); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 0); + + line.set_flags(0); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.active_state() == ::gpiod::line::ACTIVE_HIGH); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 1); + } + + SECTION("set flags (single line, drive)") + { + auto line = chip.get_line(3); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = 0; + line.request(config); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + + line.set_flags(::gpiod::line_request::FLAG_OPEN_DRAIN); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + + line.set_flags(::gpiod::line_request::FLAG_OPEN_SOURCE); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE(line.is_open_source()); + + line.set_flags(0); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + } + + SECTION("set flags (single line, bias)") + { + auto line = chip.get_line(3); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = 0; + line.request(config); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + + line.set_flags(::gpiod::line_request::FLAG_OPEN_DRAIN); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + + line.set_flags(::gpiod::line_request::FLAG_OPEN_SOURCE); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE(line.is_open_source()); + + line.set_flags(0); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE_FALSE(line.is_open_drain()); + REQUIRE_FALSE(line.is_open_source()); + } + + SECTION("set direction input (single line)") + { + auto line = chip.get_line(3); + config.request_type = ::gpiod::line_request::DIRECTION_OUTPUT; + config.flags = 0; + line.request(config); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + line.set_direction_input(); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT); + } + + SECTION("set direction output (single line)") + { + auto line = chip.get_line(3); + config.request_type = ::gpiod::line_request::DIRECTION_INPUT; + config.flags = 0; + line.request(config); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_INPUT); + line.set_direction_output(1); + REQUIRE(line.direction() == ::gpiod::line::DIRECTION_OUTPUT); + REQUIRE(mockup::instance().chip_get_value(0, 3) == 1); + } +} + TEST_CASE("Exported line can be released", "[line]") { mockup::probe_guard mockup_chips({ 8 });
Signature · 1 line
2.24.0
PATCH 16/19 bindings: python: add support for SET_CONFIG
In reply to Kent GibsonAdd methods to support setting line configuration.
--- bindings/python/gpiodmodule.c | 381 +++++++++++++++++++++++++++++++++- 1 file changed, 379 insertions(+), 2 deletions(-)
bindings/python/gpiodmodule.c +379 -2
@@ -585,14 +585,149 @@ static PyObject *gpiod_Line_set_value(gpiod_LineObject *self, PyObject *args)if (!bulk_obj)return NULL ; - vals =Py_BuildValue ("((O))" , val); + vals =Py_BuildValue ("(O)" , val);if (!vals) {Py_DECREF (bulk_obj);return NULL ; } ret =PyObject_CallMethod ((PyObject *)bulk_obj, -"set_values" ,"O" , vals); +"set_values" ,"(O)" , vals); +Py_DECREF (bulk_obj); +Py_DECREF (vals); + +return ret; +} + +PyDoc_STRVAR (gpiod_Line_set_config_doc, +"set_config(direction,flags,value) -> None\n" +"\n" +"Set the configuration of this GPIO line.\n" +"\n" +" direction\n" +" New direction (integer)\n" +" flags\n" +" New flags (integer)\n" +" value\n" +" New value (integer)" ); + +static PyObject *gpiod_Line_set_config (gpiod_LineObject *self,PyObject *args) +{ +gpiod_LineBulkObject *bulk_obj; +PyObject *dirn, *flags, *val, *vals, *ret; +int rv; + + val =NULL ; + rv =PyArg_ParseTuple (args,"OO|O" , &dirn, &flags, &val); +if (!rv) +return NULL ; + + bulk_obj =gpiod_LineToLineBulk (self); +if (!bulk_obj) +return NULL ; + +if (val) { + vals =Py_BuildValue ("(O)" , val); +if (!vals) { +Py_DECREF (bulk_obj); +return NULL ; + } + ret =PyObject_CallMethod ((PyObject *)bulk_obj, +"set_config" ,"OO(O)" , dirn, flags, vals); +Py_DECREF (vals); + }else + ret =PyObject_CallMethod ((PyObject *)bulk_obj, +"set_config" ,"OO" , dirn, flags); + +Py_DECREF (bulk_obj); + +return ret; +} + +PyDoc_STRVAR (gpiod_Line_set_flags_doc, +"set_flags(flags) -> None\n" +"\n" +"Set the flags of this GPIO line.\n" +"\n" +" flags\n" +" New flags (integer)" ); + +static PyObject *gpiod_Line_set_flags (gpiod_LineObject *self,PyObject *args) +{ +gpiod_LineBulkObject *bulk_obj; +PyObject *ret; + + bulk_obj =gpiod_LineToLineBulk (self); +if (!bulk_obj) +return NULL ; + + ret =PyObject_CallMethod ((PyObject *)bulk_obj, +"set_flags" ,"O" , args); +Py_DECREF (bulk_obj); + +return ret; +} + +PyDoc_STRVAR (gpiod_Line_set_direction_input_doc, +"set_direction_input() -> None\n" +"\n" +"Set the direction of this GPIO line to input.\n" ); + +static PyObject *gpiod_Line_set_direction_input (gpiod_LineObject *self, +PyObject *Py_UNUSED (ignored )) +{ +gpiod_LineBulkObject *bulk_obj; +PyObject *ret; + + bulk_obj =gpiod_LineToLineBulk (self); +if (!bulk_obj) +return NULL ; + + ret =PyObject_CallMethod ((PyObject *)bulk_obj, +"set_direction_input" ,"" ); +Py_DECREF (bulk_obj); + +return ret; +} + +PyDoc_STRVAR (gpiod_Line_set_direction_output_doc, +"set_direction_output(value) -> None\n" +"\n" +"Set the direction of this GPIO line to output.\n" +"\n" +" value\n" +" New value (integer)" ); + +static PyObject *gpiod_Line_set_direction_output (gpiod_LineObject *self, +PyObject *args) +{ +gpiod_LineBulkObject *bulk_obj; +PyObject *val, *vals, *ret; +int rv; +const char *fmt; + + val =NULL ; + rv =PyArg_ParseTuple (args,"|O" , &val); +if (!rv) +return NULL ; + +if (val) { + fmt ="(O)" ; + vals =Py_BuildValue (fmt, val); + }else { + vals =Py_BuildValue ("()" ); + fmt ="O" ;// pass empty args to bulk + } +if (!vals) +return NULL ; + + bulk_obj =gpiod_LineToLineBulk (self); +if (!bulk_obj) +return NULL ; + + ret =PyObject_CallMethod ((PyObject *)bulk_obj, +"set_direction_output" , fmt, vals); +Py_DECREF (bulk_obj);Py_DECREF (vals);
@@ -838,6 +973,30 @@ static PyMethodDef gpiod_Line_methods[] = { .ml_flags = METH_VARARGS, .ml_doc = gpiod_Line_set_value_doc, }, + { + .ml_name = "set_config", + .ml_meth = (PyCFunction)gpiod_Line_set_config, + .ml_flags = METH_VARARGS, + .ml_doc = gpiod_Line_set_config_doc, + }, + { + .ml_name = "set_flags", + .ml_meth = (PyCFunction)gpiod_Line_set_flags, + .ml_flags = METH_VARARGS, + .ml_doc = gpiod_Line_set_flags_doc, + }, + { + .ml_name = "set_direction_input", + .ml_meth = (PyCFunction)gpiod_Line_set_direction_input, + .ml_flags = METH_NOARGS, + .ml_doc = gpiod_Line_set_direction_input_doc, + }, + { + .ml_name = "set_direction_output", + .ml_meth = (PyCFunction)gpiod_Line_set_direction_output, + .ml_flags = METH_VARARGS, + .ml_doc = gpiod_Line_set_direction_output_doc, + }, { .ml_name = "release", .ml_meth = (PyCFunction)gpiod_Line_release,
@@ -1283,6 +1442,200 @@ static PyObject *gpiod_LineBulk_set_values(gpiod_LineBulkObject *self, Py_RETURN_NONE; } +static int convert_values (PyObject *src,int *dst,Py_ssize_t n) +{ +int val; +Py_ssize_t num_vals, i; +PyObject *iter, *next; + + num_vals =PyObject_Size (src); +if (num_vals != n) { +PyErr_SetString (PyExc_TypeError, +"Number of values must correspond to the number of lines" ); +return -1 ; + } + iter =PyObject_GetIter (src); +if (!iter) +return -1 ; +for (i =0 ;; i++) { + next =PyIter_Next (iter); +if (!next) { +Py_DECREF (iter); +break ; + } + val =PyLong_AsLong (next); +Py_DECREF (next); +if (PyErr_Occurred ()) { +Py_DECREF (iter); +return -1 ; + } + dst[i] = (int )val; + } +return 0 ; +} + +PyDoc_STRVAR (gpiod_LineBulk_set_config_doc, +"set_config(direction,flags,values) -> None\n" +"\n" +"Set the configuration of all the lines held by this LineBulk object.\n" +"\n" +" direction\n" +" New direction (integer)\n" +" flags\n" +" New flags (integer)\n" +" values\n" +" List of values (integers) to set when direction is output.\n" +"\n" +"The number of values in the list passed as argument must be the same as\n" +"the number of lines held by this gpiod.LineBulk object. The index of each\n" +"value corresponds to the index of each line in the object.\n" ); + +static PyObject *gpiod_LineBulk_set_config (gpiod_LineBulkObject *self, +PyObject *args) +{ +int rv, vals[GPIOD_LINE_BULK_MAX_LINES ]; +PyObject *val_list; +struct gpiod_line_bulk bulk; +const int *valp; +int dirn, flags; + +if (gpiod_LineBulkOwnerIsClosed (self)) +return NULL ; + +gpiod_LineBulkObjToCLineBulk (self, &bulk); + + val_list =NULL ; + rv =PyArg_ParseTuple (args,"ii|(O)" , &dirn, &flags, &val_list); +if (!rv) +return NULL ; + +if (val_list ==NULL ) + valp =NULL ; +else { +memset (vals,0 ,sizeof (vals)); + rv =convert_values (val_list, vals, self->num_lines); +if (rv) +return NULL ; + valp = vals; + } + + Py_BEGIN_ALLOW_THREADS; + rv =gpiod_line_set_config_bulk (&bulk, dirn, flags, valp); + Py_END_ALLOW_THREADS; +if (rv) +return PyErr_SetFromErrno (PyExc_OSError); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR (gpiod_LineBulk_set_flags_doc, +"set_flags(flags) -> None\n" +"\n" +"Set the flags of all the lines held by this LineBulk object.\n" +"\n" +" flags\n" +" New flags (integer)" ); + +static PyObject *gpiod_LineBulk_set_flags (gpiod_LineBulkObject *self, +PyObject *args) +{ +int rv; +struct gpiod_line_bulk bulk; +int flags; + +if (gpiod_LineBulkOwnerIsClosed (self)) +return NULL ; + +gpiod_LineBulkObjToCLineBulk (self, &bulk); + + rv =PyArg_ParseTuple (args,"i" , &flags); +if (!rv) +return NULL ; + + Py_BEGIN_ALLOW_THREADS; + rv =gpiod_line_set_flags_bulk (&bulk, flags); + Py_END_ALLOW_THREADS; +if (rv) +return PyErr_SetFromErrno (PyExc_OSError); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR (gpiod_LineBulk_set_direction_input_doc, +"set_direction_input() -> None\n" +"\n" +"Set the direction of all the lines held by this LineBulk object to input.\n" ); + +static PyObject *gpiod_LineBulk_set_direction_input (gpiod_LineBulkObject *self, +PyObject *Py_UNUSED (ignored )) +{ +struct gpiod_line_bulk bulk; +int rv; + +if (gpiod_LineBulkOwnerIsClosed (self)) +return NULL ; + +gpiod_LineBulkObjToCLineBulk (self, &bulk); + + Py_BEGIN_ALLOW_THREADS; + rv =gpiod_line_set_direction_bulk_input (&bulk); + Py_END_ALLOW_THREADS; +if (rv) +return PyErr_SetFromErrno (PyExc_OSError); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR (gpiod_LineBulk_set_direction_output_doc, +"set_direction_output(value) -> None\n" +"\n" +"Set the direction of all the lines held by this LineBulk object to output.\n" +"\n" +" values\n" +" List of values (integers) to set when direction is output.\n" +"\n" +"The number of values in the list passed as argument must be the same as\n" +"the number of lines held by this gpiod.LineBulk object. The index of each\n" +"value corresponds to the index of each line in the object.\n" ); + +static PyObject *gpiod_LineBulk_set_direction_output ( +gpiod_LineBulkObject *self, +PyObject *args) +{ +int rv, vals[GPIOD_LINE_BULK_MAX_LINES ]; +PyObject *val_list; +struct gpiod_line_bulk bulk; +const int *valp; + +if (gpiod_LineBulkOwnerIsClosed (self)) +return NULL ; + +gpiod_LineBulkObjToCLineBulk (self, &bulk); + + val_list =NULL ; + rv =PyArg_ParseTuple (args,"|O" , &val_list); +if (!rv) +return NULL ; + +if (val_list ==NULL ) + valp =NULL ; +else { +memset (vals,0 ,sizeof (vals)); + rv =convert_values (val_list, vals, self->num_lines); +if (rv) +return NULL ; + valp = vals; + } + + Py_BEGIN_ALLOW_THREADS; + rv =gpiod_line_set_direction_bulk_output (&bulk, valp); + Py_END_ALLOW_THREADS; +if (rv) +return PyErr_SetFromErrno (PyExc_OSError); + + Py_RETURN_NONE; +} +PyDoc_STRVAR (gpiod_LineBulk_release_doc,"release() -> None\n" "\n"
@@ -1431,6 +1784,30 @@ static PyMethodDef gpiod_LineBulk_methods[] = { .ml_doc = gpiod_LineBulk_set_values_doc, .ml_flags = METH_VARARGS, }, + { + .ml_name = "set_config", + .ml_meth = (PyCFunction)gpiod_LineBulk_set_config, + .ml_flags = METH_VARARGS, + .ml_doc = gpiod_LineBulk_set_config_doc, + }, + { + .ml_name = "set_flags", + .ml_meth = (PyCFunction)gpiod_LineBulk_set_flags, + .ml_flags = METH_VARARGS, + .ml_doc = gpiod_LineBulk_set_flags_doc, + }, + { + .ml_name = "set_direction_input", + .ml_meth = (PyCFunction)gpiod_LineBulk_set_direction_input, + .ml_flags = METH_NOARGS, + .ml_doc = gpiod_LineBulk_set_direction_input_doc, + }, + { + .ml_name = "set_direction_output", + .ml_meth = (PyCFunction)gpiod_LineBulk_set_direction_output, + .ml_flags = METH_VARARGS, + .ml_doc = gpiod_LineBulk_set_direction_output_doc, + }, { .ml_name = "release", .ml_meth = (PyCFunction)gpiod_LineBulk_release,
Signature · 1 line
2.24.0
PATCH 17/19 bindings: python: tests: add tests for SET_CONFIG methods
In reply to Kent GibsonExtend test coverage over set_config, set_flags, set_direction_input, and set_direction_output methods.
--- bindings/python/tests/gpiod_py_test.py | 163 +++++++++++++++++++++++++ 1 file changed, 163 insertions(+)
bindings/python/tests/gpiod_py_test.py +163 -0
@@ -493,6 +493,169 @@ class LineValues(MockupTestCase): line.set_value(0) self.assertEqual(mockup.chip_get_value(0, 3), 1) +class LineConfig(MockupTestCase): + + chip_sizes = ( 8, ) + + def test_set_config_direction(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(3) + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_IN) + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT) + line.set_config(gpiod.LINE_REQ_DIR_IN, 0, 0) + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT) + line.set_config(gpiod.LINE_REQ_DIR_OUT,0,0) + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + + def test_set_config_flags(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(3) + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT) + line.set_config(gpiod.LINE_REQ_DIR_OUT, + gpiod.LINE_REQ_FLAG_ACTIVE_LOW, 0) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + line.set_config(gpiod.LINE_REQ_DIR_OUT, 0, 0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + + def test_set_config_output_value(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(3) + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_IN) + line.set_config(gpiod.LINE_REQ_DIR_OUT,0,1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + line.set_config(gpiod.LINE_REQ_DIR_OUT,0,0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + + def test_set_config_output_no_value(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(3) + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + default_val=1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + line.set_config(gpiod.LINE_REQ_DIR_OUT,0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + + def test_set_config_bulk_output_no_values(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + lines = chip.get_lines(( 0, 3, 4, 6 )) + lines.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + default_vals=(1,1,1,1)) + self.assertEqual(mockup.chip_get_value(0, 0), 1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + self.assertEqual(mockup.chip_get_value(0, 4), 1) + self.assertEqual(mockup.chip_get_value(0, 6), 1) + lines.set_config(gpiod.LINE_REQ_DIR_OUT,0) + self.assertEqual(mockup.chip_get_value(0, 0), 0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + self.assertEqual(mockup.chip_get_value(0, 4), 0) + self.assertEqual(mockup.chip_get_value(0, 6), 0) + +class LineFlags(MockupTestCase): + + chip_sizes = ( 8, ) + + def test_set_flags(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(3) + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + default_val=1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + line.set_flags(gpiod.LINE_REQ_FLAG_ACTIVE_LOW) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + line.set_flags(0) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + + def test_set_flags_bulk(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + lines = chip.get_lines(( 0, 3, 4, 6 )) + lines.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT, + default_vals=(1,1,1,1)) + self.assertEqual(mockup.chip_get_value(0, 0), 1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + self.assertEqual(mockup.chip_get_value(0, 4), 1) + self.assertEqual(mockup.chip_get_value(0, 6), 1) + lines.set_flags(gpiod.LINE_REQ_FLAG_ACTIVE_LOW) + self.assertEqual(mockup.chip_get_value(0, 0), 0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + self.assertEqual(mockup.chip_get_value(0, 4), 0) + self.assertEqual(mockup.chip_get_value(0, 6), 0) + lines.set_flags(0) + self.assertEqual(mockup.chip_get_value(0, 0), 1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + self.assertEqual(mockup.chip_get_value(0, 4), 1) + self.assertEqual(mockup.chip_get_value(0, 6), 1) + +class LineDirection(MockupTestCase): + + chip_sizes = ( 8, ) + + def test_set_direction(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + line = chip.get_line(3) + line.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT) + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + line.set_direction_input() + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_INPUT) + line.set_direction_output(0) + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + line.set_direction_output(1) + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + line.set_direction_output() + self.assertEqual(line.direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + + def test_set_direction_bulk(self): + with gpiod.Chip(mockup.chip_name(0)) as chip: + lines = chip.get_lines(( 0, 3, 4, 6 )) + lines.request(consumer=default_consumer, + type=gpiod.LINE_REQ_DIR_OUT) + self.assertEqual(lines.to_list()[0].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[1].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[2].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[3].direction(), gpiod.Line.DIRECTION_OUTPUT) + lines.set_direction_input() + self.assertEqual(lines.to_list()[0].direction(), gpiod.Line.DIRECTION_INPUT) + self.assertEqual(lines.to_list()[1].direction(), gpiod.Line.DIRECTION_INPUT) + self.assertEqual(lines.to_list()[2].direction(), gpiod.Line.DIRECTION_INPUT) + self.assertEqual(lines.to_list()[3].direction(), gpiod.Line.DIRECTION_INPUT) + lines.set_direction_output((0,0,1,0)) + self.assertEqual(lines.to_list()[0].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[1].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[2].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[3].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(mockup.chip_get_value(0, 0), 0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + self.assertEqual(mockup.chip_get_value(0, 4), 1) + self.assertEqual(mockup.chip_get_value(0, 6), 0) + lines.set_direction_output((1,1,1,0)) + self.assertEqual(lines.to_list()[0].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[1].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[2].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[3].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(mockup.chip_get_value(0, 0), 1) + self.assertEqual(mockup.chip_get_value(0, 3), 1) + self.assertEqual(mockup.chip_get_value(0, 4), 1) + self.assertEqual(mockup.chip_get_value(0, 6), 0) + lines.set_direction_output() + self.assertEqual(lines.to_list()[0].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[1].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[2].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(lines.to_list()[3].direction(), gpiod.Line.DIRECTION_OUTPUT) + self.assertEqual(mockup.chip_get_value(0, 0), 0) + self.assertEqual(mockup.chip_get_value(0, 3), 0) + self.assertEqual(mockup.chip_get_value(0, 4), 0) + self.assertEqual(mockup.chip_get_value(0, 6), 0) + class LineRequestBehavior(MockupTestCase): chip_sizes = ( 8, )
Signature · 1 line
2.24.0
PATCH 18/19 tools: add support for bias flags
In reply to Kent GibsonAdd support for bias flags to applicable tools - gpioget, gpioset, and gpiomon.
--- tools/gpioget.c | 24 ++++++++++++++++++++---- tools/gpiomon.c | 28 ++++++++++++++++++++++------ tools/gpioset.c | 26 +++++++++++++++++++++----- 3 files changed, 63 insertions(+), 15 deletions(-)
tools/gpioget.c +20 -4
@@ -17,10 +17,13 @@ static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "active-low", no_argument, NULL, 'l' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvl" ; +static const char *const shortopts ="+hvlDUB" ;static void print_help (void ) {
@@ -32,6 +35,9 @@ static void print_help(void)printf (" -h, --help:\t\tdisplay this message and exit\n" );printf (" -v, --version:\tdisplay the version and exit\n" );printf (" -l, --active-low:\tset the line active state to low\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" ); }int main (int argc,char **argv)
@@ -39,6 +45,7 @@ int main(int argc, char **argv)unsigned int *offsets, i, num_lines;int *values, optc, opti, rv;bool active_low = false; +int flags =0 ;char *device, *end;for (;;) {
@@ -56,6 +63,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case '?' :die ("try %s --help" ,get_progname ());default :
@@ -86,9 +102,9 @@ int main(int argc, char **argv)die ("invalid GPIO offset: %s" , argv[i +1 ]); } - rv =gpiod_ctxless_get_value_multiple (device, offsets, values, - num_lines, active_low, -"gpioget" ); + rv =gpiod_ctxless_get_value_multiple_ext (device, offsets, values, + num_lines, active_low, flags, +"gpioget" );if (rv <0 )die_perror ("error reading GPIO values" );
tools/gpiomon.c +22 -6
@@ -26,12 +26,15 @@ static const struct option longopts[] = { { "silent", no_argument, NULL, 's' }, { "rising-edge", no_argument, NULL, 'r' }, { "falling-edge", no_argument, NULL, 'f' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { "line-buffered", no_argument, NULL, 'b' }, { "format", required_argument, NULL, 'F' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvln:srfbF:" ; +static const char *const shortopts ="+hvln:srfDUBbF:" ;static void print_help (void ) {
@@ -47,6 +50,9 @@ static void print_help(void)printf (" -s, --silent:\t\tdon't print event info\n" );printf (" -r, --rising-edge:\tonly process rising edge events\n" );printf (" -f, --falling-edge:\tonly process falling edge events\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" );printf (" -b, --line-buffered:\tset standard output as line buffered\n" );printf (" -F, --format=FMT\tspecify custom output format\n" );printf ("\n" );
@@ -244,6 +250,7 @@ int main(int argc, char **argv) {unsigned int offsets[GPIOD_LINE_BULK_MAX_LINES ], num_lines =0 , offset;bool active_low = false, watch_rising = false, watch_falling = false; +int flags =0 ;struct timespec timeout = {10 ,0 };int optc, opti, rv, i, event_type;struct mon_ctx ctx;
@@ -266,6 +273,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case 'n' : ctx.events_wanted =strtoul (optarg, &end,10 );if (*end !='\0' )
@@ -320,11 +336,11 @@ int main(int argc, char **argv) ctx.sigfd =make_signalfd (); - rv =gpiod_ctxless_event_monitor_multiple (argv[0 ], event_type, - offsets, num_lines, - active_low,"gpiomon" , - &timeout, poll_callback, - event_callback, &ctx); + rv =gpiod_ctxless_event_monitor_multiple_ext ( + argv[0 ], event_type, offsets, + num_lines, active_low, flags,"gpiomon" , + &timeout, poll_callback, + event_callback, &ctx);if (rv)die_perror ("error waiting for events" );
tools/gpioset.c +21 -5
@@ -27,10 +27,13 @@ static const struct option longopts[] = { { "sec", required_argument, NULL, 's' }, { "usec", required_argument, NULL, 'u' }, { "background", no_argument, NULL, 'b' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvlm:s:u:b" ; +static const char *const shortopts ="+hvlm:s:u:bDUB" ;static void print_help (void ) {
@@ -42,6 +45,9 @@ static void print_help(void)printf (" -h, --help:\t\tdisplay this message and exit\n" );printf (" -v, --version:\tdisplay the version and exit\n" );printf (" -l, --active-low:\tset the line active state to low\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" );printf (" -m, --mode=[exit|wait|time|signal] (defaults to 'exit'):\n" );printf (" tell the program what to do after setting values\n" );printf (" -s, --sec=SEC:\tspecify the number of seconds to wait (only valid for --mode=time)\n" );
@@ -182,7 +188,7 @@ int main(int argc, char **argv) {const struct mode_mapping *mode = &modes[MODE_EXIT ];unsigned int *offsets, num_lines, i; -int *values, rv, optc, opti; +int *values, rv, optc, opti, flags =0 ;struct callback_data cbdata;bool active_low = false;char *device, *end;
@@ -204,6 +210,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case 'm' : mode =parse_mode (optarg);if (!mode)
@@ -268,9 +283,10 @@ int main(int argc, char **argv)die ("invalid offset: %s" , argv[i +1 ]); } - rv =gpiod_ctxless_set_value_multiple (device, offsets, values, - num_lines, active_low,"gpioset" , - mode->callback, &cbdata); + rv =gpiod_ctxless_set_value_multiple_ext ( + device, offsets, values, + num_lines, active_low, flags,"gpioset" , + mode->callback, &cbdata);if (rv <0 )die_perror ("error setting the GPIO line values" );
Signature · 1 line
2.24.0
Re: [libgpiod] [PATCH 18/19] tools: add support for bias flags
Quoted 64 lines · Kent Gibson
Add support for bias flags to applicable tools - gpioget, gpioset, and gpiomon.
Signed-off-by Kent Gibson <[email protected]>--- tools/gpioget.c | 24 ++++++++++++++++++++---- tools/gpiomon.c | 28 ++++++++++++++++++++++------ tools/gpioset.c | 26 +++++++++++++++++++++----- 3 files changed, 63 insertions(+), 15 deletions(-)tools/gpioget.c +17
-1@@ -17,10 +17,13 @@ static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "active-low", no_argument, NULL, 'l' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvl" ; +static const char *const shortopts ="+hvlDUB" ;static void print_help (void ) {@@ -32,6 +35,9 @@ static void print_help(void)printf (" -h, --help:\t\tdisplay this message and exit\n" );printf (" -v, --version:\tdisplay the version and exit\n" );printf (" -l, --active-low:\tset the line active state to low\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" ); }int main (int argc,char **argv)@@ -39,6 +45,7 @@ int main(int argc, char **argv)unsigned int *offsets, i, num_lines;int *values, optc, opti, rv;bool active_low = false; +int flags =0 ;char *device, *end;for (;;) {@@ -56,6 +63,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case '?' :die ("try %s --help" ,get_progname ());default :
tools/gpioget.c int main(int argc, char **argv) · line 104
Quoted 3 lines
tools/gpioget.c +0
-0@@ -86,9 +102,9 @@ int main(int argc, char **argv)die ("invalid GPIO offset: %s" , argv[i +1 ]); }
Nuts - this is wrong - it should be using the CTXLESS flags, not the LINE_REQUEST flags. That applies to all three of the tools changed. I forgot to propagate the last minute CTXLESS changes to the tools. And unfortunately we don't have test cases for the tools :-(. I've got a fix in my github branch that I will incorporate into v2.
I'm also wondering if it would be preferable to replace the individual bias command line flags with a single bias parameter, e.g. --bias=pull-up I've coded that in my github branch as well, if you would care to compare.
Let me know if you'd like a v2, otherwise I'll hold off for a few days in case something else crops up.
Cheers,
Kent.
Re: [libgpiod] [PATCH 18/19] tools: add support for bias flags
sob., 16 lis 2019 o 16:40 Kent Gibson <[email protected]> napisał(a):
Quoted 66 lines · Kent Gibson
Quoted 64 lines
Add support for bias flags to applicable tools - gpioget, gpioset, and gpiomon.
Signed-off-by Kent Gibson <[email protected]>--- tools/gpioget.c | 24 ++++++++++++++++++++---- tools/gpiomon.c | 28 ++++++++++++++++++++++------ tools/gpioset.c | 26 +++++++++++++++++++++----- 3 files changed, 63 insertions(+), 15 deletions(-)tools/gpioget.c +17
-1@@ -17,10 +17,13 @@ static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "active-low", no_argument, NULL, 'l' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvl" ; +static const char *const shortopts ="+hvlDUB" ;static void print_help (void ) {@@ -32,6 +35,9 @@ static void print_help(void)printf (" -h, --help:\t\tdisplay this message and exit\n" );printf (" -v, --version:\tdisplay the version and exit\n" );printf (" -l, --active-low:\tset the line active state to low\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" ); }int main (int argc,char **argv)@@ -39,6 +45,7 @@ int main(int argc, char **argv)unsigned int *offsets, i, num_lines;int *values, optc, opti, rv;bool active_low = false; +int flags =0 ;char *device, *end;for (;;) {@@ -56,6 +63,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case '?' :die ("try %s --help" ,get_progname ());default :@@ -86,9 +102,9 @@ int main(int argc, char **argv)
Quoted 8 lines
tools/gpioget.c int main(int argc, char **argv) · line 104
Quoted 3 lines
tools/gpioget.c +0
-0die ("invalid GPIO offset: %s" , argv[i +1 ]); }Nuts - this is wrong - it should be using the CTXLESS flags, not the
LINE_REQUESTflags. That applies to all three of the tools changed. I forgot to propagate the last minute CTXLESS changes to the tools. And unfortunately we don't have test cases for the tools :-(.
But we do![1]
Quoted 9 lines
I've got a fix in my github branch that I will incorporate into v2.
I'm also wondering if it would be preferable to replace the individual bias command line flags with a single bias parameter, e.g. --bias=pull-up I've coded that in my github branch as well, if you would care to compare.
Let me know if you'd like a v2, otherwise I'll hold off for a few days in case something else crops up.
Let me review the rest before that, I'll do this tomorrow.
Bart
Quoted 3 lines
Cheers,
Kent.
[1] https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/tools/gpio-tools-test.bats
Re: [libgpiod] [PATCH 18/19] tools: add support for bias flags
Quoted 76 lines · Bartosz Golaszewski
sob., 16 lis 2019 o 16:40 Kent Gibson <[email protected]> napisał(a):
Quoted 66 lines · Kent Gibson
Quoted 64 lines
Add support for bias flags to applicable tools - gpioget, gpioset, and gpiomon.
Signed-off-by Kent Gibson <[email protected]>--- tools/gpioget.c | 24 ++++++++++++++++++++---- tools/gpiomon.c | 28 ++++++++++++++++++++++------ tools/gpioset.c | 26 +++++++++++++++++++++----- 3 files changed, 63 insertions(+), 15 deletions(-)tools/gpioget.c +17
-1@@ -17,10 +17,13 @@ static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "active-low", no_argument, NULL, 'l' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvl" ; +static const char *const shortopts ="+hvlDUB" ;static void print_help (void ) {@@ -32,6 +35,9 @@ static void print_help(void)printf (" -h, --help:\t\tdisplay this message and exit\n" );printf (" -v, --version:\tdisplay the version and exit\n" );printf (" -l, --active-low:\tset the line active state to low\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" ); }int main (int argc,char **argv)@@ -39,6 +45,7 @@ int main(int argc, char **argv)unsigned int *offsets, i, num_lines;int *values, optc, opti, rv;bool active_low = false; +int flags =0 ;char *device, *end;for (;;) {@@ -56,6 +63,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case '?' :die ("try %s --help" ,get_progname ());default :@@ -86,9 +102,9 @@ int main(int argc, char **argv)Quoted 8 lines
tools/gpioget.c int main(int argc, char **argv) · line 104
Quoted 3 lines
tools/gpioget.c +0
-0die ("invalid GPIO offset: %s" , argv[i +1 ]); }Nuts - this is wrong - it should be using the CTXLESS flags, not the
LINE_REQUESTflags. That applies to all three of the tools changed. I forgot to propagate the last minute CTXLESS changes to the tools. And unfortunately we don't have test cases for the tools :-(.
Quoted 2 lines
But we do![1]
Damn - I missed that. I'll see about adding some cases for the bias flags for v2.
Kent.
Quoted 19 lines
Quoted 9 lines
I've got a fix in my github branch that I will incorporate into v2.
I'm also wondering if it would be preferable to replace the individual bias command line flags with a single bias parameter, e.g. --bias=pull-up I've coded that in my github branch as well, if you would care to compare.
Let me know if you'd like a v2, otherwise I'll hold off for a few days in case something else crops up.
Let me review the rest before that, I'll do this tomorrow.
Bart
Quoted 3 lines
Cheers,
Kent.[1] https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/tools/gpio-tools-test.bats
Re: [libgpiod] [PATCH 18/19] tools: add support for bias flags
Quoted 77 lines · Kent Gibson
Quoted 76 lines · Bartosz Golaszewski
sob., 16 lis 2019 o 16:40 Kent Gibson <[email protected]> napisał(a):
Quoted 74 lines · Kent Gibson
Quoted 64 lines
Add support for bias flags to applicable tools - gpioget, gpioset, and gpiomon.
Signed-off-by Kent Gibson <[email protected]>--- tools/gpioget.c | 24 ++++++++++++++++++++---- tools/gpiomon.c | 28 ++++++++++++++++++++++------ tools/gpioset.c | 26 +++++++++++++++++++++----- 3 files changed, 63 insertions(+), 15 deletions(-)tools/gpioget.c +17
-1@@ -17,10 +17,13 @@ static const struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "active-low", no_argument, NULL, 'l' }, + { "pull-down", no_argument, NULL, 'D' }, + { "pull-up", no_argument, NULL, 'U' }, + { "bias-disable", no_argument, NULL, 'B' }, { GETOPT_NULL_LONGOPT }, }; -static const char *const shortopts ="+hvl" ; +static const char *const shortopts ="+hvlDUB" ;static void print_help (void ) {@@ -32,6 +35,9 @@ static void print_help(void)printf (" -h, --help:\t\tdisplay this message and exit\n" );printf (" -v, --version:\tdisplay the version and exit\n" );printf (" -l, --active-low:\tset the line active state to low\n" ); +printf (" -D, --pull-down:\tenable internal pull-down\n" ); +printf (" -U, --pull-up:\tenable internal pull-up\n" ); +printf (" -B, --bias-disable:\tdisable internal bias\n" ); }int main (int argc,char **argv)@@ -39,6 +45,7 @@ int main(int argc, char **argv)unsigned int *offsets, i, num_lines;int *values, optc, opti, rv;bool active_low = false; +int flags =0 ;char *device, *end;for (;;) {@@ -56,6 +63,15 @@ int main(int argc, char **argv)case 'l' : active_low = true;break ; +case 'D' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN ; +break ; +case 'U' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP ; +break ; +case 'B' : + flags |=GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE ; +break ;case '?' :die ("try %s --help" ,get_progname ());default :tools/gpioget.c int main(int argc, char **argv) · line 104
Quoted 3 lines
tools/gpioget.c +0
-0@@ -86,9 +102,9 @@ int main(int argc, char **argv)die ("invalid GPIO offset: %s" , argv[i +1 ]); }Nuts - this is wrong - it should be using the CTXLESS flags, not the
LINE_REQUESTflags. That applies to all three of the tools changed. I forgot to propagate the last minute CTXLESS changes to the tools. And unfortunately we don't have test cases for the tools :-(.
Quoted 6 lines
Quoted 2 lines
But we do![1]
Damn - I missed that. I'll see about adding some cases for the bias flags for v2.
I've pushed some tests for the tools bias and drive options to my github branch. I will include them in v2.
They use the --bias/--drive forms as that is what is currently at the HEAD, but it is trivial to change them to the distinct flag versions if you prefer that.
Cheers,
Kent.
Quoted 20 lines
Quoted 20 lines
Quoted 10 lines
I've got a fix in my github branch that I will incorporate into v2.
I'm also wondering if it would be preferable to replace the individual bias command line flags with a single bias parameter, e.g. --bias=pull-up I've coded that in my github branch as well, if you would care to compare.
Let me know if you'd like a v2, otherwise I'll hold off for a few days in case something else crops up.
Let me review the rest before that, I'll do this tomorrow.
Bart
Quoted 3 lines
Cheers,
Kent.[1] https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/tools/gpio-tools-test.bats
PATCH 19/19 treewide: change "correspond with" to "correspond to"
In reply to Kent GibsonTrivial grammar fix. "correspond with" can mean either being in agreement with, happening at the same time, or communication between parties. "correspond to" is used to mean equivalance, which is the intended use throughout the documentation.
--- bindings/python/gpiodmodule.c | 6 +++--- include/gpiod.h | 2 +- lib/core.c | 2 +- tests/mockup/gpio-mockup.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
bindings/python/gpiodmodule.c +3 -3
@@ -1330,7 +1330,7 @@ PyDoc_STRVAR(gpiod_LineBulk_get_values_doc,"get_values() -> list of integers\n" "\n" "Read the values of all the lines held by this LineBulk object. The index\n" -"of each value in the returned list corresponds with the index of the line\n" +"of each value in the returned list corresponds to the index of the line\n" "in this gpiod.LineBulk object."); static PyObject *gpiod_LineBulk_get_values(gpiod_LineBulkObject *self,
@@ -1385,7 +1385,7 @@ PyDoc_STRVAR(gpiod_LineBulk_set_values_doc,"\n" "The number of values in the list passed as argument must be the same as\n" "the number of lines held by this gpiod.LineBulk object. The index of each\n" -"value corresponds with the index of each line in the object.\n"); +"value corresponds to the index of each line in the object.\n");static PyObject *gpiod_LineBulk_set_values (gpiod_LineBulkObject *self,PyObject *args)
@@ -1408,7 +1408,7 @@ static PyObject *gpiod_LineBulk_set_values(gpiod_LineBulkObject *self, num_vals =PyObject_Size (val_list);if (self->num_lines != num_vals) {PyErr_SetString (PyExc_TypeError, -"Number of values must correspond with the number of lines" ); +"Number of values must correspond to the number of lines" );return NULL ; }
include/gpiod.h +1 -1
@@ -779,7 +779,7 @@ gpiod_line_bulk_num_lines(struct gpiod_line_bulk *bulk)* * This is a variant of ::gpiod_line_bulk_foreach_line which uses an integer * variable (either signed or unsigned) to store the loop state. This offset -* variable is guaranteed to correspond with the offset of the current line in +* variable is guaranteed to correspond to the offset of the current line in * the bulk->lines array. */ #define gpiod_line_bulk_foreach_line_off (bulk, line, offset) \
lib/core.c +1 -1
@@ -111,7 +111,7 @@ static bool is_gpiochip_cdev(const char *path)/* * Make sure the major and minor numbers of the character device -* correspond with the ones in the dev attribute in sysfs. +* correspond to the ones in the dev attribute in sysfs. */ snprintf (devstr,sizeof (devstr),"%u:%u" ,major (statbuf.st_rdev),minor (statbuf.st_rdev));
tests/mockup/gpio-mockup.c +1 -1
@@ -333,7 +333,7 @@ EXPORT int gpio_mockup_probe(struct gpio_mockup *ctx, unsigned int num_chips,/* * We can't assume that the order in which the mockup gpiochip * devices are created will be deterministic, yet we want the -* index passed to the test_chip_*() functions to correspond with the +* index passed to the test_chip_*() functions to correspond to the * order in which the chips were defined in the TEST_DEFINE() * macro. *
Signature · 1 line
2.24.0
Re: [libgpiod] [PATCH 19/19] treewide: change "correspond with" to "correspond to"
pt., 15 lis 2019 o 15:45 Kent Gibson <[email protected]> napisał(a):
Quoted 6 lines
Trivial grammar fix. "correspond with" can mean either being in agreement with, happening at the same time, or communication between parties. "correspond to" is used to mean equivalance, which is the intended use throughout the documentation.
Thanks for this. I'm not a native English speaker, so if you see any other language issues, please let me know, or feel free to fix them.
Bart
Quoted 81 lines
Signed-off-by Kent Gibson <[email protected]>--- bindings/python/gpiodmodule.c | 6 +++--- include/gpiod.h | 2 +- lib/core.c | 2 +- tests/mockup/gpio-mockup.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)bindings/python/gpiodmodule.c +3
-3@@ -1330,7 +1330,7 @@ PyDoc_STRVAR(gpiod_LineBulk_get_values_doc,"get_values() -> list of integers\n" "\n" "Read the values of all the lines held by this LineBulk object. The index\n" -"of each value in the returned list corresponds with the index of the line\n" +"of each value in the returned list corresponds to the index of the line\n" "in this gpiod.LineBulk object."); static PyObject *gpiod_LineBulk_get_values(gpiod_LineBulkObject *self,@@ -1385,7 +1385,7 @@ PyDoc_STRVAR(gpiod_LineBulk_set_values_doc,"\n" "The number of values in the list passed as argument must be the same as\n" "the number of lines held by this gpiod.LineBulk object. The index of each\n" -"value corresponds with the index of each line in the object.\n"); +"value corresponds to the index of each line in the object.\n");static PyObject *gpiod_LineBulk_set_values (gpiod_LineBulkObject *self,PyObject *args)@@ -1408,7 +1408,7 @@ static PyObject *gpiod_LineBulk_set_values(gpiod_LineBulkObject *self, num_vals =PyObject_Size (val_list);if (self->num_lines != num_vals) {PyErr_SetString (PyExc_TypeError, -"Number of values must correspond with the number of lines" ); +"Number of values must correspond to the number of lines" );return NULL ; }include/gpiod.h +1
-1@@ -779,7 +779,7 @@ gpiod_line_bulk_num_lines(struct gpiod_line_bulk *bulk)* * This is a variant of ::gpiod_line_bulk_foreach_line which uses an integer * variable (either signed or unsigned) to store the loop state. This offset -* variable is guaranteed to correspond with the offset of the current line in +* variable is guaranteed to correspond to the offset of the current line in * the bulk->lines array. */ #define gpiod_line_bulk_foreach_line_off (bulk, line, offset) \lib/core.c +1
-1@@ -111,7 +111,7 @@ static bool is_gpiochip_cdev(const char *path)/* * Make sure the major and minor numbers of the character device -* correspond with the ones in the dev attribute in sysfs. +* correspond to the ones in the dev attribute in sysfs. */ snprintf (devstr,sizeof (devstr),"%u:%u" ,major (statbuf.st_rdev),minor (statbuf.st_rdev));tests/mockup/gpio-mockup.c +1
-2@@ -333,7 +333,7 @@ EXPORT int gpio_mockup_probe(struct gpio_mockup *ctx, unsigned int num_chips,/* * We can't assume that the order in which the mockup gpiochip * devices are created will be deterministic, yet we want the -* index passed to the test_chip_*() functions to correspond with the +* index passed to the test_chip_*() functions to correspond to the * order in which the chips were defined in the TEST_DEFINE() * macro. * -- 2.24.0
Re: [libgpiod] [PATCH 19/19] treewide: change "correspond with" to "correspond to"
Quoted 11 lines · Bartosz Golaszewski
pt., 15 lis 2019 o 15:45 Kent Gibson <[email protected]> napisał(a):
Quoted 6 lines
Trivial grammar fix. "correspond with" can mean either being in agreement with, happening at the same time, or communication between parties. "correspond to" is used to mean equivalance, which is the intended use throughout the documentation.
Thanks for this. I'm not a native English speaker, so if you see any other language issues, please let me know, or feel free to fix them.
In general usage you most often see "correspond with" in the communication sense. Using it in the other senses is rare. Ironically I wasn't totally sure on the usage without looking it up, but it felt wrong as it was. There are one or two cases in the documentation where the "in agreement with" interpretation might work, but even there the "correspond to" felt more appropriate to me.
Cheers,
Kent.
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 57 lines
This patch series adds support for changes to the GPIO uAPI that are on track to be included in the v5.5 kernel. There are two components to the uAPI changes - the addition of bias flags and a new
SET_CONFIGioctl. This series adds support to the libgpiod API, and to both C++ and Python bindings, for both of those components.The libgpiod tools are also updated, where appropriate, to support the bias flags.
There are a few additional patches that serve to restructure the code to simplify subsequent patches, or to fix minor problems discovered during development. These patches are generally adjacent to the main patch most relevant to that patch.
The series is based on the current libgpiod master@9ed02fc.
Kent Gibson (19):
core: move request flag to handle flag conversion into a separate
function
API: add support for bias flags
core: fix misspelling of parameter
tests: add tests for bias flags
bindings: cxx: drop noexcept from direction andactive_state
bindings: cxx: initialise bitset with integer instead of string
bindings: cxx: add support for bias flags
bindings: cxx: tests: add tests for bias flags
bindings: python: add support for bias flags
bindings: python: tests: add tests for bias flags
API: add support forSET_CONFIG
tests: add tests forSET_CONFIG
core: allowgpiod_line_set_value_bulkto accept null values
bindings: cxx: add support forSET_CONFIG
bindings: cxx: tests: add tests forSET_CONFIGmethods
bindings: python: add support forSET_CONFIG
bindings: python: tests: add tests forSET_CONFIGmethods
tools: add support for bias flags
treewide: change "correspond with" to "correspond to"bindings/cxx/gpiod.hpp | 85 +++- bindings/cxx/line.cpp | 60 ++- bindings/cxx/line_bulk.cpp | 95 ++++- bindings/cxx/tests/tests-line.cpp | 215 ++++++++++ bindings/python/gpiodmodule.c | 469 +++++++++++++++++++++- bindings/python/tests/gpiod_py_test.py | 254 ++++++++++++ include/gpiod.h | 303 +++++++++++++- lib/core.c | 250 ++++++++++-- lib/ctxless.c | 115 +++++- tests/mockup/gpio-mockup.c | 2 +- tests/tests-ctxless.c | 64 ++- tests/tests-event.c | 120 ++++++ tests/tests-line.c | 522 ++++++++++++++++++++++++- tools/gpioget.c | 24 +- tools/gpiomon.c | 28 +- tools/gpioset.c | 26 +- 16 files changed, 2561 insertions(+), 71 deletions(-)
Quoted 3 lines
--
2.24.0
Hi Kent,
the series looks quite good. I addressed some obvious things. I'll review v2 more in detail, but honestly, I don't think there'll be a lot of issues.
Would you mind if I applied patches 1, 3, 5, 6, 13 & 19 right away? They fix existing problems, so there's no need to carry them over to subsequent iterations of the series.
Bart
Quoted 64 lines · Bartosz Golaszewski
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 57 lines
This patch series adds support for changes to the GPIO uAPI that are on track to be included in the v5.5 kernel. There are two components to the uAPI changes - the addition of bias flags and a new
SET_CONFIGioctl. This series adds support to the libgpiod API, and to both C++ and Python bindings, for both of those components.The libgpiod tools are also updated, where appropriate, to support the bias flags.
There are a few additional patches that serve to restructure the code to simplify subsequent patches, or to fix minor problems discovered during development. These patches are generally adjacent to the main patch most relevant to that patch.
The series is based on the current libgpiod master@9ed02fc.
Kent Gibson (19):
core: move request flag to handle flag conversion into a separate
function
API: add support for bias flags
core: fix misspelling of parameter
tests: add tests for bias flags
bindings: cxx: drop noexcept from direction andactive_state
bindings: cxx: initialise bitset with integer instead of string
bindings: cxx: add support for bias flags
bindings: cxx: tests: add tests for bias flags
bindings: python: add support for bias flags
bindings: python: tests: add tests for bias flags
API: add support forSET_CONFIG
tests: add tests forSET_CONFIG
core: allowgpiod_line_set_value_bulkto accept null values
bindings: cxx: add support forSET_CONFIG
bindings: cxx: tests: add tests forSET_CONFIGmethods
bindings: python: add support forSET_CONFIG
bindings: python: tests: add tests forSET_CONFIGmethods
tools: add support for bias flags
treewide: change "correspond with" to "correspond to"bindings/cxx/gpiod.hpp | 85 +++- bindings/cxx/line.cpp | 60 ++- bindings/cxx/line_bulk.cpp | 95 ++++- bindings/cxx/tests/tests-line.cpp | 215 ++++++++++ bindings/python/gpiodmodule.c | 469 +++++++++++++++++++++- bindings/python/tests/gpiod_py_test.py | 254 ++++++++++++ include/gpiod.h | 303 +++++++++++++- lib/core.c | 250 ++++++++++-- lib/ctxless.c | 115 +++++- tests/mockup/gpio-mockup.c | 2 +- tests/tests-ctxless.c | 64 ++- tests/tests-event.c | 120 ++++++ tests/tests-line.c | 522 ++++++++++++++++++++++++- tools/gpioget.c | 24 +- tools/gpiomon.c | 28 +- tools/gpioset.c | 26 +- 16 files changed, 2561 insertions(+), 71 deletions(-)Quoted 3 lines
--
2.24.0Hi Kent,
Quoted 8 lines
the series looks quite good. I addressed some obvious things. I'll review v2 more in detail, but honestly, I don't think there'll be a lot of issues.
Would you mind if I applied patches 1, 3, 5, 6, 13 & 19 right away? They fix existing problems, so there's no need to carry them over to subsequent iterations of the series.
I don't have a problem with that.
Cheers,
Kent.
pon., 18 lis 2019 o 15:09 Kent Gibson <[email protected]> napisał(a):
Quoted 70 lines · Bartosz Golaszewski
Quoted 68 lines
pt., 15 lis 2019 o 15:44 Kent Gibson <[email protected]> napisał(a):
Quoted 57 lines
This patch series adds support for changes to the GPIO uAPI that are on track to be included in the v5.5 kernel. There are two components to the uAPI changes - the addition of bias flags and a new
SET_CONFIGioctl. This series adds support to the libgpiod API, and to both C++ and Python bindings, for both of those components.The libgpiod tools are also updated, where appropriate, to support the bias flags.
There are a few additional patches that serve to restructure the code to simplify subsequent patches, or to fix minor problems discovered during development. These patches are generally adjacent to the main patch most relevant to that patch.
The series is based on the current libgpiod master@9ed02fc.
Kent Gibson (19):
core: move request flag to handle flag conversion into a separate
function
API: add support for bias flags
core: fix misspelling of parameter
tests: add tests for bias flags
bindings: cxx: drop noexcept from direction andactive_state
bindings: cxx: initialise bitset with integer instead of string
bindings: cxx: add support for bias flags
bindings: cxx: tests: add tests for bias flags
bindings: python: add support for bias flags
bindings: python: tests: add tests for bias flags
API: add support forSET_CONFIG
tests: add tests forSET_CONFIG
core: allowgpiod_line_set_value_bulkto accept null values
bindings: cxx: add support forSET_CONFIG
bindings: cxx: tests: add tests forSET_CONFIGmethods
bindings: python: add support forSET_CONFIG
bindings: python: tests: add tests forSET_CONFIGmethods
tools: add support for bias flags
treewide: change "correspond with" to "correspond to"bindings/cxx/gpiod.hpp | 85 +++- bindings/cxx/line.cpp | 60 ++- bindings/cxx/line_bulk.cpp | 95 ++++- bindings/cxx/tests/tests-line.cpp | 215 ++++++++++ bindings/python/gpiodmodule.c | 469 +++++++++++++++++++++- bindings/python/tests/gpiod_py_test.py | 254 ++++++++++++ include/gpiod.h | 303 +++++++++++++- lib/core.c | 250 ++++++++++-- lib/ctxless.c | 115 +++++- tests/mockup/gpio-mockup.c | 2 +- tests/tests-ctxless.c | 64 ++- tests/tests-event.c | 120 ++++++ tests/tests-line.c | 522 ++++++++++++++++++++++++- tools/gpioget.c | 24 +- tools/gpiomon.c | 28 +- tools/gpioset.c | 26 +- 16 files changed, 2561 insertions(+), 71 deletions(-)Quoted 3 lines
--
2.24.0Hi Kent,
the series looks quite good. I addressed some obvious things. I'll review v2 more in detail, but honestly, I don't think there'll be a lot of issues.
Quoted 7 lines
Quoted 4 lines
Would you mind if I applied patches 1, 3, 5, 6, 13 & 19 right away? They fix existing problems, so there's no need to carry them over to subsequent iterations of the series.
I don't have a problem with that.
Done. You should be able to rebase on top of my master branch. Let's hope there are no conflicts - I had to fix up a couple details.
Bart
Quoted 2 lines
Cheers,
Kent.