forked from rene0/dcf77pi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setclock.c
62 lines (55 loc) · 1.67 KB
/
setclock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Copyright 2013-2019 René Ladan
// SPDX-License-Identifier: BSD-2-Clause
#include "setclock.h"
#include "calendar.h"
#include "decode_time.h"
#include "input.h"
#include <locale.h>
#include <string.h>
#include <time.h>
bool
setclock_ok(unsigned init_min, struct DT_result dt, struct GB_result bit)
{
return init_min == 0 && bit.marker == emark_minute && dt.bit0_ok &&
dt.bit20_ok && dt.minute_length == emin_ok &&
dt.minute_status == eval_ok && dt.hour_status == eval_ok &&
dt.mday_status == eval_ok && dt.wday_status == eval_ok &&
dt.month_status == eval_ok && dt.year_status == eval_ok &&
(dt.dst_status == eDST_ok || dt.dst_status == eDST_done) &&
dt.leapsecond_status != els_one && !bit.bad_io &&
bit.bitval != ebv_none && bit.hwstat == ehw_ok;
}
enum eSC_status
setclock(struct tm settime)
{
time_t epochtime, t1, t2;
struct tm it;
struct timespec ts;
/* determine time difference of host to UTC (t1 - t2) */
(void)time(&t1);
(void)gmtime_r(&t1, &it);
it.tm_isdst = -1;
setlocale(LC_TIME, "");
t2 = mktime(&it);
if (t2 == -1) {
return esc_invalid;
}
if (settime.tm_year >= base_year) {
it = get_isotime(settime);
} else {
memcpy((void *)&it, (const void *)&settime, sizeof(settime));
}
it.tm_isdst = -1; /* allow mktime() when host timezone is UTC */
it.tm_sec = 0;
epochtime = mktime(&it);
if (epochtime == -1) {
return esc_invalid;
}
ts.tv_sec = epochtime;
/* UTC if t1 == t2, so adjust from local time in that case */
if (t1 == t2) {
ts.tv_sec -= 3600 * (1 + settime.tm_isdst);
}
ts.tv_nsec = 50000000; /* adjust for bit reception algorithm */
return (clock_settime(CLOCK_REALTIME, &ts) == -1) ? esc_fail : esc_ok;
}