blob: 4bcb234c0fcab7dafa2f0716dee3b044b66b6fd7 [file] [log] [blame]
Linus Walleij2a144dd2016-04-26 10:47:09 +02001/*
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>
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080026#include "gpio-utils.h"
Linus Walleij2a144dd2016-04-26 10:47:09 +020027
28int hammer_device(const char *device_name, unsigned int *lines, int nlines,
29 unsigned int loops)
30{
Linus Walleij2a144dd2016-04-26 10:47:09 +020031 struct gpiohandle_data data;
Linus Walleij2a144dd2016-04-26 10:47:09 +020032 char swirr[] = "-\\|/";
33 int fd;
34 int ret;
35 int i, j;
36 unsigned int iteration = 0;
37
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080038 memset(&data.values, 0, sizeof(data.values));
39 ret = gpiotools_request_linehandle(device_name, lines, nlines,
40 GPIOHANDLE_REQUEST_OUTPUT, &data,
Uwe Kleine-König38575ed2017-01-25 22:01:44 +010041 "gpio-hammer");
Linus Walleij2a144dd2016-04-26 10:47:09 +020042 if (ret < 0)
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080043 goto exit_error;
44 else
45 fd = ret;
Linus Walleij2a144dd2016-04-26 10:47:09 +020046
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080047 ret = gpiotools_get_values(fd, &data);
48 if (ret < 0)
Linus Walleij2a144dd2016-04-26 10:47:09 +020049 goto exit_close_error;
Linus Walleij2a144dd2016-04-26 10:47:09 +020050
Linus Walleij2a144dd2016-04-26 10:47:09 +020051 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
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080072 ret = gpiotools_set_values(fd, &data);
73 if (ret < 0)
Linus Walleij2a144dd2016-04-26 10:47:09 +020074 goto exit_close_error;
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080075
Linus Walleij2a144dd2016-04-26 10:47:09 +020076 /* Re-read values to get status */
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +080077 ret = gpiotools_get_values(fd, &data);
78 if (ret < 0)
Linus Walleij2a144dd2016-04-26 10:47:09 +020079 goto exit_close_error;
Linus Walleij2a144dd2016-04-26 10:47:09 +020080
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
102exit_close_error:
Bamvor Jian Zhang74100bb2016-10-14 10:48:26 +0800103 gpiotools_release_linehandle(fd);
104exit_error:
Linus Walleij2a144dd2016-04-26 10:47:09 +0200105 return ret;
106}
107
108void 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
122int 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}