rtc-sysfs.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * RTC subsystem, sysfs interface
  3. *
  4. * Copyright (C) 2005 Tower Technologies
  5. * Author: Alessandro Zummo <a.zummo@towertech.it>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/rtc.h>
  13. #include "rtc-core.h"
  14. /* device attributes */
  15. static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf)
  16. {
  17. return sprintf(buf, "%s\n", to_rtc_device(dev)->name);
  18. }
  19. static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf)
  20. {
  21. ssize_t retval;
  22. struct rtc_time tm;
  23. retval = rtc_read_time(to_rtc_device(dev), &tm);
  24. if (retval == 0) {
  25. retval = sprintf(buf, "%04d-%02d-%02d\n",
  26. tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
  27. }
  28. return retval;
  29. }
  30. static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf)
  31. {
  32. ssize_t retval;
  33. struct rtc_time tm;
  34. retval = rtc_read_time(to_rtc_device(dev), &tm);
  35. if (retval == 0) {
  36. retval = sprintf(buf, "%02d:%02d:%02d\n",
  37. tm.tm_hour, tm.tm_min, tm.tm_sec);
  38. }
  39. return retval;
  40. }
  41. static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf)
  42. {
  43. ssize_t retval;
  44. struct rtc_time tm;
  45. retval = rtc_read_time(to_rtc_device(dev), &tm);
  46. if (retval == 0) {
  47. unsigned long time;
  48. rtc_tm_to_time(&tm, &time);
  49. retval = sprintf(buf, "%lu\n", time);
  50. }
  51. return retval;
  52. }
  53. static struct class_device_attribute rtc_attrs[] = {
  54. __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL),
  55. __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL),
  56. __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL),
  57. __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL),
  58. { },
  59. };
  60. static ssize_t
  61. rtc_sysfs_show_wakealarm(struct class_device *dev, char *buf)
  62. {
  63. ssize_t retval;
  64. unsigned long alarm;
  65. struct rtc_wkalrm alm;
  66. /* Don't show disabled alarms; but the RTC could leave the
  67. * alarm enabled after it's already triggered. Alarms are
  68. * conceptually one-shot, even though some common hardware
  69. * (PCs) doesn't actually work that way.
  70. *
  71. * REVISIT maybe we should require RTC implementations to
  72. * disable the RTC alarm after it triggers, for uniformity.
  73. */
  74. retval = rtc_read_alarm(to_rtc_device(dev), &alm);
  75. if (retval == 0 && alm.enabled) {
  76. rtc_tm_to_time(&alm.time, &alarm);
  77. retval = sprintf(buf, "%lu\n", alarm);
  78. }
  79. return retval;
  80. }
  81. static ssize_t
  82. rtc_sysfs_set_wakealarm(struct class_device *dev, const char *buf, size_t n)
  83. {
  84. ssize_t retval;
  85. unsigned long now, alarm;
  86. struct rtc_wkalrm alm;
  87. struct rtc_device *rtc = to_rtc_device(dev);
  88. /* Only request alarms that trigger in the future. Disable them
  89. * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
  90. */
  91. retval = rtc_read_time(rtc, &alm.time);
  92. if (retval < 0)
  93. return retval;
  94. rtc_tm_to_time(&alm.time, &now);
  95. alarm = simple_strtoul(buf, NULL, 0);
  96. if (alarm > now) {
  97. /* Avoid accidentally clobbering active alarms; we can't
  98. * entirely prevent that here, without even the minimal
  99. * locking from the /dev/rtcN api.
  100. */
  101. retval = rtc_read_alarm(rtc, &alm);
  102. if (retval < 0)
  103. return retval;
  104. if (alm.enabled)
  105. return -EBUSY;
  106. alm.enabled = 1;
  107. } else {
  108. alm.enabled = 0;
  109. /* Provide a valid future alarm time. Linux isn't EFI,
  110. * this time won't be ignored when disabling the alarm.
  111. */
  112. alarm = now + 300;
  113. }
  114. rtc_time_to_tm(alarm, &alm.time);
  115. retval = rtc_set_alarm(rtc, &alm);
  116. return (retval < 0) ? retval : n;
  117. }
  118. static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
  119. rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
  120. /* The reason to trigger an alarm with no process watching it (via sysfs)
  121. * is its side effect: waking from a system state like suspend-to-RAM or
  122. * suspend-to-disk. So: no attribute unless that side effect is possible.
  123. * (Userspace may disable that mechanism later.)
  124. */
  125. static inline int rtc_does_wakealarm(struct rtc_device *rtc)
  126. {
  127. if (!device_can_wakeup(rtc->class_dev.dev))
  128. return 0;
  129. return rtc->ops->set_alarm != NULL;
  130. }
  131. void rtc_sysfs_add_device(struct rtc_device *rtc)
  132. {
  133. int err;
  134. /* not all RTCs support both alarms and wakeup */
  135. if (!rtc_does_wakealarm(rtc))
  136. return;
  137. err = class_device_create_file(&rtc->class_dev,
  138. &class_device_attr_wakealarm);
  139. if (err)
  140. dev_err(rtc->class_dev.dev, "failed to create "
  141. "alarm attribute, %d",
  142. err);
  143. }
  144. void rtc_sysfs_del_device(struct rtc_device *rtc)
  145. {
  146. /* REVISIT did we add it successfully? */
  147. if (rtc_does_wakealarm(rtc))
  148. class_device_remove_file(&rtc->class_dev,
  149. &class_device_attr_wakealarm);
  150. }
  151. void __init rtc_sysfs_init(struct class *rtc_class)
  152. {
  153. rtc_class->class_dev_attrs = rtc_attrs;
  154. }