Blame view

drivers/rtc/rtc-sysfs.c 7.05 KB
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * RTC subsystem, sysfs interface
   *
   * Copyright (C) 2005 Tower Technologies
   * Author: Alessandro Zummo <a.zummo@towertech.it>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
  */
  
  #include <linux/module.h>
  #include <linux/rtc.h>
ab6a2d70d   David Brownell   rtc: rtc interfac...
14
  #include "rtc-core.h"
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
15
  /* device attributes */
8a0bdfd7a   David Brownell   rtc-cmos alarm ac...
16
17
18
19
20
21
  /*
   * NOTE:  RTC times displayed in sysfs use the RTC's timezone.  That's
   * ideally UTC.  However, PCs that also boot to MS-Windows normally use
   * the local time and change to match daylight savings time.  That affects
   * attributes including date, time, since_epoch, and wakealarm.
   */
cd9662094   David Brownell   rtc: remove rest ...
22
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
23
  name_show(struct device *dev, struct device_attribute *attr, char *buf)
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
24
25
26
27
  {
  	return sprintf(buf, "%s
  ", to_rtc_device(dev)->name);
  }
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
28
  static DEVICE_ATTR_RO(name);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
29

cd9662094   David Brownell   rtc: remove rest ...
30
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
31
  date_show(struct device *dev, struct device_attribute *attr, char *buf)
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
32
33
34
  {
  	ssize_t retval;
  	struct rtc_time tm;
ab6a2d70d   David Brownell   rtc: rtc interfac...
35
  	retval = rtc_read_time(to_rtc_device(dev), &tm);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
36
37
38
39
40
41
42
43
  	if (retval == 0) {
  		retval = sprintf(buf, "%04d-%02d-%02d
  ",
  			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
  	}
  
  	return retval;
  }
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
44
  static DEVICE_ATTR_RO(date);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
45

cd9662094   David Brownell   rtc: remove rest ...
46
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
47
  time_show(struct device *dev, struct device_attribute *attr, char *buf)
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
48
49
50
  {
  	ssize_t retval;
  	struct rtc_time tm;
ab6a2d70d   David Brownell   rtc: rtc interfac...
51
  	retval = rtc_read_time(to_rtc_device(dev), &tm);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
52
53
54
55
56
57
58
59
  	if (retval == 0) {
  		retval = sprintf(buf, "%02d:%02d:%02d
  ",
  			tm.tm_hour, tm.tm_min, tm.tm_sec);
  	}
  
  	return retval;
  }
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
60
  static DEVICE_ATTR_RO(time);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
61

cd9662094   David Brownell   rtc: remove rest ...
62
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
63
  since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
64
65
66
  {
  	ssize_t retval;
  	struct rtc_time tm;
ab6a2d70d   David Brownell   rtc: rtc interfac...
67
  	retval = rtc_read_time(to_rtc_device(dev), &tm);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
68
69
70
71
72
73
74
75
76
  	if (retval == 0) {
  		unsigned long time;
  		rtc_tm_to_time(&tm, &time);
  		retval = sprintf(buf, "%lu
  ", time);
  	}
  
  	return retval;
  }
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
77
  static DEVICE_ATTR_RO(since_epoch);
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
78

06c65eb45   Bryan Kadzban   rtc: add max_user...
79
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
80
  max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf)
06c65eb45   Bryan Kadzban   rtc: add max_user...
81
82
83
84
85
86
  {
  	return sprintf(buf, "%d
  ", to_rtc_device(dev)->max_user_freq);
  }
  
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
87
  max_user_freq_store(struct device *dev, struct device_attribute *attr,
06c65eb45   Bryan Kadzban   rtc: add max_user...
88
89
90
  		const char *buf, size_t n)
  {
  	struct rtc_device *rtc = to_rtc_device(dev);
f571287bd   LABBE Corentin   rtc: Replace simp...
91
92
93
94
95
96
  	unsigned long val;
  	int err;
  
  	err = kstrtoul(buf, 0, &val);
  	if (err)
  		return err;
06c65eb45   Bryan Kadzban   rtc: add max_user...
97
98
99
100
101
102
103
104
  
  	if (val >= 4096 || val == 0)
  		return -EINVAL;
  
  	rtc->max_user_freq = (int)val;
  
  	return n;
  }
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
105
  static DEVICE_ATTR_RW(max_user_freq);
06c65eb45   Bryan Kadzban   rtc: add max_user...
106

4c24e29e6   David Fries   rtc_sysfs_show_hc...
107
108
109
110
111
112
  /**
   * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time
   *
   * Returns 1 if the system clock was set by this RTC at the last
   * boot or resume event.
   */
d8c1acb16   Matthew Garrett   rtc: add boot_tim...
113
  static ssize_t
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
114
  hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
d8c1acb16   Matthew Garrett   rtc: add boot_tim...
115
116
  {
  #ifdef CONFIG_RTC_HCTOSYS_DEVICE
d0ab4a4d5   Uwe Kleine-König   rtc/hctosys: only...
117
118
119
  	if (rtc_hctosys_ret == 0 &&
  			strcmp(dev_name(&to_rtc_device(dev)->dev),
  				CONFIG_RTC_HCTOSYS_DEVICE) == 0)
d8c1acb16   Matthew Garrett   rtc: add boot_tim...
120
121
122
123
124
125
126
  		return sprintf(buf, "1
  ");
  	else
  #endif
  		return sprintf(buf, "0
  ");
  }
f21e68350   Greg Kroah-Hartman   rtc: convert clas...
127
  static DEVICE_ATTR_RO(hctosys);
3925a5ce4   David Brownell   [PATCH] RTC gets ...
128
  static ssize_t
a17ccd1c6   Dmitry Torokhov   rtc: switch wakea...
129
  wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
3925a5ce4   David Brownell   [PATCH] RTC gets ...
130
131
132
133
  {
  	ssize_t retval;
  	unsigned long alarm;
  	struct rtc_wkalrm alm;
8a0bdfd7a   David Brownell   rtc-cmos alarm ac...
134
135
136
  	/* Don't show disabled alarms.  For uniformity, RTC alarms are
  	 * conceptually one-shot, even though some common RTCs (on PCs)
  	 * don't actually work that way.
3925a5ce4   David Brownell   [PATCH] RTC gets ...
137
  	 *
8a0bdfd7a   David Brownell   rtc-cmos alarm ac...
138
139
140
  	 * NOTE: RTC implementations where the alarm doesn't match an
  	 * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC
  	 * alarms after they trigger, to ensure one-shot semantics.
3925a5ce4   David Brownell   [PATCH] RTC gets ...
141
  	 */
ab6a2d70d   David Brownell   rtc: rtc interfac...
142
  	retval = rtc_read_alarm(to_rtc_device(dev), &alm);
3925a5ce4   David Brownell   [PATCH] RTC gets ...
143
144
145
146
147
148
149
150
151
152
  	if (retval == 0 && alm.enabled) {
  		rtc_tm_to_time(&alm.time, &alarm);
  		retval = sprintf(buf, "%lu
  ", alarm);
  	}
  
  	return retval;
  }
  
  static ssize_t
a17ccd1c6   Dmitry Torokhov   rtc: switch wakea...
153
  wakealarm_store(struct device *dev, struct device_attribute *attr,
cd9662094   David Brownell   rtc: remove rest ...
154
  		const char *buf, size_t n)
3925a5ce4   David Brownell   [PATCH] RTC gets ...
155
156
157
  {
  	ssize_t retval;
  	unsigned long now, alarm;
1df0a4711   Bernie Thompson   rtc: add ability ...
158
  	unsigned long push = 0;
3925a5ce4   David Brownell   [PATCH] RTC gets ...
159
  	struct rtc_wkalrm alm;
ab6a2d70d   David Brownell   rtc: rtc interfac...
160
  	struct rtc_device *rtc = to_rtc_device(dev);
84281c2d7   LABBE Corentin   rtc: sysfs: fix a...
161
  	const char *buf_ptr;
c116bc2ae   Zhao Yakui   rtc: add the supp...
162
  	int adjust = 0;
3925a5ce4   David Brownell   [PATCH] RTC gets ...
163
164
165
166
  
  	/* Only request alarms that trigger in the future.  Disable them
  	 * by writing another time, e.g. 0 meaning Jan 1 1970 UTC.
  	 */
ab6a2d70d   David Brownell   rtc: rtc interfac...
167
  	retval = rtc_read_time(rtc, &alm.time);
3925a5ce4   David Brownell   [PATCH] RTC gets ...
168
169
170
  	if (retval < 0)
  		return retval;
  	rtc_tm_to_time(&alm.time, &now);
84281c2d7   LABBE Corentin   rtc: sysfs: fix a...
171
  	buf_ptr = buf;
c116bc2ae   Zhao Yakui   rtc: add the supp...
172
173
  	if (*buf_ptr == '+') {
  		buf_ptr++;
1df0a4711   Bernie Thompson   rtc: add ability ...
174
175
176
177
178
  		if (*buf_ptr == '=') {
  			buf_ptr++;
  			push = 1;
  		} else
  			adjust = 1;
c116bc2ae   Zhao Yakui   rtc: add the supp...
179
  	}
f571287bd   LABBE Corentin   rtc: Replace simp...
180
181
182
  	retval = kstrtoul(buf_ptr, 0, &alarm);
  	if (retval)
  		return retval;
c116bc2ae   Zhao Yakui   rtc: add the supp...
183
184
185
  	if (adjust) {
  		alarm += now;
  	}
1df0a4711   Bernie Thompson   rtc: add ability ...
186
  	if (alarm > now || push) {
3925a5ce4   David Brownell   [PATCH] RTC gets ...
187
188
189
190
  		/* Avoid accidentally clobbering active alarms; we can't
  		 * entirely prevent that here, without even the minimal
  		 * locking from the /dev/rtcN api.
  		 */
ab6a2d70d   David Brownell   rtc: rtc interfac...
191
  		retval = rtc_read_alarm(rtc, &alm);
3925a5ce4   David Brownell   [PATCH] RTC gets ...
192
193
  		if (retval < 0)
  			return retval;
1df0a4711   Bernie Thompson   rtc: add ability ...
194
195
196
197
198
199
200
201
  		if (alm.enabled) {
  			if (push) {
  				rtc_tm_to_time(&alm.time, &push);
  				alarm += push;
  			} else
  				return -EBUSY;
  		} else if (push)
  			return -EINVAL;
3925a5ce4   David Brownell   [PATCH] RTC gets ...
202
203
204
205
206
207
208
209
210
211
  		alm.enabled = 1;
  	} else {
  		alm.enabled = 0;
  
  		/* Provide a valid future alarm time.  Linux isn't EFI,
  		 * this time won't be ignored when disabling the alarm.
  		 */
  		alarm = now + 300;
  	}
  	rtc_time_to_tm(alarm, &alm.time);
ab6a2d70d   David Brownell   rtc: rtc interfac...
212
  	retval = rtc_set_alarm(rtc, &alm);
3925a5ce4   David Brownell   [PATCH] RTC gets ...
213
214
  	return (retval < 0) ? retval : n;
  }
a17ccd1c6   Dmitry Torokhov   rtc: switch wakea...
215
  static DEVICE_ATTR_RW(wakealarm);
3925a5ce4   David Brownell   [PATCH] RTC gets ...
216

5495a4159   Joshua Clayton   rtc: implement a ...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  static ssize_t
  offset_show(struct device *dev, struct device_attribute *attr, char *buf)
  {
  	ssize_t retval;
  	long offset;
  
  	retval = rtc_read_offset(to_rtc_device(dev), &offset);
  	if (retval == 0)
  		retval = sprintf(buf, "%ld
  ", offset);
  
  	return retval;
  }
  
  static ssize_t
  offset_store(struct device *dev, struct device_attribute *attr,
  	     const char *buf, size_t n)
  {
  	ssize_t retval;
  	long offset;
  
  	retval = kstrtol(buf, 10, &offset);
  	if (retval == 0)
  		retval = rtc_set_offset(to_rtc_device(dev), offset);
  
  	return (retval < 0) ? retval : n;
  }
  static DEVICE_ATTR_RW(offset);
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
245
246
247
248
249
250
251
252
  static struct attribute *rtc_attrs[] = {
  	&dev_attr_name.attr,
  	&dev_attr_date.attr,
  	&dev_attr_time.attr,
  	&dev_attr_since_epoch.attr,
  	&dev_attr_max_user_freq.attr,
  	&dev_attr_hctosys.attr,
  	&dev_attr_wakealarm.attr,
5495a4159   Joshua Clayton   rtc: implement a ...
253
  	&dev_attr_offset.attr,
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
254
255
  	NULL,
  };
3925a5ce4   David Brownell   [PATCH] RTC gets ...
256
257
258
259
260
261
  
  /* The reason to trigger an alarm with no process watching it (via sysfs)
   * is its side effect:  waking from a system state like suspend-to-RAM or
   * suspend-to-disk.  So: no attribute unless that side effect is possible.
   * (Userspace may disable that mechanism later.)
   */
df100c017   Dmitry Torokhov   rtc: make rtc_doe...
262
  static bool rtc_does_wakealarm(struct rtc_device *rtc)
3925a5ce4   David Brownell   [PATCH] RTC gets ...
263
  {
cd9662094   David Brownell   rtc: remove rest ...
264
  	if (!device_can_wakeup(rtc->dev.parent))
df100c017   Dmitry Torokhov   rtc: make rtc_doe...
265
  		return false;
3925a5ce4   David Brownell   [PATCH] RTC gets ...
266
267
  	return rtc->ops->set_alarm != NULL;
  }
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
268
269
  static umode_t rtc_attr_is_visible(struct kobject *kobj,
  				   struct attribute *attr, int n)
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
270
  {
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
271
272
273
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct rtc_device *rtc = to_rtc_device(dev);
  	umode_t mode = attr->mode;
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
274

5495a4159   Joshua Clayton   rtc: implement a ...
275
  	if (attr == &dev_attr_wakealarm.attr) {
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
276
277
  		if (!rtc_does_wakealarm(rtc))
  			mode = 0;
5495a4159   Joshua Clayton   rtc: implement a ...
278
279
280
281
  	} else if (attr == &dev_attr_offset.attr) {
  		if (!rtc->ops->set_offset)
  			mode = 0;
  	}
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
282

3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
283
  	return mode;
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
284
  }
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
285
286
287
288
289
290
291
292
293
  static struct attribute_group rtc_attr_group = {
  	.is_visible	= rtc_attr_is_visible,
  	.attrs		= rtc_attrs,
  };
  
  static const struct attribute_group *rtc_attr_groups[] = {
  	&rtc_attr_group,
  	NULL
  };
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
294

3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
295
  const struct attribute_group **rtc_get_dev_attribute_groups(void)
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
296
  {
3ee2c40b7   Dmitry Torokhov   rtc: switch to us...
297
  	return rtc_attr_groups;
c5c3e1922   Alessandro Zummo   [PATCH] RTC subsy...
298
  }