mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 13:11:40 +00:00
[PATCH] rtc: Add rtc_merge_alarm()
Add rtc_merge_alarm(), which can be used by rtc drivers to turn a partially specified alarm expiry (i.e. most significant fields set to -1, as with the RTC_ALM_SET ioctl()) into a fully specified expiry. If the most significant specified field is earlier than the current time, the least significant unspecified field is incremented. Signed-off-by: Scott Wood <scottwood@freescale.com> Acked-by: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
9080d0ae0f
commit
884b4aaaa2
@ -117,4 +117,85 @@ int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
|
||||
}
|
||||
EXPORT_SYMBOL(rtc_tm_to_time);
|
||||
|
||||
|
||||
/* Merge the valid (i.e. non-negative) fields of alarm into the current
|
||||
* time. If the valid alarm fields are earlier than the equivalent
|
||||
* fields in the time, carry one into the least significant invalid
|
||||
* field, so that the alarm expiry is in the future. It assumes that the
|
||||
* least significant invalid field is more significant than the most
|
||||
* significant valid field, and that the seconds field is valid.
|
||||
*
|
||||
* This is used by alarms that take relative (rather than absolute)
|
||||
* times, and/or have a simple binary second counter instead of
|
||||
* day/hour/minute/sec registers.
|
||||
*/
|
||||
void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm)
|
||||
{
|
||||
int *alarmp = &alarm->tm_sec;
|
||||
int *timep = &now->tm_sec;
|
||||
int carry_into, i;
|
||||
|
||||
/* Ignore everything past the 6th element (tm_year). */
|
||||
for (i = 5; i > 0; i--) {
|
||||
if (alarmp[i] < 0)
|
||||
alarmp[i] = timep[i];
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* No carry needed if all fields are valid. */
|
||||
if (i == 5)
|
||||
return;
|
||||
|
||||
for (carry_into = i + 1; i >= 0; i--) {
|
||||
if (alarmp[i] < timep[i])
|
||||
break;
|
||||
|
||||
if (alarmp[i] > timep[i])
|
||||
return;
|
||||
}
|
||||
|
||||
switch (carry_into) {
|
||||
case 1:
|
||||
alarm->tm_min++;
|
||||
|
||||
if (alarm->tm_min < 60)
|
||||
return;
|
||||
|
||||
alarm->tm_min = 0;
|
||||
/* fall-through */
|
||||
|
||||
case 2:
|
||||
alarm->tm_hour++;
|
||||
|
||||
if (alarm->tm_hour < 60)
|
||||
return;
|
||||
|
||||
alarm->tm_hour = 0;
|
||||
/* fall-through */
|
||||
|
||||
case 3:
|
||||
alarm->tm_mday++;
|
||||
|
||||
if (alarm->tm_mday <= rtc_days_in_month[alarm->tm_mon])
|
||||
return;
|
||||
|
||||
alarm->tm_mday = 1;
|
||||
/* fall-through */
|
||||
|
||||
case 4:
|
||||
alarm->tm_mon++;
|
||||
|
||||
if (alarm->tm_mon <= 12)
|
||||
return;
|
||||
|
||||
alarm->tm_mon = 1;
|
||||
/* fall-through */
|
||||
|
||||
case 5:
|
||||
alarm->tm_year++;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rtc_merge_alarm);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -106,6 +106,7 @@ extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year
|
||||
extern int rtc_valid_tm(struct rtc_time *tm);
|
||||
extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
|
||||
extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
|
||||
extern void rtc_merge_alarm(struct rtc_time *now, struct rtc_time *alarm);
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
Loading…
Reference in New Issue
Block a user