summaryrefslogblamecommitdiffstats
path: root/core/modules/busybox/rtcwake-compat.patch
blob: 54cb02d7f9897e6a4c710d24b7010a8929bc2a71 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
                                                        
                             

                          
                                                                                    







                                                     
                                                                        








                                                     
                                                                        
       




                                                                              
 
                              
                                                                          

















                                                                               
                                                                          

















                                                                                                  














                                                                                                   




















                                                                                                           
 



























                                                                                
                                                                          



























                                                                               
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);