hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/tools/gpio/gpio-utils.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * GPIO tools - helpers library for the GPIO tools
34 *
45 * Copyright (C) 2015 Linus Walleij
56 * 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.
107 */
118
129 #include <unistd.h>
....@@ -20,7 +17,7 @@
2017 #include <linux/gpio.h>
2118 #include "gpio-utils.h"
2219
23
-#define COMSUMER "gpio-utils"
20
+#define CONSUMER "gpio-utils"
2421
2522 /**
2623 * doc: Operation of gpio
....@@ -41,7 +38,7 @@
4138 * such as "gpiochip0"
4239 * @lines: An array desired lines, specified by offset
4340 * index for the associated GPIO device.
44
- * @nline: The number of lines to request.
41
+ * @num_lines: The number of lines to request.
4542 * @flag: The new flag for requsted gpio. Reference
4643 * "linux/gpio.h" for the meaning of flag.
4744 * @data: Default value will be set to gpio when flag is
....@@ -59,7 +56,7 @@
5956 * On failure return the errno.
6057 */
6158 int gpiotools_request_linehandle(const char *device_name, unsigned int *lines,
62
- unsigned int nlines, unsigned int flag,
59
+ unsigned int num_lines, unsigned int flag,
6360 struct gpiohandle_data *data,
6461 const char *consumer_label)
6562 {
....@@ -78,15 +75,15 @@
7875 ret = -errno;
7976 fprintf(stderr, "Failed to open %s, %s\n",
8077 chrdev_name, strerror(errno));
81
- goto exit_close_error;
78
+ goto exit_free_name;
8279 }
8380
84
- for (i = 0; i < nlines; i++)
81
+ for (i = 0; i < num_lines; i++)
8582 req.lineoffsets[i] = lines[i];
8683
8784 req.flags = flag;
8885 strcpy(req.consumer_label, consumer_label);
89
- req.lines = nlines;
86
+ req.lines = num_lines;
9087 if (flag & GPIOHANDLE_REQUEST_OUTPUT)
9188 memcpy(req.default_values, data, sizeof(req.default_values));
9289
....@@ -97,26 +94,93 @@
9794 "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno));
9895 }
9996
100
-exit_close_error:
10197 if (close(fd) == -1)
10298 perror("Failed to close GPIO character device file");
99
+exit_free_name:
103100 free(chrdev_name);
104101 return ret < 0 ? ret : req.fd;
105102 }
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
+
106170 /**
107171 * gpiotools_set_values(): Set the value of gpio(s)
108172 * @fd: The fd returned by
109
- * gpiotools_request_linehandle().
110
- * @data: The array of values want to set.
173
+ * gpiotools_request_line().
174
+ * @values: The array of values want to set.
111175 *
112176 * Return: On success return 0;
113177 * On failure return the errno.
114178 */
115
-int gpiotools_set_values(const int fd, struct gpiohandle_data *data)
179
+int gpiotools_set_values(const int fd, struct gpio_v2_line_values *values)
116180 {
117181 int ret;
118182
119
- ret = ioctl(fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, data);
183
+ ret = ioctl(fd, GPIO_V2_LINE_SET_VALUES_IOCTL, values);
120184 if (ret == -1) {
121185 ret = -errno;
122186 fprintf(stderr, "Failed to issue %s (%d), %s\n",
....@@ -130,17 +194,17 @@
130194 /**
131195 * gpiotools_get_values(): Get the value of gpio(s)
132196 * @fd: The fd returned by
133
- * gpiotools_request_linehandle().
134
- * @data: The array of values get from hardware.
197
+ * gpiotools_request_line().
198
+ * @values: The array of values get from hardware.
135199 *
136200 * Return: On success return 0;
137201 * On failure return the errno.
138202 */
139
-int gpiotools_get_values(const int fd, struct gpiohandle_data *data)
203
+int gpiotools_get_values(const int fd, struct gpio_v2_line_values *values)
140204 {
141205 int ret;
142206
143
- ret = ioctl(fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, data);
207
+ ret = ioctl(fd, GPIO_V2_LINE_GET_VALUES_IOCTL, values);
144208 if (ret == -1) {
145209 ret = -errno;
146210 fprintf(stderr, "Failed to issue %s (%d), %s\n",
....@@ -173,6 +237,27 @@
173237 }
174238
175239 /**
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
+/**
176261 * gpiotools_get(): Get value from specific line
177262 * @device_name: The name of gpiochip without prefix "/dev/",
178263 * such as "gpiochip0"
....@@ -183,11 +268,14 @@
183268 */
184269 int gpiotools_get(const char *device_name, unsigned int line)
185270 {
186
- struct gpiohandle_data data;
271
+ int ret;
272
+ unsigned int value;
187273 unsigned int lines[] = {line};
188274
189
- gpiotools_gets(device_name, lines, 1, &data);
190
- return data.values[0];
275
+ ret = gpiotools_gets(device_name, lines, 1, &value);
276
+ if (ret)
277
+ return ret;
278
+ return value;
191279 }
192280
193281
....@@ -197,28 +285,36 @@
197285 * such as "gpiochip0".
198286 * @lines: An array desired lines, specified by offset
199287 * index for the associated GPIO device.
200
- * @nline: The number of lines to request.
201
- * @data: The array of values get from gpiochip.
288
+ * @num_lines: The number of lines to request.
289
+ * @values: The array of values get from gpiochip.
202290 *
203291 * Return: On success return 0;
204292 * On failure return the errno.
205293 */
206294 int gpiotools_gets(const char *device_name, unsigned int *lines,
207
- unsigned int nlines, struct gpiohandle_data *data)
295
+ unsigned int num_lines, unsigned int *values)
208296 {
209
- int fd;
297
+ int fd, i;
210298 int ret;
211299 int ret_close;
300
+ struct gpio_v2_line_config config;
301
+ struct gpio_v2_line_values lv;
212302
213
- ret = gpiotools_request_linehandle(device_name, lines, nlines,
214
- GPIOHANDLE_REQUEST_INPUT, data,
215
- COMSUMER);
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);
216307 if (ret < 0)
217308 return ret;
218309
219310 fd = ret;
220
- ret = gpiotools_get_values(fd, data);
221
- ret_close = gpiotools_release_linehandle(fd);
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);
222318 return ret < 0 ? ret : ret_close;
223319 }
224320
....@@ -235,11 +331,9 @@
235331 int gpiotools_set(const char *device_name, unsigned int line,
236332 unsigned int value)
237333 {
238
- struct gpiohandle_data data;
239334 unsigned int lines[] = {line};
240335
241
- data.values[0] = value;
242
- return gpiotools_sets(device_name, lines, 1, &data);
336
+ return gpiotools_sets(device_name, lines, 1, &value);
243337 }
244338
245339 /**
....@@ -248,23 +342,32 @@
248342 * such as "gpiochip0".
249343 * @lines: An array desired lines, specified by offset
250344 * index for the associated GPIO device.
251
- * @nline: The number of lines to request.
252
- * @data: The array of values set to gpiochip, must be
345
+ * @num_lines: The number of lines to request.
346
+ * @value: The array of values set to gpiochip, must be
253347 * 0(low) or 1(high).
254348 *
255349 * Return: On success return 0;
256350 * On failure return the errno.
257351 */
258352 int gpiotools_sets(const char *device_name, unsigned int *lines,
259
- unsigned int nlines, struct gpiohandle_data *data)
353
+ unsigned int num_lines, unsigned int *values)
260354 {
261
- int ret;
355
+ int ret, i;
356
+ struct gpio_v2_line_config config;
262357
263
- ret = gpiotools_request_linehandle(device_name, lines, nlines,
264
- GPIOHANDLE_REQUEST_OUTPUT, data,
265
- COMSUMER);
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);
266369 if (ret < 0)
267370 return ret;
268371
269
- return gpiotools_release_linehandle(ret);
372
+ return gpiotools_release_line(ret);
270373 }