177 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * gpio-hammer - example swiss army knife to shake GPIO lines on a system4 *5 * Copyright (C) 2016 Linus Walleij6 *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 else44 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, "%u", 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, "%u: %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 to148 * be able to accurately report on the amount of times149 * '-o' was given to give an accurate error message150 */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}177