From 4a7bc60071901dce2af85ec56a088604b6c228ce Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 17 Dec 2013 14:00:03 -0800 Subject: [PATCH] toolbox: date: use RTC subsystem on devices without /dev/alarm Change-Id: I48c0fd1f4cffef936afb8d48d6d93babf006004d Signed-off-by: Greg Hackmann --- toolbox/date.c | 94 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/toolbox/date.c b/toolbox/date.c index fc8e4f8d6..ed307c08b 100644 --- a/toolbox/date.c +++ b/toolbox/date.c @@ -6,15 +6,87 @@ #include #include #include +#include #include +static int settime_alarm(struct timespec *ts) { + int fd, ret; + + fd = open("/dev/alarm", O_RDWR); + if (fd < 0) + return fd; + + ret = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); + close(fd); + return ret; +} + +static int settime_alarm_tm(struct tm *tm) { + time_t t; + struct timespec ts; + + t = mktime(tm); + ts.tv_sec = t; + ts.tv_nsec = 0; + return settime_alarm(&ts); +} + +static int settime_alarm_timeval(struct timeval *tv) { + struct timespec ts; + + ts.tv_sec = tv->tv_sec; + ts.tv_nsec = tv->tv_usec * 1000; + return settime_alarm(&ts); +} + +static int settime_rtc_tm(struct tm *tm) { + int fd, ret; + struct timeval tv; + struct rtc_time rtc; + + fd = open("/dev/rtc0", O_RDWR); + if (fd < 0) + return fd; + + tv.tv_sec = mktime(tm); + tv.tv_usec = 0; + + ret = settimeofday(&tv, NULL); + if (ret < 0) + goto done; + + memset(&rtc, 0, sizeof(rtc)); + rtc.tm_sec = tm->tm_sec; + rtc.tm_min = tm->tm_min; + rtc.tm_hour = tm->tm_hour; + rtc.tm_mday = tm->tm_mday; + rtc.tm_mon = tm->tm_mon; + rtc.tm_year = tm->tm_year; + rtc.tm_wday = tm->tm_wday; + rtc.tm_yday = tm->tm_yday; + rtc.tm_isdst = tm->tm_isdst; + + ret = ioctl(fd, RTC_SET_TIME, rtc); +done: + close(fd); + return ret; +} + +static int settime_rtc_timeval(struct timeval *tv) { + struct tm tm, *err; + time_t t = tv->tv_sec; + + err = gmtime_r(&t, &tm); + if (!err) + return -1; + + return settime_rtc_tm(&tm); +} + static void settime(char *s) { struct tm tm; int day = atoi(s); int hour; - time_t t; - int fd; - struct timespec ts; while (*s && *s != '.') s++; @@ -32,12 +104,8 @@ static void settime(char *s) { tm.tm_sec = (hour % 100); tm.tm_isdst = -1; - t = mktime(&tm); - - fd = open("/dev/alarm", O_RDWR); - ts.tv_sec = t; - ts.tv_nsec = 0; - ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); + if (settime_alarm_tm(&tm) < 0) + settime_rtc_tm(&tm); } int date_main(int argc, char *argv[]) @@ -115,11 +183,9 @@ int date_main(int argc, char *argv[]) //tv.tv_usec = 0; strtotimeval(argv[optind], &tv); printf("time %s -> %lu.%lu\n", argv[optind], tv.tv_sec, tv.tv_usec); - fd = open("/dev/alarm", O_RDWR); - ts.tv_sec = tv.tv_sec; - ts.tv_nsec = tv.tv_usec * 1000; - res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); - //res = settimeofday(&tv, NULL); + res = settime_alarm_timeval(&tv); + if (res < 0) + res = settime_rtc_timeval(&tv); if(res < 0) { fprintf(stderr,"settimeofday failed %s\n", strerror(errno)); return 1;