1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2020 Unisoc Communications Inc. 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/*\ 7f08c3bdfSopenharmony_ci * [Description] 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * RTC device set time function test. 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * [Algorithm] 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * - Save RTC time 14f08c3bdfSopenharmony_ci * - Set RTC time 15f08c3bdfSopenharmony_ci * - Read the RTC time back 16f08c3bdfSopenharmony_ci * - Check if the set time and the read time are identical 17f08c3bdfSopenharmony_ci * - Restore RTC time 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#include <stdio.h> 21f08c3bdfSopenharmony_ci#include "tst_rtctime.h" 22f08c3bdfSopenharmony_ci#include "tst_wallclock.h" 23f08c3bdfSopenharmony_ci#include "tst_test.h" 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_cistatic char *rtc_dev = "/dev/rtc"; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_cistatic char *rtctime_to_str(struct rtc_time *tm) 28f08c3bdfSopenharmony_ci{ 29f08c3bdfSopenharmony_ci static char rtctime_buf[128]; 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci sprintf(rtctime_buf, "%04d-%02d-%02d %02d:%02d:%02d", 32f08c3bdfSopenharmony_ci tm->tm_year + 1900, 33f08c3bdfSopenharmony_ci tm->tm_mon + 1, 34f08c3bdfSopenharmony_ci tm->tm_mday, 35f08c3bdfSopenharmony_ci tm->tm_hour, 36f08c3bdfSopenharmony_ci tm->tm_min, 37f08c3bdfSopenharmony_ci tm->tm_sec); 38f08c3bdfSopenharmony_ci return rtctime_buf; 39f08c3bdfSopenharmony_ci} 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_cistatic int rtc_tm_cmp(struct rtc_time *set_tm, struct rtc_time *read_tm) 42f08c3bdfSopenharmony_ci{ 43f08c3bdfSopenharmony_ci long delta, seconds1, seconds2; 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci if (set_tm->tm_year != read_tm->tm_year) 46f08c3bdfSopenharmony_ci return 1; 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci if (set_tm->tm_mon != read_tm->tm_mon) 49f08c3bdfSopenharmony_ci return 1; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci if (set_tm->tm_mday != read_tm->tm_mday) 52f08c3bdfSopenharmony_ci return 1; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci /* 55f08c3bdfSopenharmony_ci * Convert hour/min/sec into seconds to handle the normal 56f08c3bdfSopenharmony_ci * and special situations: 57f08c3bdfSopenharmony_ci * 1# 58f08c3bdfSopenharmony_ci * set_tm: 2022-04-28 13:00:50 59f08c3bdfSopenharmony_ci * read_tm: 2022-04-28 13:00:50 60f08c3bdfSopenharmony_ci * 2# 61f08c3bdfSopenharmony_ci * set_tm: 2022-04-28 13:00:50 62f08c3bdfSopenharmony_ci * read_tm: 2022-04-28 13:00:51 63f08c3bdfSopenharmony_ci * 3# 64f08c3bdfSopenharmony_ci * set_tm: 2022-04-28 13:00:59 65f08c3bdfSopenharmony_ci * read_tm: 2022-04-28 13:01:00 66f08c3bdfSopenharmony_ci * 4# 67f08c3bdfSopenharmony_ci * set_tm: 2022-04-28 13:59:59 68f08c3bdfSopenharmony_ci * read_tm: 2022-04-28 14:00:00 69f08c3bdfSopenharmony_ci * 70f08c3bdfSopenharmony_ci * Note: as we have avoided testing around the zero 71f08c3bdfSopenharmony_ci * clock, so it's impossible to hit situation 5# 72f08c3bdfSopenharmony_ci * set_tm: 2022-04-28 23:59:59 73f08c3bdfSopenharmony_ci * read_tm: 2022-04-29 00:00:00 74f08c3bdfSopenharmony_ci */ 75f08c3bdfSopenharmony_ci if ((set_tm->tm_hour != read_tm->tm_hour) 76f08c3bdfSopenharmony_ci || (set_tm->tm_min != read_tm->tm_min) 77f08c3bdfSopenharmony_ci || (set_tm->tm_sec != read_tm->tm_sec)) { 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci seconds1 = (set_tm->tm_hour * 3600) + (set_tm->tm_min * 60) + set_tm->tm_sec; 80f08c3bdfSopenharmony_ci seconds2 = (read_tm->tm_hour * 3600) + (read_tm->tm_min * 60) + read_tm->tm_sec; 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci delta = seconds2 - seconds1; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci if (delta < 0 || delta > 3) { 85f08c3bdfSopenharmony_ci tst_res(TFAIL, "seconds1 is %ld, seconds2 is %ld", seconds1, seconds2); 86f08c3bdfSopenharmony_ci return 1; 87f08c3bdfSopenharmony_ci } 88f08c3bdfSopenharmony_ci } 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci return 0; 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_cistatic void set_rtc_test(void) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci struct rtc_time read_tm, set_tm; 96f08c3bdfSopenharmony_ci int ret; 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci /* Read current RTC Time */ 99f08c3bdfSopenharmony_ci ret = tst_rtc_gettime(rtc_dev, &read_tm); 100f08c3bdfSopenharmony_ci if (ret != 0) { 101f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "ioctl() RTC_RD_TIME"); 102f08c3bdfSopenharmony_ci return; 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci /* set rtc to +/-1 hour */ 106f08c3bdfSopenharmony_ci set_tm = read_tm; 107f08c3bdfSopenharmony_ci if (set_tm.tm_hour == 0) 108f08c3bdfSopenharmony_ci set_tm.tm_hour += 1; 109f08c3bdfSopenharmony_ci else 110f08c3bdfSopenharmony_ci set_tm.tm_hour -= 1; 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_ci tst_res(TINFO, "To set RTC date/time is: %s", rtctime_to_str(&set_tm)); 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci ret = tst_rtc_settime(rtc_dev, &set_tm); 115f08c3bdfSopenharmony_ci if (ret != 0) { 116f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "ioctl() RTC_SET_TIME"); 117f08c3bdfSopenharmony_ci return; 118f08c3bdfSopenharmony_ci } 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci /* Read new RTC Time */ 121f08c3bdfSopenharmony_ci ret = tst_rtc_gettime(rtc_dev, &read_tm); 122f08c3bdfSopenharmony_ci if (ret != 0) { 123f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "ioctl() RTC_RD_TIME"); 124f08c3bdfSopenharmony_ci return; 125f08c3bdfSopenharmony_ci } 126f08c3bdfSopenharmony_ci tst_res(TINFO, "read RTC date/time is: %s", rtctime_to_str(&read_tm)); 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci if (rtc_tm_cmp(&set_tm, &read_tm)) { 129f08c3bdfSopenharmony_ci tst_res(TFAIL, "RTC SET TEST"); 130f08c3bdfSopenharmony_ci return; 131f08c3bdfSopenharmony_ci } 132f08c3bdfSopenharmony_ci tst_res(TPASS, "The read RTC time is consistent with set time"); 133f08c3bdfSopenharmony_ci} 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_cistatic void rtc_setup(void) 136f08c3bdfSopenharmony_ci{ 137f08c3bdfSopenharmony_ci int exists = access(rtc_dev, F_OK); 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci if (exists < 0) 140f08c3bdfSopenharmony_ci tst_brk(TCONF, "RTC device %s not available", rtc_dev); 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci tst_rtc_clock_save(rtc_dev); 143f08c3bdfSopenharmony_ci} 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_cistatic void rtc_cleanup(void) 146f08c3bdfSopenharmony_ci{ 147f08c3bdfSopenharmony_ci tst_rtc_clock_restore(rtc_dev); 148f08c3bdfSopenharmony_ci} 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_cistatic struct tst_test test = { 151f08c3bdfSopenharmony_ci .setup = rtc_setup, 152f08c3bdfSopenharmony_ci .test_all = set_rtc_test, 153f08c3bdfSopenharmony_ci .cleanup = rtc_cleanup, 154f08c3bdfSopenharmony_ci .needs_root = 1, 155f08c3bdfSopenharmony_ci}; 156