18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Real Time Clock Driver Test Program 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2018 Alexandre Belloni <alexandre.belloni@bootlin.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <errno.h> 98c2ecf20Sopenharmony_ci#include <fcntl.h> 108c2ecf20Sopenharmony_ci#include <linux/rtc.h> 118c2ecf20Sopenharmony_ci#include <stdio.h> 128c2ecf20Sopenharmony_ci#include <stdlib.h> 138c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 148c2ecf20Sopenharmony_ci#include <sys/time.h> 158c2ecf20Sopenharmony_ci#include <sys/types.h> 168c2ecf20Sopenharmony_ci#include <time.h> 178c2ecf20Sopenharmony_ci#include <unistd.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "../kselftest_harness.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define NUM_UIE 3 228c2ecf20Sopenharmony_ci#define ALARM_DELTA 3 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic char *rtc_file = "/dev/rtc0"; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciFIXTURE(rtc) { 278c2ecf20Sopenharmony_ci int fd; 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciFIXTURE_SETUP(rtc) { 318c2ecf20Sopenharmony_ci self->fd = open(rtc_file, O_RDONLY); 328c2ecf20Sopenharmony_ci ASSERT_NE(-1, self->fd); 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ciFIXTURE_TEARDOWN(rtc) { 368c2ecf20Sopenharmony_ci close(self->fd); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ciTEST_F(rtc, date_read) { 408c2ecf20Sopenharmony_ci int rc; 418c2ecf20Sopenharmony_ci struct rtc_time rtc_tm; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* Read the RTC time/date */ 448c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm); 458c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci TH_LOG("Current RTC date/time is %02d/%02d/%02d %02d:%02d:%02d.", 488c2ecf20Sopenharmony_ci rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900, 498c2ecf20Sopenharmony_ci rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciTEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { 538c2ecf20Sopenharmony_ci int i, rc, irq = 0; 548c2ecf20Sopenharmony_ci unsigned long data; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* Turn on update interrupts */ 578c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_UIE_ON, 0); 588c2ecf20Sopenharmony_ci if (rc == -1) { 598c2ecf20Sopenharmony_ci ASSERT_EQ(EINVAL, errno); 608c2ecf20Sopenharmony_ci TH_LOG("skip update IRQs not supported."); 618c2ecf20Sopenharmony_ci return; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci for (i = 0; i < NUM_UIE; i++) { 658c2ecf20Sopenharmony_ci /* This read will block */ 668c2ecf20Sopenharmony_ci rc = read(self->fd, &data, sizeof(data)); 678c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 688c2ecf20Sopenharmony_ci irq++; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci EXPECT_EQ(NUM_UIE, irq); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_UIE_OFF, 0); 748c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciTEST_F(rtc, uie_select) { 788c2ecf20Sopenharmony_ci int i, rc, irq = 0; 798c2ecf20Sopenharmony_ci unsigned long data; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* Turn on update interrupts */ 828c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_UIE_ON, 0); 838c2ecf20Sopenharmony_ci if (rc == -1) { 848c2ecf20Sopenharmony_ci ASSERT_EQ(EINVAL, errno); 858c2ecf20Sopenharmony_ci TH_LOG("skip update IRQs not supported."); 868c2ecf20Sopenharmony_ci return; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci for (i = 0; i < NUM_UIE; i++) { 908c2ecf20Sopenharmony_ci struct timeval tv = { .tv_sec = 2 }; 918c2ecf20Sopenharmony_ci fd_set readfds; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci FD_ZERO(&readfds); 948c2ecf20Sopenharmony_ci FD_SET(self->fd, &readfds); 958c2ecf20Sopenharmony_ci /* The select will wait until an RTC interrupt happens. */ 968c2ecf20Sopenharmony_ci rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 978c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 988c2ecf20Sopenharmony_ci ASSERT_NE(0, rc); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* This read won't block */ 1018c2ecf20Sopenharmony_ci rc = read(self->fd, &data, sizeof(unsigned long)); 1028c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1038c2ecf20Sopenharmony_ci irq++; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci EXPECT_EQ(NUM_UIE, irq); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_UIE_OFF, 0); 1098c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciTEST_F(rtc, alarm_alm_set) { 1138c2ecf20Sopenharmony_ci struct timeval tv = { .tv_sec = ALARM_DELTA + 2 }; 1148c2ecf20Sopenharmony_ci unsigned long data; 1158c2ecf20Sopenharmony_ci struct rtc_time tm; 1168c2ecf20Sopenharmony_ci fd_set readfds; 1178c2ecf20Sopenharmony_ci time_t secs, new; 1188c2ecf20Sopenharmony_ci int rc; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &tm); 1218c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci secs = timegm((struct tm *)&tm) + ALARM_DELTA; 1248c2ecf20Sopenharmony_ci gmtime_r(&secs, (struct tm *)&tm); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_ALM_SET, &tm); 1278c2ecf20Sopenharmony_ci if (rc == -1) { 1288c2ecf20Sopenharmony_ci ASSERT_EQ(EINVAL, errno); 1298c2ecf20Sopenharmony_ci TH_LOG("skip alarms are not supported."); 1308c2ecf20Sopenharmony_ci return; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_ALM_READ, &tm); 1348c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci TH_LOG("Alarm time now set to %02d:%02d:%02d.", 1378c2ecf20Sopenharmony_ci tm.tm_hour, tm.tm_min, tm.tm_sec); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* Enable alarm interrupts */ 1408c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_AIE_ON, 0); 1418c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci FD_ZERO(&readfds); 1448c2ecf20Sopenharmony_ci FD_SET(self->fd, &readfds); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 1478c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1488c2ecf20Sopenharmony_ci ASSERT_NE(0, rc); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* Disable alarm interrupts */ 1518c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_AIE_OFF, 0); 1528c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci rc = read(self->fd, &data, sizeof(unsigned long)); 1558c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1568c2ecf20Sopenharmony_ci TH_LOG("data: %lx", data); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &tm); 1598c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci new = timegm((struct tm *)&tm); 1628c2ecf20Sopenharmony_ci ASSERT_EQ(new, secs); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciTEST_F(rtc, alarm_wkalm_set) { 1668c2ecf20Sopenharmony_ci struct timeval tv = { .tv_sec = ALARM_DELTA + 2 }; 1678c2ecf20Sopenharmony_ci struct rtc_wkalrm alarm = { 0 }; 1688c2ecf20Sopenharmony_ci struct rtc_time tm; 1698c2ecf20Sopenharmony_ci unsigned long data; 1708c2ecf20Sopenharmony_ci fd_set readfds; 1718c2ecf20Sopenharmony_ci time_t secs, new; 1728c2ecf20Sopenharmony_ci int rc; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); 1758c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci secs = timegm((struct tm *)&alarm.time) + ALARM_DELTA; 1788c2ecf20Sopenharmony_ci gmtime_r(&secs, (struct tm *)&alarm.time); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci alarm.enabled = 1; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_WKALM_SET, &alarm); 1838c2ecf20Sopenharmony_ci if (rc == -1) { 1848c2ecf20Sopenharmony_ci ASSERT_EQ(EINVAL, errno); 1858c2ecf20Sopenharmony_ci TH_LOG("skip alarms are not supported."); 1868c2ecf20Sopenharmony_ci return; 1878c2ecf20Sopenharmony_ci } 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); 1908c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.", 1938c2ecf20Sopenharmony_ci alarm.time.tm_mday, alarm.time.tm_mon + 1, 1948c2ecf20Sopenharmony_ci alarm.time.tm_year + 1900, alarm.time.tm_hour, 1958c2ecf20Sopenharmony_ci alarm.time.tm_min, alarm.time.tm_sec); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci FD_ZERO(&readfds); 1988c2ecf20Sopenharmony_ci FD_SET(self->fd, &readfds); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 2018c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2028c2ecf20Sopenharmony_ci ASSERT_NE(0, rc); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci rc = read(self->fd, &data, sizeof(unsigned long)); 2058c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &tm); 2088c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci new = timegm((struct tm *)&tm); 2118c2ecf20Sopenharmony_ci ASSERT_EQ(new, secs); 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ciTEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) { 2158c2ecf20Sopenharmony_ci struct timeval tv = { .tv_sec = 62 }; 2168c2ecf20Sopenharmony_ci unsigned long data; 2178c2ecf20Sopenharmony_ci struct rtc_time tm; 2188c2ecf20Sopenharmony_ci fd_set readfds; 2198c2ecf20Sopenharmony_ci time_t secs, new; 2208c2ecf20Sopenharmony_ci int rc; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &tm); 2238c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec; 2268c2ecf20Sopenharmony_ci gmtime_r(&secs, (struct tm *)&tm); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_ALM_SET, &tm); 2298c2ecf20Sopenharmony_ci if (rc == -1) { 2308c2ecf20Sopenharmony_ci ASSERT_EQ(EINVAL, errno); 2318c2ecf20Sopenharmony_ci TH_LOG("skip alarms are not supported."); 2328c2ecf20Sopenharmony_ci return; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_ALM_READ, &tm); 2368c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci TH_LOG("Alarm time now set to %02d:%02d:%02d.", 2398c2ecf20Sopenharmony_ci tm.tm_hour, tm.tm_min, tm.tm_sec); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* Enable alarm interrupts */ 2428c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_AIE_ON, 0); 2438c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci FD_ZERO(&readfds); 2468c2ecf20Sopenharmony_ci FD_SET(self->fd, &readfds); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 2498c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2508c2ecf20Sopenharmony_ci ASSERT_NE(0, rc); 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci /* Disable alarm interrupts */ 2538c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_AIE_OFF, 0); 2548c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci rc = read(self->fd, &data, sizeof(unsigned long)); 2578c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2588c2ecf20Sopenharmony_ci TH_LOG("data: %lx", data); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &tm); 2618c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci new = timegm((struct tm *)&tm); 2648c2ecf20Sopenharmony_ci ASSERT_EQ(new, secs); 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciTEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { 2688c2ecf20Sopenharmony_ci struct timeval tv = { .tv_sec = 62 }; 2698c2ecf20Sopenharmony_ci struct rtc_wkalrm alarm = { 0 }; 2708c2ecf20Sopenharmony_ci struct rtc_time tm; 2718c2ecf20Sopenharmony_ci unsigned long data; 2728c2ecf20Sopenharmony_ci fd_set readfds; 2738c2ecf20Sopenharmony_ci time_t secs, new; 2748c2ecf20Sopenharmony_ci int rc; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time); 2778c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec; 2808c2ecf20Sopenharmony_ci gmtime_r(&secs, (struct tm *)&alarm.time); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci alarm.enabled = 1; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_WKALM_SET, &alarm); 2858c2ecf20Sopenharmony_ci if (rc == -1) { 2868c2ecf20Sopenharmony_ci ASSERT_EQ(EINVAL, errno); 2878c2ecf20Sopenharmony_ci TH_LOG("skip alarms are not supported."); 2888c2ecf20Sopenharmony_ci return; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_WKALM_RD, &alarm); 2928c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.", 2958c2ecf20Sopenharmony_ci alarm.time.tm_mday, alarm.time.tm_mon + 1, 2968c2ecf20Sopenharmony_ci alarm.time.tm_year + 1900, alarm.time.tm_hour, 2978c2ecf20Sopenharmony_ci alarm.time.tm_min, alarm.time.tm_sec); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci FD_ZERO(&readfds); 3008c2ecf20Sopenharmony_ci FD_SET(self->fd, &readfds); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci rc = select(self->fd + 1, &readfds, NULL, NULL, &tv); 3038c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 3048c2ecf20Sopenharmony_ci ASSERT_NE(0, rc); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci rc = read(self->fd, &data, sizeof(unsigned long)); 3078c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci rc = ioctl(self->fd, RTC_RD_TIME, &tm); 3108c2ecf20Sopenharmony_ci ASSERT_NE(-1, rc); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci new = timegm((struct tm *)&tm); 3138c2ecf20Sopenharmony_ci ASSERT_EQ(new, secs); 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic void __attribute__((constructor)) 3178c2ecf20Sopenharmony_ci__constructor_order_last(void) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci if (!__constructor_order) 3208c2ecf20Sopenharmony_ci __constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ciint main(int argc, char **argv) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci switch (argc) { 3268c2ecf20Sopenharmony_ci case 2: 3278c2ecf20Sopenharmony_ci rtc_file = argv[1]; 3288c2ecf20Sopenharmony_ci /* FALLTHROUGH */ 3298c2ecf20Sopenharmony_ci case 1: 3308c2ecf20Sopenharmony_ci break; 3318c2ecf20Sopenharmony_ci default: 3328c2ecf20Sopenharmony_ci fprintf(stderr, "usage: %s [rtcdev]\n", argv[0]); 3338c2ecf20Sopenharmony_ci return 1; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci return test_harness_run(argc, argv); 3378c2ecf20Sopenharmony_ci} 338