0001
0002
0003
0004
0005
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 }