gpio-utils.c 7.3 KB

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