Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * GPIO mockup cdev test helper
0004  *
0005  * Copyright (C) 2020 Kent Gibson
0006  */
0007 
0008 #include <errno.h>
0009 #include <fcntl.h>
0010 #include <signal.h>
0011 #include <stdint.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 #include <unistd.h>
0016 #include <sys/ioctl.h>
0017 #include <linux/gpio.h>
0018 
0019 #define CONSUMER    "gpio-mockup-cdev"
0020 
0021 static int request_line_v2(int cfd, unsigned int offset,
0022                uint64_t flags, unsigned int val)
0023 {
0024     struct gpio_v2_line_request req;
0025     int ret;
0026 
0027     memset(&req, 0, sizeof(req));
0028     req.num_lines = 1;
0029     req.offsets[0] = offset;
0030     req.config.flags = flags;
0031     strcpy(req.consumer, CONSUMER);
0032     if (flags & GPIO_V2_LINE_FLAG_OUTPUT) {
0033         req.config.num_attrs = 1;
0034         req.config.attrs[0].mask = 1;
0035         req.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
0036         if (val)
0037             req.config.attrs[0].attr.values = 1;
0038     }
0039     ret = ioctl(cfd, GPIO_V2_GET_LINE_IOCTL, &req);
0040     if (ret == -1)
0041         return -errno;
0042     return req.fd;
0043 }
0044 
0045 
0046 static int get_value_v2(int lfd)
0047 {
0048     struct gpio_v2_line_values vals;
0049     int ret;
0050 
0051     memset(&vals, 0, sizeof(vals));
0052     vals.mask = 1;
0053     ret = ioctl(lfd, GPIO_V2_LINE_GET_VALUES_IOCTL, &vals);
0054     if (ret == -1)
0055         return -errno;
0056     return vals.bits & 0x1;
0057 }
0058 
0059 static int request_line_v1(int cfd, unsigned int offset,
0060                uint32_t flags, unsigned int val)
0061 {
0062     struct gpiohandle_request req;
0063     int ret;
0064 
0065     memset(&req, 0, sizeof(req));
0066     req.lines = 1;
0067     req.lineoffsets[0] = offset;
0068     req.flags = flags;
0069     strcpy(req.consumer_label, CONSUMER);
0070     if (flags & GPIOHANDLE_REQUEST_OUTPUT)
0071         req.default_values[0] = val;
0072 
0073     ret = ioctl(cfd, GPIO_GET_LINEHANDLE_IOCTL, &req);
0074     if (ret == -1)
0075         return -errno;
0076     return req.fd;
0077 }
0078 
0079 static int get_value_v1(int lfd)
0080 {
0081     struct gpiohandle_data vals;
0082     int ret;
0083 
0084     memset(&vals, 0, sizeof(vals));
0085     ret = ioctl(lfd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &vals);
0086     if (ret == -1)
0087         return -errno;
0088     return vals.values[0];
0089 }
0090 
0091 static void usage(char *prog)
0092 {
0093     printf("Usage: %s [-l] [-b <bias>] [-s <value>] [-u <uAPI>] <gpiochip> <offset>\n", prog);
0094     printf("        -b: set line bias to one of pull-down, pull-up, disabled\n");
0095     printf("               (default is to leave bias unchanged):\n");
0096     printf("        -l: set line active low (default is active high)\n");
0097     printf("        -s: set line value (default is to get line value)\n");
0098     printf("        -u: uAPI version to use (default is 2)\n");
0099     exit(-1);
0100 }
0101 
0102 static int wait_signal(void)
0103 {
0104     int sig;
0105     sigset_t wset;
0106 
0107     sigemptyset(&wset);
0108     sigaddset(&wset, SIGHUP);
0109     sigaddset(&wset, SIGINT);
0110     sigaddset(&wset, SIGTERM);
0111     sigwait(&wset, &sig);
0112 
0113     return sig;
0114 }
0115 
0116 int main(int argc, char *argv[])
0117 {
0118     char *chip;
0119     int opt, ret, cfd, lfd;
0120     unsigned int offset, val = 0, abiv;
0121     uint32_t flags_v1;
0122     uint64_t flags_v2;
0123 
0124     abiv = 2;
0125     ret = 0;
0126     flags_v1 = GPIOHANDLE_REQUEST_INPUT;
0127     flags_v2 = GPIO_V2_LINE_FLAG_INPUT;
0128 
0129     while ((opt = getopt(argc, argv, "lb:s:u:")) != -1) {
0130         switch (opt) {
0131         case 'l':
0132             flags_v1 |= GPIOHANDLE_REQUEST_ACTIVE_LOW;
0133             flags_v2 |= GPIO_V2_LINE_FLAG_ACTIVE_LOW;
0134             break;
0135         case 'b':
0136             if (strcmp("pull-up", optarg) == 0) {
0137                 flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_UP;
0138                 flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_UP;
0139             } else if (strcmp("pull-down", optarg) == 0) {
0140                 flags_v1 |= GPIOHANDLE_REQUEST_BIAS_PULL_DOWN;
0141                 flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN;
0142             } else if (strcmp("disabled", optarg) == 0) {
0143                 flags_v1 |= GPIOHANDLE_REQUEST_BIAS_DISABLE;
0144                 flags_v2 |= GPIO_V2_LINE_FLAG_BIAS_DISABLED;
0145             }
0146             break;
0147         case 's':
0148             val = atoi(optarg);
0149             flags_v1 &= ~GPIOHANDLE_REQUEST_INPUT;
0150             flags_v1 |= GPIOHANDLE_REQUEST_OUTPUT;
0151             flags_v2 &= ~GPIO_V2_LINE_FLAG_INPUT;
0152             flags_v2 |= GPIO_V2_LINE_FLAG_OUTPUT;
0153             break;
0154         case 'u':
0155             abiv = atoi(optarg);
0156             break;
0157         default:
0158             usage(argv[0]);
0159         }
0160     }
0161 
0162     if (argc < optind + 2)
0163         usage(argv[0]);
0164 
0165     chip = argv[optind];
0166     offset = atoi(argv[optind + 1]);
0167 
0168     cfd = open(chip, 0);
0169     if (cfd == -1) {
0170         fprintf(stderr, "Failed to open %s: %s\n", chip, strerror(errno));
0171         return -errno;
0172     }
0173 
0174     if (abiv == 1)
0175         lfd = request_line_v1(cfd, offset, flags_v1, val);
0176     else
0177         lfd = request_line_v2(cfd, offset, flags_v2, val);
0178 
0179     close(cfd);
0180 
0181     if (lfd < 0) {
0182         fprintf(stderr, "Failed to request %s:%d: %s\n", chip, offset, strerror(-lfd));
0183         return lfd;
0184     }
0185 
0186     if (flags_v2 & GPIO_V2_LINE_FLAG_OUTPUT) {
0187         wait_signal();
0188     } else {
0189         if (abiv == 1)
0190             ret = get_value_v1(lfd);
0191         else
0192             ret = get_value_v2(lfd);
0193     }
0194 
0195     close(lfd);
0196 
0197     return ret;
0198 }