Path: blob/master/tools/testing/selftests/gpio/gpio-mockup-cdev.c
26285 views
// SPDX-License-Identifier: GPL-2.01/*2* GPIO mockup cdev test helper3*4* Copyright (C) 2020 Kent Gibson5*/67#include <errno.h>8#include <fcntl.h>9#include <signal.h>10#include <stdint.h>11#include <stdio.h>12#include <stdlib.h>13#include <string.h>14#include <unistd.h>15#include <sys/ioctl.h>16#include <linux/gpio.h>1718#define CONSUMER "gpio-mockup-cdev"1920static int request_line_v2(int cfd, unsigned int offset,21uint64_t flags, unsigned int val)22{23struct gpio_v2_line_request req;24int ret;2526memset(&req, 0, sizeof(req));27req.num_lines = 1;28req.offsets[0] = offset;29req.config.flags = flags;30strcpy(req.consumer, CONSUMER);31if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {32req.config.num_attrs = 1;33req.config.attrs[0].mask = 1;34req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;35if (val)36req.config.attrs[0].attr.values = 1;37}38ret = ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req);39if (ret == -1)40return -errno;41return req.fd;42}434445static int get_value_v2(int lfd)46{47struct gpio_v2_line_values vals;48int ret;4950memset(&vals, 0, sizeof(vals));51vals.mask = 1;52ret = ioctl(lfd, GPIO_V2_LINE_GET_VALUES_IOCTL, &vals);53if (ret == -1)54return -errno;55return vals.bits & 0x1;56}5758static int request_line_v1(int cfd, unsigned int offset,59uint32_t flags, unsigned int val)60{61struct gpiohandle_request req;62int ret;6364memset(&req, 0, sizeof(req));65req.lines = 1;66req.lineoffsets[0] = offset;67req.flags = flags;68strcpy(req.consumer_label, CONSUMER);69if (flags & GPIOHANDLE_REQUEST_OUTPUT)70req.default_values[0] = val;7172ret = ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req);73if (ret == -1)74return -errno;75return req.fd;76}7778static int get_value_v1(int lfd)79{80struct gpiohandle_data vals;81int ret;8283memset(&vals, 0, sizeof(vals));84ret = ioctl(lfd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &vals);85if (ret == -1)86return -errno;87return vals.values[0];88}8990static void usage(char *prog)91{92printf("Usage: %s [-l] [-b <bias>] [-s <value>] [-u <uAPI>] <gpiochip> <offset>\n", prog);93printf(" -b: set line bias to one of pull-down, pull-up, disabled\n");94printf(" (default is to leave bias unchanged):\n");95printf(" -l: set line active low (default is active high)\n");96printf(" -s: set line value (default is to get line value)\n");97printf(" -u: uAPI version to use (default is 2)\n");98exit(-1);99}100101static int wait_signal(void)102{103int sig;104sigset_t wset;105106sigemptyset(&wset);107sigaddset(&wset, SIGHUP);108sigaddset(&wset, SIGINT);109sigaddset(&wset, SIGTERM);110sigwait(&wset, &sig);111112return sig;113}114115int main(int argc, char *argv[])116{117char *chip;118int opt, ret, cfd, lfd;119unsigned int offset, val = 0, abiv;120uint32_t flags_v1;121uint64_t flags_v2;122123abiv = 2;124ret = 0;125flags_v1 = GPIOHANDLE_REQUEST_INPUT;126flags_v2 = GPIO_V2_LINE_FLAG_INPUT;127128while ((opt = getopt(argc, argv, "lb:s:u:")) != -1) {129switch (opt) {130case 'l':131flags_v1 |= GPIOHANDLE_REQUEST_ACTIVE_LOW;132flags_v2 |= GPIO_V2_LINE_FLAG_ACTIVE_LOW;133break;134case 'b':135if (strcmp("pull-up", optarg) == 0) {136flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_UP;137flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP;138} else if (strcmp("pull-down", optarg) == 0) {139flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN;140flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN;141} else if (strcmp("disabled", optarg) == 0) {142flags_v1 |= GPIOHANDLE_REQUEST_BIAS_DISABLE;143flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_DISABLED;144}145break;146case 's':147val = atoi(optarg);148flags_v1 &= ~GPIOHANDLE_REQUEST_INPUT;149flags_v1 |= GPIOHANDLE_REQUEST_OUTPUT;150flags_v2 &= ~GPIO_V2_LINE_FLAG_INPUT;151flags_v2 |= GPIO_V2_LINE_FLAG_OUTPUT;152break;153case 'u':154abiv = atoi(optarg);155break;156default:157usage(argv[0]);158}159}160161if (argc < optind + 2)162usage(argv[0]);163164chip = argv[optind];165offset = atoi(argv[optind + 1]);166167cfd = open(chip, 0);168if (cfd == -1) {169fprintf(stderr, "Failed to open %s: %s\n", chip, strerror(errno));170return -errno;171}172173if (abiv == 1)174lfd = request_line_v1(cfd, offset, flags_v1, val);175else176lfd = request_line_v2(cfd, offset, flags_v2, val);177178close(cfd);179180if (lfd < 0) {181fprintf(stderr, "Failed to request %s:%d: %s\n", chip, offset, strerror(-lfd));182return lfd;183}184185if (flags_v2 & GPIO_V2_LINE_FLAG_OUTPUT) {186wait_signal();187} else {188if (abiv == 1)189ret = get_value_v1(lfd);190else191ret = get_value_v2(lfd);192}193194close(lfd);195196return ret;197}198199200