diff options
author | Greg Hackmann <ghackmann@google.com> | 2013-12-17 14:00:03 -0800 |
---|---|---|
committer | Greg Hackmann <ghackmann@google.com> | 2013-12-17 14:45:39 -0800 |
commit | 4a7bc60071901dce2af85ec56a088604b6c228ce (patch) | |
tree | bbc9afa27dc2c8e47dffc8f7b6425f4b821bf7fb | |
parent | c057503aaf53c25e67d5bf36c33cd15ec9188c5d (diff) | |
download | system_core-4a7bc60071901dce2af85ec56a088604b6c228ce.tar.gz system_core-4a7bc60071901dce2af85ec56a088604b6c228ce.tar.bz2 system_core-4a7bc60071901dce2af85ec56a088604b6c228ce.zip |
toolbox: date: use RTC subsystem on devices without /dev/alarm
Change-Id: I48c0fd1f4cffef936afb8d48d6d93babf006004d
Signed-off-by: Greg Hackmann <ghackmann@google.com>
-rw-r--r-- | toolbox/date.c | 94 |
1 files 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 <errno.h> #include <time.h> #include <linux/android_alarm.h> +#include <linux/rtc.h> #include <sys/ioctl.h> +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; |