1#include <stdio.h>
2#include <stdlib.h>
3#include <fcntl.h>
4#include <string.h>
5#include <errno.h>
6#include <time.h>
7#include <asm/ioctl.h>
8//#include <linux/rtc.h>
9#include <linux/android_alarm.h>
10
11int alarm_main(int argc, char *argv[])
12{
13	int c;
14    int res;
15	struct tm tm;
16	time_t t;
17	struct timespec ts;
18//	struct rtc_time rtc_time;
19	char strbuf[26];
20	int afd;
21	int nfd;
22//	struct timeval timeout = { 0, 0 };
23    int wait = 0;
24	fd_set rfds;
25	const char wake_lock_id[] = "alarm_test";
26	int waitalarmmask = 0;
27
28    int useutc = 0;
29	android_alarm_type_t alarmtype_low = ANDROID_ALARM_RTC_WAKEUP;
30	android_alarm_type_t alarmtype_high = ANDROID_ALARM_RTC_WAKEUP;
31	android_alarm_type_t alarmtype = 0;
32
33    do {
34        //c = getopt(argc, argv, "uw:");
35        c = getopt(argc, argv, "uwat:");
36        if (c == EOF)
37            break;
38        switch (c) {
39        case 'u':
40            useutc = 1;
41            break;
42		case 't':
43			alarmtype_low = alarmtype_high = strtol(optarg, NULL, 0);
44			break;
45		case 'a':
46			alarmtype_low = ANDROID_ALARM_RTC_WAKEUP;
47			alarmtype_high = ANDROID_ALARM_TYPE_COUNT - 1;
48			break;
49        case 'w':
50            //timeout.tv_sec = strtol(optarg, NULL, 0);
51            wait = 1;
52            break;
53        case '?':
54            fprintf(stderr, "%s: invalid option -%c\n",
55                argv[0], optopt);
56            exit(1);
57        }
58    } while (1);
59    if(optind + 2 < argc) {
60        fprintf(stderr,"%s [-uwa] [-t type] [seconds]\n", argv[0]);
61        return 1;
62    }
63
64    afd = open("/dev/alarm", O_RDWR);
65    if(afd < 0) {
66        fprintf(stderr, "Unable to open rtc: %s\n", strerror(errno));
67        return 1;
68    }
69
70    if(optind == argc) {
71		for(alarmtype = alarmtype_low; alarmtype <= alarmtype_high; alarmtype++) {
72			waitalarmmask |= 1U << alarmtype;
73		}
74#if 0
75        res = ioctl(fd, RTC_ALM_READ, &tm);
76        if(res < 0) {
77            fprintf(stderr, "Unable to read alarm: %s\n", strerror(errno));
78			return 1;
79        }
80#endif
81#if 0
82		t = timegm(&tm);
83        if(useutc)
84            gmtime_r(&t, &tm);
85        else
86            localtime_r(&t, &tm);
87#endif
88#if 0
89        asctime_r(&tm, strbuf);
90        printf("%s", strbuf);
91#endif
92    }
93    else if(optind + 1 == argc) {
94#if 0
95        res = ioctl(fd, RTC_RD_TIME, &tm);
96        if(res < 0) {
97            fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
98			return 1;
99        }
100        asctime_r(&tm, strbuf);
101        printf("Now: %s", strbuf);
102        time(&tv.tv_sec);
103#endif
104#if 0
105		time(&ts.tv_sec);
106		ts.tv_nsec = 0;
107
108        //strptime(argv[optind], NULL, &tm);
109        //tv.tv_sec = mktime(&tm);
110        //tv.tv_usec = 0;
111#endif
112		for(alarmtype = alarmtype_low; alarmtype <= alarmtype_high; alarmtype++) {
113			waitalarmmask |= 1U << alarmtype;
114		    res = ioctl(afd, ANDROID_ALARM_GET_TIME(alarmtype), &ts);
115		    if(res < 0) {
116		        fprintf(stderr, "Unable to get current time: %s\n", strerror(errno));
117				return 1;
118		    }
119		    ts.tv_sec += strtol(argv[optind], NULL, 0);
120		    //strtotimeval(argv[optind], &tv);
121			gmtime_r(&ts.tv_sec, &tm);
122		    printf("time %s -> %ld.%09ld\n", argv[optind], ts.tv_sec, ts.tv_nsec);
123		    asctime_r(&tm, strbuf);
124		    printf("Requested %s", strbuf);
125
126		    res = ioctl(afd, ANDROID_ALARM_SET(alarmtype), &ts);
127		    if(res < 0) {
128		        fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
129				return 1;
130		    }
131		}
132#if 0
133        res = ioctl(fd, RTC_ALM_SET, &tm);
134        if(res < 0) {
135            fprintf(stderr, "Unable to set alarm: %s\n", strerror(errno));
136			return 1;
137        }
138        res = ioctl(fd, RTC_AIE_ON);
139        if(res < 0) {
140            fprintf(stderr, "Unable to enable alarm: %s\n", strerror(errno));
141			return 1;
142        }
143#endif
144    }
145    else {
146        fprintf(stderr,"%s [-u] [date]\n", argv[0]);
147        return 1;
148    }
149
150	if(wait) {
151		while(waitalarmmask) {
152			printf("wait for alarm %x\n", waitalarmmask);
153			res = ioctl(afd, ANDROID_ALARM_WAIT);
154			if(res < 0) {
155				fprintf(stderr, "alarm wait failed\n");
156			}
157			printf("got alarm %x\n", res);
158			waitalarmmask &= ~res;
159			nfd = open("/sys/android_power/acquire_full_wake_lock", O_RDWR);
160			write(nfd, wake_lock_id, sizeof(wake_lock_id) - 1);
161			close(nfd);
162			//sleep(5);
163			nfd = open("/sys/android_power/release_wake_lock", O_RDWR);
164			write(nfd, wake_lock_id, sizeof(wake_lock_id) - 1);
165			close(nfd);
166		}
167		printf("done\n");
168	}
169#if 0
170	FD_ZERO(&rfds);
171	FD_SET(fd, &rfds);
172	res = select(fd + 1, &rfds, NULL, NULL, &timeout);
173    if(res < 0) {
174        fprintf(stderr, "select failed: %s\n", strerror(errno));
175		return 1;
176    }
177	if(res > 0) {
178		int event;
179		read(fd, &event, sizeof(event));
180		fprintf(stderr, "got %x\n", event);
181	}
182	else {
183		fprintf(stderr, "timeout waiting for alarm\n");
184	}
185#endif
186
187    close(afd);
188
189    return 0;
190}
191