gpio-utils.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. #include <unistd.h>
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <errno.h>
  15. #include <string.h>
  16. #include <fcntl.h>
  17. #include <getopt.h>
  18. #include <sys/ioctl.h>
  19. #include <linux/gpio.h>
  20. #include "gpio-utils.h"
  21. #define COMSUMER "gpio-utils"
  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. ret = asprintf(&chrdev_name, "/dev/%s", device_name);
  69. if (ret < 0)
  70. return -ENOMEM;
  71. fd = open(chrdev_name, 0);
  72. if (fd == -1) {
  73. ret = -errno;
  74. fprintf(stderr, "Failed to open %s\n", chrdev_name);
  75. goto exit_close_error;
  76. }
  77. for (i = 0; i < nlines; i++)
  78. req.lineoffsets[i] = lines[i];
  79. req.flags = flag;
  80. strcpy(req.consumer_label, consumer_label);
  81. req.lines = nlines;
  82. if (flag & GPIOHANDLE_REQUEST_OUTPUT)
  83. memcpy(req.default_values, data, sizeof(req.default_values));
  84. ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
  85. if (ret == -1) {
  86. ret = -errno;
  87. fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
  88. ret);
  89. }
  90. exit_close_error:
  91. if (close(fd) == -1)
  92. perror("Failed to close GPIO character device file");
  93. free(chrdev_name);
  94. return ret < 0 ? ret : req.fd;
  95. }
  96. /**
  97. * gpiotools_set_values(): Set the value of gpio(s)
  98. * @fd: The fd returned by
  99. * gpiotools_request_linehandle().
  100. * @data: The array of values want to set.
  101. *
  102. * Return: On success return 0;
  103. * On failure return the errno.
  104. */
  105. int gpiotools_set_values(const int fd, struct gpiohandle_data *data)
  106. {
  107. int ret;
  108. ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
  109. if (ret == -1) {
  110. ret = -errno;
  111. fprintf(stderr, "Failed to issue %s (%d)\n",
  112. "GPIOHANDLE_SET_LINE_VALUES_IOCTL", ret);
  113. }
  114. return ret;
  115. }
  116. /**
  117. * gpiotools_get_values(): Get the value of gpio(s)
  118. * @fd: The fd returned by
  119. * gpiotools_request_linehandle().
  120. * @data: The array of values get from hardware.
  121. *
  122. * Return: On success return 0;
  123. * On failure return the errno.
  124. */
  125. int gpiotools_get_values(const int fd, struct gpiohandle_data *data)
  126. {
  127. int ret;
  128. ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
  129. if (ret == -1) {
  130. ret = -errno;
  131. fprintf(stderr, "Failed to issue %s (%d)\n",
  132. "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret);
  133. }
  134. return ret;
  135. }
  136. /**
  137. * gpiotools_release_linehandle(): Release the line(s) of gpiochip
  138. * @fd: The fd returned by
  139. * gpiotools_request_linehandle().
  140. *
  141. * Return: On success return 0;
  142. * On failure return the errno.
  143. */
  144. int gpiotools_release_linehandle(const int fd)
  145. {
  146. int ret;
  147. ret = close(fd);
  148. if (ret == -1) {
  149. perror("Failed to close GPIO LINEHANDLE device file");
  150. ret = -errno;
  151. }
  152. return ret;
  153. }
  154. /**
  155. * gpiotools_get(): Get value from specific line
  156. * @device_name: The name of gpiochip without prefix "/dev/",
  157. * such as "gpiochip0"
  158. * @line: number of line, such as 2.
  159. *
  160. * Return: On success return 0;
  161. * On failure return the errno.
  162. */
  163. int gpiotools_get(const char *device_name, unsigned int line)
  164. {
  165. struct gpiohandle_data data;
  166. unsigned int lines[] = {line};
  167. gpiotools_gets(device_name, lines, 1, &data);
  168. return data.values[0];
  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. * @nline: The number of lines to request.
  177. * @data: 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 nlines, struct gpiohandle_data *data)
  184. {
  185. int fd;
  186. int ret;
  187. int ret_close;
  188. ret = gpiotools_request_linehandle(device_name, lines, nlines,
  189. GPIOHANDLE_REQUEST_INPUT, data,
  190. COMSUMER);
  191. if (ret < 0)
  192. return ret;
  193. fd = ret;
  194. ret = gpiotools_get_values(fd, data);
  195. ret_close = gpiotools_release_linehandle(fd);
  196. return ret < 0 ? ret : ret_close;
  197. }
  198. /**
  199. * gpiotools_set(): Set value to specific line
  200. * @device_name: The name of gpiochip without prefix "/dev/",
  201. * such as "gpiochip0"
  202. * @line: number of line, such as 2.
  203. * @value: The value of gpio, must be 0(low) or 1(high).
  204. *
  205. * Return: On success return 0;
  206. * On failure return the errno.
  207. */
  208. int gpiotools_set(const char *device_name, unsigned int line,
  209. unsigned int value)
  210. {
  211. struct gpiohandle_data data;
  212. unsigned int lines[] = {line};
  213. data.values[0] = value;
  214. return gpiotools_sets(device_name, lines, 1, &data);
  215. }
  216. /**
  217. * gpiotools_sets(): Set values to specific lines.
  218. * @device_name: The name of gpiochip without prefix "/dev/",
  219. * such as "gpiochip0".
  220. * @lines: An array desired lines, specified by offset
  221. * index for the associated GPIO device.
  222. * @nline: The number of lines to request.
  223. * @data: The array of values set to gpiochip, must be
  224. * 0(low) or 1(high).
  225. *
  226. * Return: On success return 0;
  227. * On failure return the errno.
  228. */
  229. int gpiotools_sets(const char *device_name, unsigned int *lines,
  230. unsigned int nlines, struct gpiohandle_data *data)
  231. {
  232. int ret;
  233. ret = gpiotools_request_linehandle(device_name, lines, nlines,
  234. GPIOHANDLE_REQUEST_OUTPUT, data,
  235. COMSUMER);
  236. if (ret < 0)
  237. return ret;
  238. return gpiotools_release_linehandle(ret);
  239. }