summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@bootlin.com>2018-06-05 23:19:29 +0200
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2018-06-05 23:19:29 +0200
commit4f736bf72188699e39ed4e58bd4d9ebf22c068f3 (patch)
tree8972b3bff9746e2c123834f6dc99b9e23c8e30c1
parent6a605d09ffc06986ac758fa1960e237be206f111 (diff)
downloadrtc-tools-4f736bf72188699e39ed4e58bd4d9ebf22c068f3.tar.gz
Add rtc tool
Add tool to handle RTD device ioctls. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--.gitignore2
-rw-r--r--rtc.c156
2 files changed, 158 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..61ff6a3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+rtc
+rtc-sync
diff --git a/rtc.c b/rtc.c
new file mode 100644
index 0000000..1ca128a
--- /dev/null
+++ b/rtc.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Real Time Clock tool
+ *
+ * Copyright (c) 2018 Alexandre Belloni <alexandre.belloni@bootlin.com>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/rtc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static char *rtc_file = "/dev/rtc0";
+
+#define IOCTL(f, r, d, rc) rc = ioctl(f, r, d); \
+if (rc) { \
+ fprintf(stderr, "%s returned %d (line %d)\n", #r, errno, __LINE__); \
+ exit(errno); \
+}
+
+#define ISODATEFMT "%04d-%02d-%02dT%02d:%02d:%02d"
+#define ISODATE(tm) tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \
+ tm.tm_hour, tm.tm_min, tm.tm_sec
+
+static void usage(char *name)
+{
+ fprintf(stderr, "Usage: %s <command>\n", name);
+ fprintf(stderr, " %s rd [rtc]\n", name);
+ fprintf(stderr, " %s set YYYY-MM-DDThh:mm:ss [rtc]\n", name);
+ fprintf(stderr, " %s wkalmrd [rtc]\n", name);
+ fprintf(stderr, " %s wkalmset YYYY-MM-DDThh:mm:ss [rtc]\n", name);
+ fprintf(stderr, " %s almread [rtc]\n", name);
+ fprintf(stderr, " %s almset YYYY-MM-DDThh:mm:ss [rtc]\n", name);
+ fprintf(stderr, " %s aieon [rtc]\n", name);
+ fprintf(stderr, " %s aieoff [rtc]\n", name);
+
+ exit(EINVAL);
+}
+
+int main(int argc, char **argv)
+{
+ struct rtc_time tm;
+ struct rtc_wkalrm alm;
+ int fd, rc, cmd = 0;
+
+ if (argc < 2)
+ usage(argv[0]);
+
+ if (!strcmp(argv[1], "rd")) {
+ if (argc > 2)
+ rtc_file = argv[2];
+ cmd = RTC_RD_TIME;
+ } else if (!strcmp(argv[1], "set")) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (argc > 3)
+ rtc_file = argv[3];
+ cmd = RTC_SET_TIME;
+ rc = sscanf(argv[2], "%d-%d-%dT%d:%d:%d", &tm.tm_year,
+ &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
+ &tm.tm_sec);
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
+ } else if (!strcmp(argv[1], "wkalmrd")) {
+ if (argc > 2)
+ rtc_file = argv[2];
+ cmd = RTC_WKALM_RD;
+ } else if (!strcmp(argv[1], "wkalmset")) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (argc > 3)
+ rtc_file = argv[3];
+ cmd = RTC_WKALM_SET;
+ rc = sscanf(argv[2], "%d-%d-%dT%d:%d:%d", &alm.time.tm_year,
+ &alm.time.tm_mon, &alm.time.tm_mday,
+ &alm.time.tm_hour, &alm.time.tm_min,
+ &alm.time.tm_sec);
+ alm.time.tm_year -= 1900;
+ alm.time.tm_mon -= 1;
+ alm.enabled = 1;
+ } else if (!strcmp(argv[1], "aieon")) {
+ if (argc > 2)
+ rtc_file = argv[2];
+ cmd = RTC_AIE_ON;
+ } else if (!strcmp(argv[1], "aieoff")) {
+ if (argc > 2)
+ rtc_file = argv[2];
+ cmd = RTC_AIE_OFF;
+ } else if (!strcmp(argv[1], "almread")) {
+ if (argc > 2)
+ rtc_file = argv[2];
+ cmd = RTC_ALM_READ;
+ } else if (!strcmp(argv[1], "almset")) {
+ if (argc < 3)
+ usage(argv[0]);
+ if (argc > 3)
+ rtc_file = argv[3];
+ cmd = RTC_ALM_SET;
+ rc = sscanf(argv[2], "%d-%d-%dT%d:%d:%d", &tm.tm_year,
+ &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
+ &tm.tm_sec);
+ alm.time.tm_year -= 1900;
+ alm.time.tm_mon -= 1;
+ alm.enabled = 1;
+ }
+
+ if (!cmd)
+ usage(argv[0]);
+
+ fd = open(rtc_file, O_RDONLY);
+ if (fd == -1) {
+ perror(rtc_file);
+ exit(errno);
+ }
+
+ switch (cmd) {
+ case RTC_RD_TIME:
+ IOCTL(fd, RTC_RD_TIME, &tm, rc);
+ printf("%s: " ISODATEFMT "\n", rtc_file, ISODATE(tm));
+ break;
+ case RTC_SET_TIME:
+ IOCTL(fd, RTC_SET_TIME, &tm, rc);
+ break;
+ case RTC_WKALM_RD:
+ IOCTL(fd, RTC_WKALM_RD, &alm, rc);
+ printf("%s: " ISODATEFMT "\n", rtc_file, ISODATE(alm.time));
+ break;
+ case RTC_WKALM_SET:
+ IOCTL(fd, RTC_WKALM_SET, &alm, rc);
+ break;
+ case RTC_ALM_READ:
+ IOCTL(fd, RTC_ALM_READ, &tm, rc);
+ printf("%s: " ISODATEFMT "\n", rtc_file, ISODATE(tm));
+ break;
+ case RTC_ALM_SET:
+ IOCTL(fd, RTC_ALM_SET, &tm, rc);
+ break;
+ case RTC_AIE_ON:
+ IOCTL(fd, RTC_AIE_ON, 0, rc);
+ break;
+ case RTC_AIE_OFF:
+ IOCTL(fd, RTC_AIE_OFF, 0, rc);
+ break;
+ }
+
+ close(fd);
+
+ return 0;
+}