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