Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * gpio-hammer - example swiss army knife to shake GPIO lines on a system
4 *
5 * Copyright (C) 2016 Linus Walleij
6 *
7 * Usage:
8 * gpio-hammer -n <device-name> -o <offset1> -o <offset2>
9 */
10
11#include <unistd.h>
12#include <stdlib.h>
13#include <stdbool.h>
14#include <stdio.h>
15#include <dirent.h>
16#include <errno.h>
17#include <string.h>
18#include <poll.h>
19#include <fcntl.h>
20#include <getopt.h>
21#include <sys/ioctl.h>
22#include <linux/gpio.h>
23#include "gpio-utils.h"
24
25int hammer_device(const char *device_name, unsigned int *lines, int num_lines,
26 unsigned int loops)
27{
28 struct gpio_v2_line_values values;
29 struct gpio_v2_line_config config;
30 char swirr[] = "-\\|/";
31 int fd;
32 int ret;
33 int i, j;
34 unsigned int iteration = 0;
35
36 memset(&config, 0, sizeof(config));
37 config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
38
39 ret = gpiotools_request_line(device_name, lines, num_lines,
40 &config, "gpio-hammer");
41 if (ret < 0)
42 goto exit_error;
43 else
44 fd = ret;
45
46 values.mask = 0;
47 values.bits = 0;
48 for (i = 0; i < num_lines; i++)
49 gpiotools_set_bit(&values.mask, i);
50
51 ret = gpiotools_get_values(fd, &values);
52 if (ret < 0)
53 goto exit_close_error;
54
55 fprintf(stdout, "Hammer lines [");
56 for (i = 0; i < num_lines; i++) {
57 fprintf(stdout, "%d", lines[i]);
58 if (i != (num_lines - 1))
59 fprintf(stdout, ", ");
60 }
61 fprintf(stdout, "] on %s, initial states: [", device_name);
62 for (i = 0; i < num_lines; i++) {
63 fprintf(stdout, "%d", gpiotools_test_bit(values.bits, i));
64 if (i != (num_lines - 1))
65 fprintf(stdout, ", ");
66 }
67 fprintf(stdout, "]\n");
68
69 /* Hammertime! */
70 j = 0;
71 while (1) {
72 /* Invert all lines so we blink */
73 for (i = 0; i < num_lines; i++)
74 gpiotools_change_bit(&values.bits, i);
75
76 ret = gpiotools_set_values(fd, &values);
77 if (ret < 0)
78 goto exit_close_error;
79
80 /* Re-read values to get status */
81 ret = gpiotools_get_values(fd, &values);
82 if (ret < 0)
83 goto exit_close_error;
84
85 fprintf(stdout, "[%c] ", swirr[j]);
86 j++;
87 if (j == sizeof(swirr) - 1)
88 j = 0;
89
90 fprintf(stdout, "[");
91 for (i = 0; i < num_lines; i++) {
92 fprintf(stdout, "%d: %d", lines[i],
93 gpiotools_test_bit(values.bits, i));
94 if (i != (num_lines - 1))
95 fprintf(stdout, ", ");
96 }
97 fprintf(stdout, "]\r");
98 fflush(stdout);
99 sleep(1);
100 iteration++;
101 if (loops && iteration == loops)
102 break;
103 }
104 fprintf(stdout, "\n");
105 ret = 0;
106
107exit_close_error:
108 gpiotools_release_line(fd);
109exit_error:
110 return ret;
111}
112
113void print_usage(void)
114{
115 fprintf(stderr, "Usage: gpio-hammer [options]...\n"
116 "Hammer GPIO lines, 0->1->0->1...\n"
117 " -n <name> Hammer GPIOs on a named device (must be stated)\n"
118 " -o <n> Offset[s] to hammer, at least one, several can be stated\n"
119 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
120 " -? This helptext\n"
121 "\n"
122 "Example:\n"
123 "gpio-hammer -n gpiochip0 -o 4\n"
124 );
125}
126
127int main(int argc, char **argv)
128{
129 const char *device_name = NULL;
130 unsigned int lines[GPIOHANDLES_MAX];
131 unsigned int loops = 0;
132 int num_lines;
133 int c;
134 int i;
135
136 i = 0;
137 while ((c = getopt(argc, argv, "c:n:o:?")) != -1) {
138 switch (c) {
139 case 'c':
140 loops = strtoul(optarg, NULL, 10);
141 break;
142 case 'n':
143 device_name = optarg;
144 break;
145 case 'o':
146 /*
147 * Avoid overflow. Do not immediately error, we want to
148 * be able to accurately report on the amount of times
149 * '-o' was given to give an accurate error message
150 */
151 if (i < GPIOHANDLES_MAX)
152 lines[i] = strtoul(optarg, NULL, 10);
153
154 i++;
155 break;
156 case '?':
157 print_usage();
158 return -1;
159 }
160 }
161
162 if (i >= GPIOHANDLES_MAX) {
163 fprintf(stderr,
164 "Only %d occurrences of '-o' are allowed, %d were found\n",
165 GPIOHANDLES_MAX, i + 1);
166 return -1;
167 }
168
169 num_lines = i;
170
171 if (!device_name || !num_lines) {
172 print_usage();
173 return -1;
174 }
175 return hammer_device(device_name, lines, num_lines, loops);
176}
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * gpio-hammer - example swiss army knife to shake GPIO lines on a system
4 *
5 * Copyright (C) 2016 Linus Walleij
6 *
7 * Usage:
8 * gpio-hammer -n <device-name> -o <offset1> -o <offset2>
9 */
10
11#include <unistd.h>
12#include <stdlib.h>
13#include <stdbool.h>
14#include <stdio.h>
15#include <dirent.h>
16#include <errno.h>
17#include <string.h>
18#include <poll.h>
19#include <fcntl.h>
20#include <getopt.h>
21#include <sys/ioctl.h>
22#include <linux/gpio.h>
23#include "gpio-utils.h"
24
25int hammer_device(const char *device_name, unsigned int *lines, int nlines,
26 unsigned int loops)
27{
28 struct gpiohandle_data data;
29 char swirr[] = "-\\|/";
30 int fd;
31 int ret;
32 int i, j;
33 unsigned int iteration = 0;
34
35 memset(&data.values, 0, sizeof(data.values));
36 ret = gpiotools_request_linehandle(device_name, lines, nlines,
37 GPIOHANDLE_REQUEST_OUTPUT, &data,
38 "gpio-hammer");
39 if (ret < 0)
40 goto exit_error;
41 else
42 fd = ret;
43
44 ret = gpiotools_get_values(fd, &data);
45 if (ret < 0)
46 goto exit_close_error;
47
48 fprintf(stdout, "Hammer lines [");
49 for (i = 0; i < nlines; i++) {
50 fprintf(stdout, "%d", lines[i]);
51 if (i != (nlines - 1))
52 fprintf(stdout, ", ");
53 }
54 fprintf(stdout, "] on %s, initial states: [", device_name);
55 for (i = 0; i < nlines; i++) {
56 fprintf(stdout, "%d", data.values[i]);
57 if (i != (nlines - 1))
58 fprintf(stdout, ", ");
59 }
60 fprintf(stdout, "]\n");
61
62 /* Hammertime! */
63 j = 0;
64 while (1) {
65 /* Invert all lines so we blink */
66 for (i = 0; i < nlines; i++)
67 data.values[i] = !data.values[i];
68
69 ret = gpiotools_set_values(fd, &data);
70 if (ret < 0)
71 goto exit_close_error;
72
73 /* Re-read values to get status */
74 ret = gpiotools_get_values(fd, &data);
75 if (ret < 0)
76 goto exit_close_error;
77
78 fprintf(stdout, "[%c] ", swirr[j]);
79 j++;
80 if (j == sizeof(swirr) - 1)
81 j = 0;
82
83 fprintf(stdout, "[");
84 for (i = 0; i < nlines; i++) {
85 fprintf(stdout, "%d: %d", lines[i], data.values[i]);
86 if (i != (nlines - 1))
87 fprintf(stdout, ", ");
88 }
89 fprintf(stdout, "]\r");
90 fflush(stdout);
91 sleep(1);
92 iteration++;
93 if (loops && iteration == loops)
94 break;
95 }
96 fprintf(stdout, "\n");
97 ret = 0;
98
99exit_close_error:
100 gpiotools_release_linehandle(fd);
101exit_error:
102 return ret;
103}
104
105void print_usage(void)
106{
107 fprintf(stderr, "Usage: gpio-hammer [options]...\n"
108 "Hammer GPIO lines, 0->1->0->1...\n"
109 " -n <name> Hammer GPIOs on a named device (must be stated)\n"
110 " -o <n> Offset[s] to hammer, at least one, several can be stated\n"
111 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
112 " -? This helptext\n"
113 "\n"
114 "Example:\n"
115 "gpio-hammer -n gpiochip0 -o 4\n"
116 );
117}
118
119int main(int argc, char **argv)
120{
121 const char *device_name = NULL;
122 unsigned int lines[GPIOHANDLES_MAX];
123 unsigned int loops = 0;
124 int nlines;
125 int c;
126 int i;
127
128 i = 0;
129 while ((c = getopt(argc, argv, "c:n:o:?")) != -1) {
130 switch (c) {
131 case 'c':
132 loops = strtoul(optarg, NULL, 10);
133 break;
134 case 'n':
135 device_name = optarg;
136 break;
137 case 'o':
138 /*
139 * Avoid overflow. Do not immediately error, we want to
140 * be able to accurately report on the amount of times
141 * '-o' was given to give an accurate error message
142 */
143 if (i < GPIOHANDLES_MAX)
144 lines[i] = strtoul(optarg, NULL, 10);
145
146 i++;
147 break;
148 case '?':
149 print_usage();
150 return -1;
151 }
152 }
153
154 if (i >= GPIOHANDLES_MAX) {
155 fprintf(stderr,
156 "Only %d occurrences of '-o' are allowed, %d were found\n",
157 GPIOHANDLES_MAX, i + 1);
158 return -1;
159 }
160
161 nlines = i;
162
163 if (!device_name || !nlines) {
164 print_usage();
165 return -1;
166 }
167 return hammer_device(device_name, lines, nlines, loops);
168}