All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cyril Hrubis <chrubis@suse.cz>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH 1/3] lib: add tst_rtctime* for rtc test
Date: Thu, 7 Jan 2021 14:50:11 +0100	[thread overview]
Message-ID: <X/cRkxEahPFoAYms@yuki.lan> (raw)
In-Reply-To: <20201223033517.1464263-2-gengcixi@gmail.com>

Hi!
>     get rtc time and set rtc time in default /dev/rtc;
>     Implemented a function that covert rtc time to time_t
>     this will be used in tst_rtc_save and tst_rtc_restore
> 
> Signed-off-by: Cixi Geng <cixi.geng1@unisoc.com>
> ---
>  include/tst_rtctime.h |  15 ++++
>  lib/tst_rtctime.c     | 161 ++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 176 insertions(+)
>  create mode 100644 include/tst_rtctime.h
>  create mode 100644 lib/tst_rtctime.c
> 
> diff --git a/include/tst_rtctime.h b/include/tst_rtctime.h
> new file mode 100644
> index 000000000..61ec6f0eb
> --- /dev/null
> +++ b/include/tst_rtctime.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

This is not correct format for the identifiers, the comment has to start
with //

Also the default license for new LTP code i GPL-2.0-or-later, so please
us that unless you have a reason to stick to GPL-2.0.

> +/*
> + * Copyright (C) 2020 Unisoc Inc.
> + */
> +
> +#ifndef TST_RTCTIME
> +#define TST_RTCTIME
> +
> +#include <linux/rtc.h>
> +
> +int tst_rtc_gettime(struct rtc_time *rtc_tm);
> +
> +int tst_rtc_settime(struct rtc_time *rtc_tm);

Should we add a path to the RTC device to these functions as well?

Are there any boards that have more than one RTC where we would need to
loop over all available devices during the test?

> +#endif /* TST_RTCTIME */
> diff --git a/lib/tst_rtctime.c b/lib/tst_rtctime.c
> new file mode 100644
> index 000000000..580ef0fdf
> --- /dev/null
> +++ b/lib/tst_rtctime.c
> @@ -0,0 +1,161 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2020 Unisoc Communications Inc.
> + *
> + * Filename : tst_rtctime.c
> + * Abstract : This file is a implementation for rtc set read,covert to tm functions
> + */
> +
> +#include <linux/rtc.h>
> +#include <stdbool.h>
> +#include <limits.h>
> +#define TST_NO_DEFAULT_MAIN
> +#include "tst_test.h"
> +#include "tst_rtctime.h"
> +
> +#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
> +
> +static const unsigned char rtc_days_in_month[] = {
> +	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
> +};
> +
> +static inline bool is_leap_year(unsigned int year)
> +{
> +	return (!(year % 4) && (year % 100)) || !(year % 400);
> +}
> +
> +static long long 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)
> +{
> +	unsigned int mon = mon0, year = year0;
> +
> +	/* 1..12 -> 11,12,1..10 */
> +	mon -= 2;
> +	if (0 >= (int) (mon)) {
> +		mon += 12;	/* Puts Feb last since it has leap day */
> +		year -= 1;
> +	}
> +
> +	return ((((long long)
> +		(year/4 - year/100 + year/400 + 367*mon/12 + day) +
> +		year*365 - 719499
> +		)*24 + hour /* now have hours - midnight tomorrow handled here */
> +		)*60 + min /* now have minutes */
> +		)*60 + sec; /* finally seconds */
> +}
> +
> +/*
> + * The number of days in the month.
> + */
> +static int rtc_month_days(unsigned int month, unsigned int year)
> +{
> +	return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
> +}
> +
> +/*
> + * tst_rtc_time_to_tm - Converts time_t to rtc_time.
> + * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
> + */
> +void tst_rtc_time_to_tm(long long time, struct rtc_time *tm)
> +{
> +	unsigned int month, year, secs;
> +	int days;
> +
> +	/* time must be positive */
> +	days = time / 86400;
> +	secs = time % 86400;
> +
> +	/* day of the week, 1970-01-01 was a Thursday */
> +	tm->tm_wday = (days + 4) % 7;
> +
> +	year = 1970 + days / 365;
> +	days -= (year - 1970) * 365
> +		+ LEAPS_THRU_END_OF(year - 1)
> +		- LEAPS_THRU_END_OF(1970 - 1);
> +	while (days < 0) {
> +		year -= 1;
> +		days += 365 + is_leap_year(year);
> +	}
> +	tm->tm_year = year - 1900;
> +	tm->tm_yday = days + 1;
> +
> +	for (month = 0; month < 11; month++) {
> +		int newdays;
> +
> +		newdays = days - rtc_month_days(month, year);
> +		if (newdays < 0)
> +			break;
> +		days = newdays;
> +	}
> +	tm->tm_mon = month;
> +	tm->tm_mday = days + 1;
> +
> +	tm->tm_hour = secs / 3600;
> +	secs -= tm->tm_hour * 3600;
> +	tm->tm_min = secs / 60;
> +	tm->tm_sec = secs - tm->tm_min * 60;
> +
> +	tm->tm_isdst = 0;
> +}
> +
> +/*
> + * tst_rtc_tm_to_time - Converts rtc_time to time_t.
> + * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
> + */
> +long long tst_rtc_tm_to_time(struct rtc_time *tm)
> +{
> +	return tst_mktime(((unsigned int)tm->tm_year + 1900), tm->tm_mon + 1,
> +			tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

So I guess that the reason why we can't use libc mktime() and gmtime_r()
is that time_t is 32bit on older 32bit architectures, right?

> +}
> +
> +static int rtc_supported_by_kernel(const char *rtc_dev)
> +{
> +	int exists = access(rtc_dev, F_OK);
> +
> +	if (exists < 0)
> +		tst_brk(TCONF, "RTC device %s not available", rtc_dev);
> +	return 0;
> +}

This function should be called by the tests rather than from the test
library.

> +static int tst_rtc_ioctl(unsigned long request, struct rtc_time *rtc_tm)
> +{
> +	int ret;
> +	int rtc_fd = -1;
> +	static const char *rtc_dev = "/dev/rtc";
> +
> +	if (!rtc_supported_by_kernel(rtc_dev))
> +		rtc_fd = SAFE_OPEN(rtc_dev, O_RDONLY);
> +
> +	ret = ioctl(rtc_fd, request, rtc_tm);
> +
> +	if (ret != 0)
> +		return -1;
> +
> +	if (rtc_fd > 0)
> +		SAFE_CLOSE(rtc_fd);
> +
> +	return 0;
> +}
> +
> +int tst_rtc_gettime(struct rtc_time *rtc_tm)
> +{
> +	int ret;
> +
> +	ret = tst_rtc_ioctl(RTC_RD_TIME, rtc_tm);
> +
> +	if (ret != 0)
> +		return -1;
> +	return 0;
> +}
> +
> +int tst_rtc_settime(struct rtc_time *rtc_tm)
> +{
> +	int ret;
> +
> +	ret = tst_rtc_ioctl(RTC_SET_TIME, rtc_tm);
> +
> +	if (ret != 0)
> +		return -1;
> +	return 0;
> +}

These two functions can be static inline and declared in the header as:


static inline int tst_rtc_settime(struct rtc_time *rtc_tm)
{
	return tst_rtc_ioctl(RTC_SET_TIME, rtc_tm);
}

-- 
Cyril Hrubis
chrubis@suse.cz

  reply	other threads:[~2021-01-07 13:50 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-23  3:35 [LTP] [PATCH 0/3] add rtctime libs and rtc02 case gengcixi
2020-12-23  3:35 ` [LTP] [PATCH 1/3] lib: add tst_rtctime* for rtc test gengcixi
2021-01-07 13:50   ` Cyril Hrubis [this message]
2021-01-08  8:30     ` Cixi Geng
2020-12-23  3:35 ` [LTP] [PATCH 2/3] lib: implement rtctime_save and rtctime_restore function gengcixi
2021-01-07 13:57   ` Cyril Hrubis
2021-01-08  9:19     ` Cixi Geng
2021-01-08  9:34       ` Cyril Hrubis
2021-01-08  9:45         ` Cixi Geng
2020-12-23  3:35 ` [LTP] [PATCH 3/3] rtc02: add rtc set time verify case gengcixi
2021-01-07 14:32   ` Cyril Hrubis
2021-01-07 14:33 ` [LTP] [PATCH 0/3] add rtctime libs and rtc02 case Cyril Hrubis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=X/cRkxEahPFoAYms@yuki.lan \
    --to=chrubis@suse.cz \
    --cc=ltp@lists.linux.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.