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