From 3719a82eb92f6af18d974093d464b03287606571 Mon Sep 17 00:00:00 2001 From: "Vanya A. Sergeev" Date: Wed, 20 May 2020 02:00:30 -0500 Subject: [PATCH] gpio: add getter for line consumer label --- docs/gpio.md | 14 ++++++++++++++ src/gpio.c | 37 +++++++++++++++++++++++++++++++++++-- src/gpio.h | 1 + tests/test_gpio.c | 6 ++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/docs/gpio.md b/docs/gpio.md index d55c684..1b66efc 100644 --- a/docs/gpio.md +++ b/docs/gpio.md @@ -36,6 +36,7 @@ int gpio_set_edge(gpio_t *gpio, gpio_edge_t edge); unsigned int gpio_line(gpio_t *gpio); int gpio_fd(gpio_t *gpio); int gpio_name(gpio_t *gpio, char *str, size_t len); +int gpio_label(gpio_t *gpio, char *str, size_t len); int gpio_chip_fd(gpio_t *gpio); int gpio_chip_name(gpio_t *gpio, char *str, size_t len); int gpio_chip_label(gpio_t *gpio, char *str, size_t len); @@ -243,6 +244,19 @@ Returns 0 on success, or a negative [GPIO error code](#return-value) on failure. ------ +``` c +int gpio_label(gpio_t *gpio, char *str, size_t len); +``` +Return the line consumer label of the GPIO. + +This method is intended for use with character device GPIOs and always returns the empty string for sysfs GPIOs. + +`gpio` should be a valid pointer to a GPIO handle opened with one of the `gpio_open*()` functions. + +Returns 0 on success, or a negative [GPIO error code](#return-value) on failure. + +------ + ``` c int gpio_chip_fd(gpio_t *gpio); ``` diff --git a/src/gpio.c b/src/gpio.c index 5a8eec4..c5b47b4 100644 --- a/src/gpio.c +++ b/src/gpio.c @@ -39,6 +39,7 @@ struct gpio_ops { unsigned int (*line)(gpio_t *gpio); int (*fd)(gpio_t *gpio); int (*name)(gpio_t *gpio, char *str, size_t len); + int (*label)(gpio_t *gpio, char *str, size_t len); int (*chip_fd)(gpio_t *gpio); int (*chip_name)(gpio_t *gpio, char *str, size_t len); int (*chip_label)(gpio_t *gpio, char *str, size_t len); @@ -149,6 +150,10 @@ int gpio_name(gpio_t *gpio, char *str, size_t len) { return gpio->ops->name(gpio, str, len); } +int gpio_label(gpio_t *gpio, char *str, size_t len) { + return gpio->ops->label(gpio, str, len); +} + int gpio_chip_fd(gpio_t *gpio) { return gpio->ops->chip_fd(gpio); } @@ -487,6 +492,11 @@ static int gpio_sysfs_name(gpio_t *gpio, char *str, size_t len) { return 0; } +static int gpio_sysfs_label(gpio_t *gpio, char *str, size_t len) { + strncpy(str, "", len); + return 0; +} + static int gpio_sysfs_chip_fd(gpio_t *gpio) { return _gpio_error(gpio, GPIO_ERROR_UNSUPPORTED, 0, "GPIO of type sysfs has no chip fd"); } @@ -596,6 +606,7 @@ static const struct gpio_ops gpio_sysfs_ops = { .line = gpio_sysfs_line, .fd = gpio_sysfs_fd, .name = gpio_sysfs_name, + .label = gpio_sysfs_label, .chip_fd = gpio_sysfs_chip_fd, .chip_name = gpio_sysfs_chip_name, .chip_label = gpio_sysfs_chip_label, @@ -891,6 +902,20 @@ static int gpio_cdev_name(gpio_t *gpio, char *str, size_t len) { return 0; } +static int gpio_cdev_label(gpio_t *gpio, char *str, size_t len) { + struct gpioline_info line_info = {0}; + + line_info.line_offset = gpio->u.cdev.line; + + if (ioctl(gpio->u.cdev.chip_fd, GPIO_GET_LINEINFO_IOCTL, &line_info) < 0) + return _gpio_error(gpio, GPIO_ERROR_QUERY, errno, "Querying GPIO line info for line %u", gpio->u.cdev.line); + + strncpy(str, line_info.consumer, len); + str[len - 1] = '\0'; + + return 0; +} + static int gpio_cdev_chip_fd(gpio_t *gpio) { return gpio->u.cdev.chip_fd; } @@ -926,6 +951,8 @@ static int gpio_cdev_tostring(gpio_t *gpio, char *str, size_t len) { const char *edge_str; char line_name[32]; const char *line_name_str; + char line_label[32]; + const char *line_label_str; char chip_name[32]; const char *chip_name_str; char chip_label[32]; @@ -950,6 +977,11 @@ static int gpio_cdev_tostring(gpio_t *gpio, char *str, size_t len) { else line_name_str = line_name; + if (gpio_cdev_label(gpio, line_label, sizeof(line_label)) < 0) + line_label_str = ""; + else + line_label_str = line_label; + if (gpio_cdev_chip_name(gpio, chip_name, sizeof(chip_name)) < 0) chip_name_str = ""; else @@ -960,8 +992,8 @@ static int gpio_cdev_tostring(gpio_t *gpio, char *str, size_t len) { else chip_label_str = chip_label; - return snprintf(str, len, "GPIO %u (name=\"%s\", line_fd=%d, chip_fd=%d, direction=%s, edge=%s, chip_name=\"%s\", chip_label=\"%s\", type=cdev)", - gpio->u.cdev.line, line_name_str, gpio->u.cdev.line_fd, gpio->u.cdev.chip_fd, direction_str, edge_str, chip_name_str, chip_label_str); + return snprintf(str, len, "GPIO %u (name=\"%s\", label=\"%s\", line_fd=%d, chip_fd=%d, direction=%s, edge=%s, chip_name=\"%s\", chip_label=\"%s\", type=cdev)", + gpio->u.cdev.line, line_name_str, line_label_str, gpio->u.cdev.line_fd, gpio->u.cdev.chip_fd, direction_str, edge_str, chip_name_str, chip_label_str); } static const struct gpio_ops gpio_cdev_ops = { @@ -977,6 +1009,7 @@ static const struct gpio_ops gpio_cdev_ops = { .line = gpio_cdev_line, .fd = gpio_cdev_fd, .name = gpio_cdev_name, + .label = gpio_cdev_label, .chip_fd = gpio_cdev_chip_fd, .chip_name = gpio_cdev_chip_name, .chip_label = gpio_cdev_chip_label, diff --git a/src/gpio.h b/src/gpio.h index d489cec..12b0369 100644 --- a/src/gpio.h +++ b/src/gpio.h @@ -72,6 +72,7 @@ int gpio_set_edge(gpio_t *gpio, gpio_edge_t edge); unsigned int gpio_line(gpio_t *gpio); int gpio_fd(gpio_t *gpio); int gpio_name(gpio_t *gpio, char *str, size_t len); +int gpio_label(gpio_t *gpio, char *str, size_t len); int gpio_chip_fd(gpio_t *gpio); int gpio_chip_name(gpio_t *gpio, char *str, size_t len); int gpio_chip_label(gpio_t *gpio, char *str, size_t len); diff --git a/tests/test_gpio.c b/tests/test_gpio.c index 47ffb38..9c71e71 100644 --- a/tests/test_gpio.c +++ b/tests/test_gpio.c @@ -7,6 +7,7 @@ #include "test.h" #include +#include #include #include @@ -40,6 +41,7 @@ void test_open_config_close(void) { bool value; gpio_direction_t direction; gpio_edge_t edge; + char label[32]; ptest(); @@ -59,6 +61,10 @@ void test_open_config_close(void) { passert(gpio_fd(gpio) >= 0); passert(gpio_chip_fd(gpio) >= 0); + /* Check default label */ + passert(gpio_label(gpio, label, sizeof(label)) == 0); + passert(strncmp(label, "periphery", sizeof(label)) == 0); + /* Invalid direction */ passert(gpio_set_direction(gpio, 5) == GPIO_ERROR_ARG); /* Invalid interrupt edge */