• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation version 2
7  * of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18  *
19  * Based on dvb-apps tzap utility, made by:
20  *	Bernard Hatt 24/2/04
21  */
22 
23 #define _FILE_OFFSET_BITS 64
24 #define _LARGEFILE_SOURCE 1
25 #define _LARGEFILE64_SOURCE 1
26 
27 /*
28  * Use a buffer big enough at least 1 second of data. It is interesting
29  * To have it multiple of a page. So, define it as a multiply of
30  * 4096.
31  */
32 #define DVB_BUF_SIZE	(4096 * 8 * 188)
33 
34 /*
35  * Size of the buffer on read operations. The better is if it is
36  * smaller than DVB_BUF_SIZE, as we want to give more time for
37  * write() syscalls to be able to flush data.
38  */
39 #define BUFLEN (188 * 512)
40 
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <ctype.h>
46 #include <errno.h>
47 #include <signal.h>
48 #include <argp.h>
49 #include <sys/time.h>
50 #include <time.h>
51 
52 #ifdef ENABLE_NLS
53 # define _(string) gettext(string)
54 # include "gettext.h"
55 # include <locale.h>
56 # include <langinfo.h>
57 # include <iconv.h>
58 #else
59 # define _(string) string
60 #endif
61 
62 # define N_(string) string
63 
64 #include <linux/dvb/dmx.h>
65 #include "libdvbv5/dvb-file.h"
66 #include "libdvbv5/dvb-demux.h"
67 #include "libdvbv5/dvb-dev.h"
68 #include "libdvbv5/dvb-scan.h"
69 #include "libdvbv5/header.h"
70 #include "libdvbv5/countries.h"
71 
72 #define CHANNEL_FILE	"channels.conf"
73 #define PROGRAM_NAME	"dvbv5-zap"
74 
75 
76 #ifndef O_LARGEFILE
77 #  define O_LARGEFILE 0
78 #endif
79 
80 
81 const int NANO_SECONDS_IN_SEC = 1000000000;
82 
83 const char *argp_program_version = PROGRAM_NAME " version " V4L_UTILS_VERSION;
84 const char *argp_program_bug_address = "Mauro Carvalho Chehab <mchehab@kernel.org>";
85 
86 struct arguments {
87 	char *confname, *lnb_name, *output, *demux_dev, *dvr_dev, *dvr_fname;
88 	char *filename, *dvr_pipe;
89 	unsigned adapter, frontend, demux, get_detected, get_nit;
90 	int lna, lnb, sat_number;
91 	unsigned diseqc_wait, silent, verbose, frontend_only, freq_bpf;
92 	unsigned timeout, dvr, rec_psi, exit_after_tuning;
93 	unsigned n_apid, n_vpid, extra_pids, all_pids;
94 	enum dvb_file_formats input_format, output_format;
95 	unsigned traffic_monitor, low_traffic, non_human, port;
96 	char *search, *server;
97 	const char *cc;
98 
99 	/* Used by status print */
100 	unsigned n_status_lines;
101 };
102 
103 static const struct argp_option options[] = {
104 	{"adapter",	'a', N_("adapter#"),		0, N_("use given adapter (default 0)"), 0},
105 	{"audio_pid",	'A', N_("audio_pid#"),		0, N_("audio pid program to use (default 0)"), 0},
106 	{"channels",	'c', N_("file"),		0, N_("read channels list from 'file'"), 0},
107 	{"extra-pids",	'E', NULL,			0, N_("output all channel pids"), 0 },
108 	{"demux",	'd', N_("demux#"),		0, N_("use given demux (default 0)"), 0},
109 	{"frontend",	'f', N_("frontend#"),		0, N_("use given frontend (default 0)"), 0},
110 	{"input-format", 'I',	N_("format"),		0, N_("Input format: ZAP, CHANNEL, DVBV5 (default: DVBV5)"), 0},
111 	{"lna",		'w', N_("LNA (0, 1, -1)"),	0, N_("enable/disable/auto LNA power"), 0},
112 	{"lnbf",	'l', N_("LNBf_type"),		0, N_("type of LNBf to use. 'help' lists the available ones"), 0},
113 	{"search",	'L', N_("string"),		0, N_("search/look for a string inside the traffic"), 0},
114 	{"monitor",	'm', NULL,			0, N_("monitors the DVB traffic"), 0},
115 	{"output",	'o', N_("file"),		0, N_("output filename (use -o - for stdout)"), 0},
116 	{"pat",		'p', NULL,			0, N_("add pat and pmt to TS recording (implies -r)"), 0},
117 	{"all-pids",	'P', NULL,			0, N_("don't filter any pids. Instead, outputs all of them"), 0 },
118 	{"record",	'r', NULL,			0, N_("set up /dev/dvb/adapterX/dvr0 for TS recording"), 0},
119 	{"silence",	's', NULL,			0, N_("increases silence (can be used more than once)"), 0},
120 	{"sat_number",	'S', N_("satellite_number"),	0, N_("satellite number. If not specified, disable DISEqC"), 0},
121 	{"timeout",	't', N_("seconds"),		0, N_("timeout for zapping and for recording"), 0},
122 	{"freq_bpf",	'U', N_("frequency"),		0, N_("SCR/Unicable band-pass filter frequency to use, in kHz"), 0},
123 	{"verbose",	'v', NULL,			0, N_("verbose debug messages (can be used more than once)"), 0},
124 	{"video_pid",	'V', N_("video_pid#"),		0, N_("video pid program to use (default 0)"), 0},
125 	{"wait",	'W', N_("time"),		0, N_("adds additional wait time for DISEqC command completion"), 0},
126 	{"exit",	'x', NULL,			0, N_("exit after tuning"), 0},
127 	{"low_traffic",	'X', N_("packets_per_sec"),	0, N_("sets DVB low traffic threshold. PIDs with less than this amount of packets per second will be ignored. Default: 1 packet per second"), 0},
128 	{"cc",		'C', N_("country_code"),	0, N_("Set the default country to be used (in ISO 3166-1 two letter code)"), 0},
129 	{"non-numan",	'N', NULL,			0, N_("Non-human formatted stats (useful for scripts)"), 0},
130 	{"server",	'H', N_("SERVER"),		0, N_("dvbv5-daemon host IP address"), 0},
131 	{"tcp-port",	'T', N_("PORT"),		0, N_("dvbv5-daemon host tcp port"), 0},
132 	{"dvr-pipe",	'D', N_("PIPE"),		0, N_("Named pipe for DVR output, when using remote access (by default: /tmp/dvr-pipe)"), 0},
133 	{"help",        '?', 0,				0, N_("Give this help list"), -1},
134 	{"usage",	-3,  0,				0, N_("Give a short usage message")},
135 	{"version",	-4,  0,				0, N_("Print program version"), -1},
136 	{ 0, 0, 0, 0, 0, 0 }
137 };
138 
139 static int timeout_flag = 0;
140 
141 #define ERROR(x...)                                                     \
142 	do {                                                            \
143 		fprintf(stderr, _("ERROR: "));                             \
144 		fprintf(stderr, x);                                     \
145 		fprintf(stderr, "\n");                                 \
146 	} while (0)
147 
148 #define PERROR(x...)                                                    \
149 	do {                                                            \
150 		fprintf(stderr, _("ERROR: "));                             \
151 		fprintf(stderr, x);                                     \
152 		fprintf(stderr, " (%s)\n", strerror(errno));		\
153 	} while (0)
154 
155 #define monitor_log(msg, args...)						\
156 	do {									\
157 		struct timespec __now = { 0 };					\
158 		float __diff;							\
159 										\
160 		clock_gettime(CLOCK_MONOTONIC, &__now);				\
161 		__diff = __now.tv_sec * 1.					\
162 			 + __now.tv_nsec *1. / NANO_SECONDS_IN_SEC;		\
163 		fprintf(stderr, msg, __diff, ##args);				\
164 	} while (0)
165 
166 
167 /*
168  * Find channel configuration.
169  * On success, the caller must dvb_file_free(*out_file).
170  */
parse(struct arguments * args,struct dvb_v5_fe_parms * parms,const char * channel,struct dvb_file ** out_file,const struct dvb_entry ** out_entry)171 static int parse(struct arguments *args,
172 		 struct dvb_v5_fe_parms *parms,
173 		 const char *channel,
174 		 struct dvb_file **out_file,
175 		 const struct dvb_entry **out_entry)
176 {
177 	struct dvb_file *dvb_file;
178 	struct dvb_entry *entry;
179 	int i;
180 	uint32_t sys;
181 
182 	*out_file = NULL;
183 	*out_entry = NULL;
184 
185 	/* This is used only when reading old formats */
186 	switch (parms->current_sys) {
187 	case SYS_DVBT:
188 	case SYS_DVBS:
189 	case SYS_DVBC_ANNEX_A:
190 	case SYS_ATSC:
191 		sys = parms->current_sys;
192 		break;
193 	case SYS_DVBC_ANNEX_C:
194 		sys = SYS_DVBC_ANNEX_A;
195 		break;
196 	case SYS_DVBC_ANNEX_B:
197 		sys = SYS_ATSC;
198 		break;
199 	case SYS_ISDBT:
200 	case SYS_DTMB:
201 		sys = SYS_DVBT;
202 		break;
203 	default:
204 		sys = SYS_UNDEFINED;
205 		break;
206 	}
207 	dvb_file = dvb_read_file_format(args->confname, sys,
208 				    args->input_format);
209 	if (!dvb_file)
210 		return -2;
211 
212 	for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
213 		if (entry->channel && !strcmp(entry->channel, channel))
214 			break;
215 		if (entry->vchannel && !strcmp(entry->vchannel, channel))
216 			break;
217 	}
218 	/*
219 	 * Give a second shot, using a case insensitive seek
220 	 */
221 	if (!entry) {
222 		for (entry = dvb_file->first_entry; entry != NULL;
223 		     entry = entry->next) {
224 			if (entry->channel && !strcasecmp(entry->channel, channel))
225 				break;
226 		}
227 	}
228 
229 	/*
230 	 * When this tool is used to just tune to a channel, to monitor it or
231 	 * to capture all PIDs, all it needs is a frequency.
232 	 * So, let the tool to accept a frequency as the tuning channel on those
233 	 * cases.
234 	 * This way, a file in "channel" format can be used instead of a zap file.
235 	 * It is also easier to use it for testing purposes.
236 	 */
237 	if (!entry && (!args->dvr && !args->rec_psi)) {
238 		uint32_t f, freq = atoi(channel);
239 		if (freq) {
240 			for (entry = dvb_file->first_entry; entry != NULL;
241 			entry = entry->next) {
242 				dvb_retrieve_entry_prop(entry, DTV_FREQUENCY, &f);
243 				if (f == freq)
244 					break;
245 			}
246 
247 		}
248 	}
249 
250 	if (!entry) {
251 		ERROR("Can't find channel");
252 		dvb_file_free(dvb_file);
253 		return -3;
254 	}
255 
256 	/*
257 	 * Both the DVBv5 format and the command line parameters may
258 	 * specify the LNBf. If both have the definition, use the one
259 	 * provided by the command line parameter, overriding the one
260 	 * stored in the channel file.
261 	 */
262 	if (entry->lnb && !parms->lnb) {
263 		int lnb = dvb_sat_search_lnb(entry->lnb);
264 		if (lnb == -1) {
265 			ERROR("unknown LNB %s\n", entry->lnb);
266 			dvb_file_free(dvb_file);
267 			return -1;
268 		}
269 		parms->lnb = dvb_sat_get_lnb(lnb);
270 	}
271 
272 	if (parms->sat_number < 0 && entry->sat_number >= 0)
273 		parms->sat_number = entry->sat_number;
274 
275 	if (entry->other_el_pid) {
276 		int i, type = -1;
277 		for (i = 0; i < entry->other_el_pid_len; i++) {
278 			if (type != entry->other_el_pid[i].type) {
279 				type = entry->other_el_pid[i].type;
280 				if (i)
281 					fprintf(stderr, "\n");
282 				fprintf(stderr, _("service has pid type %02x: "), type);
283 			}
284 			fprintf(stderr, " %d", entry->other_el_pid[i].pid);
285 		}
286 		fprintf(stderr, "\n");
287 	}
288 
289         /* First of all, set the delivery system */
290 	dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &sys);
291 	dvb_set_compat_delivery_system(parms, sys);
292 
293 	/* Copy data into parms */
294 	for (i = 0; i < entry->n_props; i++) {
295 		uint32_t data = entry->props[i].u.data;
296 		/* Don't change the delivery system */
297 		if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM)
298 			continue;
299 		dvb_fe_store_parm(parms, entry->props[i].cmd, data);
300 		if (parms->current_sys == SYS_ISDBT) {
301 			dvb_fe_store_parm(parms, DTV_ISDBT_PARTIAL_RECEPTION, 0);
302 			dvb_fe_store_parm(parms, DTV_ISDBT_SOUND_BROADCASTING, 0);
303 			dvb_fe_store_parm(parms, DTV_ISDBT_LAYER_ENABLED, 0x07);
304 			if (entry->props[i].cmd == DTV_CODE_RATE_HP) {
305 				dvb_fe_store_parm(parms, DTV_ISDBT_LAYERA_FEC,
306 						  data);
307 				dvb_fe_store_parm(parms, DTV_ISDBT_LAYERB_FEC,
308 						  data);
309 				dvb_fe_store_parm(parms, DTV_ISDBT_LAYERC_FEC,
310 						  data);
311 			} else if (entry->props[i].cmd == DTV_MODULATION) {
312 				dvb_fe_store_parm(parms,
313 						  DTV_ISDBT_LAYERA_MODULATION,
314 						  data);
315 				dvb_fe_store_parm(parms,
316 						  DTV_ISDBT_LAYERB_MODULATION,
317 						  data);
318 				dvb_fe_store_parm(parms,
319 						  DTV_ISDBT_LAYERC_MODULATION,
320 						  data);
321 			}
322 		}
323 		if (parms->current_sys == SYS_ATSC &&
324 		    entry->props[i].cmd == DTV_MODULATION) {
325 			if (data != VSB_8 && data != VSB_16)
326 				dvb_fe_store_parm(parms,
327 						  DTV_DELIVERY_SYSTEM,
328 						  SYS_DVBC_ANNEX_B);
329 		}
330 	}
331 
332 	*out_file = dvb_file;
333 	*out_entry = entry;
334 	return 0;
335 }
336 
setup_frontend(struct arguments * args,struct dvb_v5_fe_parms * parms)337 static int setup_frontend(struct arguments *args,
338 			  struct dvb_v5_fe_parms *parms)
339 {
340 	int rc;
341 	uint32_t freq;
342 
343 	if (args->silent < 2) {
344 		rc = dvb_fe_retrieve_parm(parms, DTV_FREQUENCY, &freq);
345 		if (rc < 0) {
346 			ERROR("can't get the frequency");
347 			return -1;
348 		}
349 		fprintf(stderr, _("tuning to %i Hz\n"), freq);
350 	}
351 
352 	rc = dvb_fe_set_parms(parms);
353 	if (rc < 0) {
354 		ERROR("dvb_fe_set_parms failed");
355 		return -1;
356 	}
357 
358 	return 0;
359 }
360 
do_timeout(int x)361 static void do_timeout(int x)
362 {
363 	(void)x;
364 
365 	if (timeout_flag == 0) {
366 		timeout_flag = 1;
367 		alarm(2);
368 		signal(SIGALRM, do_timeout);
369 	} else {
370 		/* something has gone wrong ... exit */
371 		fprintf(stderr, "Forcing program stop due to timeout or terminate signal\n");
372 		exit(1);
373 	}
374 }
375 
print_non_human_stats(FILE * fd,struct dvb_v5_fe_parms * parms)376 static int print_non_human_stats(FILE *fd, struct dvb_v5_fe_parms *parms)
377 {
378 	int rc;
379 	fe_status_t status;
380 	uint32_t snr = 0, _signal = 0, quality = 0;
381 	uint32_t ber = 0, per = 0, pre_ber = 0, uncorrected_blocks = 0;
382 
383 	rc = dvb_fe_get_stats(parms);
384 	if (rc < 0) {
385 		PERROR("dvb_fe_get_stats failed");
386 		return -1;
387 	}
388 
389 	dvb_fe_retrieve_stats(parms, DTV_STATUS, &status);
390 	dvb_fe_retrieve_stats(parms, DTV_QUALITY, &quality);
391 	dvb_fe_retrieve_stats(parms, DTV_STAT_SIGNAL_STRENGTH, &_signal);
392 	dvb_fe_retrieve_stats(parms, DTV_STAT_CNR, &snr);
393 	dvb_fe_retrieve_stats(parms, DTV_BER, &ber);
394 	dvb_fe_retrieve_stats(parms, DTV_STAT_ERROR_BLOCK_COUNT, &uncorrected_blocks);
395 	dvb_fe_retrieve_stats(parms, DTV_PRE_BER, &pre_ber);
396 	dvb_fe_retrieve_stats(parms, DTV_PER, &per);
397 
398 	fprintf(fd,"status %02x | quality %02x | signal %04x | snr %04x | ber %08x | unc %08x | pre_ber %08x | per %08x | ",
399 		status, quality, _signal, snr, ber, uncorrected_blocks, pre_ber, per);
400 
401 	if (status & FE_HAS_LOCK)
402 		fprintf(fd, "FE_HAS_LOCK");
403 
404 	fprintf(fd, "\n");
405 	fflush(fd);
406 
407 	return 0;
408 }
409 
print_frontend_stats(FILE * fd,struct arguments * args,struct dvb_v5_fe_parms * parms)410 static int print_frontend_stats(FILE *fd,
411 				struct arguments *args,
412 				struct dvb_v5_fe_parms *parms)
413 {
414 	char buf[512], *p;
415 	int rc, i, len, show;
416 	uint32_t status = 0;
417 
418 	if (args->non_human)
419 		return print_non_human_stats(fd, parms);
420 
421 	/* Move cursor up and cleans down */
422 	if (isatty(fileno(fd)) && args->n_status_lines)
423 		fprintf(fd, "\r\x1b[%dA\x1b[J", args->n_status_lines);
424 
425 	args->n_status_lines = 0;
426 
427 	rc = dvb_fe_get_stats(parms);
428 	if (rc) {
429 		ERROR("dvb_fe_get_stats failed");
430 		return -1;
431 	}
432 
433 	p = buf;
434 	len = sizeof(buf);
435 	dvb_fe_snprintf_stat(parms,  DTV_STATUS, NULL, 0, &p, &len, &show);
436 
437 	for (i = 0; i < MAX_DTV_STATS; i++) {
438 		show = 1;
439 
440 		dvb_fe_snprintf_stat(parms, DTV_QUALITY, _("Quality"),
441 				     i, &p, &len, &show);
442 
443 		dvb_fe_snprintf_stat(parms, DTV_STAT_SIGNAL_STRENGTH, _("Signal"),
444 				     i, &p, &len, &show);
445 
446 		dvb_fe_snprintf_stat(parms, DTV_STAT_CNR, _("C/N"),
447 				     i, &p, &len, &show);
448 
449 		dvb_fe_snprintf_stat(parms, DTV_STAT_ERROR_BLOCK_COUNT, _("UCB"),
450 				     i,  &p, &len, &show);
451 
452 		dvb_fe_snprintf_stat(parms, DTV_BER, _("postBER"),
453 				     i,  &p, &len, &show);
454 
455 		dvb_fe_snprintf_stat(parms, DTV_PRE_BER, _("preBER"),
456 				     i,  &p, &len, &show);
457 
458 		dvb_fe_snprintf_stat(parms, DTV_PER, _("PER"),
459 				     i,  &p, &len, &show);
460 
461 		if (p != buf) {
462 			if (args->n_status_lines)
463 				fprintf(fd, "\t%s\n", buf);
464 			else
465 				fprintf(fd, "%s\n", buf);
466 
467 			args->n_status_lines++;
468 
469 			p = buf;
470 			len = sizeof(buf);
471 		}
472 	}
473 
474 	fflush(fd);
475 
476 	/* While not lock, display status on a new line */
477 	dvb_fe_retrieve_stats(parms, DTV_STATUS, &status);
478 	if (!isatty(fileno(fd)) || !(status & FE_HAS_LOCK))
479 		fprintf(fd, "\n");
480 
481 	return 0;
482 }
483 
check_frontend(struct arguments * args,struct dvb_v5_fe_parms * parms)484 static int check_frontend(struct arguments *args,
485 			  struct dvb_v5_fe_parms *parms)
486 {
487 	int rc;
488 	fe_status_t status = 0;
489 	do {
490 		rc = dvb_fe_get_stats(parms);
491 		if (rc) {
492 			ERROR("dvb_fe_get_stats failed");
493 			usleep(1000000);
494 			continue;
495 		}
496 
497 		status = 0;
498 		rc = dvb_fe_retrieve_stats(parms, DTV_STATUS, &status);
499 		if (rc) {
500 			ERROR("dvb_fe_retrieve_stats failed");
501 			usleep(1000000);
502 			continue;
503 		}
504 		if (!args->silent)
505 			print_frontend_stats(stderr, args, parms);
506 		if (status & FE_HAS_LOCK)
507 			break;
508 		usleep(1000000);
509 	} while (!timeout_flag);
510 	if (args->silent < 2)
511 		print_frontend_stats(stderr, args, parms);
512 
513 	return status & FE_HAS_LOCK;
514 }
515 
get_show_stats(FILE * fp,struct arguments * args,struct dvb_v5_fe_parms * parms,int loop)516 static void get_show_stats(FILE *fp, struct arguments *args,
517 			   struct dvb_v5_fe_parms *parms,
518 			   int loop)
519 {
520 	int rc;
521 
522 	args->n_status_lines = 0;
523 	do {
524 		rc = dvb_fe_get_stats(parms);
525 		if (!rc)
526 			print_frontend_stats(fp, args, parms);
527 		if (!timeout_flag && loop)
528 			usleep(1000000);
529 	} while (!timeout_flag && loop);
530 }
531 
elapsed_time(struct timespec * start)532 static struct timespec *elapsed_time(struct timespec *start)
533 {
534 	static struct timespec elapsed;
535 	struct timespec end;
536 
537 	if (!start->tv_sec && !start->tv_nsec)
538 		return NULL;
539 
540 	if (clock_gettime(CLOCK_MONOTONIC, &end))
541 		return NULL;
542 
543 	elapsed.tv_sec = end.tv_sec - start->tv_sec;
544 	elapsed.tv_nsec = end.tv_nsec - start->tv_nsec;
545 	if (elapsed.tv_nsec < 0) {
546 		elapsed.tv_sec--;
547 		elapsed.tv_nsec += NANO_SECONDS_IN_SEC;
548 	}
549 	return &elapsed;
550 }
551 
copy_to_file(struct dvb_open_descriptor * in_fd,int out_fd,int timeout,int silent)552 static void copy_to_file(struct dvb_open_descriptor *in_fd, int out_fd,
553 			 int timeout, int silent)
554 {
555 	char buf[BUFLEN];
556 	int r, first = 1;
557 	long long int rc = 0LL;
558 	struct timespec start, *elapsed;
559 
560 	/* Initialize start time, due to -EOVERFLOW with first == 1 */
561 	clock_gettime(CLOCK_MONOTONIC, &start);
562 
563 	while (timeout_flag == 0) {
564 		r = dvb_dev_read(in_fd, buf, sizeof(buf));
565 		if (r < 0) {
566 			if (r == -EOVERFLOW) {
567 				elapsed = elapsed_time(&start);
568 				if (!elapsed)
569 					fprintf(stderr, _("buffer overrun at %lld\n"), rc);
570 				else
571 					fprintf(stderr, _("buffer overrun after %lld.%02ld seconds\n"),
572 						(long long)elapsed->tv_sec,
573 						elapsed->tv_nsec / 10000000);
574 				continue;
575 			}
576 			ERROR("Read failed");
577 			break;
578 		}
579 
580 		/*
581 		 * It takes a while for a DVB device to start streaming, as the
582 		 * hardware may be waiting for some locks. The safest way to
583 		 * ensure that a program record will have the start amount of
584 		 * time specified by the user is to restart the timeout alarm
585 		 * here, after the first succeded read.
586 		 *
587 		 * So, let's reset the start time here.
588 		 */
589 		if (first) {
590 			if (timeout > 0)
591 				alarm(timeout);
592 
593 			clock_gettime(CLOCK_MONOTONIC, &start);
594 			first = 0;
595 		}
596 
597 		if (write(out_fd, buf, r) < 0) {
598 			PERROR(_("Write failed"));
599 			break;
600 		}
601 
602 		rc += r;
603 	}
604 	if (silent < 2) {
605 		if (timeout)
606 			fprintf(stderr, _("received %lld bytes (%lld Kbytes/sec)\n"), rc,
607 				rc / (1024 * timeout));
608 		else
609 			fprintf(stderr, _("received %lld bytes\n"), rc);
610 	}
611 }
612 
parse_opt(int k,char * optarg,struct argp_state * state)613 static error_t parse_opt(int k, char *optarg, struct argp_state *state)
614 {
615 	struct arguments *args = state->input;
616 
617 	switch (k) {
618 	case 'a':
619 		args->adapter = strtoul(optarg, NULL, 0);
620 		break;
621 	case 'f':
622 		args->frontend = strtoul(optarg, NULL, 0);
623 		break;
624 	case 'd':
625 		args->demux = strtoul(optarg, NULL, 0);
626 		break;
627 	case 't':
628 		args->timeout = strtoul(optarg, NULL, 0);
629 		break;
630 	case 'I':
631 		args->input_format = dvb_parse_format(optarg);
632 		break;
633 	case 'o':
634 		args->filename = strdup(optarg);
635 		/* fall through */
636 	case 'r':
637 		args->dvr = 1;
638 		break;
639 	case 'p':
640 		args->rec_psi = 1;
641 		break;
642 	case 'x':
643 		args->exit_after_tuning = 1;
644 		break;
645 	case 'c':
646 		args->confname = strdup(optarg);
647 		break;
648 	case 'w':
649 		if (!strcasecmp(optarg,"on")) {
650 			args->lna = 1;
651 		} else if (!strcasecmp(optarg,"off")) {
652 			args->lna = 0;
653 		} else if (!strcasecmp(optarg,"auto")) {
654 			args->lna = LNA_AUTO;
655 		} else {
656 			int val = strtoul(optarg, NULL, 0);
657 			if (!val)
658 				args->lna = 0;
659 			else if (val > 0)
660 				args->lna = 1;
661 			else
662 				args->lna = LNA_AUTO;
663 		}
664 		break;
665 	case 'l':
666 		args->lnb_name = strdup(optarg);
667 		break;
668 	case 'S':
669 		args->sat_number = strtoul(optarg, NULL, 0);
670 		break;
671 	case 'U':
672 		args->freq_bpf = strtoul(optarg, NULL, 0);
673 		break;
674 	case 'W':
675 		args->diseqc_wait = strtoul(optarg, NULL, 0);
676 		break;
677 	case 's':
678 		args->silent++;
679 		break;
680 	case 'v':
681 		args->verbose++;
682 		break;
683 	case 'A':
684 		args->n_apid = strtoul(optarg, NULL, 0);
685 		break;
686 	case 'V':
687 		args->n_vpid = strtoul(optarg, NULL, 0);
688 		break;
689 	case 'E':
690 		args->extra_pids = 1;
691 		break;
692 	case 'P':
693 		args->all_pids = 1;
694 		break;
695 	case 'm':
696 		args->traffic_monitor = 1;
697 		break;
698 	case 'N':
699 		args->non_human = 1;
700 		break;
701 	case 'X':
702 		args->low_traffic = atoi(optarg);
703 		break;
704 	case 'L':
705 		args->search = strdup(optarg);
706 		break;
707 	case 'C':
708 		args->cc = strndup(optarg, 2);
709 		break;
710 	case 'H':
711 		args->server = strdup(optarg);
712 		break;
713 	case 'T':
714 		args->port = atoi(optarg);
715 		break;
716 	case 'D':
717 		args->dvr_pipe = strdup(optarg);
718 		break;
719 	case '?':
720 		argp_state_help(state, state->out_stream,
721 				ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG
722 				| ARGP_HELP_DOC);
723 		fprintf(state->out_stream, _("\nReport bugs to %s.\n"), argp_program_bug_address);
724 		exit(0);
725 	case -4:
726 		fprintf (state->out_stream, "%s\n", argp_program_version);
727 		exit(0);
728 	case -3:
729 		argp_state_help(state, state->out_stream, ARGP_HELP_USAGE);
730 		exit(0);
731 	default:
732 		return ARGP_ERR_UNKNOWN;
733 	};
734 	return 0;
735 }
736 
print_bytes(float val)737 static char *print_bytes(float val)
738 {
739 	static char buf[20];
740 	char *prefix = "";
741 
742 	if (val >= 500 * 1024 * 1024) {
743 		prefix = "G";
744 		val /= 1024 * 1024 * 1024.;
745 	} else if (val >= 500 * 1024) {
746 		prefix = "M";
747 		val /= 1024 * 1024.;
748 	} else if (val >= 500) {
749 		prefix = "K";
750 		val /= 1024.;
751 	}
752 	if (*prefix) {
753 		if (snprintf(buf, sizeof(buf), "%8.3f %s", val, prefix) <= 0)
754 			return "      NaN ";
755 	} else {
756 		if (snprintf(buf, sizeof(buf), "%9.3f ", val) <= 0)
757 			return "      NaN ";
758 	}
759 
760 	return buf;
761 }
762 
do_traffic_monitor(struct arguments * args,struct dvb_device * dvb,int out_fd,int timeout)763 int do_traffic_monitor(struct arguments *args, struct dvb_device *dvb,
764 		       int out_fd, int timeout)
765 {
766 	struct dvb_open_descriptor *fd, *dvr_fd;
767 	struct timespec startt;
768 	struct dvb_v5_fe_parms *parms = dvb->fe_parms;
769 	unsigned long long pidt[0x2001], wait, cont_err = 0;
770 	unsigned long long err_cnt[0x2000];
771 	signed char pid_cont[0x2000];
772 	int i, first = 1;
773 
774 	memset(pidt, 0, sizeof(pidt));
775 	memset(err_cnt, 0, sizeof(err_cnt));
776 	memset(pid_cont, 0, sizeof(pid_cont));
777 
778 	args->exit_after_tuning = 1;
779 	check_frontend(args, parms);
780 
781 	dvr_fd = dvb_dev_open(dvb, args->dvr_dev, O_RDONLY);
782 	if (!dvr_fd)
783 		return -1;
784 
785 	fprintf(stderr, _("dvb_dev_set_bufsize: buffer set to %d\n"), DVB_BUF_SIZE);
786 	dvb_dev_set_bufsize(dvr_fd, DVB_BUF_SIZE);
787 
788 	fd = dvb_dev_open(dvb, args->demux_dev, O_RDWR);
789 	if (!fd) {
790 		dvb_dev_close(dvr_fd);
791 		return -1;
792 	}
793 
794 	if (args->silent < 2)
795 		fprintf(stderr, _("  dvb_set_pesfilter to 0x2000\n"));
796 	if (dvb_dev_dmx_set_pesfilter(fd, 0x2000, DMX_PES_OTHER,
797 				      DMX_OUT_TS_TAP, 0) < 0) {
798 		dvb_dev_close(dvr_fd);
799 		dvb_dev_close(fd);
800 		return -1;
801 	}
802 
803 	if (clock_gettime(CLOCK_MONOTONIC, &startt)) {
804 		fprintf(stderr, _("Can't get timespec\n"));
805                 return -1;
806 	}
807 
808 	wait = 1000;
809 
810 	monitor_log(_("%.2fs: Starting capture\n"));
811 	while (1) {
812 		struct timespec *elapsed;
813 		unsigned char buffer[BUFLEN];
814 		int pid, ok, diff;
815 		ssize_t r;
816 
817 		if (timeout_flag)
818 			break;
819 
820 		if ((r = dvb_dev_read(dvr_fd, buffer, BUFLEN)) <= 0) {
821 			if (r == -EOVERFLOW) {
822 				monitor_log(_("%.2fs: buffer overrun\n"));
823 				continue;
824 			}
825 			monitor_log(_("%.2fs: read() returned error %zd\n"), r);
826 			break;
827 		}
828 
829 		/*
830 		 * It takes a while for a DVB device to start streaming, as the
831 		 * hardware may be waiting for some locks. The safest way to
832 		 * ensure that a program record will have the start amount of
833 		 * time specified by the user is to restart the timeout alarm
834 		 * here, after the first succeded read.
835 		 */
836 		if (first) {
837 			if (timeout > 0)
838 				alarm(timeout);
839 			first = 0;
840 		}
841 		if (out_fd >= 0) {
842 			if (write(out_fd, buffer, r) < 0) {
843 				PERROR(_("Write failed"));
844 				break;
845 			}
846 		}
847 		if (r != BUFLEN) {
848 			monitor_log(_("%.2fs: only read %zd bytes\n"), r);
849 			break;
850 		}
851 
852 		for (i = 0; i < BUFLEN; i += 188) {
853 			struct dvb_ts_packet_header *h = (void *)&buffer[i];
854 			if (h->sync_byte != 0x47) {
855 				monitor_log(_("%.2fs: invalid sync byte. Discarding %zd bytes\n"), r);
856 				continue;
857 			}
858 
859 			bswap16(h->bitfield);
860 
861 #if 0
862 			/*
863 			 * ITU-T Rec. H.222.0 decoders shall discard Transport
864 			 * Stream packets with the adaptation_field_control
865 			 * field set to a value of '00' (invalid). Packets with
866 			 * a value of '01' are NULL packets. Yet, as those are
867 			 * actually part of the stream, we won't be discarding,
868 			 * as we want to take them into account for traffic
869 			 * estimation purposes.
870 			 */
871 			if (h->adaptation_field_control == 0)
872 				continue;
873 #endif
874 			ok = 1;
875 			pid = h->pid;
876 
877 			if (pid > 0x1fff) {
878 				monitor_log(_("%.2fs: invalid pid: 0x%04x\n"),
879 					    pid);
880 				pid = 0x1fff;
881 			}
882 
883 			/*
884 			 * After 1 second of processing, check if are there
885 			 * any issues with regards to frame continuity for
886 			 * non-NULL packets.
887 			 *
888 			 * According to ITU-T H.222.0 | ISO/IEC 13818-1, the
889 			 * continuity counter isn't incremented if the packet
890 			 * is 00 or 10. It is only incremented on odd values.
891 			 *
892 			 * Also, don't check continuity errors on the first
893 			 * second, as the frontend is still starting streaming
894 			 */
895 			if (pid < 0x1fff && h->adaptation_field_control & 1) {
896 				int discontinued = 0;
897 
898 				if (h->adaptation_field_control & 2) {
899 					if (h->adaptation_field_length >= 1) {
900 						discontinued = h->discontinued;
901 					} else {
902 						monitor_log(_("%.2fs: pid %d has adaption layer, but size is too small!\n"),
903 							    pid);
904 					}
905 				}
906 
907 				if (wait < 2000)
908 					discontinued = 1;
909 
910 				if (!discontinued && pid_cont[pid] >= 0) {
911 					unsigned int next = (pid_cont[pid] + 1) % 16;
912 					if (next != h->continuity_counter) {
913 						monitor_log(_("%.2fs: pid %d, expecting %d received %d\n"),
914 							    pid, next,
915 							    h->continuity_counter);
916 						discontinued = 1;
917 						cont_err++;
918 						err_cnt[pid]++;
919 					}
920 				}
921 				if (discontinued)
922 					pid_cont[pid] = -1;
923 				else
924 					pid_cont[pid] = h->continuity_counter;
925 			}
926 
927 			if (args->search) {
928 				int i, sl = strlen(args->search);
929 				ok = 0;
930 				if (pid != 0x1fff) {
931 					for (i = 0; i < (188 - sl); ++i) {
932 						if (!memcmp((char *)h + i, args->search, sl))
933 							ok = 1;
934 					}
935 				}
936 			}
937 
938 			if (ok) {
939 				pidt[pid]++;
940 				pidt[0x2000]++;
941 			}
942 		}
943 
944 		elapsed = elapsed_time(&startt);
945 		if (!elapsed)
946 			diff = wait;
947 		else
948 			diff = (unsigned long long)elapsed->tv_sec * 1000
949 				+ elapsed->tv_nsec * 1000 / NANO_SECONDS_IN_SEC;
950 
951 		if (diff > wait) {
952 			unsigned long long other_pidt = 0, other_err_cnt = 0;
953 
954 			if (isatty(STDOUT_FILENO))
955 				printf("\x1b[1H\x1b[2J");
956 
957 			args->n_status_lines = 0;
958 			printf(_(" PID           FREQ         SPEED       TOTAL\n"));
959 			int _pid = 0;
960 			for (_pid = 0; _pid < 0x2000; _pid++) {
961 				if (pidt[_pid]) {
962 					if (args->low_traffic && (pidt[_pid] * 1000. / diff) < args->low_traffic) {
963 						other_pidt += pidt[_pid];
964 						other_err_cnt += err_cnt[_pid];
965 						continue;
966 					}
967 					printf("%5d %9.2f p/s %sbps ",
968 						_pid,
969 						pidt[_pid] * 1000. / diff,
970 						print_bytes(pidt[_pid] * 1000. * 8 * 188/ diff));
971 					if (pidt[_pid] * 188 / 1024)
972 						printf("%8llu KB", (pidt[_pid] * 188 + 512) / 1024);
973 					else
974 						printf(" %8llu B", pidt[_pid] * 188);
975 					if (err_cnt[_pid] > 0)
976 						printf(" %8llu continuity errors",
977 						       err_cnt[_pid]);
978 
979 					printf("\n");
980 				}
981 			}
982 			if (other_pidt) {
983 				printf(_("OTHER"));
984 				printf(" %9.2f p/s %sbps ",
985 					other_pidt * 1000. / diff,
986 					print_bytes(other_pidt * 1000. * 8 * 188/ diff));
987 				if (other_pidt * 188 / 1024)
988 					printf("%8llu KB", (other_pidt * 188 + 512) / 1024);
989 				else
990 					printf(" %8llu B", other_pidt * 188);
991 				if (other_err_cnt > 0)
992 					printf(" %8llu continuity errors",
993 					       other_err_cnt);
994 				printf("\n");
995 			}
996 
997 			/* 0x2000 is the total traffic */
998 			printf("TOT %11.2f p/s %sbps %8llu KB\n",
999 				pidt[_pid] * 1000. / diff,
1000 				print_bytes(pidt[_pid] * 1000. * 8 * 188/ diff),
1001 				(pidt[_pid] * 188 + 512) / 1024);
1002 			printf("\n");
1003 			get_show_stats(stdout, args, parms, 0);
1004 			wait += 1000;
1005 			if (cont_err)
1006 				printf("CONTINUITY errors: %llu\n", cont_err);
1007 		}
1008 	}
1009 	monitor_log(_("%.2fs: Stopping capture\n"));
1010 	dvb_dev_close(dvr_fd);
1011 	dvb_dev_close(fd);
1012 	return 0;
1013 }
1014 
set_signals(struct arguments * args)1015 static void set_signals(struct arguments *args)
1016 {
1017 	signal(SIGTERM, do_timeout);
1018 	signal(SIGINT, do_timeout);
1019 	if (args->timeout > 0) {
1020 		signal(SIGALRM, do_timeout);
1021 		alarm(args->timeout);
1022 	}
1023 }
1024 
1025 static char *default_dvr_pipe = "/tmp/dvr-pipe";
1026 
main(int argc,char ** argv)1027 int main(int argc, char **argv)
1028 {
1029 	struct arguments args = {};
1030 	char *homedir = getenv("HOME");
1031 	char *channel = NULL;
1032 	int lnb = -1, idx = -1;
1033 	int pmtpid = 0;
1034 	struct dvb_file *dvb_file = NULL;
1035 	const struct dvb_entry *dvb_entry = NULL;
1036 	struct dvb_open_descriptor *pat_fd = NULL, *pmt_fd = NULL;
1037 	struct dvb_open_descriptor *sdt_fd = NULL;
1038 	struct dvb_open_descriptor *sid_fd = NULL, *dvr_fd = NULL;
1039 	int file_fd = -1;
1040 	int err = -1;
1041 	int r, ret;
1042 	struct dvb_v5_fe_parms *parms = NULL;
1043 	struct dvb_device *dvb;
1044 	struct dvb_dev_list *dvb_dev;
1045 	const struct argp argp = {
1046 		.options = options,
1047 		.parser = parse_opt,
1048 		.doc = N_("DVB zap utility"),
1049 		.args_doc = N_("<channel name> [or <frequency> if in monitor mode]"),
1050 	};
1051 
1052 #ifdef ENABLE_NLS
1053 	setlocale (LC_ALL, "");
1054 	bindtextdomain (PACKAGE, LOCALEDIR);
1055 	textdomain (PACKAGE);
1056 #endif
1057 
1058 	args.sat_number = -1;
1059 	args.lna = LNA_AUTO;
1060 	args.input_format = FILE_DVBV5;
1061 	args.dvr_pipe = default_dvr_pipe;
1062 	args.low_traffic = 1;
1063 
1064 	if (argp_parse(&argp, argc, argv, ARGP_NO_HELP | ARGP_NO_EXIT, &idx, &args)) {
1065 		argp_help(&argp, stderr, ARGP_HELP_SHORT_USAGE, PROGRAM_NAME);
1066 		return -1;
1067 	}
1068 
1069 	if (idx < argc)
1070 		channel = argv[idx];
1071 
1072 	if (!channel) {
1073 		argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
1074 		return -1;
1075 	}
1076 
1077 	if (args.input_format == FILE_UNKNOWN) {
1078 		ERROR("Please specify a valid format\n");
1079 		argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
1080 		return -1;
1081 	}
1082 
1083 	if (!args.traffic_monitor && args.search) {
1084 		ERROR("search string can be used only on monitor mode\n");
1085 		argp_help(&argp, stderr, ARGP_HELP_STD_HELP, PROGRAM_NAME);
1086 		return -1;
1087 	}
1088 
1089 	if (args.lnb_name) {
1090 		lnb = dvb_sat_search_lnb(args.lnb_name);
1091 		if (lnb < 0) {
1092 			printf(_("Please select one of the LNBf's below:\n"));
1093 			dvb_print_all_lnb();
1094 			exit(1);
1095 		} else {
1096 			printf(_("Using LNBf "));
1097 			dvb_print_lnb(lnb);
1098 		}
1099 	}
1100 
1101 	dvb = dvb_dev_alloc();
1102 	if (!dvb)
1103 		return -1;
1104 
1105 	if (args.server && args.port) {
1106 		printf(_("Connecting to %s:%d\n"), args.server, args.port);
1107 		ret = dvb_dev_remote_init(dvb, args.server, args.port);
1108 		if (ret < 0)
1109 			return -1;
1110 	}
1111 
1112 	dvb_dev_set_log(dvb, args.verbose, NULL);
1113 	dvb_dev_find(dvb, NULL, NULL);
1114 	parms = dvb->fe_parms;
1115 
1116 	dvb_dev = dvb_dev_seek_by_adapter(dvb, args.adapter, args.demux, DVB_DEVICE_DEMUX);
1117 	if (!dvb_dev) {
1118 		fprintf(stderr, _("Couldn't find demux device node\n"));
1119 		dvb_dev_free(dvb);
1120 		return -1;
1121 	}
1122 	args.demux_dev = dvb_dev->sysname;
1123 
1124 	dvb_dev = dvb_dev_seek_by_adapter(dvb, args.adapter, args.demux, DVB_DEVICE_DVR);
1125 	if (!dvb_dev) {
1126 		fprintf(stderr, _("Couldn't find dvr device node\n"));
1127 		dvb_dev_free(dvb);
1128 		return -1;
1129 	}
1130 	args.dvr_dev = dvb_dev->sysname;
1131 	args.dvr_fname = dvb_dev->path;
1132 
1133 	if (args.silent < 2)
1134 		fprintf(stderr, _("using demux '%s'\n"), args.demux_dev);
1135 
1136 	if (!args.confname) {
1137 		if (!homedir)
1138 			ERROR("$HOME not set");
1139 		r = asprintf(&args.confname, "%s/.tzap/%i/%s",
1140 			 homedir, args.adapter, CHANNEL_FILE);
1141 		if (access(args.confname, R_OK)) {
1142 			free(args.confname);
1143 			r = asprintf(&args.confname, "%s/.tzap/%s",
1144 				homedir, CHANNEL_FILE);
1145 		}
1146 	}
1147 	fprintf(stderr, _("reading channels from file '%s'\n"), args.confname);
1148 
1149 	dvb_dev = dvb_dev_seek_by_adapter(dvb, args.adapter, args.frontend,
1150 					  DVB_DEVICE_FRONTEND);
1151 	if (!dvb_dev)
1152 		return -1;
1153 
1154 	if (!dvb_dev_open(dvb, dvb_dev->sysname, O_RDWR))
1155 		goto err;
1156 	if (lnb >= 0)
1157 		parms->lnb = dvb_sat_get_lnb(lnb);
1158 	if (args.sat_number >= 0)
1159 		parms->sat_number = args.sat_number;
1160 	parms->diseqc_wait = args.diseqc_wait;
1161 	parms->freq_bpf = args.freq_bpf;
1162 	parms->lna = args.lna;
1163 
1164 	r = dvb_fe_set_default_country(parms, args.cc);
1165 	if (r < 0)
1166 		fprintf(stderr, _("Failed to set the country code:%s\n"), args.cc);
1167 
1168 	if (parse(&args, parms, channel, &dvb_file, &dvb_entry))
1169 		goto err;
1170 
1171 	if (setup_frontend(&args, parms) < 0)
1172 		goto err;
1173 
1174 	if (args.exit_after_tuning) {
1175 		set_signals(&args);
1176 		err = 0;
1177 		check_frontend(&args, parms);
1178 		goto err;
1179 	}
1180 
1181 	if (args.traffic_monitor) {
1182 		if (args.filename) {
1183 			file_fd = open(args.filename,
1184 					 O_LARGEFILE |
1185 					 O_WRONLY | O_CREAT | O_TRUNC,
1186 					 0644);
1187 			if (file_fd < 0) {
1188 				PERROR(_("open of '%s' failed"), args.filename);
1189 				return -1;
1190 			}
1191 		}
1192 		set_signals(&args);
1193 		err = do_traffic_monitor(&args, dvb, file_fd, args.timeout);
1194 		goto err;
1195 	}
1196 
1197 	if (args.rec_psi) {
1198 		sid_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1199 		if (!sid_fd) {
1200 			ERROR("opening sid demux failed");
1201 			return -1;
1202 		}
1203 		pmtpid = dvb_dev_dmx_get_pmt_pid(sid_fd, dvb_entry->service_id);
1204 		dvb_dev_close(sid_fd);
1205 		if (pmtpid <= 0) {
1206 			fprintf(stderr, _("couldn't find pmt-pid for sid %04x\n"),
1207 				dvb_entry->service_id);
1208 			goto err;
1209 		}
1210 
1211 		pat_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1212 		if (!pat_fd) {
1213 			ERROR("opening pat demux failed");
1214 			goto err;
1215 		}
1216 		if (dvb_dev_dmx_set_pesfilter(pat_fd, 0, DMX_PES_OTHER,
1217 				args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
1218 				args.dvr ? 64 * 1024 : 0) < 0)
1219 			goto err;
1220 
1221 		pmt_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1222 		if (!pmt_fd) {
1223 			ERROR("opening pmt demux failed");
1224 			goto err;
1225 		}
1226 		if (dvb_dev_dmx_set_pesfilter(pmt_fd, pmtpid, DMX_PES_OTHER,
1227 				args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
1228 				args.dvr ? 64 * 1024 : 0) < 0)
1229 			goto err;
1230 
1231 		/*
1232 		 * SDT may also be needed in order to play some streams
1233 		 */
1234 		sdt_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1235 		if (!sdt_fd) {
1236 			ERROR("opening sdt demux failed");
1237 			goto err;
1238 		}
1239 		if (dvb_dev_dmx_set_pesfilter(sdt_fd, 0x0011, DMX_PES_OTHER,
1240 				args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
1241 				args.dvr ? 64 * 1024 : 0) < 0)
1242 			goto err;
1243 	}
1244 
1245 	if (args.all_pids) {
1246 		struct dvb_open_descriptor *video_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1247 		if (!video_fd) {
1248 			ERROR("failed opening '%s'", args.demux_dev);
1249 			goto err;
1250 		}
1251 
1252 		fprintf(stderr, _("dvb_dev_set_bufsize: buffer set to %d\n"), DVB_BUF_SIZE);
1253 		dvb_dev_set_bufsize(video_fd, DVB_BUF_SIZE);
1254 
1255 		if (args.silent < 2) {
1256 			fprintf(stderr, _("pass all PIDs to TS\n"));
1257 			fprintf(stderr, _("  dvb_set_pesfilter %d\n"), 0x2000);
1258 		}
1259 
1260 		if (dvb_dev_dmx_set_pesfilter(video_fd, 0x2000, DMX_PES_OTHER,
1261 				      DMX_OUT_TS_TAP, 0) < 0) {
1262 			goto err;
1263 		}
1264 	} else {
1265 		if (dvb_entry->video_pid_len) {
1266 			struct dvb_open_descriptor *video_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1267 			if (!video_fd) {
1268 				ERROR("failed opening '%s'", args.demux_dev);
1269 				goto err;
1270 			}
1271 
1272 			fprintf(stderr, _("dvb_dev_set_bufsize: buffer set to %d\n"), DVB_BUF_SIZE);
1273 			dvb_dev_set_bufsize(video_fd, DVB_BUF_SIZE);
1274 
1275 			if (args.n_vpid >= dvb_entry->video_pid_len) {
1276 				args.n_vpid = 0;
1277 			}
1278 
1279 			for (int i = 0; i < dvb_entry->video_pid_len; i++) {
1280 				if (!args.extra_pids && i != args.n_vpid) {
1281 					continue;
1282 				}
1283 
1284 				if (args.silent < 2) {
1285 					fprintf(stderr, _("video%2$s pid %1$d\n"),
1286 						dvb_entry->video_pid[i], i == args.n_vpid ? "" : "+");
1287 				}
1288 
1289 				if (dvb_dev_dmx_set_pesfilter(video_fd, dvb_entry->video_pid[i],
1290 					i == args.n_vpid ? DMX_PES_VIDEO : DMX_PES_OTHER,
1291 					args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
1292 					args.dvr ? 1024 * 1024 : 0) < 0) {
1293 					goto err;
1294 				}
1295 			}
1296 		}
1297 
1298 		if (dvb_entry->audio_pid_len) {
1299 			if (args.n_apid >= dvb_entry->audio_pid_len) {
1300 				args.n_apid = 0;
1301 			}
1302 
1303 			for (int i = 0; i < dvb_entry->audio_pid_len; i++) {
1304 				if (!args.extra_pids && i != args.n_apid) {
1305 					continue;
1306 				}
1307 
1308 				struct dvb_open_descriptor *audio_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1309 				if (!audio_fd) {
1310 					ERROR("failed opening '%s'", args.demux_dev);
1311 					goto err;
1312 				}
1313 
1314 				if (args.silent < 2) {
1315 					fprintf(stderr, _("audio%2$s pid %1$d\n"),
1316 						dvb_entry->audio_pid[i], i == args.n_apid ? "" : "+");
1317 				}
1318 
1319 				if (dvb_dev_dmx_set_pesfilter(audio_fd, dvb_entry->audio_pid[i],
1320 						i == args.n_apid ? DMX_PES_AUDIO : DMX_PES_OTHER,
1321 						args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
1322 						args.dvr ? 64 * 1024 : 0) < 0) {
1323 					goto err;
1324 				}
1325 			}
1326 		}
1327 
1328 		if (args.extra_pids && dvb_entry->other_el_pid_len) {
1329 			for (int i = dvb_entry->other_el_pid_len - 1; i >= 0; i--) {
1330 				struct dvb_open_descriptor * other_fd = dvb_dev_open(dvb, args.demux_dev, O_RDWR);
1331 				if (!other_fd) {
1332 					ERROR("failed opening '%s'", args.demux_dev);
1333 					goto err;
1334 				}
1335 
1336 				if (args.silent < 2) {
1337 					fprintf(stderr, _("other pid %d (%d)\n"),
1338 						dvb_entry->other_el_pid[i].pid, dvb_entry->other_el_pid[i].type);
1339 				}
1340 
1341 				if (dvb_dev_dmx_set_pesfilter(other_fd, dvb_entry->other_el_pid[i].pid, DMX_PES_OTHER,
1342 						args.dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER,
1343 						args.dvr ? 64 * 1024 : 0) < 0) {
1344 					goto err;
1345 				}
1346 			}
1347 		}
1348 	}
1349 
1350 	if ((dvb_entry->video_pid_len || dvb_entry->audio_pid_len) && !args.all_pids && !args.rec_psi) {
1351 		printf(_("PMT record is disabled.\n"
1352 		         "Please notice that some streams can only be decoded with PMT data.\n"
1353 			 "Use '-p' option to also record PMT.\n"));
1354 	}
1355 
1356 	set_signals(&args);
1357 
1358 	if (!check_frontend(&args, parms)) {
1359 		err = 1;
1360 		fprintf(stderr, _("frontend doesn't lock\n"));
1361 		goto err;
1362 	}
1363 
1364 	if (args.dvr) {
1365 		if (args.filename) {
1366 			file_fd = STDOUT_FILENO;
1367 
1368 			if (strcmp(args.filename, "-") != 0) {
1369 				file_fd = open(args.filename,
1370 					 O_LARGEFILE |
1371 					 O_WRONLY | O_CREAT | O_TRUNC,
1372 					 0644);
1373 				if (file_fd < 0) {
1374 					PERROR(_("open of '%s' failed"),
1375 					       args.filename);
1376 					return -1;
1377 				}
1378 			}
1379 		}
1380 
1381 		if (args.silent < 2)
1382 			get_show_stats(stderr, &args, parms, 0);
1383 
1384 		if (file_fd >= 0) {
1385 			dvr_fd = dvb_dev_open(dvb, args.dvr_dev, O_RDONLY);
1386 			if (!dvr_fd) {
1387 				ERROR("failed opening '%s'", args.dvr_dev);
1388 				goto err;
1389 			}
1390 			if (!timeout_flag)
1391 				fprintf(stderr, _("Record to file '%s' started\n"), args.filename);
1392 			copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
1393 		} else if (args.server && args.port) {
1394 			struct stat st;
1395 			if (stat(args.dvr_pipe, &st) == -1) {
1396 				if (mknod(args.dvr_pipe,
1397 					S_IRUSR | S_IWUSR | S_IFIFO, 0) < 0) {
1398 					PERROR("Can't create pipe %s",
1399 					args.dvr_pipe);
1400 					return -1;
1401 				}
1402 			} else {
1403 				if (!S_ISFIFO(st.st_mode)) {
1404 					ERROR("%s exists but is not a pipe",
1405 					args.dvr_pipe);
1406 					return -1;
1407 				}
1408 			}
1409 
1410 			fprintf(stderr, _("DVR pipe interface '%s' will be opened\n"), args.dvr_pipe);
1411 
1412 			dvr_fd = dvb_dev_open(dvb, args.dvr_dev, O_RDONLY);
1413 			if (!dvr_fd) {
1414 				ERROR("failed opening '%s'", args.dvr_dev);
1415 				err = -1;
1416 				goto err;
1417 			}
1418 
1419 			file_fd = open(args.dvr_pipe,
1420 #ifdef O_LARGEFILE
1421 					O_LARGEFILE |
1422 #endif
1423 					O_WRONLY,
1424 					0644);
1425 			if (file_fd < 0) {
1426 				PERROR(_("open of '%s' failed"),
1427 					args.filename);
1428 				err = -1;
1429 				goto err;
1430 			}
1431 			copy_to_file(dvr_fd, file_fd, args.timeout, args.silent);
1432 		} else {
1433 			if (!timeout_flag)
1434 				fprintf(stderr, _("DVR interface '%s' can now be opened\n"), args.dvr_fname);
1435 
1436 			get_show_stats(stderr, &args, parms, 1);
1437 		}
1438 		if (args.silent < 2)
1439 			get_show_stats(stderr, &args, parms, 0);
1440 	} else {
1441 		/* Wait until timeout or being killed */
1442 		while (!timeout_flag) {
1443 			get_show_stats(stderr, &args, parms, 1);
1444 			usleep(1000000);
1445 		}
1446 	}
1447 	err = 0;
1448 
1449 err:
1450 	dvb_dev_free(dvb);
1451 
1452 	if (dvb_file) {
1453 		dvb_file_free(dvb_file);
1454 	}
1455 
1456 	/*
1457 	 * Just to make Valgrind happier. It should be noticed
1458 	 * That, if an error happens or if the program exits via
1459 	 * timeout code at forced mode, it may not free those.
1460 	 */
1461 	if (args.confname)
1462 		free(args.confname);
1463 	if (args.filename)
1464 		free(args.filename);
1465 	if (args.lnb_name)
1466 		free(args.lnb_name);
1467 	if (args.search)
1468 		free(args.search);
1469 	if (args.server)
1470 		free(args.server);
1471 	if (args.dvr_pipe != default_dvr_pipe)
1472 		free(args.dvr_pipe);
1473 
1474 	return err;
1475 }
1476