From: Michael Welling <mwelling@ieee.org>
To: bamvor.zhangjian@linaro.org
Cc: linux-gpio@vger.kernel.org, linus.walleij@linaro.org, broonie@kernel.org
Subject: Re: [PATCH v3 1/5] tools/gpio: add gpio basic opereations
Date: Wed, 28 Sep 2016 14:16:42 -0500 [thread overview]
Message-ID: <20160928191642.hqfkmfafy7l3ss2b@qwertyuiop> (raw)
In-Reply-To: <20160831094548.12574-2-bamvor.zhangjian@linaro.org>
On Wed, Aug 31, 2016 at 11:45:44AM +0200, bamvor.zhangjian@linaro.org wrote:
> From: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
>
> Add basic gpio operations. User could get/set gpio value and/or flag for
> specific gpio chardev.
>
> Reference the "tools/testing/selftest/gpio/gpio-mockup-chardev.c" for
> how to use it.
>
> Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
> ---
> tools/gpio/gpio-utils.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++
> tools/gpio/gpio-utils.h | 121 +++++++++++++++++++++++++++++++++++
> 2 files changed, 284 insertions(+)
>
> diff --git a/tools/gpio/gpio-utils.c b/tools/gpio/gpio-utils.c
> index 8208718..3c0a35c 100644
> --- a/tools/gpio/gpio-utils.c
> +++ b/tools/gpio/gpio-utils.c
> @@ -2,10 +2,173 @@
> * GPIO tools - helpers library for the GPIO tools
> *
> * Copyright (C) 2015 Linus Walleij
> + * Copyright (C) 2016 Bamvor Jian Zhang
> *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms of the GNU General Public License version 2 as published by
> * the Free Software Foundation.
> */
>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <fcntl.h>
> +#include <getopt.h>
> +#include <sys/ioctl.h>
> +#include <linux/gpio.h>
> #include "gpio-utils.h"
> +
> +#define COMSUMER "gpio-utils"
> +
> +int gpio_request(const char *device_name, unsigned int *lines,
> + unsigned int nlines, unsigned int flag,
> + struct gpiohandle_data *data, const char *consumer_label)
> +{
> + struct gpiohandle_request req;
> + char *chrdev_name;
> + int fd;
> + int i;
> + int ret;
> +
> + ret = asprintf(&chrdev_name, "/dev/%s", device_name);
> + if (ret < 0)
> + return -ENOMEM;
> +
> + fd = open(chrdev_name, 0);
> + if (fd == -1) {
> + ret = -errno;
> + fprintf(stderr, "Failed to open %s\n", chrdev_name);
> + goto exit_close_error;
> + }
> +
> + for (i = 0; i < nlines; i++)
> + req.lineoffsets[i] = lines[i];
> +
> + req.flags = flag;
> + strcpy(req.consumer_label, consumer_label);
> + req.lines = nlines;
> + if (flag & GPIOHANDLE_REQUEST_OUTPUT)
> + memcpy(req.default_values, data, sizeof(req.default_values));
> +
> + ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
> + if (ret == -1) {
> + ret = -errno;
> + fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
> + ret);
> + goto exit_close_error;
> + }
> +
> +exit_close_error:
> + if (close(fd) == -1)
> + perror("Failed to close GPIO character device file");
> + free(chrdev_name);
> + return ret < 0 ? ret : req.fd;
> +}
> +
> +int gpio_set_values(const int fd, struct gpiohandle_data *data)
> +{
> + int ret;
> +
> + ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
> + if (ret == -1) {
> + ret = -errno;
> + fprintf(stderr, "Failed to issue %s (%d)\n",
> + "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
> + goto exit_close_error;
This goto is unnecessary because there is no code to be skipped.
> + }
> +
> +exit_close_error:
> + return ret;
> +}
> +
> +int gpio_get_values(const int fd, struct gpiohandle_data *data)
> +{
> + int ret;
> +
> + ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
> + if (ret == -1) {
> + ret = -errno;
> + fprintf(stderr, "Failed to issue %s (%d)\n",
> + "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret);
> + goto exit_close_error;
Same here.
> + }
> +
> +exit_close_error:
> + return ret;
> +}
> +
> +int gpio_release(const int fd)
> +{
> + int ret;
> +
> + ret = close(fd);
> + if (ret < -1)
> + perror("Failed to close GPIO LINEHANDLE device file");
> +
> + return ret;
> +}
> +
> +int gpio_gets(const char *device_name, unsigned int *lines, unsigned int nlines,
> + unsigned int flag, struct gpiohandle_data *data)
> +{
> + int fd;
> + int ret;
> +
> + ret = gpio_request(device_name, lines, nlines, flag, data, COMSUMER);
> + if (ret < 0)
> + return ret;
> +
> + fd = ret;
> + ret = gpio_get_values(fd, data);
The error checking is missing here.
> + ret = gpio_release(fd);
Shouldn't we leave it up the user how they want the deal with the file handle?
There is more system call overhead if we open and close the GPIO device for
each access.
> + return ret;
> +}
> +
> +int gpio_sets(const char *device_name, unsigned int *lines, unsigned int nlines,
> + unsigned int flag, struct gpiohandle_data *data)
> +{
> + int ret;
> +
> + ret = gpio_request(device_name, lines, nlines, flag, data, COMSUMER);
> + if (ret < 0)
> + return ret;
> +
> + ret = gpio_release(ret);
> + return ret;
> +}
> +
> +int gpio_get(const char *device_name, unsigned int line, unsigned int flag)
> +{
> + struct gpiohandle_data data;
> + unsigned int lines[] = {line};
Is the lines variable really needed?
> +
> + gpio_gets(device_name, lines, 1, flag, &data);
> + return data.values[0];
> +}
> +
> +int gpio_set(const char *device_name, unsigned int line, unsigned int flag,
> + unsigned int value)
> +{
> + struct gpiohandle_data data;
> + unsigned int lines[] = {line};
> +
> + data.values[0] = value;
> + return gpio_sets(device_name, lines, 1, flag, &data);
> +}
> +
> +int gpio_set_flag(const char *device_name, unsigned int line, unsigned int flag)
> +{
> + struct gpiohandle_data data;
> + unsigned int lines[] = {line};
> + int ret;
> +
> + ret = gpio_request(device_name, lines, 1, flag, &data, COMSUMER);
> + if (ret < 0)
> + return ret;
> +
> + ret = gpio_release(ret);
> + return ret;
> +}
> +
> diff --git a/tools/gpio/gpio-utils.h b/tools/gpio/gpio-utils.h
> index 5f57133..fcf87b6 100644
> --- a/tools/gpio/gpio-utils.h
> +++ b/tools/gpio/gpio-utils.h
> @@ -24,4 +24,125 @@ static inline int check_prefix(const char *str, const char *prefix)
> strncmp(str, prefix, strlen(prefix)) == 0;
> }
>
> +/* Basic operation of gpio */
> +/*
> + * Request the lines for gpio with device_name. Could set the default value
> + * in request.
> + * device_name: the name of gpiochip in "/dev", such as gpiochip0.
> + * lines: the array of which line should be requested.
> + * nline: the total number of line
> + * flag: input, output and so on. Reference "linux/gpio.h" for the
> + * meaning for flag.
> + * data: default value when flag is GPIOHANDLE_REQUEST_OUTPUT.
> + * consumer_label: the name of consumer, such as "sysfs", "powerkey".
> + *
> + * Return value: On success return the fd of specific gpiochip. It could be
> + * release by gpio_release.
> + * On failure return the errno.
> + */
> +int gpio_request(const char *device_name, unsigned int *lines,
> + unsigned int nlines, unsigned int flag,
> + struct gpiohandle_data *data, const char *consumer_label);
> +/*
> + * Set the value of gpio for fd
> + * fd: the fd returned by gpio_request
> + * data: the value want to set
> + *
> + * Return value: On success return 0
> + * On failure return the errno.
> + */
> +int gpio_set_values(const int fd, struct gpiohandle_data *data);
> +
> +/*
> + * Get the value of gpio for fd
> + * fd: the fd returned by gpio_request
> + * data: the valud get from gpiochip.
> + *
> + * Return value: On success return 0
> + * On failure return the errno.
> + */
> +int gpio_get_values(const int fd, struct gpiohandle_data *data);
> +
> +/*
> + * release the fd for gpiochip
> + */
> +int gpio_release(const int fd);
> +
> +/* Easy operation for one time get/set */
> +/*
> + * Get one pin value from line of device_name. Could change the flag if
> + * necessary.
> + * device_name: the name of gpiochip in "/dev", such as gpiochip0.
> + * line: number of line, such as 2.
> + * flag: input, output and so on. Reference "linux/gpio.h" for the
> + * meaning for flag. Set to 0 if do not want to update the
> + * flag. It is the recommandation value.
> + *
> + * Return value: On success return the value get from gpiochip.
> + * On failure return the errno.
> + */
> +int gpio_get(const char *device_name, unsigned int line, unsigned int flag);
> +
> +/*
> + * Get pins value from line of device_name. Could change the flag if
> + * necessary.
> + * device_name: the name of gpiochip in "/dev", such as gpiochip0.
> + * lines: the array of which line should be requested.
> + * nline: the total number of line
> + * flag: input, output and so on. Reference "linux/gpio.h" for the
> + * meaning for flag.
> + * data: the valud get from gpiochip.
> + *
> + * Return value: On success return 0
> + * On failure return the errno.
> + */
> +int gpio_gets(const char *device_name, unsigned int *lines, unsigned int nlines,
> + unsigned int flag, struct gpiohandle_data *data);
> +
> +/*
> + * Set one pin value from line of device_name. Could change the flag if
> + * necessary.
> + * device_name: the name of gpiochip in "/dev", such as gpiochip0.
> + * line: number of line, such as 2.
> + * flag: input, output and so on. Reference "linux/gpio.h" for the
> + * meaning for flag. Set to 0 if do not want to update the
> + * flag. It is the recommandation value.
> + * value: the value want to set the gpio line.
> + *
> + * Return value: On success return 0
> + * On failure return the errno.
> + */
> +int gpio_set(const char *device_name, unsigned int line, unsigned int flag,
> + unsigned int value);
> +
> +/*
> + * Set pins value from line of device_name. Could change the flag if
> + * necessary.
> + * device_name: the name of gpiochip in "/dev", such as gpiochip0.
> + * lines: the array of which line should be requested.
> + * nline: the total number of line
> + * flag: input, output and so on. Reference "linux/gpio.h" for the
> + * meaning for flag.
> + * data: the value want to set
> + *
> + * Return value: On success return 0
> + * On failure return the errno.
> + */
> +int gpio_sets(const char *device_name, unsigned int *lines, unsigned int nlines,
> + unsigned int flag, struct gpiohandle_data *data);
> +
> +/*
> + * set the flag for device_name. Mainly for changing the direction of gpio
> + *
> + * device_name: the name of gpiochip in "/dev", such as gpiochip0.
> + * line: number of line, such as 2.
> + * flag: input, output and so on. Reference "linux/gpio.h" for the
> + * meaning for flag.
> + *
> + * Return value: On success return 0
> + * On failure return the errno.
> + */
> +int gpio_set_flag(const char *device_name, unsigned int line,
> + unsigned int flag);
> +
> #endif /* _GPIO_UTILS_H_ */
> --
> 1.8.4.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2016-09-28 19:16 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-31 9:45 [PATCH v3 0/5] Add gpio test framework bamvor.zhangjian
2016-08-31 9:45 ` [PATCH v3 1/5] tools/gpio: add gpio basic opereations bamvor.zhangjian
2016-09-26 19:37 ` Linus Walleij
2016-09-28 19:16 ` Michael Welling [this message]
2016-09-28 21:35 ` Bamvor Zhang Jian
2016-09-28 22:12 ` Michael Welling
2016-08-31 9:45 ` [PATCH v3 2/5] tools/gpio: re-work gpio hammer with gpio operations bamvor.zhangjian
2016-10-13 4:28 ` Bamvor Zhang Jian
2016-08-31 9:45 ` [PATCH v3 3/5] gpio/mockup: add virtual gpio device bamvor.zhangjian
2016-09-26 18:48 ` Linus Walleij
2016-08-31 9:45 ` [PATCH v3 4/5] selftest/gpio: add gpio test case bamvor.zhangjian
2016-08-31 9:45 ` [PATCH v3 5/5] gpio: MAINTAINERS: Add an entry for GPIO mockup driver bamvor.zhangjian
2016-09-26 18:50 ` Linus Walleij
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160928191642.hqfkmfafy7l3ss2b@qwertyuiop \
--to=mwelling@ieee.org \
--cc=bamvor.zhangjian@linaro.org \
--cc=broonie@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).