From 6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d Mon Sep 17 00:00:00 2001 From: etobi Date: Tue, 3 Sep 2013 09:48:38 +0200 Subject: Imported Upstream version 1.1.0 --- util/dvbdate/dvbdate.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 util/dvbdate/dvbdate.c (limited to 'util/dvbdate/dvbdate.c') diff --git a/util/dvbdate/dvbdate.c b/util/dvbdate/dvbdate.c new file mode 100644 index 0000000..9821012 --- /dev/null +++ b/util/dvbdate/dvbdate.c @@ -0,0 +1,346 @@ +/* + + dvbdate - a program to set the system date and time from a TDT multiplex + + Copyright (C) Laurence Culhane 2002 + + Mercilessly ripped off from dvbtune, Copyright (C) Dave Chapman 2001 + + Revamped by Johannes Stezenbach + and Michael Hunold + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Or, point your browser to http://www.gnu.org/copyleft/gpl.html + + Copyright (C) Laurence Culhane 2002 + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define bcdtoint(i) ((((i & 0xf0) >> 4) * 10) + (i & 0x0f)) + +/* How many seconds can the system clock be out before we get warned? */ +#define ALLOWABLE_DELTA 30*60 + +char *ProgName; +int do_print; +int do_set; +int do_force; +int do_quiet; +int timeout = 25; + +void errmsg(char *message, ...) +{ + va_list ap; + + va_start(ap, message); + fprintf(stderr, "%s: ", ProgName); + vfprintf(stderr, message, ap); + va_end(ap); +} + +void usage() +{ + fprintf(stderr, "usage: %s [-p] [-s] [-f] [-q] [-h]\n", ProgName); + _exit(1); +} + +void help() +{ + fprintf(stderr, "\nhelp:\n" "%s [-p] [-s] [-f] [-q] [-h] [-t n]\n" " --print (print current time, TDT time and delta)\n" " --set (set the system clock to TDT time)\n" " --force (force the setting of the clock)\n" " --quiet (be silent)\n" " --help (display this message)\n"" --timout n (max seconds to wait, default: 25)\n", ProgName); + _exit(1); +} + +int do_options(int arg_count, char **arg_strings) +{ + static struct option Long_Options[] = { + {"print", 0, 0, 'p'}, + {"set", 0, 0, 's'}, + {"force", 0, 0, 'f'}, + {"quiet", 0, 0, 'q'}, + {"help", 0, 0, 'h'}, + {"timeout", 1, 0, 't'}, + {0, 0, 0, 0} + }; + int c; + int Option_Index = 0; + + while (1) { + c = getopt_long(arg_count, arg_strings, "psfqht:", Long_Options, &Option_Index); + if (c == EOF) + break; + switch (c) { + case 't': + timeout = atoi(optarg); + if (0 == timeout) { + fprintf(stderr, "%s: invalid timeout value\n", ProgName); + usage(); + } + break; + case 'p': + do_print = 1; + break; + case 's': + do_set = 1; + break; + case 'f': + do_force = 1; + break; + case 'q': + do_quiet = 1; + break; + case 'h': + help(); + break; + case '?': + usage(); + break; + case 0: +/* + * Which long option has been selected? We only need this extra switch + * to cope with the case of wanting to assign two long options the same + * short character code. + */ + printf("long option index %d\n", Option_Index); + switch (Option_Index) { + case 0: /* Print */ + case 1: /* Set */ + case 2: /* Force */ + case 3: /* Quiet */ + case 4: /* Help */ + case 5: /* timout */ + break; + default: + fprintf(stderr, "%s: unknown long option %d\n", ProgName, Option_Index); + usage(); + } + break; +/* + * End of Special Long-opt handling code + */ + default: + fprintf(stderr, "%s: unknown getopt error - returned code %02x\n", ProgName, c); + _exit(1); + } + } + return 0; +} + +/* + * return the TDT time in UNIX time_t format + */ + +time_t convert_date(char *dvb_buf) +{ + int i; + int year, month, day, hour, min, sec; + long int mjd; + struct tm dvb_time; + + mjd = (dvb_buf[0] & 0xff) << 8; + mjd += (dvb_buf[1] & 0xff); + hour = bcdtoint(dvb_buf[2] & 0xff); + min = bcdtoint(dvb_buf[3] & 0xff); + sec = bcdtoint(dvb_buf[4] & 0xff); +/* + * Use the routine specified in ETSI EN 300 468 V1.4.1, + * "Specification for Service Information in Digital Video Broadcasting" + * to convert from Modified Julian Date to Year, Month, Day. + */ + year = (int) ((mjd - 15078.2) / 365.25); + month = (int) ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001); + day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001); + if (month == 14 || month == 15) + i = 1; + else + i = 0; + year += i; + month = month - 1 - i * 12; + + dvb_time.tm_sec = sec; + dvb_time.tm_min = min; + dvb_time.tm_hour = hour; + dvb_time.tm_mday = day; + dvb_time.tm_mon = month - 1; + dvb_time.tm_year = year; + dvb_time.tm_isdst = -1; + dvb_time.tm_wday = 0; + dvb_time.tm_yday = 0; + return (timegm(&dvb_time)); +} + + +/* + * Get the next UTC date packet from the TDT multiplex + */ + +int scan_date(time_t *dvb_time, unsigned int to) +{ + int fd_date; + int n, seclen; + time_t t; + unsigned char buf[4096]; + struct dmx_sct_filter_params sctFilterParams; + struct pollfd ufd; + int found = 0; + + t = 0; + if ((fd_date = open("/dev/dvb/adapter0/demux0", O_RDWR | O_NONBLOCK)) < 0) { + perror("fd_date DEVICE: "); + return -1; + } + + memset(&sctFilterParams, 0, sizeof(sctFilterParams)); + sctFilterParams.pid = 0x14; + sctFilterParams.timeout = 0; + sctFilterParams.flags = DMX_IMMEDIATE_START; + sctFilterParams.filter.filter[0] = 0x70; + sctFilterParams.filter.mask[0] = 0xff; + + if (ioctl(fd_date, DMX_SET_FILTER, &sctFilterParams) < 0) { + perror("DATE - DMX_SET_FILTER:"); + close(fd_date); + return -1; + } + + while (to > 0) { + int res; + + memset(&ufd,0,sizeof(ufd)); + ufd.fd=fd_date; + ufd.events=POLLIN; + + res = poll(&ufd,1,1000); + if (0 == res) { + fprintf(stdout, "."); + fflush(stdout); + to--; + continue; + } + if (1 == res) { + found = 1; + break; + } + errmsg("error polling for data"); + close(fd_date); + return -1; + } + fprintf(stdout, "\n"); + if (0 == found) { + errmsg("timeout - try tuning to a multiplex?\n"); + close(fd_date); + return -1; + } + + if ((n = read(fd_date, buf, 4096)) >= 3) { + seclen = ((buf[1] & 0x0f) << 8) | (buf[2] & 0xff); + if (n == seclen + 3) { + t = convert_date(&(buf[3])); + } else { + errmsg("Under-read bytes for DATE - wanted %d, got %d\n", seclen, n); + return 0; + } + } else { + errmsg("Nothing to read from fd_date - try tuning to a multiplex?\n"); + return 0; + } + close(fd_date); + *dvb_time = t; + return 0; +} + + +/* + * Set the system time + */ +int set_time(time_t * new_time) +{ + if (stime(new_time)) { + perror("Unable to set time"); + return -1; + } + return 0; +} + + +int main(int argc, char **argv) +{ + time_t dvb_time; + time_t real_time; + time_t offset; + int ret; + + do_print = 0; + do_force = 0; + do_set = 0; + do_quiet = 0; + ProgName = argv[0]; + +/* + * Process command line arguments + */ + do_options(argc, argv); + if (do_quiet && do_print) { + errmsg("quiet and print options are mutually exclusive.\n"); + exit(1); + } +/* + * Get the date from the currently tuned TDT multiplex + */ + ret = scan_date(&dvb_time, timeout); + if (ret != 0) { + errmsg("Unable to get time from multiplex.\n"); + exit(1); + } + time(&real_time); + offset = dvb_time - real_time; + if (do_print) { + fprintf(stdout, "System time: %s", ctime(&real_time)); + fprintf(stdout, " TDT time: %s", ctime(&dvb_time)); + fprintf(stdout, " Offset: %ld seconds\n", offset); + } else if (!do_quiet) { + fprintf(stdout, "%s", ctime(&dvb_time)); + } + if (do_set) { + if (labs(offset) > ALLOWABLE_DELTA) { + if (do_force) { + if (0 != set_time(&dvb_time)) { + errmsg("setting the time failed\n"); + } + } else { + errmsg("multiplex time differs by more than %d from system.\n", ALLOWABLE_DELTA); + errmsg("use -f to force system clock to new time.\n"); + exit(1); + } + } else { + set_time(&dvb_time); + } + } /* #end if (do_set) */ + return (0); +} -- cgit v1.2.3