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;