diff options
author | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2021-01-22 21:03:30 +0100 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2021-10-11 00:28:49 +0200 |
commit | 36f663fdcc8b865ec5fa2174591503d379a9640b (patch) | |
tree | b645be1ebde2ab77c41fa2ee43f9804e5726e235 | |
parent | d3f6e86ccdda179fb3ea1b82f962f435148599d1 (diff) | |
download | rtc-tools-36f663fdcc8b865ec5fa2174591503d379a9640b.tar.gz |
rtc: add param support
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r-- | rtc.c | 150 |
1 files changed, 149 insertions, 1 deletions
@@ -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(¶m, 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(¶m, 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, ¶m, rc); + break; + case RTC_PARAM_GET: + IOCTL(fd, RTC_PARAM_GET, ¶m, 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); |