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