1 /* 2 * gpio-hammer - example swiss army knife to shake GPIO lines on a system 3 * 4 * Copyright (C) 2016 Linus Walleij 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 * 10 * Usage: 11 * gpio-hammer -n <device-name> -o <offset1> -o <offset2> 12 */ 13 14 #include <unistd.h> 15 #include <stdlib.h> 16 #include <stdbool.h> 17 #include <stdio.h> 18 #include <dirent.h> 19 #include <errno.h> 20 #include <string.h> 21 #include <poll.h> 22 #include <fcntl.h> 23 #include <getopt.h> 24 #include <sys/ioctl.h> 25 #include <linux/gpio.h> 26 #include "gpio-utils.h" 27 28 int hammer_device(const char *device_name, unsigned int *lines, int nlines, 29 unsigned int loops) 30 { 31 struct gpiohandle_data data; 32 char swirr[] = "-\\|/"; 33 int fd; 34 int ret; 35 int i, j; 36 unsigned int iteration = 0; 37 38 memset(&data.values, 0, sizeof(data.values)); 39 ret = gpiotools_request_linehandle(device_name, lines, nlines, 40 GPIOHANDLE_REQUEST_OUTPUT, &data, 41 "gpio-hammer"); 42 if (ret < 0) 43 goto exit_error; 44 else 45 fd = ret; 46 47 ret = gpiotools_get_values(fd, &data); 48 if (ret < 0) 49 goto exit_close_error; 50 51 fprintf(stdout, "Hammer lines ["); 52 for (i = 0; i < nlines; i++) { 53 fprintf(stdout, "%d", lines[i]); 54 if (i != (nlines - 1)) 55 fprintf(stdout, ", "); 56 } 57 fprintf(stdout, "] on %s, initial states: [", device_name); 58 for (i = 0; i < nlines; i++) { 59 fprintf(stdout, "%d", data.values[i]); 60 if (i != (nlines - 1)) 61 fprintf(stdout, ", "); 62 } 63 fprintf(stdout, "]\n"); 64 65 /* Hammertime! */ 66 j = 0; 67 while (1) { 68 /* Invert all lines so we blink */ 69 for (i = 0; i < nlines; i++) 70 data.values[i] = !data.values[i]; 71 72 ret = gpiotools_set_values(fd, &data); 73 if (ret < 0) 74 goto exit_close_error; 75 76 /* Re-read values to get status */ 77 ret = gpiotools_get_values(fd, &data); 78 if (ret < 0) 79 goto exit_close_error; 80 81 fprintf(stdout, "[%c] ", swirr[j]); 82 j++; 83 if (j == sizeof(swirr)-1) 84 j = 0; 85 86 fprintf(stdout, "["); 87 for (i = 0; i < nlines; i++) { 88 fprintf(stdout, "%d: %d", lines[i], data.values[i]); 89 if (i != (nlines - 1)) 90 fprintf(stdout, ", "); 91 } 92 fprintf(stdout, "]\r"); 93 fflush(stdout); 94 sleep(1); 95 iteration++; 96 if (loops && iteration == loops) 97 break; 98 } 99 fprintf(stdout, "\n"); 100 ret = 0; 101 102 exit_close_error: 103 gpiotools_release_linehandle(fd); 104 exit_error: 105 return ret; 106 } 107 108 void print_usage(void) 109 { 110 fprintf(stderr, "Usage: gpio-hammer [options]...\n" 111 "Hammer GPIO lines, 0->1->0->1...\n" 112 " -n <name> Hammer GPIOs on a named device (must be stated)\n" 113 " -o <n> Offset[s] to hammer, at least one, several can be stated\n" 114 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" 115 " -? This helptext\n" 116 "\n" 117 "Example:\n" 118 "gpio-hammer -n gpiochip0 -o 4\n" 119 ); 120 } 121 122 int main(int argc, char **argv) 123 { 124 const char *device_name = NULL; 125 unsigned int lines[GPIOHANDLES_MAX]; 126 unsigned int loops = 0; 127 int nlines; 128 int c; 129 int i; 130 131 i = 0; 132 while ((c = getopt(argc, argv, "c:n:o:?")) != -1) { 133 switch (c) { 134 case 'c': 135 loops = strtoul(optarg, NULL, 10); 136 break; 137 case 'n': 138 device_name = optarg; 139 break; 140 case 'o': 141 lines[i] = strtoul(optarg, NULL, 10); 142 i++; 143 break; 144 case '?': 145 print_usage(); 146 return -1; 147 } 148 } 149 nlines = i; 150 151 if (!device_name || !nlines) { 152 print_usage(); 153 return -1; 154 } 155 return hammer_device(device_name, lines, nlines, loops); 156 } 157