From: Hugo Villeneuve Date: Mon, 9 Mar 2026 19:34:16 +0000 (-0400) Subject: Add test option X-Git-Url: http://gitweb.hugovil.com/sitemap.xml?a=commitdiff_plain;h=74cb85554995402917d87929a3c2eb1fc95ac84e;p=hvrtc.git Add test option Signed-off-by: Hugo Villeneuve --- diff --git a/src/main.c b/src/main.c index e824131..2c6b453 100644 --- a/src/main.c +++ b/src/main.c @@ -81,227 +81,297 @@ static int rtc_param_set_bsm(int fd, int value) return 0; } -int -main(int argc, char **argv) +static int rtc_test_uie(int fd) { + unsigned long data; + int irqcount = 0; int rc; - int i, fd, retval, irqcount = 0; - unsigned long tmp, data; - struct rtc_time rtc_tm; - - rc = parse_command_line_options(argc, argv); - if (rc) - exit(EXIT_FAILURE); - - fd = open(options.rtc_path, O_RDONLY); - if (fd == -1) { - perror(options.rtc_path); - exit(errno); - } - - if (options.bsm) { - if (options.bsm_arg >= 0) { - retval = rtc_param_set_bsm(fd, options.bsm_arg); - if (retval < 0) - exit(retval); - } else { - retval = rtc_param_get_bsm(fd); - if (retval < 0) - exit(retval); - } - } - - printf("RTC test\n"); - - /* Test for backup conditions */ - retval = ioctl(fd, RTC_VL_READ, &tmp); - if (retval < 0) { - fprintf(stderr, "\n...RTC_VL_READ ioctl not supported.\n"); - } else { - fprintf(stderr, "RTC_VL_READ: $%02lX\n", tmp); - - if (tmp & RTC_VL_BACKUP_LOW) - fprintf(stderr, "Backup low voltage detected, check/replace RTC battery\n"); - - if (tmp & RTC_VL_BACKUP_SWITCH) - fprintf(stderr, "Backup switchover happened\n"); - - if (tmp & RTC_VL_DATA_INVALID) - fprintf(stderr, "Voltage too low, RTC data is invalid\n"); - } + int i; /* Turn on update interrupts (one per second) */ - retval = ioctl(fd, RTC_UIE_ON, 0); - if (retval == -1) { + rc = ioctl(fd, RTC_UIE_ON, 0); + if (rc == -1) { if (errno == ENOTTY) { - fprintf(stderr, - "\n...Update IRQs not supported.\n"); - goto test_READ; + fprintf(stderr, "Update IRQs not supported\n"); + return 0; } perror("RTC_UIE_ON ioctl"); - exit(errno); + return -errno; } - fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading %s:", - options.rtc_path); - fflush(stderr); - for (i=1; i<6; i++) { + + printf("Counting 5 update (1/sec) interrupts from %s:", options.rtc_path); + fflush(stdout); + + for (i = 1; i < 6; i++) { /* This read will block */ - retval = read(fd, &data, sizeof(unsigned long)); - if (retval == -1) { + rc = read(fd, &data, sizeof(unsigned long)); + if (rc == -1) { + printf("\n"); perror("read"); - exit(errno); + return -errno; } - fprintf(stderr, " %d",i); - fflush(stderr); + + printf(" %d", i); + fflush(stdout); irqcount++; } - fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:"); - fflush(stderr); - for (i=1; i<6; i++) { + + printf("\n"); + + printf("Again, using select(2) from %s:", options.rtc_path); + fflush(stdout); + + for (i = 1; i < 6; i++) { struct timeval tv = {5, 0}; /* 5 second timeout on select */ fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); /* The select will wait until an RTC interrupt happens. */ - retval = select(fd+1, &readfds, NULL, NULL, &tv); - if (retval == -1) { + rc = select(fd+1, &readfds, NULL, NULL, &tv); + if (rc == -1) { + printf("\n"); perror("select"); - exit(errno); + return -errno; } + /* This read won't block unlike the select-less case above. */ - retval = read(fd, &data, sizeof(unsigned long)); - if (retval == -1) { + rc = read(fd, &data, sizeof(unsigned long)); + if (rc == -1) { + printf("\n"); perror("read"); - exit(errno); + return -errno; } - fprintf(stderr, " %d",i); - fflush(stderr); + + printf(" %d", i); + fflush(stdout); irqcount++; } + + printf("\n"); + /* Turn off update interrupts */ - retval = ioctl(fd, RTC_UIE_OFF, 0); - if (retval == -1) { + rc = ioctl(fd, RTC_UIE_OFF, 0); + if (rc == -1) { perror("RTC_UIE_OFF ioctl"); - exit(errno); + return -errno; } -test_READ: + + return 0; +} + +static int rtc_test_read(int fd) +{ + struct rtc_time rtc_tm; + unsigned long data; + int rc; + /* Read the RTC time/date */ - retval = ioctl(fd, RTC_RD_TIME, &rtc_tm); - if (retval == -1) { + rc = ioctl(fd, RTC_RD_TIME, &rtc_tm); + if (rc == -1) { perror("RTC_RD_TIME ioctl"); - exit(errno); + return -errno; } - fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n", - rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900, - rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); + + printf("Current RTC date/time: %d-%d-%d, %02d:%02d:%02d\n", + rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900, + rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); + /* Set the alarm to 5 sec in the future, and check for rollover */ rtc_tm.tm_sec += 5; if (rtc_tm.tm_sec >= 60) { rtc_tm.tm_sec %= 60; rtc_tm.tm_min++; } + if (rtc_tm.tm_min == 60) { rtc_tm.tm_min = 0; rtc_tm.tm_hour++; } + if (rtc_tm.tm_hour == 24) rtc_tm.tm_hour = 0; - retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); - if (retval == -1) { + + rc = ioctl(fd, RTC_ALM_SET, &rtc_tm); + if (rc == -1) { if (errno == ENOTTY) { - fprintf(stderr, - "\n...Alarm IRQs not supported.\n"); - goto test_PIE; + fprintf(stderr, "Alarm IRQs not supported\n"); + return 0; } perror("RTC_ALM_SET ioctl"); - exit(errno); + return -errno; } + /* Read the current alarm settings */ - retval = ioctl(fd, RTC_ALM_READ, &rtc_tm); - if (retval == -1) { + rc = ioctl(fd, RTC_ALM_READ, &rtc_tm); + if (rc == -1) { perror("RTC_ALM_READ ioctl"); - exit(errno); + return -errno; } - fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n", - rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); + + printf("Alarm time: %02d:%02d:%02d\n", + rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); /* Enable alarm interrupts */ - retval = ioctl(fd, RTC_AIE_ON, 0); - if (retval == -1) { + rc = ioctl(fd, RTC_AIE_ON, 0); + if (rc == -1) { perror("RTC_AIE_ON ioctl"); - exit(errno); + return -errno; } - fprintf(stderr, "Waiting 5 seconds for alarm..."); - fflush(stderr); + + printf("Waiting 5 seconds for alarm... "); + fflush(stdout); + /* This blocks until the alarm ring causes an interrupt */ - retval = read(fd, &data, sizeof(unsigned long)); - if (retval == -1) { + rc = read(fd, &data, sizeof(unsigned long)); + if (rc == -1) { + printf("\n"); perror("read"); - exit(errno); + return -errno; } - irqcount++; - fprintf(stderr, " okay. Alarm rang.\n"); + + printf("Ok: Alarm rang\n"); + /* Disable alarm interrupts */ - retval = ioctl(fd, RTC_AIE_OFF, 0); - if (retval == -1) { + rc = ioctl(fd, RTC_AIE_OFF, 0); + if (rc == -1) { perror("RTC_AIE_OFF ioctl"); - exit(errno); + return -errno; } -test_PIE: + + return 0; +} + +static int rtc_test_pie(int fd) +{ + unsigned long data; + unsigned long tmp; + int rc; + unsigned int i; + /* Read periodic IRQ rate */ - retval = ioctl(fd, RTC_IRQP_READ, &tmp); - if (retval == -1) { + rc = ioctl(fd, RTC_IRQP_READ, &tmp); + if (rc == -1) { /* not all RTCs support periodic IRQs */ if (errno == ENOTTY) { - fprintf(stderr, "\nNo periodic IRQ support\n"); - goto done; + printf("No periodic IRQ support\n"); + return -errno; } perror("RTC_IRQP_READ ioctl"); - exit(errno); + return -errno; } - fprintf(stderr, "\nPeriodic IRQ rate is %ldHz.\n", tmp); - fprintf(stderr, "Counting 20 interrupts at:"); - fflush(stderr); + + printf("Periodic IRQ rate is %ldHz\n", tmp); + + printf("Counting 20 interrupts at:"); + fflush(stdout); + /* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */ - for (tmp=2; tmp<=64; tmp*=2) { - retval = ioctl(fd, RTC_IRQP_SET, tmp); - if (retval == -1) { + for (tmp = 2; tmp <= 64; tmp *= 2) { + rc = ioctl(fd, RTC_IRQP_SET, tmp); + if (rc == -1) { /* not all RTCs can change their periodic IRQ rate */ if (errno == ENOTTY) { - fprintf(stderr, - "\n...Periodic IRQ rate is fixed\n"); - goto done; + printf("\n"); + printf("Periodic IRQ rate is fixed\n"); + return -errno; } perror("RTC_IRQP_SET ioctl"); - exit(errno); + return -errno; } - fprintf(stderr, "\n%ldHz:\t", tmp); - fflush(stderr); + + printf("\n"); + printf("%ldHz:\t", tmp); + fflush(stdout); + /* Enable periodic interrupts */ - retval = ioctl(fd, RTC_PIE_ON, 0); - if (retval == -1) { + rc = ioctl(fd, RTC_PIE_ON, 0); + if (rc == -1) { + printf("\n"); perror("RTC_PIE_ON ioctl"); - exit(errno); + return -errno; } - for (i=1; i<21; i++) { + + for (i = 1; i < 21; i++) { /* This blocks */ - retval = read(fd, &data, sizeof(unsigned long)); - if (retval == -1) { + rc = read(fd, &data, sizeof(unsigned long)); + if (rc == -1) { + printf("\n"); perror("read"); - exit(errno); + return -errno; } - fprintf(stderr, " %d",i); - fflush(stderr); - irqcount++; + printf(" %d", i); + fflush(stdout); } + /* Disable periodic interrupts */ - retval = ioctl(fd, RTC_PIE_OFF, 0); - if (retval == -1) { + rc = ioctl(fd, RTC_PIE_OFF, 0); + if (rc == -1) { + printf("\n"); perror("RTC_PIE_OFF ioctl"); - exit(errno); + return -errno; } } -done: + + printf("\n"); + + return 0; +} + +static int rtc_test(int fd) +{ + int rc; + + printf("RTC test:\n"); + + rc = rtc_test_uie(fd); + if (rc) + return rc; + + rc = rtc_test_read(fd); + if (rc) + return rc; + + rc = rtc_test_pie(fd); + if (rc) + return rc; + + return 0; +} + +int +main(int argc, char **argv) +{ + int rc; + int fd; + + rc = parse_command_line_options(argc, argv); + if (rc) + exit(EXIT_FAILURE); + + fd = open(options.rtc_path, O_RDONLY); + if (fd == -1) { + perror(options.rtc_path); + exit(errno); + } + + if (options.bsm) { + if (options.bsm_arg >= 0) { + rc = rtc_param_set_bsm(fd, options.bsm_arg); + if (rc < 0) + exit(rc); + } else { + rc = rtc_param_get_bsm(fd); + if (rc < 0) + exit(rc); + } + } + + if (options.test) { + rc = rtc_test(fd); + if (rc < 0) + exit(rc); + } + close(fd); return 0; diff --git a/src/options.c b/src/options.c index e92f3a1..0dff2d7 100644 --- a/src/options.c +++ b/src/options.c @@ -46,6 +46,7 @@ static const char args_doc[] = ""; static struct argp_option argp_options[] = { {"bsm", 'b', "value", OPTION_ARG_OPTIONAL, "Get/Set Backup Switch Mode (BSM)", 0}, {"dev", 'd', "path", 0, "RTC device path (optional)", 0}, + {"test", 't', 0, 0, "Test RTC", 0}, { 0 } }; @@ -104,6 +105,9 @@ parse_opt(int key, char *arg, struct argp_state *state) /* We do not support any arguments after the options. */ argp_usage(state); break; + case 't': + options.test = true; + break; default: return ARGP_ERR_UNKNOWN; } diff --git a/src/options.h b/src/options.h index a4077ff..44c967b 100644 --- a/src/options.h +++ b/src/options.h @@ -19,6 +19,7 @@ struct options_t { char *rtc_path; int bsm; int bsm_arg; + int test; }; int parse_command_line_options(int argc, char *argv[]);