2 * Real Time Clock Driver Test/Example Program
5 * gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
7 * Copyright (C) 1996, Paul Gortmaker.
9 * Released under the GNU General Public License, version 2,
10 * included herein by reference.
15 #include <linux/rtc.h>
16 #include <sys/ioctl.h>
18 #include <sys/types.h>
26 * This expects the new RTC class driver framework, working with
27 * clocks that will often not be clones of what the PC-AT had.
28 * Use the command line to specify another RTC if you need one.
30 static const char default_rtc
[] = "/dev/rtc0";
33 int main(int argc
, char **argv
)
35 int i
, fd
, retval
, irqcount
= 0;
36 unsigned long tmp
, data
;
37 struct rtc_time rtc_tm
;
38 const char *rtc
= default_rtc
;
39 struct timeval start
, end
, diff
;
48 fprintf(stderr
, "usage: rtctest [rtcdev]\n");
52 fd
= open(rtc
, O_RDONLY
);
59 fprintf(stderr
, "\n\t\t\tRTC Driver Test Example.\n\n");
61 /* Turn on update interrupts (one per second) */
62 retval
= ioctl(fd
, RTC_UIE_ON
, 0);
64 if (errno
== ENOTTY
) {
66 "\n...Update IRQs not supported.\n");
69 perror("RTC_UIE_ON ioctl");
73 fprintf(stderr
, "Counting 5 update (1/sec) interrupts from reading %s:",
77 /* This read will block */
78 retval
= read(fd
, &data
, sizeof(unsigned long));
83 fprintf(stderr
, " %d",i
);
88 fprintf(stderr
, "\nAgain, from using select(2) on /dev/rtc:");
91 struct timeval tv
= {5, 0}; /* 5 second timeout on select */
96 /* The select will wait until an RTC interrupt happens. */
97 retval
= select(fd
+1, &readfds
, NULL
, NULL
, &tv
);
102 /* This read won't block unlike the select-less case above. */
103 retval
= read(fd
, &data
, sizeof(unsigned long));
108 fprintf(stderr
, " %d",i
);
113 /* Turn off update interrupts */
114 retval
= ioctl(fd
, RTC_UIE_OFF
, 0);
116 perror("RTC_UIE_OFF ioctl");
121 /* Read the RTC time/date */
122 retval
= ioctl(fd
, RTC_RD_TIME
, &rtc_tm
);
124 perror("RTC_RD_TIME ioctl");
128 fprintf(stderr
, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
129 rtc_tm
.tm_mday
, rtc_tm
.tm_mon
+ 1, rtc_tm
.tm_year
+ 1900,
130 rtc_tm
.tm_hour
, rtc_tm
.tm_min
, rtc_tm
.tm_sec
);
132 /* Set the alarm to 5 sec in the future, and check for rollover */
134 if (rtc_tm
.tm_sec
>= 60) {
138 if (rtc_tm
.tm_min
== 60) {
142 if (rtc_tm
.tm_hour
== 24)
145 retval
= ioctl(fd
, RTC_ALM_SET
, &rtc_tm
);
147 if (errno
== ENOTTY
) {
149 "\n...Alarm IRQs not supported.\n");
152 perror("RTC_ALM_SET ioctl");
156 /* Read the current alarm settings */
157 retval
= ioctl(fd
, RTC_ALM_READ
, &rtc_tm
);
159 perror("RTC_ALM_READ ioctl");
163 fprintf(stderr
, "Alarm time now set to %02d:%02d:%02d.\n",
164 rtc_tm
.tm_hour
, rtc_tm
.tm_min
, rtc_tm
.tm_sec
);
166 /* Enable alarm interrupts */
167 retval
= ioctl(fd
, RTC_AIE_ON
, 0);
169 perror("RTC_AIE_ON ioctl");
173 fprintf(stderr
, "Waiting 5 seconds for alarm...");
175 /* This blocks until the alarm ring causes an interrupt */
176 retval
= read(fd
, &data
, sizeof(unsigned long));
182 fprintf(stderr
, " okay. Alarm rang.\n");
184 /* Disable alarm interrupts */
185 retval
= ioctl(fd
, RTC_AIE_OFF
, 0);
187 perror("RTC_AIE_OFF ioctl");
192 /* Read periodic IRQ rate */
193 retval
= ioctl(fd
, RTC_IRQP_READ
, &tmp
);
195 /* not all RTCs support periodic IRQs */
196 if (errno
== ENOTTY
) {
197 fprintf(stderr
, "\nNo periodic IRQ support\n");
200 perror("RTC_IRQP_READ ioctl");
203 fprintf(stderr
, "\nPeriodic IRQ rate is %ldHz.\n", tmp
);
205 fprintf(stderr
, "Counting 20 interrupts at:");
208 /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
209 for (tmp
=2; tmp
<=64; tmp
*=2) {
211 retval
= ioctl(fd
, RTC_IRQP_SET
, tmp
);
213 /* not all RTCs can change their periodic IRQ rate */
214 if (errno
== ENOTTY
) {
216 "\n...Periodic IRQ rate is fixed\n");
219 perror("RTC_IRQP_SET ioctl");
223 fprintf(stderr
, "\n%ldHz:\t", tmp
);
226 /* Enable periodic interrupts */
227 retval
= ioctl(fd
, RTC_PIE_ON
, 0);
229 perror("RTC_PIE_ON ioctl");
233 for (i
=1; i
<21; i
++) {
234 gettimeofday(&start
, NULL
);
236 retval
= read(fd
, &data
, sizeof(unsigned long));
241 gettimeofday(&end
, NULL
);
242 timersub(&end
, &start
, &diff
);
243 if (diff
.tv_sec
> 0 ||
244 diff
.tv_usec
> ((1000000L / tmp
) * 1.10)) {
245 fprintf(stderr
, "\nPIE delta error: %ld.%06ld should be close to 0.%06ld\n",
246 diff
.tv_sec
, diff
.tv_usec
,
252 fprintf(stderr
, " %d",i
);
257 /* Disable periodic interrupts */
258 retval
= ioctl(fd
, RTC_PIE_OFF
, 0);
260 perror("RTC_PIE_OFF ioctl");
266 fprintf(stderr
, "\n\n\t\t\t *** Test complete ***\n");