📄 scan.c
字号:
t->param.frequency, pol[0], sr, t->param.u.qpsk.fec_inner); } else if (sscanf(buf, "C %u %u %4s %6s\n", &f, &sr, fec, qam) == 4) { t = alloc_transponder(f); t->type = FE_QAM; t->param.inversion = spectral_inversion; t->param.u.qam.symbol_rate = sr; t->param.u.qam.fec_inner = str2fec(fec); t->param.u.qam.modulation = str2qam(qam); info("initial transponder %u %u %d %d\n", t->param.frequency, sr, t->param.u.qam.fec_inner, t->param.u.qam.modulation); } else if (sscanf(buf, "T %u %4s %4s %4s %7s %4s %4s %4s\n", &f, bw, fec, fec2, qam, mode, guard, hier) == 8) { t = alloc_transponder(f); t->type = FE_OFDM; t->param.inversion = spectral_inversion; t->param.u.ofdm.bandwidth = str2bandwidth(bw); t->param.u.ofdm.code_rate_HP = str2fec(fec); if (t->param.u.ofdm.code_rate_HP == FEC_NONE) t->param.u.ofdm.code_rate_HP = FEC_AUTO; t->param.u.ofdm.code_rate_LP = str2fec(fec2); if (t->param.u.ofdm.code_rate_LP == FEC_NONE) t->param.u.ofdm.code_rate_LP = FEC_AUTO; t->param.u.ofdm.constellation = str2qam(qam); t->param.u.ofdm.transmission_mode = str2mode(mode); t->param.u.ofdm.guard_interval = str2guard(guard); t->param.u.ofdm.hierarchy_information = str2hier(hier); info("initial transponder %u %d %d %d %d %d %d %d\n", t->param.frequency, t->param.u.ofdm.bandwidth, t->param.u.ofdm.code_rate_HP, t->param.u.ofdm.code_rate_LP, t->param.u.ofdm.constellation, t->param.u.ofdm.transmission_mode, t->param.u.ofdm.guard_interval, t->param.u.ofdm.hierarchy_information); } else if (sscanf(buf, "A %u %7s\n", &f,qam) == 2) { t = alloc_transponder(f); t->type = FE_ATSC; t->param.u.vsb.modulation = str2qam(qam); } else error("cannot parse'%s'\n", buf); } fclose(inif); return tune_to_next_transponder(frontend_fd);}static void scan_tp_atsc(void){ struct section_buf s0,s1,s2; if (no_ATSC_PSIP) { setup_filter(&s0, demux_devname, 0x00, 0x00, -1, 1, 0, 5); /* PAT */ add_filter(&s0); } else { if (ATSC_type & 0x1) { setup_filter(&s0, demux_devname, 0x1ffb, 0xc8, -1, 1, 0, 5); /* terrestrial VCT */ add_filter(&s0); } if (ATSC_type & 0x2) { setup_filter(&s1, demux_devname, 0x1ffb, 0xc9, -1, 1, 0, 5); /* cable VCT */ add_filter(&s1); } setup_filter(&s2, demux_devname, 0x00, 0x00, -1, 1, 0, 5); /* PAT */ add_filter(&s2); } do { read_filters (); } while (!(list_empty(&running_filters) && list_empty(&waiting_filters)));}static void scan_tp_dvb (void){ struct section_buf s0; struct section_buf s1; struct section_buf s2; struct section_buf s3; /** * filter timeouts > min repetition rates specified in ETR211 */ setup_filter (&s0, demux_devname, 0x00, 0x00, -1, 1, 0, 5); /* PAT */ setup_filter (&s1, demux_devname, 0x11, 0x42, -1, 1, 0, 5); /* SDT */ add_filter (&s0); add_filter (&s1); if (!current_tp_only || output_format != OUTPUT_PIDS) { setup_filter (&s2, demux_devname, 0x10, 0x40, -1, 1, 0, 15); /* NIT */ add_filter (&s2); if (get_other_nits) { /* get NIT-others * Note: There is more than one NIT-other: one per * network, separated by the network_id. */ setup_filter (&s3, demux_devname, 0x10, 0x41, -1, 1, 1, 15); add_filter (&s3); } } do { read_filters (); } while (!(list_empty(&running_filters) && list_empty(&waiting_filters)));}static void scan_tp(void){ switch(fe_info.type) { case FE_QPSK: case FE_QAM: case FE_OFDM: scan_tp_dvb(); break; case FE_ATSC: scan_tp_atsc(); break; default: break; }}static void scan_network (int frontend_fd, const char *initial){ if (tune_initial (frontend_fd, initial) < 0) { error("initial tuning failed\n"); return; } do { scan_tp(); } while (tune_to_next_transponder(frontend_fd) == 0);}static void pids_dump_service_parameter_set(FILE *f, struct service *s){ int i; fprintf(f, "%-24.24s (0x%04x) %02x: ", s->service_name, s->service_id, s->type); if (!s->pcr_pid || (s->type > 2)) fprintf(f, " "); else if (s->pcr_pid == s->video_pid) fprintf(f, "PCR == V "); else if ((s->audio_num == 1) && (s->pcr_pid == s->audio_pid[0])) fprintf(f, "PCR == A "); else fprintf(f, "PCR 0x%04x ", s->pcr_pid); if (s->video_pid) fprintf(f, "V 0x%04x", s->video_pid); else fprintf(f, " "); if (s->audio_num) fprintf(f, " A"); for (i = 0; i < s->audio_num; i++) { fprintf(f, " 0x%04x", s->audio_pid[i]); if (s->audio_lang[i][0]) fprintf(f, " (%.3s)", s->audio_lang[i]); else if (s->audio_num == 1) fprintf(f, " "); } if (s->teletext_pid) fprintf(f, " TT 0x%04x", s->teletext_pid); if (s->ac3_pid) fprintf(f, " AC3 0x%04x", s->ac3_pid); if (s->subtitling_pid) fprintf(f, " SUB 0x%04x", s->subtitling_pid); fprintf(f, "\n");}static char sat_polarisation (struct transponder *t){ return t->polarisation == POLARISATION_VERTICAL ? 'v' : 'h';}static int sat_number (struct transponder *t){ (void) t; return switch_pos;}static void dump_lists (void){ struct list_head *p1, *p2; struct transponder *t; struct service *s; int n = 0, i; char sn[20]; int anon_services = 0; list_for_each(p1, &scanned_transponders) { t = list_entry(p1, struct transponder, list); if (t->wrong_frequency) continue; list_for_each(p2, &t->services) { n++; } } info("dumping lists (%d services)\n", n); list_for_each(p1, &scanned_transponders) { t = list_entry(p1, struct transponder, list); if (t->wrong_frequency) continue; list_for_each(p2, &t->services) { s = list_entry(p2, struct service, list); if (!s->service_name) { /* not in SDT */ if (unique_anon_services) snprintf(sn, sizeof(sn), "[%03x-%04x]", anon_services, s->service_id); else snprintf(sn, sizeof(sn), "[%04x]", s->service_id); s->service_name = strdup(sn); anon_services++; } /* ':' is field separator in szap and vdr service lists */ for (i = 0; s->service_name[i]; i++) { if (s->service_name[i] == ':') s->service_name[i] = ' '; } for (i = 0; s->provider_name && s->provider_name[i]; i++) { if (s->provider_name[i] == ':') s->provider_name[i] = ' '; } if (s->video_pid && !(serv_select & 1)) continue; /* no TV services */ if (!s->video_pid && s->audio_num && !(serv_select & 2)) continue; /* no radio services */ if (!s->video_pid && !s->audio_num && !(serv_select & 4)) continue; /* no data/other services */ if (s->scrambled && !ca_select) continue; /* FTA only */ switch (output_format) { case OUTPUT_PIDS: pids_dump_service_parameter_set (stdout, s); break; case OUTPUT_VDR: vdr_dump_service_parameter_set (stdout, s->service_name, s->provider_name, t->type, &t->param, sat_polarisation(t), s->video_pid, s->pcr_pid, s->audio_pid, s->audio_lang, s->audio_num, s->teletext_pid, s->scrambled, //FIXME: s->subtitling_pid s->ac3_pid, s->service_id, t->network_id, s->transport_stream_id, t->orbital_pos, t->we_flag, vdr_dump_provider, ca_select, vdr_version, vdr_dump_channum, s->channel_num); break; case OUTPUT_ZAP: zap_dump_service_parameter_set (stdout, s->service_name, t->type, &t->param, sat_polarisation(t), sat_number(t), s->video_pid, s->audio_pid, s->service_id); default: break; } } } info("Done.\n");}static void show_existing_tuning_data_files(void){#ifndef DATADIR#define DATADIR "/usr/local/share"#endif static const char* prefixlist[] = { DATADIR "/dvb", "/etc/dvb", DATADIR "/doc/packages/dvb", 0 }; unsigned int i; const char **prefix; fprintf(stderr, "initial tuning data files:\n"); for (prefix = prefixlist; *prefix; prefix++) { glob_t globbuf; char* globspec = malloc (strlen(*prefix)+9); strcpy (globspec, *prefix); strcat (globspec, "/dvb-?/*"); if (! glob (globspec, 0, 0, &globbuf)) { for (i=0; i < globbuf.gl_pathc; i++) fprintf(stderr, " file: %s\n", globbuf.gl_pathv[i]); } free (globspec); globfree (&globbuf); }}static void handle_sigint(int sig){ (void)sig; error("interrupted by SIGINT, dumping partial result...\n"); dump_lists(); exit(2);}static const char *usage = "\n" "usage: %s [options...] [-c | initial-tuning-data-file]\n" " atsc/dvbscan doesn't do frequency scans, hence it needs initial\n" " tuning data for at least one transponder/channel.\n" " -c scan on currently tuned transponder only\n" " -v verbose (repeat for more)\n" " -q quiet (repeat for less)\n" " -a N use DVB /dev/dvb/adapterN/\n" " -f N use DVB /dev/dvb/adapter?/frontendN\n" " -d N use DVB /dev/dvb/adapter?/demuxN\n" " -s N use DiSEqC switch position N (DVB-S only)\n" " -i N spectral inversion setting (0: off, 1: on, 2: auto [default])\n" " -n evaluate NIT-other for full network scan (slow!)\n" " -5 multiply all filter timeouts by factor 5\n" " for non-DVB-compliant section repitition rates\n" " -o fmt output format: 'zap' (default), 'vdr' or 'pids' (default with -c)\n" " -x N Conditional Axcess, (default 1)\n" " N=0 gets only FTA channels\n" " N=xxx sets ca field in vdr output to :xxx:\n" " -t N Service select, Combined bitfield parameter.\n" " 1 = TV, 2 = Radio, 4 = Other, (default 7)\n" " -p for vdr output format: dump provider name\n" " -e N VDR version, default 2 for VDR-1.2.x\n" " ANYTHING ELSE GIVES NONZERO NIT and TID\n" " Vdr version 1.3.x and up implies -p.\n" " -l lnb-type (DVB-S Only) (use -l help to print types) or \n" " -l low[,high[,switch]] in Mhz\n" " -u UK DVB-T Freeview channel numbering for VDR\n\n" " -P do not use ATSC PSIP tables for scanning\n" " (but only PAT and PMT) (applies for ATSC only)\n" " -A N check for ATSC 1=Terrestrial [default], 2=Cable or 3=both\n" " -U Uniquely name unknown services\n";voidbad_usage(char *pname, int problem){ int i; struct lnb_types_st *lnbp; char **cp; switch (problem) { default: case 0: fprintf (stderr, usage, pname); break; case 1: i = 0; fprintf(stderr, "-l <lnb-type> or -l low[,high[,switch]] in Mhz\n" "where <lnb-type> is:\n"); while(NULL != (lnbp = lnb_enum(i))) { fprintf (stderr, "%s\n", lnbp->name); for (cp = lnbp->desc; *cp ; cp++) { fprintf (stderr, " %s\n", *cp); } i++; } break; case 2: show_existing_tuning_data_files(); fprintf (stderr, usage, pname); }}int main (int argc, char **argv){ char frontend_devname [80]; int adapter = 0, frontend = 0, demux = 0; int opt, i; int frontend_fd; int fe_open_mode; const char *initial = NULL; if (argc <= 1) { bad_usage(argv[0], 2); return -1; } /* start with default lnb type */ lnb_type = *lnb_enum(0); while ((opt = getopt(argc, argv, "5cnpa:f:d:s:o:x:e:t:i:l:vquPA:U")) != -1) { switch (opt) { case 'a': adapter = strtoul(optarg, NULL, 0); break; case 'c': current_tp_only = 1; if (!output_format_set) output_format = OUTPUT_PIDS; break; case 'n': get_other_nits = 1; break; case 'd': demux = strtoul(optarg, NULL, 0); break; case 'f': frontend = strtoul(optarg, NULL, 0); break; case 'p': vdr_dump_provider = 1; break; case 's': switch_pos = strtoul(optarg, NULL, 0); break; case 'o': if (strcmp(optarg, "zap") == 0) output_format = OUTPUT_ZAP; else if (strcmp(optarg, "vdr") == 0) output_format = OUTPUT_VDR; else if (strcmp(optarg, "pids") == 0) output_format = OUTPUT_PIDS; else { bad_usage(argv[0], 0); return -1; } output_format_set = 1; break; case '5': long_timeout = 1; break; case 'x': ca_select = strtoul(optarg, NULL, 0); break; case 'e': vdr_version = strtoul(optarg, NULL, 0); break; case 't': serv_select = strtoul(optarg, NULL, 0); break; case 'i': spectral_inversion = strtoul(optarg, NULL, 0); break; case 'l': if (lnb_decode(optarg, &lnb_type) < 0) { bad_usage(argv[0], 1); return -1; } break; case 'v': verbosity++; break; case 'q': if (--verbosity < 0) verbosity = 0; break; case 'u': vdr_dump_channum = 1; break; case 'P': no_ATSC_PSIP = 1; break; case 'A': ATSC_type = strtoul(optarg,NULL,0); if (ATSC_type == 0 || ATSC_type > 3) { bad_usage(argv[0], 1); return -1; } break; case 'U': unique_anon_services = 1; break; default: bad_usage(argv[0], 0); return -1; }; } if (optind < argc) initial = argv[optind]; if ((!initial && !current_tp_only) || (initial && current_tp_only) || (spectral_inversion > 2)) { bad_usage(argv[0], 0); return -1; } lnb_type.low_val *= 1000; /* convert to kiloherz */ lnb_type.high_val *= 1000; /* convert to kiloherz */ lnb_type.switch_val *= 1000; /* convert to kiloherz */ if (switch_pos >= 4) { fprintf (stderr, "switch position needs to be < 4!\n"); return -1; } if (initial) info("scanning %s\n", initial); snprintf (frontend_devname, sizeof(frontend_devname), "/dev/dvb/adapter%i/frontend%i", adapter, frontend); snprintf (demux_devname, sizeof(demux_devname), "/dev/dvb/adapter%i/demux%i", adapter, demux); info("using '%s' and '%s'\n", frontend_devname, demux_devname); for (i = 0; i < MAX_RUNNING; i++) poll_fds[i].fd = -1; fe_open_mode = current_tp_only ? O_RDONLY : O_RDWR; if ((frontend_fd = open (frontend_devname, fe_open_mode)) < 0) fatal("failed to open '%s': %d %m\n", frontend_devname, errno); /* determine FE type and caps */ if (ioctl(frontend_fd, FE_GET_INFO, &fe_info) == -1) fatal("FE_GET_INFO failed: %d %m\n", errno); if ((spectral_inversion == INVERSION_AUTO ) && !(fe_info.caps & FE_CAN_INVERSION_AUTO)) { info("Frontend can not do INVERSION_AUTO, trying INVERSION_OFF instead\n"); spectral_inversion = INVERSION_OFF; } signal(SIGINT, handle_sigint); if (current_tp_only) { current_tp = alloc_transponder(0); /* dummy */ /* move TP from "new" to "scanned" list */ list_del_init(¤t_tp->list); list_add_tail(¤t_tp->list, &scanned_transponders); current_tp->scan_done = 1; scan_tp (); } else scan_network (frontend_fd, initial); close (frontend_fd); dump_lists (); return 0;}static void dump_dvb_parameters (FILE *f, struct transponder *t){ switch (output_format) { case OUTPUT_PIDS: case OUTPUT_VDR: vdr_dump_dvb_parameters(f, t->type, &t->param, sat_polarisation (t), t->orbital_pos, t->we_flag); break; case OUTPUT_ZAP: zap_dump_dvb_parameters (f, t->type, &t->param, sat_polarisation (t), sat_number (t)); break; default: break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -