diff options
author | etobi <git@e-tobi.net> | 2013-09-03 09:48:41 +0200 |
---|---|---|
committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:41 +0200 |
commit | ab959d7b4194715870128e616b8e29d4a101e488 (patch) | |
tree | 61a746231d30817be73416a7d67763fd677a1042 /util/dvbdate/dvbdate.c | |
parent | 6b350466c4902c5b137e0efaf1d189128a7f18f5 (diff) | |
download | linux-dvb-apps-ab959d7b4194715870128e616b8e29d4a101e488.tar.gz |
Imported Upstream version 1.1.1+rev1207upstream/1.1.1+rev1207
Diffstat (limited to 'util/dvbdate/dvbdate.c')
-rw-r--r-- | util/dvbdate/dvbdate.c | 288 |
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); |