diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 29c440b..1bdf906 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -132,7 +132,7 @@ int rtcwake_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int rtcwake_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; - const char *rtcname = NULL; + const char *rtcname = "/dev/rtc0"; const char *suspend = "standby"; const char *opt_seconds; const char *opt_time; @@ -144,6 +144,9 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv) int utc = -1; int fd; + bool is_disable = false; + bool is_general_alarm = false; + #if ENABLE_LONG_OPTS static const char rtcwake_longopts[] ALIGN1 = "auto\0" No_argument "a" @@ -157,7 +160,7 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv) #endif opt = getopt32long(argv, /* Must have -s or -t, exclusive */ - "^alud:m:s:t:" "\0" "s:t:s--t:t--s", rtcwake_longopts, + "^alud:m:s:t:" "\0" "s--t:t--s", rtcwake_longopts, &rtcname, &suspend, &opt_seconds, &opt_time); /* this is the default @@ -169,13 +172,16 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv) if (opt & RTCWAKE_OPT_SECONDS) { /* alarm time, seconds-to-sleep (relative) */ seconds = xatou(opt_seconds); - } else { - /* RTCWAKE_OPT_TIME */ + } else if (opt & RTCWAKE_OPT_TIME) { /* alarm time, time_t (absolute, seconds since 1/1 1970 UTC) */ if (sizeof(alarm_time) <= sizeof(long)) alarm_time = xatol(opt_time); else alarm_time = xatoll(opt_time); + } else if (strcmp(suspend, "disable") == 0) { + is_disable = true; + } else { + bb_show_usage(); } if (utc == -1) @@ -187,43 +193,51 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv) /* this RTC must exist and (if we'll sleep) be wakeup-enabled */ fd = rtc_xopen(&rtcname, O_RDONLY); - if (strcmp(suspend, "on") != 0) - if (!may_wakeup(rtcname)) - bb_error_msg_and_die("%s not enabled for wakeup events", rtcname); + if (!is_disable) { - /* relative or absolute alarm time, normalized to time_t */ - sys_time = time(NULL); - { - struct tm tm_time; - rtc_read_tm(&tm_time, fd); - rtc_time = rtc_tm2time(&tm_time, utc); - } + if (strcmp(suspend, "on") != 0) + if (!may_wakeup(rtcname)) + bb_error_msg_and_die("%s not enabled for wakeup events", rtcname); - if (opt & RTCWAKE_OPT_TIME) { - /* Correct for RTC<->system clock difference */ - alarm_time += rtc_time - sys_time; - if (alarm_time < rtc_time) - /* - * Compat message text. - * I'd say "RTC time is already ahead of ..." instead. - */ - bb_error_msg_and_die("time doesn't go backward to %s", ctime(&alarm_time)); - } else - alarm_time = rtc_time + seconds + 1; - - setup_alarm(fd, &alarm_time, rtc_time); - sync(); + /* relative or absolute alarm time, normalized to time_t */ + sys_time = time(NULL); + { + struct tm tm_time; + rtc_read_tm(&tm_time, fd); + rtc_time = rtc_tm2time(&tm_time, utc); + } + + if (opt & RTCWAKE_OPT_TIME) { + /* Correct for RTC<->system clock difference */ + alarm_time += rtc_time - sys_time; + if (alarm_time < rtc_time) + /* + * Compat message text. + * I'd say "RTC time is already ahead of ..." instead. + */ + bb_error_msg_and_die("time doesn't go backward to %s", ctime(&alarm_time)); + } else + alarm_time = rtc_time + seconds + 1; + + is_general_alarm = (rtc_time + (24 * 60 * 60)) > alarm_time; + + setup_alarm(fd, &alarm_time, rtc_time); + sync(); #if 0 /*debug*/ - printf("sys_time: %s", ctime(&sys_time)); - printf("rtc_time: %s", ctime(&rtc_time)); + printf("sys_time: %s", ctime(&sys_time)); + printf("rtc_time: %s", ctime(&rtc_time)); #endif - printf("wakeup from \"%s\" at %s", suspend, ctime(&alarm_time)); - fflush_all(); - usleep(10 * 1000); + printf("wakeup from \"%s\" at %s", suspend, ctime(&alarm_time)); + fflush_all(); + usleep(10 * 1000); + } - if (strcmp(suspend, "on") != 0) - xopen_xwrite_close(SYS_POWER_PATH, suspend); - else { + if (is_disable) { + printf("disabling current alarm\n"); + } else if (strcmp(suspend, "no") == 0) { + printf("just setting alarm, no powersaving mode requested\n"); + goto at_exit; + } else if (strcmp(suspend, "on") == 0) { /* "fake" suspend ... we'll do the delay ourselves */ unsigned long data; @@ -234,10 +248,27 @@ int rtcwake_main(int argc UNUSED_PARAM, char **argv) break; } } while (!(data & RTC_AF)); + } else { + xopen_xwrite_close(SYS_POWER_PATH, suspend); } - xioctl(fd, RTC_AIE_OFF, 0); + if (!is_general_alarm || is_disable) { + struct linux_rtc_wkalrm wake; + if (ioctl(fd, RTC_WKALM_RD, &wake) < 0) { + printf("read rtc alarm failed\n"); + } else { + wake.enabled = 0; + if (ioctl(fd, RTC_WKALM_SET, &wake) < 0) { + printf("disable rtc alarm interrupt failed\n"); + } + } + + } + if (is_general_alarm || is_disable) { + xioctl(fd, RTC_AIE_OFF, 0); + } +at_exit:; if (ENABLE_FEATURE_CLEAN_UP) close(fd);