diff options
| author | etobi <git@e-tobi.net> | 2013-09-03 09:48:38 +0200 | 
|---|---|---|
| committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:38 +0200 | 
| commit | 6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d (patch) | |
| tree | 024bef311226653bdd1da4fa588becf5098bcff7 /util/dvbdate | |
| download | linux-dvb-apps-6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d.tar.gz | |
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'util/dvbdate')
| -rw-r--r-- | util/dvbdate/Makefile | 25 | ||||
| -rw-r--r-- | util/dvbdate/dvbdate.c | 346 | 
2 files changed, 371 insertions, 0 deletions
| diff --git a/util/dvbdate/Makefile b/util/dvbdate/Makefile new file mode 100644 index 0000000..ea514db --- /dev/null +++ b/util/dvbdate/Makefile @@ -0,0 +1,25 @@ + +CC      = gcc +CFLAGS  = -g -O2 -MD -Wall -I. -I../../include +LFLAGS  = + +OBJS    = dvbdate.o +TARGET  = dvbdate +DESTDIR = /usr/local/bin/ + +all: $(TARGET) + +.c.o: +	$(CC) $(CFLAGS) -c $< -o $@ + +$(TARGET): $(OBJS) +	$(CC) -o $@ $(OBJS) $(LFLAGS) + +install: all +	install -m 755 $(TARGET) $(DESTDIR)  + +clean: +	rm -f $(TARGET) $(OBJS) core* *~ *.d + +-include $(wildcard *.d) dummy + 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 <dvbdate@holmes.demon.co.uk> + +   Mercilessly ripped off from dvbtune, Copyright (C) Dave Chapman 2001 + +   Revamped by Johannes Stezenbach <js@convergence.de> +   and Michael Hunold <hunold@convergence.de> +   +   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 <dvbdate@holmes.demon.co.uk> + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#include <errno.h> +#include <getopt.h> +#include <stdarg.h> + +#include <linux/dvb/dmx.h> + +#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); +} | 
