1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Watchdog Driver Test Program 4 */ 5 6 #include <errno.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <fcntl.h> 12 #include <signal.h> 13 #include <getopt.h> 14 #include <sys/ioctl.h> 15 #include <linux/types.h> 16 #include <linux/watchdog.h> 17 18 #define DEFAULT_PING_RATE 1 19 20 int fd; 21 const char v = 'V'; 22 static const char sopts[] = "bdehp:t:Tn:N"; 23 static const struct option lopts[] = { 24 {"bootstatus", no_argument, NULL, 'b'}, 25 {"disable", no_argument, NULL, 'd'}, 26 {"enable", no_argument, NULL, 'e'}, 27 {"help", no_argument, NULL, 'h'}, 28 {"pingrate", required_argument, NULL, 'p'}, 29 {"timeout", required_argument, NULL, 't'}, 30 {"gettimeout", no_argument, NULL, 'T'}, 31 {"pretimeout", required_argument, NULL, 'n'}, 32 {"getpretimeout", no_argument, NULL, 'N'}, 33 {NULL, no_argument, NULL, 0x0} 34 }; 35 36 /* 37 * This function simply sends an IOCTL to the driver, which in turn ticks 38 * the PC Watchdog card to reset its internal timer so it doesn't trigger 39 * a computer reset. 40 */ 41 static void keep_alive(void) 42 { 43 int dummy; 44 int ret; 45 46 ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy); 47 if (!ret) 48 printf("."); 49 } 50 51 /* 52 * The main program. Run the program with "-d" to disable the card, 53 * or "-e" to enable the card. 54 */ 55 56 static void term(int sig) 57 { 58 int ret = write(fd, &v, 1); 59 60 close(fd); 61 if (ret < 0) 62 printf("\nStopping watchdog ticks failed (%d)...\n", errno); 63 else 64 printf("\nStopping watchdog ticks...\n"); 65 exit(0); 66 } 67 68 static void usage(char *progname) 69 { 70 printf("Usage: %s [options]\n", progname); 71 printf(" -b, --bootstatus Get last boot status (Watchdog/POR)\n"); 72 printf(" -d, --disable Turn off the watchdog timer\n"); 73 printf(" -e, --enable Turn on the watchdog timer\n"); 74 printf(" -h, --help Print the help message\n"); 75 printf(" -p, --pingrate=P Set ping rate to P seconds (default %d)\n", DEFAULT_PING_RATE); 76 printf(" -t, --timeout=T Set timeout to T seconds\n"); 77 printf(" -T, --gettimeout Get the timeout\n"); 78 printf(" -n, --pretimeout=T Set the pretimeout to T seconds\n"); 79 printf(" -N, --getpretimeout Get the pretimeout\n"); 80 printf("\n"); 81 printf("Parameters are parsed left-to-right in real-time.\n"); 82 printf("Example: %s -d -t 10 -p 5 -e\n", progname); 83 printf("Example: %s -t 12 -T -n 7 -N\n", progname); 84 } 85 86 int main(int argc, char *argv[]) 87 { 88 int flags; 89 unsigned int ping_rate = DEFAULT_PING_RATE; 90 int ret; 91 int c; 92 int oneshot = 0; 93 94 setbuf(stdout, NULL); 95 96 fd = open("/dev/watchdog", O_WRONLY); 97 98 if (fd == -1) { 99 if (errno == ENOENT) 100 printf("Watchdog device not enabled.\n"); 101 else if (errno == EACCES) 102 printf("Run watchdog as root.\n"); 103 else 104 printf("Watchdog device open failed %s\n", 105 strerror(errno)); 106 exit(-1); 107 } 108 109 while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) { 110 switch (c) { 111 case 'b': 112 flags = 0; 113 oneshot = 1; 114 ret = ioctl(fd, WDIOC_GETBOOTSTATUS, &flags); 115 if (!ret) 116 printf("Last boot is caused by: %s.\n", (flags != 0) ? 117 "Watchdog" : "Power-On-Reset"); 118 else 119 printf("WDIOC_GETBOOTSTATUS error '%s'\n", strerror(errno)); 120 break; 121 case 'd': 122 flags = WDIOS_DISABLECARD; 123 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 124 if (!ret) 125 printf("Watchdog card disabled.\n"); 126 else { 127 printf("WDIOS_DISABLECARD error '%s'\n", strerror(errno)); 128 oneshot = 1; 129 } 130 break; 131 case 'e': 132 flags = WDIOS_ENABLECARD; 133 ret = ioctl(fd, WDIOC_SETOPTIONS, &flags); 134 if (!ret) 135 printf("Watchdog card enabled.\n"); 136 else { 137 printf("WDIOS_ENABLECARD error '%s'\n", strerror(errno)); 138 oneshot = 1; 139 } 140 break; 141 case 'p': 142 ping_rate = strtoul(optarg, NULL, 0); 143 if (!ping_rate) 144 ping_rate = DEFAULT_PING_RATE; 145 printf("Watchdog ping rate set to %u seconds.\n", ping_rate); 146 break; 147 case 't': 148 flags = strtoul(optarg, NULL, 0); 149 ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags); 150 if (!ret) 151 printf("Watchdog timeout set to %u seconds.\n", flags); 152 else { 153 printf("WDIOC_SETTIMEOUT error '%s'\n", strerror(errno)); 154 oneshot = 1; 155 } 156 break; 157 case 'T': 158 oneshot = 1; 159 ret = ioctl(fd, WDIOC_GETTIMEOUT, &flags); 160 if (!ret) 161 printf("WDIOC_GETTIMEOUT returns %u seconds.\n", flags); 162 else 163 printf("WDIOC_GETTIMEOUT error '%s'\n", strerror(errno)); 164 break; 165 case 'n': 166 flags = strtoul(optarg, NULL, 0); 167 ret = ioctl(fd, WDIOC_SETPRETIMEOUT, &flags); 168 if (!ret) 169 printf("Watchdog pretimeout set to %u seconds.\n", flags); 170 else { 171 printf("WDIOC_SETPRETIMEOUT error '%s'\n", strerror(errno)); 172 oneshot = 1; 173 } 174 break; 175 case 'N': 176 oneshot = 1; 177 ret = ioctl(fd, WDIOC_GETPRETIMEOUT, &flags); 178 if (!ret) 179 printf("WDIOC_GETPRETIMEOUT returns %u seconds.\n", flags); 180 else 181 printf("WDIOC_GETPRETIMEOUT error '%s'\n", strerror(errno)); 182 break; 183 default: 184 usage(argv[0]); 185 goto end; 186 } 187 } 188 189 if (oneshot) 190 goto end; 191 192 printf("Watchdog Ticking Away!\n"); 193 194 signal(SIGINT, term); 195 196 while (1) { 197 keep_alive(); 198 sleep(ping_rate); 199 } 200 end: 201 ret = write(fd, &v, 1); 202 if (ret < 0) 203 printf("Stopping watchdog ticks failed (%d)...\n", errno); 204 close(fd); 205 return 0; 206 } 207