| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * GPIO mockup cdev test helper
- *
- * Copyright (C) 2020 Kent Gibson
- */
- #include <errno.h>
- #include <fcntl.h>
- #include <signal.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <linux/gpio.h>
- #define CONSUMER "gpio-mockup-cdev"
- static int request_line_v2(int cfd, unsigned int offset,
- uint64_t flags, unsigned int val)
- {
- struct gpio_v2_line_request req;
- int ret;
- memset(&req, 0, sizeof(req));
- req.num_lines = 1;
- req.offsets[0] = offset;
- req.config.flags = flags;
- strcpy(req.consumer, CONSUMER);
- if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
- req.config.num_attrs = 1;
- req.config.attrs[0].mask = 1;
- req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
- if (val)
- req.config.attrs[0].attr.values = 1;
- }
- ret = ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req);
- if (ret == -1)
- return -errno;
- return req.fd;
- }
- static int get_value_v2(int lfd)
- {
- struct gpio_v2_line_values vals;
- int ret;
- memset(&vals, 0, sizeof(vals));
- vals.mask = 1;
- ret = ioctl(lfd, GPIO_V2_LINE_GET_VALUES_IOCTL, &vals);
- if (ret == -1)
- return -errno;
- return vals.bits & 0x1;
- }
- static int request_line_v1(int cfd, unsigned int offset,
- uint32_t flags, unsigned int val)
- {
- struct gpiohandle_request req;
- int ret;
- memset(&req, 0, sizeof(req));
- req.lines = 1;
- req.lineoffsets[0] = offset;
- req.flags = flags;
- strcpy(req.consumer_label, CONSUMER);
- if (flags & GPIOHANDLE_REQUEST_OUTPUT)
- req.default_values[0] = val;
- ret = ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req);
- if (ret == -1)
- return -errno;
- return req.fd;
- }
- static int get_value_v1(int lfd)
- {
- struct gpiohandle_data vals;
- int ret;
- memset(&vals, 0, sizeof(vals));
- ret = ioctl(lfd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &vals);
- if (ret == -1)
- return -errno;
- return vals.values[0];
- }
- static void usage(char *prog)
- {
- printf("Usage: %s [-l] [-b <bias>] [-s <value>] [-u <uAPI>] <gpiochip> <offset>\n", prog);
- printf(" -b: set line bias to one of pull-down, pull-up, disabled\n");
- printf(" (default is to leave bias unchanged):\n");
- printf(" -l: set line active low (default is active high)\n");
- printf(" -s: set line value (default is to get line value)\n");
- printf(" -u: uAPI version to use (default is 2)\n");
- exit(-1);
- }
- static int wait_signal(void)
- {
- int sig;
- sigset_t wset;
- sigemptyset(&wset);
- sigaddset(&wset, SIGHUP);
- sigaddset(&wset, SIGINT);
- sigaddset(&wset, SIGTERM);
- sigwait(&wset, &sig);
- return sig;
- }
- int main(int argc, char *argv[])
- {
- char *chip;
- int opt, ret, cfd, lfd;
- unsigned int offset, val = 0, abiv;
- uint32_t flags_v1;
- uint64_t flags_v2;
- abiv = 2;
- ret = 0;
- flags_v1 = GPIOHANDLE_REQUEST_INPUT;
- flags_v2 = GPIO_V2_LINE_FLAG_INPUT;
- while ((opt = getopt(argc, argv, "lb:s:u:")) != -1) {
- switch (opt) {
- case 'l':
- flags_v1 |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
- flags_v2 |= GPIO_V2_LINE_FLAG_ACTIVE_LOW;
- break;
- case 'b':
- if (strcmp("pull-up", optarg) == 0) {
- flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_UP;
- flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP;
- } else if (strcmp("pull-down", optarg) == 0) {
- flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN;
- flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN;
- } else if (strcmp("disabled", optarg) == 0) {
- flags_v1 |= GPIOHANDLE_REQUEST_BIAS_DISABLE;
- flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_DISABLED;
- }
- break;
- case 's':
- val = atoi(optarg);
- flags_v1 &= ~GPIOHANDLE_REQUEST_INPUT;
- flags_v1 |= GPIOHANDLE_REQUEST_OUTPUT;
- flags_v2 &= ~GPIO_V2_LINE_FLAG_INPUT;
- flags_v2 |= GPIO_V2_LINE_FLAG_OUTPUT;
- break;
- case 'u':
- abiv = atoi(optarg);
- break;
- default:
- usage(argv[0]);
- }
- }
- if (argc < optind + 2)
- usage(argv[0]);
- chip = argv[optind];
- offset = atoi(argv[optind + 1]);
- cfd = open(chip, 0);
- if (cfd == -1) {
- fprintf(stderr, "Failed to open %s: %s\n", chip, strerror(errno));
- return -errno;
- }
- if (abiv == 1)
- lfd = request_line_v1(cfd, offset, flags_v1, val);
- else
- lfd = request_line_v2(cfd, offset, flags_v2, val);
- close(cfd);
- if (lfd < 0) {
- fprintf(stderr, "Failed to request %s:%d: %s\n", chip, offset, strerror(-lfd));
- return lfd;
- }
- if (flags_v2 & GPIO_V2_LINE_FLAG_OUTPUT) {
- wait_signal();
- } else {
- if (abiv == 1)
- ret = get_value_v1(lfd);
- else
- ret = get_value_v2(lfd);
- }
- close(lfd);
- return ret;
- }
|