xref: /aosp_15_r20/external/ltp/lib/tst_rtctime.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2020 Unisoc Communications Inc.
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  * This file is a implementation for rtc set read,covert to tm functions
6*49cdfc7eSAndroid Build Coastguard Worker  */
7*49cdfc7eSAndroid Build Coastguard Worker 
8*49cdfc7eSAndroid Build Coastguard Worker #include <stdbool.h>
9*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
10*49cdfc7eSAndroid Build Coastguard Worker #define TST_NO_DEFAULT_MAIN
11*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
12*49cdfc7eSAndroid Build Coastguard Worker #include "tst_rtctime.h"
13*49cdfc7eSAndroid Build Coastguard Worker 
14*49cdfc7eSAndroid Build Coastguard Worker #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
15*49cdfc7eSAndroid Build Coastguard Worker 
16*49cdfc7eSAndroid Build Coastguard Worker static const unsigned char rtc_days_in_month[] = {
17*49cdfc7eSAndroid Build Coastguard Worker 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
18*49cdfc7eSAndroid Build Coastguard Worker };
19*49cdfc7eSAndroid Build Coastguard Worker 
is_leap_year(unsigned int year)20*49cdfc7eSAndroid Build Coastguard Worker static inline bool is_leap_year(unsigned int year)
21*49cdfc7eSAndroid Build Coastguard Worker {
22*49cdfc7eSAndroid Build Coastguard Worker 	return (!(year % 4) && (year % 100)) || !(year % 400);
23*49cdfc7eSAndroid Build Coastguard Worker }
24*49cdfc7eSAndroid Build Coastguard Worker 
tst_mktime(const unsigned int year0,const unsigned int mon0,const unsigned int day,const unsigned int hour,const unsigned int min,const unsigned int sec)25*49cdfc7eSAndroid Build Coastguard Worker static long long tst_mktime(const unsigned int year0, const unsigned int mon0,
26*49cdfc7eSAndroid Build Coastguard Worker 		const unsigned int day, const unsigned int hour,
27*49cdfc7eSAndroid Build Coastguard Worker 		const unsigned int min, const unsigned int sec)
28*49cdfc7eSAndroid Build Coastguard Worker {
29*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int mon = mon0, year = year0;
30*49cdfc7eSAndroid Build Coastguard Worker 
31*49cdfc7eSAndroid Build Coastguard Worker 	/* 1..12 -> 11,12,1..10 */
32*49cdfc7eSAndroid Build Coastguard Worker 	mon -= 2;
33*49cdfc7eSAndroid Build Coastguard Worker 	if (0 >= (int) (mon)) {
34*49cdfc7eSAndroid Build Coastguard Worker 		mon += 12;	/* Puts Feb last since it has leap day */
35*49cdfc7eSAndroid Build Coastguard Worker 		year -= 1;
36*49cdfc7eSAndroid Build Coastguard Worker 	}
37*49cdfc7eSAndroid Build Coastguard Worker 
38*49cdfc7eSAndroid Build Coastguard Worker 	return ((((long long)
39*49cdfc7eSAndroid Build Coastguard Worker 		(year/4 - year/100 + year/400 + 367*mon/12 + day) +
40*49cdfc7eSAndroid Build Coastguard Worker 		year*365 - 719499
41*49cdfc7eSAndroid Build Coastguard Worker 		)*24 + hour /* now have hours - midnight tomorrow handled here */
42*49cdfc7eSAndroid Build Coastguard Worker 		)*60 + min /* now have minutes */
43*49cdfc7eSAndroid Build Coastguard Worker 		)*60 + sec; /* finally seconds */
44*49cdfc7eSAndroid Build Coastguard Worker }
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker /*
47*49cdfc7eSAndroid Build Coastguard Worker  * The number of days in the month.
48*49cdfc7eSAndroid Build Coastguard Worker  */
rtc_month_days(unsigned int month,unsigned int year)49*49cdfc7eSAndroid Build Coastguard Worker static int rtc_month_days(unsigned int month, unsigned int year)
50*49cdfc7eSAndroid Build Coastguard Worker {
51*49cdfc7eSAndroid Build Coastguard Worker 	return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
52*49cdfc7eSAndroid Build Coastguard Worker }
53*49cdfc7eSAndroid Build Coastguard Worker 
54*49cdfc7eSAndroid Build Coastguard Worker /*
55*49cdfc7eSAndroid Build Coastguard Worker  * tst_rtc_time_to_tm - Converts time_t to rtc_time.
56*49cdfc7eSAndroid Build Coastguard Worker  * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
57*49cdfc7eSAndroid Build Coastguard Worker  */
tst_rtc_time_to_tm(long long time,struct rtc_time * tm)58*49cdfc7eSAndroid Build Coastguard Worker void tst_rtc_time_to_tm(long long time, struct rtc_time *tm)
59*49cdfc7eSAndroid Build Coastguard Worker {
60*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int month, year, secs;
61*49cdfc7eSAndroid Build Coastguard Worker 	int days;
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker 	/* time must be positive */
64*49cdfc7eSAndroid Build Coastguard Worker 	days = time / 86400;
65*49cdfc7eSAndroid Build Coastguard Worker 	secs = time % 86400;
66*49cdfc7eSAndroid Build Coastguard Worker 
67*49cdfc7eSAndroid Build Coastguard Worker 	/* day of the week, 1970-01-01 was a Thursday */
68*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_wday = (days + 4) % 7;
69*49cdfc7eSAndroid Build Coastguard Worker 
70*49cdfc7eSAndroid Build Coastguard Worker 	year = 1970 + days / 365;
71*49cdfc7eSAndroid Build Coastguard Worker 	days -= (year - 1970) * 365
72*49cdfc7eSAndroid Build Coastguard Worker 		+ LEAPS_THRU_END_OF(year - 1)
73*49cdfc7eSAndroid Build Coastguard Worker 		- LEAPS_THRU_END_OF(1970 - 1);
74*49cdfc7eSAndroid Build Coastguard Worker 	while (days < 0) {
75*49cdfc7eSAndroid Build Coastguard Worker 		year -= 1;
76*49cdfc7eSAndroid Build Coastguard Worker 		days += 365 + is_leap_year(year);
77*49cdfc7eSAndroid Build Coastguard Worker 	}
78*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_year = year - 1900;
79*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_yday = days + 1;
80*49cdfc7eSAndroid Build Coastguard Worker 
81*49cdfc7eSAndroid Build Coastguard Worker 	for (month = 0; month < 11; month++) {
82*49cdfc7eSAndroid Build Coastguard Worker 		int newdays;
83*49cdfc7eSAndroid Build Coastguard Worker 
84*49cdfc7eSAndroid Build Coastguard Worker 		newdays = days - rtc_month_days(month, year);
85*49cdfc7eSAndroid Build Coastguard Worker 		if (newdays < 0)
86*49cdfc7eSAndroid Build Coastguard Worker 			break;
87*49cdfc7eSAndroid Build Coastguard Worker 		days = newdays;
88*49cdfc7eSAndroid Build Coastguard Worker 	}
89*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_mon = month;
90*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_mday = days + 1;
91*49cdfc7eSAndroid Build Coastguard Worker 
92*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_hour = secs / 3600;
93*49cdfc7eSAndroid Build Coastguard Worker 	secs -= tm->tm_hour * 3600;
94*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_min = secs / 60;
95*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_sec = secs - tm->tm_min * 60;
96*49cdfc7eSAndroid Build Coastguard Worker 
97*49cdfc7eSAndroid Build Coastguard Worker 	tm->tm_isdst = 0;
98*49cdfc7eSAndroid Build Coastguard Worker }
99*49cdfc7eSAndroid Build Coastguard Worker 
100*49cdfc7eSAndroid Build Coastguard Worker /*
101*49cdfc7eSAndroid Build Coastguard Worker  * tst_rtc_tm_to_time - Converts rtc_time to time_t.
102*49cdfc7eSAndroid Build Coastguard Worker  * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
103*49cdfc7eSAndroid Build Coastguard Worker  */
tst_rtc_tm_to_time(struct rtc_time * tm)104*49cdfc7eSAndroid Build Coastguard Worker long long tst_rtc_tm_to_time(struct rtc_time *tm)
105*49cdfc7eSAndroid Build Coastguard Worker {
106*49cdfc7eSAndroid Build Coastguard Worker 	return tst_mktime(((unsigned int)tm->tm_year + 1900), tm->tm_mon + 1,
107*49cdfc7eSAndroid Build Coastguard Worker 			tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
108*49cdfc7eSAndroid Build Coastguard Worker }
109*49cdfc7eSAndroid Build Coastguard Worker 
tst_rtc_ioctl(const char * rtc_dev,unsigned long request,struct rtc_time * rtc_tm)110*49cdfc7eSAndroid Build Coastguard Worker int tst_rtc_ioctl(const char *rtc_dev, unsigned long request,
111*49cdfc7eSAndroid Build Coastguard Worker                   struct rtc_time *rtc_tm)
112*49cdfc7eSAndroid Build Coastguard Worker {
113*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
114*49cdfc7eSAndroid Build Coastguard Worker 	int rtc_fd = -1;
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 	rtc_fd = SAFE_OPEN(rtc_dev, O_RDONLY);
117*49cdfc7eSAndroid Build Coastguard Worker 
118*49cdfc7eSAndroid Build Coastguard Worker 	ret = ioctl(rtc_fd, request, rtc_tm);
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	if (ret != 0)
121*49cdfc7eSAndroid Build Coastguard Worker 		return -1;
122*49cdfc7eSAndroid Build Coastguard Worker 
123*49cdfc7eSAndroid Build Coastguard Worker 	if (rtc_fd > 0)
124*49cdfc7eSAndroid Build Coastguard Worker 		SAFE_CLOSE(rtc_fd);
125*49cdfc7eSAndroid Build Coastguard Worker 
126*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
127*49cdfc7eSAndroid Build Coastguard Worker }
128