Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * gpio-hammer - example swiss army knife to shake GPIO lines on a system
0004  *
0005  * Copyright (C) 2016 Linus Walleij
0006  *
0007  * Usage:
0008  *  gpio-hammer -n <device-name> -o <offset1> -o <offset2>
0009  */
0010 
0011 #include <unistd.h>
0012 #include <stdlib.h>
0013 #include <stdbool.h>
0014 #include <stdio.h>
0015 #include <dirent.h>
0016 #include <errno.h>
0017 #include <string.h>
0018 #include <poll.h>
0019 #include <fcntl.h>
0020 #include <getopt.h>
0021 #include <sys/ioctl.h>
0022 #include <linux/gpio.h>
0023 #include "gpio-utils.h"
0024 
0025 int hammer_device(const char *device_name, unsigned int *lines, int num_lines,
0026           unsigned int loops)
0027 {
0028     struct gpio_v2_line_values values;
0029     struct gpio_v2_line_config config;
0030     char swirr[] = "-\\|/";
0031     int fd;
0032     int ret;
0033     int i, j;
0034     unsigned int iteration = 0;
0035 
0036     memset(&config, 0, sizeof(config));
0037     config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
0038 
0039     ret = gpiotools_request_line(device_name, lines, num_lines,
0040                      &config, "gpio-hammer");
0041     if (ret < 0)
0042         goto exit_error;
0043     else
0044         fd = ret;
0045 
0046     values.mask = 0;
0047     values.bits = 0;
0048     for (i = 0; i < num_lines; i++)
0049         gpiotools_set_bit(&values.mask, i);
0050 
0051     ret = gpiotools_get_values(fd, &values);
0052     if (ret < 0)
0053         goto exit_close_error;
0054 
0055     fprintf(stdout, "Hammer lines [");
0056     for (i = 0; i < num_lines; i++) {
0057         fprintf(stdout, "%d", lines[i]);
0058         if (i != (num_lines - 1))
0059             fprintf(stdout, ", ");
0060     }
0061     fprintf(stdout, "] on %s, initial states: [", device_name);
0062     for (i = 0; i < num_lines; i++) {
0063         fprintf(stdout, "%d", gpiotools_test_bit(values.bits, i));
0064         if (i != (num_lines - 1))
0065             fprintf(stdout, ", ");
0066     }
0067     fprintf(stdout, "]\n");
0068 
0069     /* Hammertime! */
0070     j = 0;
0071     while (1) {
0072         /* Invert all lines so we blink */
0073         for (i = 0; i < num_lines; i++)
0074             gpiotools_change_bit(&values.bits, i);
0075 
0076         ret = gpiotools_set_values(fd, &values);
0077         if (ret < 0)
0078             goto exit_close_error;
0079 
0080         /* Re-read values to get status */
0081         ret = gpiotools_get_values(fd, &values);
0082         if (ret < 0)
0083             goto exit_close_error;
0084 
0085         fprintf(stdout, "[%c] ", swirr[j]);
0086         j++;
0087         if (j == sizeof(swirr) - 1)
0088             j = 0;
0089 
0090         fprintf(stdout, "[");
0091         for (i = 0; i < num_lines; i++) {
0092             fprintf(stdout, "%d: %d", lines[i],
0093                 gpiotools_test_bit(values.bits, i));
0094             if (i != (num_lines - 1))
0095                 fprintf(stdout, ", ");
0096         }
0097         fprintf(stdout, "]\r");
0098         fflush(stdout);
0099         sleep(1);
0100         iteration++;
0101         if (loops && iteration == loops)
0102             break;
0103     }
0104     fprintf(stdout, "\n");
0105     ret = 0;
0106 
0107 exit_close_error:
0108     gpiotools_release_line(fd);
0109 exit_error:
0110     return ret;
0111 }
0112 
0113 void print_usage(void)
0114 {
0115     fprintf(stderr, "Usage: gpio-hammer [options]...\n"
0116         "Hammer GPIO lines, 0->1->0->1...\n"
0117         "  -n <name>  Hammer GPIOs on a named device (must be stated)\n"
0118         "  -o <n>     Offset[s] to hammer, at least one, several can be stated\n"
0119         " [-c <n>]    Do <n> loops (optional, infinite loop if not stated)\n"
0120         "  -?         This helptext\n"
0121         "\n"
0122         "Example:\n"
0123         "gpio-hammer -n gpiochip0 -o 4\n"
0124     );
0125 }
0126 
0127 int main(int argc, char **argv)
0128 {
0129     const char *device_name = NULL;
0130     unsigned int lines[GPIOHANDLES_MAX];
0131     unsigned int loops = 0;
0132     int num_lines;
0133     int c;
0134     int i;
0135 
0136     i = 0;
0137     while ((c = getopt(argc, argv, "c:n:o:?")) != -1) {
0138         switch (c) {
0139         case 'c':
0140             loops = strtoul(optarg, NULL, 10);
0141             break;
0142         case 'n':
0143             device_name = optarg;
0144             break;
0145         case 'o':
0146             /*
0147              * Avoid overflow. Do not immediately error, we want to
0148              * be able to accurately report on the amount of times
0149              * '-o' was given to give an accurate error message
0150              */
0151             if (i < GPIOHANDLES_MAX)
0152                 lines[i] = strtoul(optarg, NULL, 10);
0153 
0154             i++;
0155             break;
0156         case '?':
0157             print_usage();
0158             return -1;
0159         }
0160     }
0161 
0162     if (i >= GPIOHANDLES_MAX) {
0163         fprintf(stderr,
0164             "Only %d occurrences of '-o' are allowed, %d were found\n",
0165             GPIOHANDLES_MAX, i + 1);
0166         return -1;
0167     }
0168 
0169     num_lines = i;
0170 
0171     if (!device_name || !num_lines) {
0172         print_usage();
0173         return -1;
0174     }
0175     return hammer_device(device_name, lines, num_lines, loops);
0176 }