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 */
58int 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");
99exit_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 */
125int 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");
165exit_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 */
179int 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 */
203int 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 */
226int 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 */
247int 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 */
269int 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 */
294int 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 */
331int 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 */
352int 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