forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
3.8 KiB
176 lines
3.8 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* gpio-hammer - example swiss army knife to shake GPIO lines on a system |
|
* |
|
* Copyright (C) 2016 Linus Walleij |
|
* |
|
* Usage: |
|
* gpio-hammer -n <device-name> -o <offset1> -o <offset2> |
|
*/ |
|
|
|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdbool.h> |
|
#include <stdio.h> |
|
#include <dirent.h> |
|
#include <errno.h> |
|
#include <string.h> |
|
#include <poll.h> |
|
#include <fcntl.h> |
|
#include <getopt.h> |
|
#include <sys/ioctl.h> |
|
#include <linux/gpio.h> |
|
#include "gpio-utils.h" |
|
|
|
int hammer_device(const char *device_name, unsigned int *lines, int num_lines, |
|
unsigned int loops) |
|
{ |
|
struct gpio_v2_line_values values; |
|
struct gpio_v2_line_config config; |
|
char swirr[] = "-\\|/"; |
|
int fd; |
|
int ret; |
|
int i, j; |
|
unsigned int iteration = 0; |
|
|
|
memset(&config, 0, sizeof(config)); |
|
config.flags = GPIO_V2_LINE_FLAG_OUTPUT; |
|
|
|
ret = gpiotools_request_line(device_name, lines, num_lines, |
|
&config, "gpio-hammer"); |
|
if (ret < 0) |
|
goto exit_error; |
|
else |
|
fd = ret; |
|
|
|
values.mask = 0; |
|
values.bits = 0; |
|
for (i = 0; i < num_lines; i++) |
|
gpiotools_set_bit(&values.mask, i); |
|
|
|
ret = gpiotools_get_values(fd, &values); |
|
if (ret < 0) |
|
goto exit_close_error; |
|
|
|
fprintf(stdout, "Hammer lines ["); |
|
for (i = 0; i < num_lines; i++) { |
|
fprintf(stdout, "%d", lines[i]); |
|
if (i != (num_lines - 1)) |
|
fprintf(stdout, ", "); |
|
} |
|
fprintf(stdout, "] on %s, initial states: [", device_name); |
|
for (i = 0; i < num_lines; i++) { |
|
fprintf(stdout, "%d", gpiotools_test_bit(values.bits, i)); |
|
if (i != (num_lines - 1)) |
|
fprintf(stdout, ", "); |
|
} |
|
fprintf(stdout, "]\n"); |
|
|
|
/* Hammertime! */ |
|
j = 0; |
|
while (1) { |
|
/* Invert all lines so we blink */ |
|
for (i = 0; i < num_lines; i++) |
|
gpiotools_change_bit(&values.bits, i); |
|
|
|
ret = gpiotools_set_values(fd, &values); |
|
if (ret < 0) |
|
goto exit_close_error; |
|
|
|
/* Re-read values to get status */ |
|
ret = gpiotools_get_values(fd, &values); |
|
if (ret < 0) |
|
goto exit_close_error; |
|
|
|
fprintf(stdout, "[%c] ", swirr[j]); |
|
j++; |
|
if (j == sizeof(swirr) - 1) |
|
j = 0; |
|
|
|
fprintf(stdout, "["); |
|
for (i = 0; i < num_lines; i++) { |
|
fprintf(stdout, "%d: %d", lines[i], |
|
gpiotools_test_bit(values.bits, i)); |
|
if (i != (num_lines - 1)) |
|
fprintf(stdout, ", "); |
|
} |
|
fprintf(stdout, "]\r"); |
|
fflush(stdout); |
|
sleep(1); |
|
iteration++; |
|
if (loops && iteration == loops) |
|
break; |
|
} |
|
fprintf(stdout, "\n"); |
|
ret = 0; |
|
|
|
exit_close_error: |
|
gpiotools_release_line(fd); |
|
exit_error: |
|
return ret; |
|
} |
|
|
|
void print_usage(void) |
|
{ |
|
fprintf(stderr, "Usage: gpio-hammer [options]...\n" |
|
"Hammer GPIO lines, 0->1->0->1...\n" |
|
" -n <name> Hammer GPIOs on a named device (must be stated)\n" |
|
" -o <n> Offset[s] to hammer, at least one, several can be stated\n" |
|
" [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n" |
|
" -? This helptext\n" |
|
"\n" |
|
"Example:\n" |
|
"gpio-hammer -n gpiochip0 -o 4\n" |
|
); |
|
} |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
const char *device_name = NULL; |
|
unsigned int lines[GPIOHANDLES_MAX]; |
|
unsigned int loops = 0; |
|
int num_lines; |
|
int c; |
|
int i; |
|
|
|
i = 0; |
|
while ((c = getopt(argc, argv, "c:n:o:?")) != -1) { |
|
switch (c) { |
|
case 'c': |
|
loops = strtoul(optarg, NULL, 10); |
|
break; |
|
case 'n': |
|
device_name = optarg; |
|
break; |
|
case 'o': |
|
/* |
|
* Avoid overflow. Do not immediately error, we want to |
|
* be able to accurately report on the amount of times |
|
* '-o' was given to give an accurate error message |
|
*/ |
|
if (i < GPIOHANDLES_MAX) |
|
lines[i] = strtoul(optarg, NULL, 10); |
|
|
|
i++; |
|
break; |
|
case '?': |
|
print_usage(); |
|
return -1; |
|
} |
|
} |
|
|
|
if (i >= GPIOHANDLES_MAX) { |
|
fprintf(stderr, |
|
"Only %d occurrences of '-o' are allowed, %d were found\n", |
|
GPIOHANDLES_MAX, i + 1); |
|
return -1; |
|
} |
|
|
|
num_lines = i; |
|
|
|
if (!device_name || !num_lines) { |
|
print_usage(); |
|
return -1; |
|
} |
|
return hammer_device(device_name, lines, num_lines, loops); |
|
}
|
|
|