linux/tools/gpio/gpio-utils.c
<<
>>
Prefs
   1/*
   2 * GPIO tools - helpers library for the GPIO tools
   3 *
   4 * Copyright (C) 2015 Linus Walleij
   5 * Copyright (C) 2016 Bamvor Jian Zhang
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License version 2 as published by
   9 * the Free Software Foundation.
  10 */
  11
  12#include <unistd.h>
  13#include <stdlib.h>
  14#include <stdio.h>
  15#include <errno.h>
  16#include <string.h>
  17#include <fcntl.h>
  18#include <getopt.h>
  19#include <sys/ioctl.h>
  20#include <linux/gpio.h>
  21#include "gpio-utils.h"
  22
  23#define COMSUMER "gpio-utils"
  24
  25/**
  26 * doc: Operation of gpio
  27 *
  28 * Provide the api of gpiochip for chardev interface. There are two
  29 * types of api.  The first one provide as same function as each
  30 * ioctl, including request and release for lines of gpio, read/write
  31 * the value of gpio. If the user want to do lots of read and write of
  32 * lines of gpio, user should use this type of api.
  33 *
  34 * The second one provide the easy to use api for user. Each of the
  35 * following api will request gpio lines, do the operation and then
  36 * release these lines.
  37 */
  38/**
  39 * gpiotools_request_linehandle() - request gpio lines in a gpiochip
  40 * @device_name:        The name of gpiochip without prefix "/dev/",
  41 *                      such as "gpiochip0"
  42 * @lines:              An array desired lines, specified by offset
  43 *                      index for the associated GPIO device.
  44 * @nline:              The number of lines to request.
  45 * @flag:               The new flag for requsted gpio. Reference
  46 *                      "linux/gpio.h" for the meaning of flag.
  47 * @data:               Default value will be set to gpio when flag is
  48 *                      GPIOHANDLE_REQUEST_OUTPUT.
  49 * @consumer_label:     The name of consumer, such as "sysfs",
  50 *                      "powerkey". This is useful for other users to
  51 *                      know who is using.
  52 *
  53 * Request gpio lines through the ioctl provided by chardev. User
  54 * could call gpiotools_set_values() and gpiotools_get_values() to
  55 * read and write respectively through the returned fd. Call
  56 * gpiotools_release_linehandle() to release these lines after that.
  57 *
  58 * Return:              On success return the fd;
  59 *                      On failure return the errno.
  60 */
  61int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
  62                                 unsigned int nlines, unsigned int flag,
  63                                 struct gpiohandle_data *data,
  64                                 const char *consumer_label)
  65{
  66        struct gpiohandle_request req;
  67        char *chrdev_name;
  68        int fd;
  69        int i;
  70        int ret;
  71
  72        ret = asprintf(&chrdev_name, "/dev/%s", device_name);
  73        if (ret < 0)
  74                return -ENOMEM;
  75
  76        fd = open(chrdev_name, 0);
  77        if (fd == -1) {
  78                ret = -errno;
  79                fprintf(stderr, "Failed to open %s, %s\n",
  80                        chrdev_name, strerror(errno));
  81                goto exit_close_error;
  82        }
  83
  84        for (i = 0; i < nlines; i++)
  85                req.lineoffsets[i] = lines[i];
  86
  87        req.flags = flag;
  88        strcpy(req.consumer_label, consumer_label);
  89        req.lines = nlines;
  90        if (flag & GPIOHANDLE_REQUEST_OUTPUT)
  91                memcpy(req.default_values, data, sizeof(req.default_values));
  92
  93        ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
  94        if (ret == -1) {
  95                ret = -errno;
  96                fprintf(stderr, "Failed to issue %s (%d), %s\n",
  97                        "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
  98        }
  99
 100exit_close_error:
 101        if (close(fd) == -1)
 102                perror("Failed to close GPIO character device file");
 103        free(chrdev_name);
 104        return ret < 0 ? ret : req.fd;
 105}
 106/**
 107 * gpiotools_set_values(): Set the value of gpio(s)
 108 * @fd:                 The fd returned by
 109 *                      gpiotools_request_linehandle().
 110 * @data:               The array of values want to set.
 111 *
 112 * Return:              On success return 0;
 113 *                      On failure return the errno.
 114 */
 115int gpiotools_set_values(const int fd, struct gpiohandle_data *data)
 116{
 117        int ret;
 118
 119        ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
 120        if (ret == -1) {
 121                ret = -errno;
 122                fprintf(stderr, "Failed to issue %s (%d), %s\n",
 123                        "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret,
 124                        strerror(errno));
 125        }
 126
 127        return ret;
 128}
 129
 130/**
 131 * gpiotools_get_values(): Get the value of gpio(s)
 132 * @fd:                 The fd returned by
 133 *                      gpiotools_request_linehandle().
 134 * @data:               The array of values get from hardware.
 135 *
 136 * Return:              On success return 0;
 137 *                      On failure return the errno.
 138 */
 139int gpiotools_get_values(const int fd, struct gpiohandle_data *data)
 140{
 141        int ret;
 142
 143        ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
 144        if (ret == -1) {
 145                ret = -errno;
 146                fprintf(stderr, "Failed to issue %s (%d), %s\n",
 147                        "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret,
 148                        strerror(errno));
 149        }
 150
 151        return ret;
 152}
 153
 154/**
 155 * gpiotools_release_linehandle(): Release the line(s) of gpiochip
 156 * @fd:                 The fd returned by
 157 *                      gpiotools_request_linehandle().
 158 *
 159 * Return:              On success return 0;
 160 *                      On failure return the errno.
 161 */
 162int gpiotools_release_linehandle(const int fd)
 163{
 164        int ret;
 165
 166        ret = close(fd);
 167        if (ret == -1) {
 168                perror("Failed to close GPIO LINEHANDLE device file");
 169                ret = -errno;
 170        }
 171
 172        return ret;
 173}
 174
 175/**
 176 * gpiotools_get(): Get value from specific line
 177 * @device_name:        The name of gpiochip without prefix "/dev/",
 178 *                      such as "gpiochip0"
 179 * @line:               number of line, such as 2.
 180 *
 181 * Return:              On success return 0;
 182 *                      On failure return the errno.
 183 */
 184int gpiotools_get(const char *device_name, unsigned int line)
 185{
 186        struct gpiohandle_data data;
 187        unsigned int lines[] = {line};
 188
 189        gpiotools_gets(device_name, lines, 1, &data);
 190        return data.values[0];
 191}
 192
 193
 194/**
 195 * gpiotools_gets(): Get values from specific lines.
 196 * @device_name:        The name of gpiochip without prefix "/dev/",
 197 *                      such as "gpiochip0".
 198 * @lines:              An array desired lines, specified by offset
 199 *                      index for the associated GPIO device.
 200 * @nline:              The number of lines to request.
 201 * @data:               The array of values get from gpiochip.
 202 *
 203 * Return:              On success return 0;
 204 *                      On failure return the errno.
 205 */
 206int gpiotools_gets(const char *device_name, unsigned int *lines,
 207                   unsigned int nlines, struct gpiohandle_data *data)
 208{
 209        int fd;
 210        int ret;
 211        int ret_close;
 212
 213        ret = gpiotools_request_linehandle(device_name, lines, nlines,
 214                                           GPIOHANDLE_REQUEST_INPUT, data,
 215                                           COMSUMER);
 216        if (ret < 0)
 217                return ret;
 218
 219        fd = ret;
 220        ret = gpiotools_get_values(fd, data);
 221        ret_close = gpiotools_release_linehandle(fd);
 222        return ret < 0 ? ret : ret_close;
 223}
 224
 225/**
 226 * gpiotools_set(): Set value to specific line
 227 * @device_name:        The name of gpiochip without prefix "/dev/",
 228 *                      such as "gpiochip0"
 229 * @line:               number of line, such as 2.
 230 * @value:              The value of gpio, must be 0(low) or 1(high).
 231 *
 232 * Return:              On success return 0;
 233 *                      On failure return the errno.
 234 */
 235int gpiotools_set(const char *device_name, unsigned int line,
 236                  unsigned int value)
 237{
 238        struct gpiohandle_data data;
 239        unsigned int lines[] = {line};
 240
 241        data.values[0] = value;
 242        return gpiotools_sets(device_name, lines, 1, &data);
 243}
 244
 245/**
 246 * gpiotools_sets(): Set values to specific lines.
 247 * @device_name:        The name of gpiochip without prefix "/dev/",
 248 *                      such as "gpiochip0".
 249 * @lines:              An array desired lines, specified by offset
 250 *                      index for the associated GPIO device.
 251 * @nline:              The number of lines to request.
 252 * @data:               The array of values set to gpiochip, must be
 253 *                      0(low) or 1(high).
 254 *
 255 * Return:              On success return 0;
 256 *                      On failure return the errno.
 257 */
 258int gpiotools_sets(const char *device_name, unsigned int *lines,
 259                   unsigned int nlines, struct gpiohandle_data *data)
 260{
 261        int ret;
 262
 263        ret = gpiotools_request_linehandle(device_name, lines, nlines,
 264                                           GPIOHANDLE_REQUEST_OUTPUT, data,
 265                                           COMSUMER);
 266        if (ret < 0)
 267                return ret;
 268
 269        return gpiotools_release_linehandle(ret);
 270}
 271