aboutsummaryrefslogtreecommitdiffstats
path: root/util/dvbdate/dvbdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/dvbdate/dvbdate.c')
-rw-r--r--util/dvbdate/dvbdate.c288
1 files changed, 171 insertions, 117 deletions
diff --git a/util/dvbdate/dvbdate.c b/util/dvbdate/dvbdate.c
index 9821012..f0df437 100644
--- a/util/dvbdate/dvbdate.c
+++ b/util/dvbdate/dvbdate.c
@@ -8,7 +8,10 @@
Revamped by Johannes Stezenbach <js@convergence.de>
and Michael Hunold <hunold@convergence.de>
-
+
+ Ported to use the standard dvb libraries and add ATSC STT
+ support Andrew de Quincey <adq_dvb@lidskialf.net>
+
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
@@ -40,10 +43,10 @@
#include <errno.h>
#include <getopt.h>
#include <stdarg.h>
-
-#include <linux/dvb/dmx.h>
-
-#define bcdtoint(i) ((((i & 0xf0) >> 4) * 10) + (i & 0x0f))
+#include <libdvbapi/dvbfe.h>
+#include <libdvbapi/dvbdemux.h>
+#include <libucsi/dvb/section.h>
+#include <libucsi/atsc/section.h>
/* How many seconds can the system clock be out before we get warned? */
#define ALLOWABLE_DELTA 30*60
@@ -54,6 +57,7 @@ int do_set;
int do_force;
int do_quiet;
int timeout = 25;
+int adapter = 0;
void errmsg(char *message, ...)
{
@@ -65,15 +69,24 @@ void errmsg(char *message, ...)
va_end(ap);
}
-void usage()
+void usage(void)
{
- fprintf(stderr, "usage: %s [-p] [-s] [-f] [-q] [-h]\n", ProgName);
+ fprintf(stderr, "usage: %s [-a] [-p] [-s] [-f] [-q] [-h]\n", ProgName);
_exit(1);
}
-void help()
+void help(void)
{
- 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);
+ fprintf(stderr,
+ "\nhelp:\n"
+ "%s [-a] [-p] [-s] [-f] [-q] [-h] [-t n]\n"
+ " --adapter (adapter to use, default: 0)\n"
+ " --print (print current time, received time and delta)\n"
+ " --set (set the system clock to received time)\n"
+ " --force (force the setting of the clock)\n"
+ " --quiet (be silent)\n"
+ " --help (display this message)\n"
+ " --timeout n (max seconds to wait, default: 25)\n", ProgName);
_exit(1);
}
@@ -86,13 +99,14 @@ int do_options(int arg_count, char **arg_strings)
{"quiet", 0, 0, 'q'},
{"help", 0, 0, 'h'},
{"timeout", 1, 0, 't'},
+ {"adapter", 1, 0, 'a'},
{0, 0, 0, 0}
};
int c;
int Option_Index = 0;
while (1) {
- c = getopt_long(arg_count, arg_strings, "psfqht:", Long_Options, &Option_Index);
+ c = getopt_long(arg_count, arg_strings, "a:psfqht:", Long_Options, &Option_Index);
if (c == EOF)
break;
switch (c) {
@@ -103,6 +117,9 @@ int do_options(int arg_count, char **arg_strings)
usage();
}
break;
+ case 'a':
+ adapter = atoi(optarg);
+ break;
case 'p':
do_print = 1;
break;
@@ -134,7 +151,8 @@ int do_options(int arg_count, char **arg_strings)
case 2: /* Force */
case 3: /* Quiet */
case 4: /* Help */
- case 5: /* timout */
+ case 5: /* timeout */
+ case 6: /* adapter */
break;
default:
fprintf(stderr, "%s: unknown long option %d\n", ProgName, Option_Index);
@@ -153,125 +171,135 @@ int do_options(int arg_count, char **arg_strings)
}
/*
- * return the TDT time in UNIX time_t format
+ * Get the next UTC date packet from the TDT section
*/
-
-time_t convert_date(char *dvb_buf)
+int dvb_scan_date(time_t *rx_time, unsigned int to)
{
- 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));
+ int tdt_fd;
+ uint8_t filter[18];
+ uint8_t mask[18];
+ unsigned char sibuf[4096];
+ int size;
+
+ // open the demuxer
+ if ((tdt_fd = dvbdemux_open_demux(adapter, 0, 0)) < 0) {
+ return -1;
+ }
+
+ // create a section filter for the TDT
+ memset(filter, 0, sizeof(filter));
+ memset(mask, 0, sizeof(mask));
+ filter[0] = stag_dvb_time_date;
+ mask[0] = 0xFF;
+ if (dvbdemux_set_section_filter(tdt_fd, TRANSPORT_TDT_PID, filter, mask, 1, 1)) {
+ close(tdt_fd);
+ return -1;
+ }
+
+ // poll for data
+ struct pollfd pollfd;
+ pollfd.fd = tdt_fd;
+ pollfd.events = POLLIN|POLLERR|POLLPRI;
+ if (poll(&pollfd, 1, to * 1000) != 1) {
+ close(tdt_fd);
+ return -1;
+ }
+
+ // read it
+ if ((size = read(tdt_fd, sibuf, sizeof(sibuf))) < 0) {
+ close(tdt_fd);
+ return -1;
+ }
+
+ // parse section
+ struct section *section = section_codec(sibuf, size);
+ if (section == NULL) {
+ close(tdt_fd);
+ return -1;
+ }
+
+ // parse TDT
+ struct dvb_tdt_section *tdt = dvb_tdt_section_codec(section);
+ if (tdt == NULL) {
+ close(tdt_fd);
+ return -1;
+ }
+
+ // done
+ *rx_time = dvbdate_to_unixtime(tdt->utc_time);
+ close(tdt_fd);
+ return 0;
}
/*
- * Get the next UTC date packet from the TDT multiplex
+ * Get the next date packet from the STT section
*/
-
-int scan_date(time_t *dvb_time, unsigned int to)
+int atsc_scan_date(time_t *rx_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: ");
+ int stt_fd;
+ uint8_t filter[18];
+ uint8_t mask[18];
+ unsigned char sibuf[4096];
+ int size;
+
+ // open the demuxer
+ if ((stt_fd = dvbdemux_open_demux(adapter, 0, 0)) < 0) {
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;
+ // create a section filter for the STT
+ memset(filter, 0, sizeof(filter));
+ memset(mask, 0, sizeof(mask));
+ filter[0] = stag_atsc_system_time;
+ mask[0] = 0xFF;
+ if (dvbdemux_set_section_filter(stt_fd, ATSC_BASE_PID, filter, mask, 1, 1)) {
+ close(stt_fd);
+ return -1;
+ }
- if (ioctl(fd_date, DMX_SET_FILTER, &sctFilterParams) < 0) {
- perror("DATE - DMX_SET_FILTER:");
- close(fd_date);
+ // poll for data
+ struct pollfd pollfd;
+ pollfd.fd = stt_fd;
+ pollfd.events = POLLIN|POLLERR|POLLPRI;
+ if (poll(&pollfd, 1, to * 1000) != 1) {
+ close(stt_fd);
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);
+ // read it
+ if ((size = read(stt_fd, sibuf, sizeof(sibuf))) < 0) {
+ close(stt_fd);
+ return -1;
+ }
+
+ // parse section
+ struct section *section = section_codec(sibuf, size);
+ if (section == NULL) {
+ close(stt_fd);
+ return -1;
+ }
+ struct section_ext *section_ext = section_ext_decode(section, 0);
+ if (section_ext == NULL) {
+ close(stt_fd);
return -1;
}
- fprintf(stdout, "\n");
- if (0 == found) {
- errmsg("timeout - try tuning to a multiplex?\n");
- close(fd_date);
+ struct atsc_section_psip *psip = atsc_section_psip_decode(section_ext);
+ if (psip == NULL) {
+ close(stt_fd);
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;
+ // parse STT
+ struct atsc_stt_section *stt = atsc_stt_section_codec(psip);
+ if (stt == NULL) {
+ close(stt_fd);
+ return -1;
}
- close(fd_date);
- *dvb_time = t;
+
+ // done
+ *rx_time = atsctime_to_unixtime(stt->system_time);
+ close(stt_fd);
return 0;
}
@@ -291,10 +319,12 @@ int set_time(time_t * new_time)
int main(int argc, char **argv)
{
- time_t dvb_time;
+ time_t rx_time;
time_t real_time;
time_t offset;
int ret;
+ struct dvbfe_handle *fe;
+ struct dvbfe_info fe_info;
do_print = 0;
do_force = 0;
@@ -310,27 +340,51 @@ int main(int argc, char **argv)
errmsg("quiet and print options are mutually exclusive.\n");
exit(1);
}
+
+/*
+ * Find the frontend type
+ */
+ if ((fe = dvbfe_open(adapter, 0, 1)) == NULL) {
+ errmsg("Unable to open frontend.\n");
+ exit(1);
+ }
+ dvbfe_get_info(fe, 0, &fe_info, DVBFE_INFO_QUERYTYPE_IMMEDIATE, 0);
+
/*
- * Get the date from the currently tuned TDT multiplex
+ * Get the date from the currently tuned multiplex
*/
- ret = scan_date(&dvb_time, timeout);
+ switch(fe_info.type) {
+ case DVBFE_TYPE_DVBS:
+ case DVBFE_TYPE_DVBC:
+ case DVBFE_TYPE_DVBT:
+ ret = dvb_scan_date(&rx_time, timeout);
+ break;
+
+ case DVBFE_TYPE_ATSC:
+ ret = atsc_scan_date(&rx_time, timeout);
+ break;
+
+ default:
+ errmsg("Unsupported frontend type.\n");
+ exit(1);
+ }
if (ret != 0) {
errmsg("Unable to get time from multiplex.\n");
exit(1);
}
time(&real_time);
- offset = dvb_time - real_time;
+ offset = rx_time - real_time;
if (do_print) {
fprintf(stdout, "System time: %s", ctime(&real_time));
- fprintf(stdout, " TDT time: %s", ctime(&dvb_time));
+ fprintf(stdout, " RX time: %s", ctime(&rx_time));
fprintf(stdout, " Offset: %ld seconds\n", offset);
} else if (!do_quiet) {
- fprintf(stdout, "%s", ctime(&dvb_time));
+ fprintf(stdout, "%s", ctime(&rx_time));
}
if (do_set) {
if (labs(offset) > ALLOWABLE_DELTA) {
if (do_force) {
- if (0 != set_time(&dvb_time)) {
+ if (0 != set_time(&rx_time)) {
errmsg("setting the time failed\n");
}
} else {
@@ -339,7 +393,7 @@ int main(int argc, char **argv)
exit(1);
}
} else {
- set_time(&dvb_time);
+ set_time(&rx_time);
}
} /* #end if (do_set) */
return (0);