From ab959d7b4194715870128e616b8e29d4a101e488 Mon Sep 17 00:00:00 2001 From: etobi Date: Tue, 3 Sep 2013 09:48:41 +0200 Subject: Imported Upstream version 1.1.1+rev1207 --- util/dvbscan/Makefile | 22 +++ util/dvbscan/dvbscan.c | 370 +++++++++++++++++++++++++++++++++++++ util/dvbscan/dvbscan.h | 136 ++++++++++++++ util/dvbscan/dvbscan_atsc.c | 30 +++ util/dvbscan/dvbscan_dvb.c | 30 +++ util/dvbscan/dvbscan_structutils.c | 99 ++++++++++ 6 files changed, 687 insertions(+) create mode 100644 util/dvbscan/Makefile create mode 100644 util/dvbscan/dvbscan.c create mode 100644 util/dvbscan/dvbscan.h create mode 100644 util/dvbscan/dvbscan_atsc.c create mode 100644 util/dvbscan/dvbscan_dvb.c create mode 100644 util/dvbscan/dvbscan_structutils.c (limited to 'util/dvbscan') diff --git a/util/dvbscan/Makefile b/util/dvbscan/Makefile new file mode 100644 index 0000000..d7e5de5 --- /dev/null +++ b/util/dvbscan/Makefile @@ -0,0 +1,22 @@ +# Makefile for linuxtv.org dvb-apps/util/dvbscan + +objects = dvbscan.o \ + dvbscan_structutils.o \ + dvbscan_dvb.o \ + dvbscan_atsc.o + +binaries = dvbscan + +inst_bin = $(binaries) + +CPPFLAGS += -I../../lib +LDFLAGS += -L../../lib/libdvbapi -L../../lib/libdvbcfg -L../../lib/libdvbsec -L../../lib/libucsi +LDLIBS += -ldvbcfg -lucsi -ldvbsec -ldvbapi -lpthread + +.PHONY: all + +all: $(binaries) + +$(binaries): $(objects) + +include ../../Make.rules diff --git a/util/dvbscan/dvbscan.c b/util/dvbscan/dvbscan.c new file mode 100644 index 0000000..c6f9ea8 --- /dev/null +++ b/util/dvbscan/dvbscan.c @@ -0,0 +1,370 @@ +/* + dvbscan utility + + Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "dvbscan.h" + + +#define OUTPUT_TYPE_RAW 1 +#define OUTPUT_TYPE_CHANNELS 2 +#define OUTPUT_TYPE_VDR12 3 +#define OUTPUT_TYPE_VDR13 4 + +#define SERVICE_FILTER_TV 1 +#define SERVICE_FILTER_RADIO 2 +#define SERVICE_FILTER_OTHER 4 +#define SERVICE_FILTER_ENCRYPTED 8 + +#define TIMEOUT_WAIT_LOCK 2 + + +// transponders we have yet to scan +static struct transponder *toscan = NULL; +static struct transponder *toscan_end = NULL; + +// transponders we have scanned +static struct transponder *scanned = NULL; +static struct transponder *scanned_end = NULL; + + +static void usage(void) +{ + static const char *_usage = "\n" + " dvbscan: A digital tv channel scanning utility\n" + " Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)\n\n" + " usage: dvbscan as follows:\n" + " -h help\n" + " -adapter adapter to use (default 0)\n" + " -frontend frontend to use (default 0)\n" + " -demux demux to use (default 0)\n" + " -secfile Optional sec.conf file.\n" + " -secid ID of the SEC configuration to use, one of:\n" + " * UNIVERSAL (default) - Europe, 10800 to 11800 MHz and 11600 to 12700 Mhz,\n" + " Dual LO, loband 9750, hiband 10600 MHz.\n" + " * DBS - Expressvu, North America, 12200 to 12700 MHz, Single LO, 11250 MHz.\n" + " * STANDARD - 10945 to 11450 Mhz, Single LO, 10000 Mhz.\n" + " * ENHANCED - Astra, 10700 to 11700 MHz, Single LO, 9750 MHz.\n" + " * C-BAND - Big Dish, 3700 to 4200 MHz, Single LO, 5150 Mhz.\n" + " * C-MULTI - Big Dish - Multipoint LNBf, 3700 to 4200 MHz,\n" + " Dual LO, H:5150MHz, V:5750MHz.\n" + " * One of the sec definitions from the secfile if supplied\n" + " -satpos Specify DISEQC switch position for DVB-S.\n" + " -inversion Specify inversion (default: auto).\n" + " -uk-ordering Use UK DVB-T channel ordering if present.\n" + " -timeout Specify filter timeout to use (standard specced values will be used by default)\n" + " -filter Specify service filter, a comma seperated list of the following tokens:\n" + " (If no filter is supplied, all services will be output)\n" + " * tv - Output TV channels\n" + " * radio - Output radio channels\n" + " * other - Output other channels\n" + " * encrypted - Output encrypted channels\n" + " -out raw |- Output in raw format to or stdout\n" + " channels |- Output in channels.conf format to or stdout.\n" + " vdr12 |- Output in vdr 1.2.x format to or stdout.\n" + " vdr13 |- Output in vdr 1.3.x format to or stdout.\n" + " \n"; + fprintf(stderr, "%s\n", _usage); + + exit(1); +} + + +static int scan_load_callback(struct dvbcfg_scanfile *channel, void *private_data) +{ + struct dvbfe_info *feinfo = (struct dvbfe_info *) private_data; + + if (channel->fe_type != feinfo->type) + return 0; + + struct transponder *t = new_transponder(); + append_transponder(t, &toscan, &toscan_end); + memcpy(&t->params, &channel->fe_params, sizeof(struct dvbfe_parameters)); + + add_frequency(t, t->params.frequency); + t->params.frequency = 0; + + return 0; +} + +int main(int argc, char *argv[]) +{ + uint32_t i; + int argpos = 1; + int adapter_id = 0; + int frontend_id = 0; + int demux_id = 0; + char *secfile = NULL; + char *secid = NULL; + int satpos = 0; + enum dvbfe_spectral_inversion inversion = DVBFE_INVERSION_AUTO; + int service_filter = -1; + int uk_ordering = 0; + int timeout = 5; + int output_type = OUTPUT_TYPE_RAW; + char *output_filename = NULL; + char *scan_filename = NULL; + struct dvbsec_config sec; + int valid_sec = 0; + + while(argpos != argc) { + if (!strcmp(argv[argpos], "-h")) { + usage(); + } else if (!strcmp(argv[argpos], "-adapter")) { + if ((argc - argpos) < 2) + usage(); + if (sscanf(argv[argpos+1], "%i", &adapter_id) != 1) + usage(); + argpos+=2; + } else if (!strcmp(argv[argpos], "-frontend")) { + if ((argc - argpos) < 2) + usage(); + if (sscanf(argv[argpos+1], "%i", &frontend_id) != 1) + usage(); + argpos+=2; + } else if (!strcmp(argv[argpos], "-demux")) { + if ((argc - argpos) < 2) + usage(); + if (sscanf(argv[argpos+1], "%i", &demux_id) != 1) + usage(); + argpos+=2; + } else if (!strcmp(argv[argpos], "-secfile")) { + if ((argc - argpos) < 2) + usage(); + secfile = argv[argpos+1]; + argpos+=2; + } else if (!strcmp(argv[argpos], "-secid")) { + if ((argc - argpos) < 2) + usage(); + secid = argv[argpos+1]; + argpos+=2; + } else if (!strcmp(argv[argpos], "-satpos")) { + if ((argc - argpos) < 2) + usage(); + if (sscanf(argv[argpos+1], "%i", &satpos) != 1) + usage(); + argpos+=2; + } else if (!strcmp(argv[argpos], "-inversion")) { + if ((argc - argpos) < 2) + usage(); + if (!strcmp(argv[argpos+1], "off")) { + inversion = DVBFE_INVERSION_OFF; + } else if (!strcmp(argv[argpos+1], "on")) { + inversion = DVBFE_INVERSION_ON; + } else if (!strcmp(argv[argpos+1], "auto")) { + inversion = DVBFE_INVERSION_AUTO; + } else { + usage(); + } + argpos+=2; + } else if (!strcmp(argv[argpos], "-uk-ordering")) { + if ((argc - argpos) < 1) + usage(); + uk_ordering = 1; + } else if (!strcmp(argv[argpos], "-timeout")) { + if ((argc - argpos) < 2) + usage(); + if (sscanf(argv[argpos+1], "%i", &timeout) != 1) + usage(); + argpos+=2; + } else if (!strcmp(argv[argpos], "-filter")) { + if ((argc - argpos) < 2) + usage(); + service_filter = 0; + if (!strstr(argv[argpos+1], "tv")) { + service_filter |= SERVICE_FILTER_TV; + } + if (!strstr(argv[argpos+1], "radio")) { + service_filter |= SERVICE_FILTER_RADIO; + } + if (!strstr(argv[argpos+1], "other")) { + service_filter |= SERVICE_FILTER_OTHER; + } + if (!strstr(argv[argpos+1], "encrypted")) { + service_filter |= SERVICE_FILTER_ENCRYPTED; + } + argpos+=2; + } else if (!strcmp(argv[argpos], "-out")) { + if ((argc - argpos) < 3) + usage(); + if (!strcmp(argv[argpos+1], "raw")) { + output_type = OUTPUT_TYPE_RAW; + } else if (!strcmp(argv[argpos+1], "channels")) { + output_type = OUTPUT_TYPE_CHANNELS; + } else if (!strcmp(argv[argpos+1], "vdr12")) { + output_type = OUTPUT_TYPE_VDR12; + } else if (!strcmp(argv[argpos+1], "vdr13")) { + output_type = OUTPUT_TYPE_VDR13; + } else { + usage(); + } + output_filename = argv[argpos+2]; + if (!strcmp(output_filename, "-")) + output_filename = NULL; + } else { + if ((argc - argpos) != 1) + usage(); + scan_filename = argv[argpos]; + argpos++; + } + } + + // open the frontend & get its type + struct dvbfe_handle *fe = dvbfe_open(adapter_id, frontend_id, 0); + if (fe == NULL) { + fprintf(stderr, "Failed to open frontend\n"); + exit(1); + } + struct dvbfe_info feinfo; + if (dvbfe_get_info(fe, 0, &feinfo, DVBFE_INFO_QUERYTYPE_IMMEDIATE, 0) != 0) { + fprintf(stderr, "Failed to query frontend\n"); + exit(1); + } + + // default SEC with a DVBS card + if ((secid == NULL) && (feinfo.type == DVBFE_TYPE_DVBS)) + secid = "UNIVERSAL"; + + // look up SECID if one was supplied + if (secid != NULL) { + if (dvbsec_cfg_find(secfile, secid, &sec)) { + fprintf(stderr, "Unable to find suitable sec/lnb configuration for channel\n"); + exit(1); + } + valid_sec = 1; + } + + // load the initial scan file + FILE *scan_file = fopen(scan_filename, "r"); + if (scan_file == NULL) { + fprintf(stderr, "Could not open scan file %s\n", scan_filename); + exit(1); + } + if (dvbcfg_scanfile_parse(scan_file, scan_load_callback, &feinfo) < 0) { + fprintf(stderr, "Could not parse scan file %s\n", scan_filename); + exit(1); + } + fclose(scan_file); + + // main scan loop + while(toscan) { + // get the first item on the toscan list + struct transponder *tmp = first_transponder(&toscan, &toscan_end); + + // have we already seen this transponder? + if (seen_transponder(tmp, scanned)) { + free_transponder(tmp); + continue; + } + + // do we have a valid SEC configuration? + struct dvbsec_config *psec = NULL; + if (valid_sec) + psec = &sec; + + // tune it + int tuned_ok = 0; + for(i=0; i < tmp->frequency_count; i++) { + tmp->params.frequency = tmp->frequencies[i]; + if (dvbsec_set(fe, + psec, + tmp->polarization, + (satpos & 0x01) ? DISEQC_SWITCH_B : DISEQC_SWITCH_A, + (satpos & 0x02) ? DISEQC_SWITCH_B : DISEQC_SWITCH_A, + &tmp->params, + 0)) { + fprintf(stderr, "Failed to set frontend\n"); + exit(1); + } + + // wait for lock + time_t starttime = time(NULL); + while((time(NULL) - starttime) < TIMEOUT_WAIT_LOCK) { + if (dvbfe_get_info(fe, DVBFE_INFO_LOCKSTATUS, &feinfo, + DVBFE_INFO_QUERYTYPE_IMMEDIATE, 0) != + DVBFE_INFO_QUERYTYPE_IMMEDIATE) { + fprintf(stderr, "Unable to query frontend status\n"); + exit(1); + } + if (feinfo.lock) { + tuned_ok = 1; + break; + } + usleep(100000); + } + } + if (!tuned_ok) { + free_transponder(tmp); + continue; + } + + // scan it + switch(feinfo.type) { + case DVBFE_TYPE_DVBS: + case DVBFE_TYPE_DVBC: + case DVBFE_TYPE_DVBT: + dvbscan_scan_dvb(fe); + break; + + case DVBFE_TYPE_ATSC: + dvbscan_scan_atsc(fe); + break; + } + + // add to scanned list. + append_transponder(tmp, &scanned, &scanned_end); + } + + // FIXME: output the data + + return 0; +} + +int create_section_filter(int adapter, int demux, uint16_t pid, uint8_t table_id) +{ + int demux_fd = -1; + uint8_t filter[18]; + uint8_t mask[18]; + + // open the demuxer + if ((demux_fd = dvbdemux_open_demux(adapter, demux, 0)) < 0) { + return -1; + } + + // create a section filter + memset(filter, 0, sizeof(filter)); + memset(mask, 0, sizeof(mask)); + filter[0] = table_id; + mask[0] = 0xFF; + if (dvbdemux_set_section_filter(demux_fd, pid, filter, mask, 1, 1)) { + close(demux_fd); + return -1; + } + + // done + return demux_fd; +} diff --git a/util/dvbscan/dvbscan.h b/util/dvbscan/dvbscan.h new file mode 100644 index 0000000..ddf61cf --- /dev/null +++ b/util/dvbscan/dvbscan.h @@ -0,0 +1,136 @@ +/* + dvbscan utility + + Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef DVBSCAN_H +#define DVBSCAN_H 1 + +#include +#include +#include + +/** + * A stream which is part of a service. + */ +struct stream +{ + uint8_t stream_type; + iso639lang_t language; + + struct stream *next; +}; + +/** + * A service (programme) which is part of a transponder. + */ +struct service +{ + /** + * Service identification stuff. Strings are in UTF-8. + */ + uint16_t service_id; + char *provider_name; + char *service_name; + + /** + * Pids common to the whole service. + */ + uint16_t pmt_pid; + uint16_t pcr_pid; + + /** + * CA stuff. + */ + uint16_t *ca_ids; + uint32_t ca_ids_count; + uint8_t is_scrambled; + + /** + * BBC channel number (-1 if unknown). + */ + int bbc_channel_number; + + /** + * Streams composing this service. + */ + struct stream *streams; + struct stream *streams_end; + + /** + * Next service in list. + */ + struct service *next; +}; + +/** + * A collection of multiplexed services. + */ +struct transponder +{ + /** + * we need to have a seperate list of frequencies since the + * DVB standard allows a frequency list descriptor of alternate + * frequencies to be supplied. + */ + uint32_t *frequencies; + uint32_t frequency_count; + + /** + * The rest of the tuning parameters. + */ + struct dvbfe_parameters params; + + /** + * DVBS specific parameters + */ + enum dvbsec_diseqc_polarization polarization; + int oribital_position; + + /** + * Numerical IDs + */ + uint16_t network_id; + uint16_t original_network_id; + uint16_t transport_stream_id; + + /** + * Services detected on this transponder. + */ + struct service *services; + struct service *services_end; + + /** + * Next item in list. + */ + struct transponder *next; +}; + +extern void append_transponder(struct transponder *t, struct transponder **tlist, struct transponder **tlist_end); +extern struct transponder *new_transponder(void); +extern void free_transponder(struct transponder *t); +extern int seen_transponder(struct transponder *t, struct transponder *checklist); +extern void add_frequency(struct transponder *t, uint32_t frequency); +extern struct transponder *first_transponder(struct transponder **tlist, struct transponder **tlist_end); + +extern int create_section_filter(int adapter, int demux, uint16_t pid, uint8_t table_id); +extern void dvbscan_scan_dvb(struct dvbfe_handle *fe); +extern void dvbscan_scan_atsc(struct dvbfe_handle *fe); + +#endif diff --git a/util/dvbscan/dvbscan_atsc.c b/util/dvbscan/dvbscan_atsc.c new file mode 100644 index 0000000..b346f78 --- /dev/null +++ b/util/dvbscan/dvbscan_atsc.c @@ -0,0 +1,30 @@ +/* + dvbscan utility + + Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include "dvbscan.h" + +void dvbscan_scan_atsc(struct dvbfe_handle *fe) +{ + // FIXME +} diff --git a/util/dvbscan/dvbscan_dvb.c b/util/dvbscan/dvbscan_dvb.c new file mode 100644 index 0000000..c76d072 --- /dev/null +++ b/util/dvbscan/dvbscan_dvb.c @@ -0,0 +1,30 @@ +/* + dvbscan utility + + Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include "dvbscan.h" + +void dvbscan_scan_dvb(struct dvbfe_handle *fe) +{ + // FIXME +} diff --git a/util/dvbscan/dvbscan_structutils.c b/util/dvbscan/dvbscan_structutils.c new file mode 100644 index 0000000..6fe3124 --- /dev/null +++ b/util/dvbscan/dvbscan_structutils.c @@ -0,0 +1,99 @@ +/* + dvbscan utility + + Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include "dvbscan.h" + +void append_transponder(struct transponder *t, struct transponder **tlist, struct transponder **tlist_end) +{ + if (*tlist_end == NULL) { + *tlist = t; + } else { + (*tlist_end)->next = t; + } + *tlist_end = t; + t->next = NULL; +} + +struct transponder *new_transponder(void) +{ + struct transponder *t = (struct transponder *) malloc(sizeof(struct transponder)); + if (t == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + memset(t, 0, sizeof(struct transponder)); + + return t; +} + +void free_transponder(struct transponder *t) +{ + if (t->frequencies) + free(t->frequencies); + // FIXME: free services + free(t); +} + +int seen_transponder(struct transponder *t, struct transponder *checklist) +{ + uint32_t i; + + struct transponder *cur_check = checklist; + while(cur_check) { + uint32_t freq1 = cur_check->params.frequency / 2000; + for(i=0; i < t->frequency_count; i++) { + uint32_t freq2 = t->frequencies[i] / 2000; + if (freq1 == freq2) { + return 1; + } + } + cur_check = cur_check->next; + } + + return 0; +} + +void add_frequency(struct transponder *t, uint32_t frequency) +{ + uint32_t *tmp; + + tmp = (uint32_t*) realloc(t->frequencies, sizeof(uint32_t) * (t->frequency_count + 1)); + if (tmp == NULL) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + tmp[t->frequency_count++] = frequency; + t->frequencies = tmp; +} + +struct transponder *first_transponder(struct transponder **tlist, struct transponder **tlist_end) +{ + struct transponder *t = *tlist; + + *tlist = t->next; + if (*tlist == NULL) + *tlist_end = NULL; + + return t; +} -- cgit v1.2.3