9
0
Fork 0

commands: add hwclock

The hwclock command allows to query or set the hardware clock (RTC).

Barebox' 'hwclock' command uses busybox' 'date' compatible
time format ccyymmddHHMM[.SS]:

  # /bin/busybox date -s 201407292005.41 ; /bin/date
  Tue Jul 29 20:05:41 MSK 2014
  Tue Jul 29 20:05:41 MSK 2014

Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Antony Pavlov 2014-07-30 00:10:20 +04:00 committed by Sascha Hauer
parent 686df208b3
commit 2bcf7f4dc8
3 changed files with 170 additions and 0 deletions

View File

@ -1691,6 +1691,14 @@ config CMD_GPIO
Usage: gpio_set_value GPIO VALUE
config CMD_HWCLOCK
bool
depends on RTC_CLASS
prompt "hwclock command"
default y
help
The hwclock command allows to query or set the hardware clock (RTC).
config CMD_I2C
bool
depends on I2C

View File

@ -100,3 +100,4 @@ obj-$(CONFIG_CMD_MENUTREE) += menutree.o
obj-$(CONFIG_CMD_2048) += 2048.o
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
obj-$(CONFIG_CMD_LSPCI) += lspci.o
obj-$(CONFIG_CMD_HWCLOCK) += hwclock.o

161
commands/hwclock.c Normal file
View File

@ -0,0 +1,161 @@
#include <common.h>
#include <command.h>
#include <getopt.h>
#include <linux/err.h>
#include <linux/ctype.h>
#include <rtc.h>
#include <linux/rtc.h>
#include <string.h>
#include <environment.h>
static char *strchrnul(const char *s, int c)
{
while (*s != '\0' && *s != c)
s++;
return (char *)s;
}
static int sscanf_two_digits(char *s, int *res)
{
char buf[3];
unsigned long t;
if (!isdigit(s[0]) || !isdigit(s[1])) {
return -EINVAL;
}
buf[0] = s[0];
buf[1] = s[1];
buf[2] = '\0';
t = simple_strtoul(buf, NULL, 10);
*res = t;
return 0;
}
static int parse_datestr(char *date_str, struct rtc_time *ptm)
{
char end = '\0';
int len = strchrnul(date_str, '.') - date_str;
int year;
/* ccyymmddHHMM[.SS] */
if (len != 12) {
return -EINVAL;
}
if (sscanf_two_digits(date_str, &year) ||
sscanf_two_digits(&date_str[2], &ptm->tm_year)) {
return -EINVAL;
}
ptm->tm_year = year * 100 + ptm->tm_year;
/* Adjust years */
ptm->tm_year -= 1900;
if (sscanf_two_digits(&date_str[4], &ptm->tm_mon) ||
sscanf_two_digits(&date_str[6], &ptm->tm_mday) ||
sscanf_two_digits(&date_str[8], &ptm->tm_hour) ||
sscanf_two_digits(&date_str[10], &ptm->tm_min)) {
return -EINVAL;
}
/* Adjust month from 1-12 to 0-11 */
ptm->tm_mon -= 1;
end = date_str[12];
if (end == '.') {
/* xxx.SS */
if (!sscanf_two_digits(&date_str[13], &ptm->tm_sec)) {
end = '\0';
}
/* else end != NUL and we error out */
}
if (end != '\0') {
return -EINVAL;
}
return 0;
}
static int do_hwclock(int argc, char *argv[])
{
struct rtc_device *r;
struct rtc_time tm;
struct rtc_time stm;
char rtc_name[16] = "rtc0";
char *env_name = NULL;
int opt;
int set = 0;
while ((opt = getopt(argc, argv, "f:s:e:")) > 0) {
int ret;
switch (opt) {
case 'f':
strncpy(rtc_name, optarg, 16);
break;
case 's':
memset(&stm, 0, sizeof(stm));
ret = parse_datestr(optarg, &stm);
if (ret)
return ret;
ret = rtc_valid_tm(&stm);
if (ret)
return ret;
set = 1;
break;
case 'e':
env_name = optarg;
break;
}
}
r = rtc_lookup(rtc_name);
if (IS_ERR(r))
return PTR_ERR(r);
if (set) {
rtc_set_time(r, &stm);
return 0;
}
rtc_read_time(r, &tm);
if (env_name) {
unsigned long time;
char t[12];
rtc_tm_to_time(&tm, &time);
snprintf(t, 12, "%lu", time);
setenv(env_name, t);
} else {
printf("%02d:%02d:%02d %02d-%02d-%04d\n",
tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900);
}
return 0;
}
BAREBOX_CMD_HELP_START(hwclock)
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-f NAME\t\t\t", "RTC device name (default rtc0)")
BAREBOX_CMD_HELP_OPT ("-e VARNAME\t\t", "store RTC readout into variable VARNAME")
BAREBOX_CMD_HELP_OPT ("-s ccyymmddHHMM[.SS]\t", "set time")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(hwclock)
.cmd = do_hwclock,
BAREBOX_CMD_DESC("query or set the hardware clock (RTC)")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_hwclock_help)
BAREBOX_CMD_END