summaryrefslogtreecommitdiffstats
path: root/tools/gpio/gpio-hammer.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gpio/gpio-hammer.c')
-rw-r--r--tools/gpio/gpio-hammer.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c
new file mode 100644
index 000000000..54fdf59dd
--- /dev/null
+++ b/tools/gpio/gpio-hammer.c
@@ -0,0 +1,176 @@
+// 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);
+}