#include "wdt.h" #include #include #include #include #include #include #include #include #include #define WDT_DEVICE "/dev/watchdog" #define WDT_MAX_TIMEOUT 40 #define WDT_CMD_BUFLEN 32 #define WDT_MAX_NAME_LEN 64 /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_announce(char* name, int timeout) { int fd; int ret; struct stat stat_buf; char* buf; size_t len; if ((timeout < 0) || (timeout > WDT_MAX_TIMEOUT)) return WDT_INVALID_TIMEOUT; if (name == NULL) return WDT_INVALID_NAME; fd = open(WDT_DEVICE, O_RDWR); if (fd < 0) return WDT_ALREADY_REGISTERED; ret = fstat(fd, &stat_buf); /*--- prüfen ob /dev/watchdog ein char device ist ---*/ if(! S_ISCHR(stat_buf.st_mode)) { close(fd); return WDT_UNKNOWN_HANDLE; } len = strnlen(name, WDT_MAX_NAME_LEN) + strlen("start") + 2; buf = (char*)malloc(len); if (buf == NULL) return WDT_RESOURCE_ERROR; strcpy(buf, "start "); strncat(buf, name, WDT_MAX_NAME_LEN); if (write(fd, buf, len) < 0) { switch (errno) { case EBADF: free(buf); return WDT_UNKNOWN_HANDLE; default: free(buf); return WDT_RESOURCE_ERROR; } } free(buf); watchdog_settimeout(fd, timeout); close(fd); return WDT_OK; } #if 0 /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_log(const char * __restrict format, ...) { FILE *fd; va_list arg; fd = fopen("/var/wdtlog", "a+"); va_start(arg, format); vfprintf(fd, format, arg); va_end(arg); fclose(fd); } #endif /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_register(char* name) { int fd; char* buf; int ret; struct stat stat_buf; size_t len; fd = open(WDT_DEVICE, O_RDWR); if (fd < 0) { return WDT_ALREADY_REGISTERED; } ret = fstat(fd, &stat_buf); /*--- prüfen ob /dev/watchdog ein char device ist ---*/ if(! S_ISCHR(stat_buf.st_mode)) { close(fd); return WDT_UNKNOWN_HANDLE; } if (name == NULL) return WDT_INVALID_NAME; len = strnlen(name, WDT_MAX_NAME_LEN) + 2 + strlen("register"); buf = (char*)malloc(len); if (buf == NULL) { return WDT_RESOURCE_ERROR; } strcpy(buf, "register "); strncat(buf, name, WDT_MAX_NAME_LEN); if (write(fd, buf, len) < 0) { switch (errno) { case EBADF: free(buf); return WDT_UNKNOWN_HANDLE; default: free(buf); return WDT_RESOURCE_ERROR; } } free(buf); return fd + 1; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_get_fd(int handle) { return handle - 1; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_release(int handle) { char buf[WDT_CMD_BUFLEN]; handle--; if(handle < 0) { return WDT_UNKNOWN_HANDLE; } strncpy(buf, "release", WDT_CMD_BUFLEN); buf[WDT_CMD_BUFLEN - 1] = 0; if (write(handle, buf, strlen("release") + 1) < 0) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } close(handle); return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_settimeout(int handle, int timeout) { char buf[WDT_CMD_BUFLEN]; handle--; if(handle < 0) { return WDT_UNKNOWN_HANDLE; } if (timeout <= 0) return WDT_INVALID_TIMEOUT; if (snprintf(buf, WDT_CMD_BUFLEN, "timeout %d", timeout) >= WDT_CMD_BUFLEN) return WDT_INVALID_TIMEOUT; if (write(handle, buf, strlen(buf)) < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_trigger(int handle) { handle--; if(handle < 0) { return WDT_UNKNOWN_HANDLE; } if (write(handle, "trigger", strlen("trigger")) < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ static int watchdog_set_non_blocking(int fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } if ((flags & O_NONBLOCK)) return WDT_OK; flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags)) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_set_blocking(int fd) { int flags; flags = fcntl(fd, F_GETFL); if (flags == -1) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } if ((flags & O_NONBLOCK) == 0) return WDT_OK; flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags)) { switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } } return WDT_OK; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_wait(int handle) { char c; int ret; handle--; watchdog_set_blocking(handle); ret = read(handle, (void*)&c, 1); if (ret < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; default: return WDT_RESOURCE_ERROR; } return WDT_REQUEST; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int watchdog_poll(int handle) { char c; int ret; handle--; if(handle < 0) { return WDT_UNKNOWN_HANDLE; } watchdog_set_non_blocking(handle); ret = read(handle, (void*)&c, 1); if (ret < 0) switch (errno) { case EBADF: return WDT_UNKNOWN_HANDLE; case EAGAIN: return WDT_OK; default: return WDT_RESOURCE_ERROR; } return WDT_REQUEST; }