Upload Tizen:Base source
[framework/base/util-linux-ng.git] / hwclock / rtc.c
1 /* rtc.c - Use /dev/rtc for clock access */
2 #include <unistd.h>             /* for close() */
3 #include <fcntl.h>              /* for O_RDONLY */
4 #include <errno.h>
5 #include <sysexits.h>
6 #include <sys/ioctl.h>
7 #include <sys/time.h>           /* for struct timeval */
8
9 #include "clock.h"
10 #include "nls.h"
11
12 /*
13  * Get defines for rtc stuff.
14  *
15  * Getting the rtc defines is nontrivial.
16  * The obvious way is by including <linux/mc146818rtc.h>
17  * but that again includes <asm/io.h> which again includes ...
18  * and on sparc and alpha this gives compilation errors for
19  * many kernel versions. So, we give the defines ourselves here.
20  * Moreover, some Sparc person decided to be incompatible, and
21  * used a struct rtc_time different from that used in mc146818rtc.h.
22  */
23
24 /* On Sparcs, there is a <asm/rtc.h> that defines different ioctls
25    (that are required on my machine). However, this include file
26    does not exist on other architectures. */
27 /* One might do:
28 #ifdef __sparc__
29 #include <asm/rtc.h>
30 #endif
31  */
32 /* The following is roughly equivalent */
33 struct sparc_rtc_time
34 {
35         int     sec;    /* Seconds (0-59) */
36         int     min;    /* Minutes (0-59) */
37         int     hour;   /* Hour (0-23) */
38         int     dow;    /* Day of the week (1-7) */
39         int     dom;    /* Day of the month (1-31) */
40         int     month;  /* Month of year (1-12) */
41         int     year;   /* Year (0-99) */
42 };
43
44 #define RTCGET _IOR('p', 20, struct sparc_rtc_time)
45 #define RTCSET _IOW('p', 21, struct sparc_rtc_time)
46
47
48 /* non-sparc stuff */
49 #if 0
50 #include <linux/version.h>
51 /* Check if the /dev/rtc interface is available in this version of
52    the system headers.  131072 is linux 2.0.0. */
53 #if LINUX_VERSION_CODE >= 131072
54 #include <linux/mc146818rtc.h>
55 #endif
56 #endif
57
58 /* struct rtc_time is present since 1.3.99 */
59 /* Earlier (since 1.3.89), a struct tm was used. */
60 struct linux_rtc_time {
61         int tm_sec;
62         int tm_min;
63         int tm_hour;
64         int tm_mday;
65         int tm_mon;
66         int tm_year;
67         int tm_wday;
68         int tm_yday;
69         int tm_isdst;
70 };
71
72 /* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */
73 #ifndef RTC_RD_TIME
74 #define RTC_RD_TIME       _IOR('p', 0x09, struct linux_rtc_time)
75 #define RTC_SET_TIME      _IOW('p', 0x0a, struct linux_rtc_time)
76 #define RTC_UIE_ON        _IO('p', 0x03)        /* Update int. enable on */
77 #define RTC_UIE_OFF       _IO('p', 0x04)        /* Update int. enable off */
78 #endif
79 /* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */
80 #ifndef RTC_EPOCH_READ
81 #define RTC_EPOCH_READ  _IOR('p', 0x0d, unsigned long)   /* Read epoch */
82 #define RTC_EPOCH_SET   _IOW('p', 0x0e, unsigned long)   /* Set epoch */
83 #endif
84
85 /* /dev/rtc is conventionally chardev 10/135
86  * ia64 uses /dev/efirtc, chardev 10/136
87  * devfs (obsolete) used /dev/misc/... for miscdev
88  * new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
89  * ... so we need an overridable default
90  */
91
92 /* default or user defined dev (by hwclock --rtc=<path>) */
93 char *rtc_dev_name;
94
95 static int rtc_dev_fd = -1;
96
97 static void
98 close_rtc(void) {
99         if (rtc_dev_fd != -1)
100                 close(rtc_dev_fd);
101         rtc_dev_fd = -1;
102 }
103
104 static int
105 open_rtc(void) {
106         char *fls[] = {
107 #ifdef __ia64__
108                 "/dev/efirtc",
109                 "/dev/misc/efirtc",
110 #endif
111                 "/dev/rtc",
112                 "/dev/rtc0",
113                 "/dev/misc/rtc",
114                 NULL
115         };
116         char **p;
117
118         if (rtc_dev_fd != -1)
119                 return rtc_dev_fd;
120
121         /* --rtc option has been given */
122         if (rtc_dev_name)
123                 rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
124         else {
125                 for (p=fls; *p; ++p) {
126                         rtc_dev_fd = open(*p, O_RDONLY);
127
128                         if (rtc_dev_fd < 0 && (errno == ENOENT || errno == ENODEV))
129                                 continue;
130                         rtc_dev_name = *p;
131                         break;
132                 }
133                 if (rtc_dev_fd < 0)
134                         rtc_dev_name = *fls;    /* default for error messages */
135         }
136
137         if (rtc_dev_fd != 1)
138                 atexit(close_rtc);
139         return rtc_dev_fd;
140 }
141
142 static int
143 open_rtc_or_exit(void) {
144         int rtc_fd = open_rtc();
145
146         if (rtc_fd < 0) {
147                 outsyserr(_("open() of %s failed"), rtc_dev_name);
148                 hwclock_exit(EX_OSFILE);
149         }
150         return rtc_fd;
151 }
152
153 static int
154 do_rtc_read_ioctl(int rtc_fd, struct tm *tm) {
155         int rc = -1;
156         char *ioctlname;
157
158 #ifdef __sparc__
159         /* some but not all sparcs use a different ioctl and struct */
160         struct sparc_rtc_time stm;
161
162         ioctlname = "RTCGET";
163         rc = ioctl(rtc_fd, RTCGET, &stm);
164         if (rc == 0) {
165                 tm->tm_sec = stm.sec;
166                 tm->tm_min = stm.min;
167                 tm->tm_hour = stm.hour;
168                 tm->tm_mday = stm.dom;
169                 tm->tm_mon = stm.month - 1;
170                 tm->tm_year = stm.year - 1900;
171                 tm->tm_wday = stm.dow - 1;
172                 tm->tm_yday = -1;               /* day in the year */
173         }
174 #endif
175         if (rc == -1) {         /* no sparc, or RTCGET failed */
176                 ioctlname = "RTC_RD_TIME";
177                 rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
178         }
179         if (rc == -1) {
180                 perror(ioctlname);
181                 fprintf(stderr, _("ioctl() to %s to read the time failed.\n"),
182                         rtc_dev_name);
183                 return -1;
184         }
185
186         tm->tm_isdst = -1;          /* don't know whether it's dst */
187         return 0;
188 }
189
190 static int
191 busywait_for_rtc_clock_tick(const int rtc_fd) {
192 /*----------------------------------------------------------------------------
193    Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
194    we see it.
195 -----------------------------------------------------------------------------*/
196   struct tm start_time;
197     /* The time when we were called (and started waiting) */
198   struct tm nowtime;
199   int rc;
200   struct timeval begin, now;
201
202   if (debug)
203     printf(_("Waiting in loop for time from %s to change\n"),
204            rtc_dev_name);
205
206   rc = do_rtc_read_ioctl(rtc_fd, &start_time);
207   if (rc)
208     return 1;
209
210   /* Wait for change.  Should be within a second, but in case something
211    * weird happens, we have a time limit (1.5s) on this loop to reduce the
212    * impact of this failure.
213    */
214   gettimeofday(&begin, NULL);
215   do {
216     rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
217     if (rc || start_time.tm_sec != nowtime.tm_sec)
218       break;
219     gettimeofday(&now, NULL);
220     if (time_diff(now, begin) > 1.5) {
221       fprintf(stderr, _("Timed out waiting for time change.\n"));
222       return 2;
223     }
224   } while(1);
225
226   if (rc)
227     return 3;
228   return 0;
229 }
230
231 static int
232 synchronize_to_clock_tick_rtc(void) {
233 /*----------------------------------------------------------------------------
234   Same as synchronize_to_clock_tick(), but just for /dev/rtc.
235 -----------------------------------------------------------------------------*/
236 int rtc_fd;  /* File descriptor of /dev/rtc */
237 int ret;
238
239   rtc_fd = open_rtc();
240   if (rtc_fd == -1) {
241     outsyserr(_("open() of %s failed"), rtc_dev_name);
242     ret = 1;
243   } else {
244     int rc;  /* Return code from ioctl */
245     /* Turn on update interrupts (one per second) */
246 #if defined(__alpha__) || defined(__sparc__)
247     /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */
248     rc = -1;
249     errno = EINVAL;
250 #else
251     rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
252 #endif
253     if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
254       /* This rtc device doesn't have interrupt functions.  This is typical
255          on an Alpha, where the Hardware Clock interrupts are used by the
256          kernel for the system clock, so aren't at the user's disposal.
257          */
258       if (debug)
259               printf(_("%s does not have interrupt functions. "),
260                      rtc_dev_name);
261       ret = busywait_for_rtc_clock_tick(rtc_fd);
262     } else if (rc == 0) {
263 #ifdef Wait_until_update_interrupt
264       unsigned long dummy;
265
266       /* this blocks until the next update interrupt */
267       rc = read(rtc_fd, &dummy, sizeof(dummy));
268       ret = 1;
269       if (rc == -1)
270         outsyserr(_("read() to %s to wait for clock tick failed"),
271                   rtc_dev_name);
272       else
273         ret = 0;
274 #else
275       /* Just reading rtc_fd fails on broken hardware: no update
276          interrupt comes and a bootscript with a hwclock call hangs */
277       fd_set rfds;
278       struct timeval tv;
279
280       /* Wait up to five seconds for the next update interrupt */
281       FD_ZERO(&rfds);
282       FD_SET(rtc_fd, &rfds);
283       tv.tv_sec = 5;
284       tv.tv_usec = 0;
285       rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
286       ret = 1;
287       if (rc == -1)
288         outsyserr(_("select() to %s to wait for clock tick failed"),
289                   rtc_dev_name);
290       else if (rc == 0)
291         fprintf(stderr, _("select() to %s to wait for clock tick timed out\n"),
292                           rtc_dev_name);
293       else
294         ret = 0;
295 #endif
296
297       /* Turn off update interrupts */
298       rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
299       if (rc == -1)
300         outsyserr(_("ioctl() to %s to turn off update interrupts failed"),
301                   rtc_dev_name);
302     } else {
303       outsyserr(_("ioctl() to %s to turn on update interrupts "
304                 "failed unexpectedly"), rtc_dev_name);
305       ret = 1;
306     }
307   }
308   return ret;
309 }
310
311
312 static int
313 read_hardware_clock_rtc(struct tm *tm) {
314         int rtc_fd, rc;
315
316         rtc_fd = open_rtc_or_exit();
317
318         /* Read the RTC time/date, return answer via tm */
319         rc = do_rtc_read_ioctl(rtc_fd, tm);
320
321         return rc;
322 }
323
324
325 static int
326 set_hardware_clock_rtc(const struct tm *new_broken_time) {
327 /*-------------------------------------------------------------------------
328   Set the Hardware Clock to the broken down time <new_broken_time>.
329   Use ioctls to "rtc" device /dev/rtc.
330   -------------------------------------------------------------------------*/
331         int rc = -1;
332         int rtc_fd;
333         char *ioctlname;
334
335         rtc_fd = open_rtc_or_exit();
336
337 #ifdef __sparc__
338         {
339                 struct sparc_rtc_time stm;
340
341                 stm.sec = new_broken_time->tm_sec;
342                 stm.min = new_broken_time->tm_min;
343                 stm.hour = new_broken_time->tm_hour;
344                 stm.dom = new_broken_time->tm_mday;
345                 stm.month = new_broken_time->tm_mon + 1;
346                 stm.year = new_broken_time->tm_year + 1900;
347                 stm.dow = new_broken_time->tm_wday + 1;
348
349                 ioctlname = "RTCSET";
350                 rc = ioctl(rtc_fd, RTCSET, &stm);
351         }
352 #endif
353         if (rc == -1) {         /* no sparc, or RTCSET failed */
354                 ioctlname = "RTC_SET_TIME";
355                 rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
356         }
357
358         if (rc == -1) {
359                 perror(ioctlname);
360                 fprintf(stderr, _("ioctl() to %s to set the time failed.\n"),
361                         rtc_dev_name);
362                 hwclock_exit(EX_IOERR);
363         }
364
365         if (debug)
366                 printf(_("ioctl(%s) was successful.\n"), ioctlname);
367
368         return 0;
369 }
370
371
372 static int
373 get_permissions_rtc(void) {
374         return 0;
375 }
376
377 static struct clock_ops rtc = {
378         "/dev interface to clock",
379         get_permissions_rtc,
380         read_hardware_clock_rtc,
381         set_hardware_clock_rtc,
382         synchronize_to_clock_tick_rtc,
383 };
384
385 /* return &rtc if /dev/rtc can be opened, NULL otherwise */
386 struct clock_ops *
387 probe_for_rtc_clock(){
388         int rtc_fd = open_rtc();
389         if (rtc_fd >= 0)
390                 return &rtc;
391         if (debug)
392                 outsyserr(_("Open of %s failed"), rtc_dev_name);
393         return NULL;
394 }
395
396
397
398 int
399 get_epoch_rtc(unsigned long *epoch_p, int silent) {
400 /*----------------------------------------------------------------------------
401   Get the Hardware Clock epoch setting from the kernel.
402 ----------------------------------------------------------------------------*/
403   int rtc_fd;
404
405   rtc_fd = open_rtc();
406   if (rtc_fd < 0) {
407     if (!silent) {
408       if (errno == ENOENT)
409         fprintf(stderr, _(
410                 "To manipulate the epoch value in the kernel, we must "
411                 "access the Linux 'rtc' device driver via the device special "
412                 "file %s.  This file does not exist on this system.\n"),
413                 rtc_dev_name);
414       else
415         outsyserr(_("Unable to open %s"), rtc_dev_name);
416     }
417     return 1;
418   }
419
420   if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
421     if (!silent)
422       outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"), rtc_dev_name);
423     return 1;
424   }
425
426   if (debug)
427           printf(_("we have read epoch %ld from %s "
428                  "with RTC_EPOCH_READ ioctl.\n"), *epoch_p, rtc_dev_name);
429
430   return 0;
431 }
432
433
434
435 int
436 set_epoch_rtc(unsigned long epoch) {
437 /*----------------------------------------------------------------------------
438   Set the Hardware Clock epoch in the kernel.
439 ----------------------------------------------------------------------------*/
440   int rtc_fd;
441
442   if (epoch < 1900) {
443     /* kernel would not accept this epoch value */
444     /* Hmm - bad habit, deciding not to do what the user asks
445        just because one believes that the kernel might not like it. */
446     fprintf(stderr, _("The epoch value may not be less than 1900.  "
447             "You requested %ld\n"), epoch);
448     return 1;
449   }
450
451   rtc_fd = open_rtc();
452   if (rtc_fd < 0) {
453     if (errno == ENOENT)
454       fprintf(stderr, _("To manipulate the epoch value in the kernel, we must "
455               "access the Linux 'rtc' device driver via the device special "
456               "file %s.  This file does not exist on this system.\n"),
457               rtc_dev_name);
458     else
459       outsyserr(_("Unable to open %s"), rtc_dev_name);
460     return 1;
461   }
462
463   if (debug)
464     printf(_("setting epoch to %ld "
465            "with RTC_EPOCH_SET ioctl to %s.\n"), epoch, rtc_dev_name);
466
467   if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
468     if (errno == EINVAL)
469       fprintf(stderr, _("The kernel device driver for %s "
470               "does not have the RTC_EPOCH_SET ioctl.\n"), rtc_dev_name);
471     else
472       outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"), rtc_dev_name);
473     return 1;
474   }
475
476   return 0;
477 }