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