gpio-utils.c 7.2 KB

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