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 CONSUMER "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 * @num_lines: 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 num_lines, 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_free_name; 79 } 80 81 for (i = 0; i < num_lines; i++) 82 req.lineoffsets[i] = lines[i]; 83 84 req.flags = flag; 85 strcpy(req.consumer_label, consumer_label); 86 req.lines = num_lines; 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 if (close(fd) == -1) 98 perror("Failed to close GPIO character device file"); 99 exit_free_name: 100 free(chrdev_name); 101 return ret < 0 ? ret : req.fd; 102 } 103 104 /** 105 * gpiotools_request_line() - request gpio lines in a gpiochip 106 * @device_name: The name of gpiochip without prefix "/dev/", 107 * such as "gpiochip0" 108 * @lines: An array desired lines, specified by offset 109 * index for the associated GPIO device. 110 * @num_lines: The number of lines to request. 111 * @config: The new config for requested gpio. Reference 112 * "linux/gpio.h" for config details. 113 * @consumer: The name of consumer, such as "sysfs", 114 * "powerkey". This is useful for other users to 115 * know who is using. 116 * 117 * Request gpio lines through the ioctl provided by chardev. User 118 * could call gpiotools_set_values() and gpiotools_get_values() to 119 * read and write respectively through the returned fd. Call 120 * gpiotools_release_line() to release these lines after that. 121 * 122 * Return: On success return the fd; 123 * On failure return the errno. 124 */ 125 int gpiotools_request_line(const char *device_name, unsigned int *lines, 126 unsigned int num_lines, 127 struct gpio_v2_line_config *config, 128 const char *consumer) 129 { 130 struct gpio_v2_line_request req; 131 char *chrdev_name; 132 int fd; 133 int i; 134 int ret; 135 136 ret = asprintf(&chrdev_name, "/dev/%s", device_name); 137 if (ret < 0) 138 return -ENOMEM; 139 140 fd = open(chrdev_name, 0); 141 if (fd == -1) { 142 ret = -errno; 143 fprintf(stderr, "Failed to open %s, %s\n", 144 chrdev_name, strerror(errno)); 145 goto exit_free_name; 146 } 147 148 memset(&req, 0, sizeof(req)); 149 for (i = 0; i < num_lines; i++) 150 req.offsets[i] = lines[i]; 151 152 req.config = *config; 153 strcpy(req.consumer, consumer); 154 req.num_lines = num_lines; 155 156 ret = ioctl(fd, GPIO_V2_GET_LINE_IOCTL, &req); 157 if (ret == -1) { 158 ret = -errno; 159 fprintf(stderr, "Failed to issue %s (%d), %s\n", 160 "GPIO_GET_LINE_IOCTL", ret, strerror(errno)); 161 } 162 163 if (close(fd) == -1) 164 perror("Failed to close GPIO character device file"); 165 exit_free_name: 166 free(chrdev_name); 167 return ret < 0 ? ret : req.fd; 168 } 169 170 /** 171 * gpiotools_set_values(): Set the value of gpio(s) 172 * @fd: The fd returned by 173 * gpiotools_request_line(). 174 * @values: The array of values want to set. 175 * 176 * Return: On success return 0; 177 * On failure return the errno. 178 */ 179 int gpiotools_set_values(const int fd, struct gpio_v2_line_values *values) 180 { 181 int ret; 182 183 ret = ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, values); 184 if (ret == -1) { 185 ret = -errno; 186 fprintf(stderr, "Failed to issue %s (%d), %s\n", 187 "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret, 188 strerror(errno)); 189 } 190 191 return ret; 192 } 193 194 /** 195 * gpiotools_get_values(): Get the value of gpio(s) 196 * @fd: The fd returned by 197 * gpiotools_request_line(). 198 * @values: The array of values get from hardware. 199 * 200 * Return: On success return 0; 201 * On failure return the errno. 202 */ 203 int gpiotools_get_values(const int fd, struct gpio_v2_line_values *values) 204 { 205 int ret; 206 207 ret = ioctl(fd, GPIO_V2_LINE_GET_VALUES_IOCTL, values); 208 if (ret == -1) { 209 ret = -errno; 210 fprintf(stderr, "Failed to issue %s (%d), %s\n", 211 "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, 212 strerror(errno)); 213 } 214 215 return ret; 216 } 217 218 /** 219 * gpiotools_release_linehandle(): Release the line(s) of gpiochip 220 * @fd: The fd returned by 221 * gpiotools_request_linehandle(). 222 * 223 * Return: On success return 0; 224 * On failure return the errno. 225 */ 226 int gpiotools_release_linehandle(const int fd) 227 { 228 int ret; 229 230 ret = close(fd); 231 if (ret == -1) { 232 perror("Failed to close GPIO LINEHANDLE device file"); 233 ret = -errno; 234 } 235 236 return ret; 237 } 238 239 /** 240 * gpiotools_release_line(): Release the line(s) of gpiochip 241 * @fd: The fd returned by 242 * gpiotools_request_line(). 243 * 244 * Return: On success return 0; 245 * On failure return the errno. 246 */ 247 int gpiotools_release_line(const int fd) 248 { 249 int ret; 250 251 ret = close(fd); 252 if (ret == -1) { 253 perror("Failed to close GPIO LINE device file"); 254 ret = -errno; 255 } 256 257 return ret; 258 } 259 260 /** 261 * gpiotools_get(): Get value from specific line 262 * @device_name: The name of gpiochip without prefix "/dev/", 263 * such as "gpiochip0" 264 * @line: number of line, such as 2. 265 * 266 * Return: On success return 0; 267 * On failure return the errno. 268 */ 269 int gpiotools_get(const char *device_name, unsigned int line) 270 { 271 int ret; 272 unsigned int value; 273 unsigned int lines[] = {line}; 274 275 ret = gpiotools_gets(device_name, lines, 1, &value); 276 if (ret) 277 return ret; 278 return value; 279 } 280 281 282 /** 283 * gpiotools_gets(): Get values from specific lines. 284 * @device_name: The name of gpiochip without prefix "/dev/", 285 * such as "gpiochip0". 286 * @lines: An array desired lines, specified by offset 287 * index for the associated GPIO device. 288 * @num_lines: The number of lines to request. 289 * @values: The array of values get from gpiochip. 290 * 291 * Return: On success return 0; 292 * On failure return the errno. 293 */ 294 int gpiotools_gets(const char *device_name, unsigned int *lines, 295 unsigned int num_lines, unsigned int *values) 296 { 297 int fd, i; 298 int ret; 299 int ret_close; 300 struct gpio_v2_line_config config; 301 struct gpio_v2_line_values lv; 302 303 memset(&config, 0, sizeof(config)); 304 config.flags = GPIO_V2_LINE_FLAG_INPUT; 305 ret = gpiotools_request_line(device_name, lines, num_lines, 306 &config, CONSUMER); 307 if (ret < 0) 308 return ret; 309 310 fd = ret; 311 for (i = 0; i < num_lines; i++) 312 gpiotools_set_bit(&lv.mask, i); 313 ret = gpiotools_get_values(fd, &lv); 314 if (!ret) 315 for (i = 0; i < num_lines; i++) 316 values[i] = gpiotools_test_bit(lv.bits, i); 317 ret_close = gpiotools_release_line(fd); 318 return ret < 0 ? ret : ret_close; 319 } 320 321 /** 322 * gpiotools_set(): Set value to specific line 323 * @device_name: The name of gpiochip without prefix "/dev/", 324 * such as "gpiochip0" 325 * @line: number of line, such as 2. 326 * @value: The value of gpio, must be 0(low) or 1(high). 327 * 328 * Return: On success return 0; 329 * On failure return the errno. 330 */ 331 int gpiotools_set(const char *device_name, unsigned int line, 332 unsigned int value) 333 { 334 unsigned int lines[] = {line}; 335 336 return gpiotools_sets(device_name, lines, 1, &value); 337 } 338 339 /** 340 * gpiotools_sets(): Set values to specific lines. 341 * @device_name: The name of gpiochip without prefix "/dev/", 342 * such as "gpiochip0". 343 * @lines: An array desired lines, specified by offset 344 * index for the associated GPIO device. 345 * @num_lines: The number of lines to request. 346 * @value: The array of values set to gpiochip, must be 347 * 0(low) or 1(high). 348 * 349 * Return: On success return 0; 350 * On failure return the errno. 351 */ 352 int gpiotools_sets(const char *device_name, unsigned int *lines, 353 unsigned int num_lines, unsigned int *values) 354 { 355 int ret, i; 356 struct gpio_v2_line_config config; 357 358 memset(&config, 0, sizeof(config)); 359 config.flags = GPIO_V2_LINE_FLAG_OUTPUT; 360 config.num_attrs = 1; 361 config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES; 362 for (i = 0; i < num_lines; i++) { 363 gpiotools_set_bit(&config.attrs[0].mask, i); 364 gpiotools_assign_bit(&config.attrs[0].attr.values, 365 i, values[i]); 366 } 367 ret = gpiotools_request_line(device_name, lines, num_lines, 368 &config, CONSUMER); 369 if (ret < 0) 370 return ret; 371 372 return gpiotools_release_line(ret); 373 } 374