#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <asm/ioctl.h>
//#include <linux/rtc.h>
#include <linux/android_alarm.h>
int alarm_main(int argc, char *argv[])
{
int c;
int res;
struct tm tm;
time_t t;
struct timespec ts;
// struct rtc_time rtc_time;
char strbuf[26];
int afd;
int nfd;
// struct timeval timeout = { 0, 0 };
int wait = 0;
fd_set rfds;
const char wake_lock_id[] = "alarm_test";
int waitalarmmask = 0;
int useutc = 0;
android_alarm_type_t alarmtype_low = ANDROID_ALARM_RTC_WAKEUP;
android_alarm_type_t alarmtype_high = ANDROID_ALARM_RTC_WAKEUP;
android_alarm_type_t alarmtype = 0;
do {
//c = getopt(argc, argv, "uw:");
c = getopt(argc, argv, "uwat:");
if (c == EOF)
break;
switch (c) {
case 'u':
useutc = 1;
break;
case 't':
alarmtype_low = alarmtype_high = strtol(optarg, NULL, 0);
break;
case 'a':
alarmtype_low = ANDROID_ALARM_RTC_WAKEUP;
alarmtype_high = ANDROID_ALARM_TYPE_COUNT - 1;
break;
case 'w':
//timeout.tv_sec = strtol(optarg, NULL, 0);
wait = 1;
break;
case '?':
fprintf(stderr, "%s: invalid option -%c\n",
argv[0], optopt);
exit(1);
}
} while (1);
if(optind + 2 < argc) {
fprintf(stderr,"%s [-uwa] [-t type] [seconds]\n", argv[0]);
return 1;
}
afd = open("/dev/alarm", O_RDWR);
if(afd < 0) {
fprintf(stderr, "Unable to open rtc: %s\n", strerror(errno));
return 1;
}
if(optind == argc) {
for(alarmtype = alarmtype_low; alarmtype <= alarmtype_high; alarmtype++) {
waitalarmmask |= 1U << alarmtype;
}
#if 0
res = ioctl(fd, RTC_ALM_READ, &tm);
if(res < 0) {
fprintf(stderr, "Unable to read alarm: %s\n", strerror(errno));
return 1;
}
#endif
#if 0
t = timegm(&tm);
if(useutc)
gmtime_r(&t, &tm);
else
localtime_r(&t, &tm);
#endif
#if 0
asctime_r(&tm, strbuf);
printf("%s", strbuf);
#endif
}
else if(optind + 1 == argc) {
#if 0
res = ioctl(fd, RTC_RD_TIME, &tm);
if(res < 0) {
fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
return 1;
}
asctime_r(&tm, strbuf);
printf("Now: %s", strbuf);
time(&tv.tv_sec);
#endif
#if 0
time(&ts.tv_sec);
ts.tv_nsec = 0;
//strptime(argv[optind], NULL, &tm);
//tv.tv_sec = mktime(&tm);
//tv.tv_usec = 0;
#endif
for(alarmtype = alarmtype_low; alarmtype <= alarmtype_high; alarmtype++) {
waitalarmmask |= 1U << alarmtype;
res = ioctl(afd, ANDROID_ALARM_GET_TIME(alarmtype), &ts);
if(res < 0) {
fprintf(stderr, "Unable to get current time: %s\n", strerror(errno));
return 1;
}
ts.tv_sec += strtol(argv[optind], NULL, 0);
//strtotimeval(argv[optind], &tv);
gmtime_r(&ts.tv_sec, &tm);
printf("time %s -> %ld.%09ld\n", argv[optind], ts.tv_sec, ts.tv_nsec);
asctime_r(&tm, strbuf);
printf("Requested %s", strbuf);
res = ioctl(afd, ANDROID_ALARM_SET(alarmtype), &ts);
if(res < 0) {
fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
return 1;
}
}
#if 0
res = ioctl(fd, RTC_ALM_SET, &tm);
if(res < 0) {
fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
return 1;
}
res = ioctl(fd, RTC_AIE_ON);
if(res < 0) {
fprintf(stderr, "Unable to enable alarm: %s\n", strerror(errno));
return 1;
}
#endif
}
else {
fprintf(stderr,"%s [-u] [date]\n", argv[0]);
return 1;
}
if(wait) {
while(waitalarmmask) {
printf("wait for alarm %x\n", waitalarmmask);
res = ioctl(afd, ANDROID_ALARM_WAIT);
if(res < 0) {
fprintf(stderr, "alarm wait failed\n");
}
printf("got alarm %x\n", res);
waitalarmmask &= ~res;
nfd = open("/sys/android_power/acquire_full_wake_lock", O_RDWR);
write(nfd, wake_lock_id, sizeof(wake_lock_id) - 1);
close(nfd);
//sleep(5);
nfd = open("/sys/android_power/release_wake_lock", O_RDWR);
write(nfd, wake_lock_id, sizeof(wake_lock_id) - 1);
close(nfd);
}
printf("done\n");
}
#if 0
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
res = select(fd + 1, &rfds, NULL, NULL, &timeout);
if(res < 0) {
fprintf(stderr, "select failed: %s\n", strerror(errno));
return 1;
}
if(res > 0) {
int event;
read(fd, &event, sizeof(event));
fprintf(stderr, "got %x\n", event);
}
else {
fprintf(stderr, "timeout waiting for alarm\n");
}
#endif
close(afd);
return 0;
}