summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@bootlin.com>2021-01-22 21:03:30 +0100
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2021-10-11 00:28:49 +0200
commit36f663fdcc8b865ec5fa2174591503d379a9640b (patch)
treeb645be1ebde2ab77c41fa2ee43f9804e5726e235
parentd3f6e86ccdda179fb3ea1b82f962f435148599d1 (diff)
downloadrtc-tools-36f663fdcc8b865ec5fa2174591503d379a9640b.tar.gz
rtc: add param support
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--rtc.c150
1 files changed, 149 insertions, 1 deletions
diff --git a/rtc.c b/rtc.c
index fc6af31..bbc2d0d 100644
--- a/rtc.c
+++ b/rtc.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <linux/const.h>
#include <linux/rtc.h>
+#include <linux/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
@@ -28,6 +29,40 @@ static char *rtc_file = "/dev/rtc0";
#define RTC_VL_BACKUP_SWITCH _BITUL(4) /* Backup switchover happened */
#endif
+#ifndef RTC_PARAM_GET
+struct rtc_param {
+ __u64 param;
+ union {
+ __u64 uvalue;
+ __s64 svalue;
+ __u64 ptr;
+ };
+ __u32 index;
+ __u32 __pad;
+};
+
+#define RTC_PARAM_GET _IOW('p', 0x13, struct rtc_param) /* Get parameter */
+#define RTC_PARAM_SET _IOW('p', 0x14, struct rtc_param) /* Set parameter */
+
+#define RTC_PARAM_FEATURES 0
+#define RTC_PARAM_CORRECTION 1
+#define RTC_PARAM_BACKUP_SWITCH_MODE 2
+
+#define RTC_FEATURE_ALARM 0
+#define RTC_FEATURE_ALARM_RES_MINUTE 1
+#define RTC_FEATURE_NEED_WEEK_DAY 2
+#define RTC_FEATURE_UPDATE_INTERRUPT 3
+#define RTC_FEATURE_CORRECTION 4
+#define RTC_FEATURE_BACKUP_SWITCH_MODE 5
+#define RTC_FEATURE_CNT 6
+
+#define RTC_BSM_DISABLED 0
+#define RTC_BSM_DIRECT 1
+#define RTC_BSM_LEVEL 2
+#define RTC_BSM_STANDBY 3
+
+#endif
+
#define IOCTL(f, r, d, rc) rc = ioctl(f, r, d); \
if (rc) { \
fprintf(stderr, "%s returned %s (%d) at line %d\n", #r, \
@@ -39,8 +74,34 @@ if (rc) { \
#define ISODATE(tm) tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, \
tm.tm_hour, tm.tm_min, tm.tm_sec
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+static const char *param_names[] = {
+ "RTC_PARAM_FEATURES",
+ "RTC_PARAM_CORRECTION",
+ "RTC_PARAM_BACKUP_SWITCH_MODE",
+};
+
+static const char *bsm_names[] = {
+ "RTC_BSM_DISABLED",
+ "RTC_BSM_DIRECT",
+ "RTC_BSM_LEVEL",
+ "RTC_BSM_STANDBY",
+};
+
+static const char *feature_names[] = {
+ "RTC_FEATURE_ALARM",
+ "RTC_FEATURE_ALARM_RES_MINUTE",
+ "RTC_FEATURE_NEED_WEEK_DAY",
+ "RTC_FEATURE_UPDATE_INTERRUPT",
+ "RTC_FEATURE_CORRECTION",
+ "RTC_FEATURE_BACKUP_SWITCH_MODE",
+};
+
static void usage(char *name)
{
+ int i;
+
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);
@@ -52,15 +113,61 @@ static void usage(char *name)
fprintf(stderr, " %s aieoff [rtc]\n", name);
fprintf(stderr, " %s vlrd [rtc]\n", name);
fprintf(stderr, " %s vlclr [rtc]\n", name);
+ fprintf(stderr, " %s paramget param index [rtc]\n", name);
+ fprintf(stderr, " %s paramset param index value [rtc]\n", name);
+ fprintf(stderr, " Valid parameters:\n");
+ for (i = 0; i < ARRAY_SIZE(param_names); i++)
+ fprintf(stderr, " - %s\n", param_names[i]);
exit(EINVAL);
}
+static int parse_rtc_param(struct rtc_param *param, char *param_name, char *index, char *value)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(param_names); i++)
+ if (!strcmp(param_name, param_names[i]))
+ break;
+
+ if (i == ARRAY_SIZE(param_names))
+ return -EINVAL;
+
+ param->param = i;
+
+ param->index = strtoul(index, NULL, 10);
+
+ if (value) {
+ switch(param->param) {
+ case RTC_PARAM_BACKUP_SWITCH_MODE:
+ for (i = 0; i < ARRAY_SIZE(bsm_names); i++)
+ if (!strcmp(value, bsm_names[i]))
+ break;
+
+ if (i == ARRAY_SIZE(bsm_names))
+ return -EINVAL;
+
+ param->uvalue = i;
+ break;
+
+ case RTC_PARAM_CORRECTION:
+ param->svalue = strtol(value, NULL, 10);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
struct rtc_time tm;
struct rtc_wkalrm alm;
- int fd, rc, cmd = 0;
+ struct rtc_param param;
+ int i, fd, rc, cmd = 0;
unsigned int flags;
if (argc < 2)
@@ -130,6 +237,26 @@ int main(int argc, char **argv)
if (argc > 2)
rtc_file = argv[2];
cmd = RTC_VL_CLR;
+ } else if (!strcmp(argv[1], "paramget")) {
+
+ if (argc < 4)
+ usage(argv[0]);
+ if (argc > 4)
+ rtc_file = argv[4];
+ cmd = RTC_PARAM_GET;
+
+ if (parse_rtc_param(&param, argv[2], argv[3], NULL) < 0)
+ usage(argv[0]);
+
+ } else if (!strcmp(argv[1], "paramset")) {
+ if (argc < 5)
+ usage(argv[0]);
+ if (argc > 5)
+ rtc_file = argv[5];
+ cmd = RTC_PARAM_SET;
+
+ if (parse_rtc_param(&param, argv[2], argv[3], argv[4]) < 0)
+ usage(argv[0]);
}
if (!cmd)
@@ -186,6 +313,27 @@ int main(int argc, char **argv)
case RTC_VL_CLR:
IOCTL(fd, RTC_VL_CLR, 0, rc);
break;
+ case RTC_PARAM_SET:
+ IOCTL(fd, RTC_PARAM_SET, &param, rc);
+ break;
+ case RTC_PARAM_GET:
+ IOCTL(fd, RTC_PARAM_GET, &param, rc);
+ switch(param.param) {
+ case RTC_PARAM_FEATURES:
+ printf("%s[%u]:\n", param_names[param.param], param.index);
+ for (i = 0; i < ARRAY_SIZE(feature_names); i++)
+ if (param.uvalue & _BITUL(i))
+ printf(" %s\n", feature_names[i]);
+ break;
+ case RTC_PARAM_CORRECTION:
+ printf("%s[%u] = %lld\n", param_names[param.param], param.index, param.svalue);
+ break;
+ case RTC_PARAM_BACKUP_SWITCH_MODE:
+ printf("%s[%u] = %s\n", param_names[param.param], param.index, bsm_names[param.uvalue]);
+ break;
+ default:
+ printf("%s[%u] = %llx\n", param_names[param.param], param.index, param.uvalue);
+ }
}
close(fd);