📄 scan.c
字号:
warning("truncated section (PID 0x%04x, lenght %d)", s->pid, section_length + 9); return 0; } if (!get_bit(s->section_done, section_number)) { set_bit (s->section_done, section_number); debug("pid 0x%02x tid 0x%02x table_id_ext 0x%04x, " "%i/%i (version %i)\n", s->pid, table_id, table_id_ext, section_number, last_section_number, section_version_number); switch (table_id) { case 0x00: verbose("PAT\n"); parse_pat (buf, section_length, table_id_ext); break; case 0x02: verbose("PMT 0x%04x for service 0x%04x\n", s->pid, table_id_ext); parse_pmt (buf, section_length, table_id_ext); break; case 0x41: verbose("////////////////////////////////////////////// NIT other\n"); case 0x40: verbose("NIT (%s TS)\n", table_id == 0x40 ? "actual":"other"); parse_nit (buf, section_length, table_id_ext); break; case 0x42: case 0x46: verbose("SDT (%s TS)\n", table_id == 0x42 ? "actual":"other"); parse_sdt (buf, section_length, table_id_ext); break; case 0xc8: case 0xc9: verbose("ATSC VCT\n"); parse_psip_vct(buf, section_length, table_id, table_id_ext); break; default: ; }; for (i = 0; i <= last_section_number; i++) if (get_bit (s->section_done, i) == 0) break; if (i > last_section_number) s->sectionfilter_done = 1; } if (s->segmented) { /* always wait for timeout; this is because we don't now how * many segments there are */ return 0; } else if (s->sectionfilter_done) return 1; return 0;}static int read_sections (struct section_buf *s){ int section_length, count; if (s->sectionfilter_done && !s->segmented) return 1; /* the section filter API guarantess that we get one full section * per read(), provided that the buffer is large enough (it is) */ if (((count = read (s->fd, s->buf, sizeof(s->buf))) < 0) && errno == EOVERFLOW) count = read (s->fd, s->buf, sizeof(s->buf)); if (count < 0) { errorn("read_sections: read error"); return -1; } if (count < 4) return -1; section_length = ((s->buf[1] & 0x0f) << 8) | s->buf[2]; if (count != section_length + 3) return -1; if (parse_section(s) == 1) return 1; return 0;}static LIST_HEAD(running_filters);static LIST_HEAD(waiting_filters);static int n_running;#define MAX_RUNNING 27static struct pollfd poll_fds[MAX_RUNNING];static struct section_buf* poll_section_bufs[MAX_RUNNING];static void setup_filter (struct section_buf* s, const char *dmx_devname, int pid, int tid, int tid_ext, int run_once, int segmented, int timeout){ memset (s, 0, sizeof(struct section_buf)); s->fd = -1; s->dmx_devname = dmx_devname; s->pid = pid; s->table_id = tid; s->run_once = run_once; s->segmented = segmented; if (long_timeout) s->timeout = 5 * timeout; else s->timeout = timeout; s->table_id_ext = tid_ext; s->section_version_number = -1; INIT_LIST_HEAD (&s->list);}static void update_poll_fds(void){ struct list_head *p; struct section_buf* s; int i; memset(poll_section_bufs, 0, sizeof(poll_section_bufs)); for (i = 0; i < MAX_RUNNING; i++) poll_fds[i].fd = -1; i = 0; list_for_each (p, &running_filters) { if (i >= MAX_RUNNING) fatal("too many poll_fds\n"); s = list_entry (p, struct section_buf, list); if (s->fd == -1) fatal("s->fd == -1 on running_filters\n"); verbosedebug("poll fd %d\n", s->fd); poll_fds[i].fd = s->fd; poll_fds[i].events = POLLIN; poll_fds[i].revents = 0; poll_section_bufs[i] = s; i++; } if (i != n_running) fatal("n_running is hosed\n");}static int start_filter (struct section_buf* s){ struct dmx_sct_filter_params f; if (n_running >= MAX_RUNNING) goto err0; if ((s->fd = open (s->dmx_devname, O_RDWR | O_NONBLOCK)) < 0) goto err0; verbosedebug("start filter pid 0x%04x table_id 0x%02x\n", s->pid, s->table_id); memset(&f, 0, sizeof(f)); f.pid = (uint16_t) s->pid; if (s->table_id < 0x100 && s->table_id > 0) { f.filter.filter[0] = (uint8_t) s->table_id; f.filter.mask[0] = 0xff; } if (s->table_id_ext < 0x10000 && s->table_id_ext > 0) { f.filter.filter[1] = (uint8_t) ((s->table_id_ext >> 8) & 0xff); f.filter.filter[2] = (uint8_t) (s->table_id_ext & 0xff); f.filter.mask[1] = 0xff; f.filter.mask[2] = 0xff; } f.timeout = 0; f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC; if (ioctl(s->fd, DMX_SET_FILTER, &f) == -1) { errorn ("ioctl DMX_SET_FILTER failed"); goto err1; } s->sectionfilter_done = 0; time(&s->start_time); list_del_init (&s->list); /* might be in waiting filter list */ list_add (&s->list, &running_filters); n_running++; update_poll_fds(); return 0;err1: ioctl (s->fd, DMX_STOP); close (s->fd);err0: return -1;}static void stop_filter (struct section_buf *s){ verbosedebug("stop filter pid 0x%04x\n", s->pid); ioctl (s->fd, DMX_STOP); close (s->fd); s->fd = -1; list_del (&s->list); s->running_time += time(NULL) - s->start_time; n_running--; update_poll_fds();}static void add_filter (struct section_buf *s){ verbosedebug("add filter pid 0x%04x\n", s->pid); if (start_filter (s)) list_add_tail (&s->list, &waiting_filters);}static void remove_filter (struct section_buf *s){ verbosedebug("remove filter pid 0x%04x\n", s->pid); stop_filter (s); while (!list_empty(&waiting_filters)) { struct list_head *next = waiting_filters.next; s = list_entry (next, struct section_buf, list); if (start_filter (s)) break; };}static void read_filters (void){ struct section_buf *s; int i, n, done; n = poll(poll_fds, n_running, 1000); if (n == -1) errorn("poll"); for (i = 0; i < n_running; i++) { s = poll_section_bufs[i]; if (!s) fatal("poll_section_bufs[%d] is NULL\n", i); if (poll_fds[i].revents) done = read_sections (s) == 1; else done = 0; /* timeout */ if (done || time(NULL) > s->start_time + s->timeout) { if (s->run_once) { if (done) verbosedebug("filter done pid 0x%04x\n", s->pid); else warning("filter timeout pid 0x%04x\n", s->pid); remove_filter (s); } } }}static int mem_is_zero (const void *mem, int size){ const char *p = mem; int i; for (i=0; i<size; i++) { if (p[i] != 0x00) return 0; } return 1;}static int switch_pos = 0;static int __tune_to_transponder (int frontend_fd, struct transponder *t){ struct dvb_frontend_parameters p; fe_status_t s; int i; current_tp = t; if (mem_is_zero (&t->param, sizeof(struct dvb_frontend_parameters))) return -1; memcpy (&p, &t->param, sizeof(struct dvb_frontend_parameters)); if (verbosity >= 1) { dprintf(1, ">>> tune to: "); dump_dvb_parameters (stderr, t); if (t->last_tuning_failed) dprintf(1, " (tuning failed)"); dprintf(1, "\n"); } if (t->type == FE_QPSK) { int hiband = 0; if (lnb_type.switch_val && lnb_type.high_val && p.frequency >= lnb_type.switch_val) hiband = 1; setup_switch (frontend_fd, switch_pos, t->polarisation == POLARISATION_VERTICAL ? 0 : 1, hiband); usleep(50000); if (hiband) p.frequency = abs(p.frequency - lnb_type.high_val); else p.frequency = abs(p.frequency - lnb_type.low_val); } if (ioctl(frontend_fd, FE_SET_FRONTEND, &p) == -1) { errorn("Setting frontend parameters failed"); return -1; } for (i = 0; i < 10; i++) { usleep (200000); if (ioctl(frontend_fd, FE_READ_STATUS, &s) == -1) { errorn("FE_READ_STATUS failed"); return -1; } verbose(">>> tuning status == 0x%02x\n", s); if (s & FE_HAS_LOCK) { t->last_tuning_failed = 0; return 0; } } warning(">>> tuning failed!!!\n"); t->last_tuning_failed = 1; return -1;}static int tune_to_transponder (int frontend_fd, struct transponder *t){ /* move TP from "new" to "scanned" list */ list_del_init(&t->list); list_add_tail(&t->list, &scanned_transponders); t->scan_done = 1; if (t->type != fe_info.type) { warning("frontend type (%s) is not compatible with requested tuning type (%s)\n", fe_type2str(fe_info.type),fe_type2str(t->type)); /* ignore cable descriptors in sat NIT and vice versa */ t->last_tuning_failed = 1; return -1; } if (__tune_to_transponder (frontend_fd, t) == 0) return 0; return __tune_to_transponder (frontend_fd, t);}static int tune_to_next_transponder (int frontend_fd){ struct list_head *pos, *tmp; struct transponder *t, *to; uint32_t freq; list_for_each_safe(pos, tmp, &new_transponders) { t = list_entry (pos, struct transponder, list);retry: if (tune_to_transponder (frontend_fd, t) == 0) return 0;next: if (t->other_frequency_flag && t->other_f && t->n_other_f) { /* check if the alternate freqeuncy is really new to us */ freq = t->other_f[t->n_other_f - 1]; t->n_other_f--; if (find_transponder(freq)) goto next; /* remember tuning to the old frequency failed */ to = calloc(1, sizeof(*to)); to->param.frequency = t->param.frequency; to->wrong_frequency = 1; INIT_LIST_HEAD(&to->list); INIT_LIST_HEAD(&to->services); list_add_tail(&to->list, &scanned_transponders); copy_transponder(to, t); t->param.frequency = freq; info("retrying with f=%d\n", t->param.frequency); goto retry; } } return -1;}struct strtab { const char *str; int val;};static int str2enum(const char *str, const struct strtab *tab, int deflt){ while (tab->str) { if (!strcmp(tab->str, str)) return tab->val; tab++; } error("invalid enum value '%s'\n", str); return deflt;}static const char * enum2str(int v, const struct strtab *tab, const char *deflt){ while (tab->str) { if (v == tab->val) return tab->str; tab++; } error("invalid enum value '%d'\n", v); return deflt;}static enum fe_code_rate str2fec(const char *fec){ struct strtab fectab[] = { { "NONE", FEC_NONE }, { "1/2", FEC_1_2 }, { "2/3", FEC_2_3 }, { "3/4", FEC_3_4 }, { "4/5", FEC_4_5 }, { "5/6", FEC_5_6 }, { "6/7", FEC_6_7 }, { "7/8", FEC_7_8 }, { "8/9", FEC_8_9 }, { "AUTO", FEC_AUTO }, { NULL, 0 } }; return str2enum(fec, fectab, FEC_AUTO);}static enum fe_modulation str2qam(const char *qam){ struct strtab qamtab[] = { { "QPSK", QPSK }, { "QAM16", QAM_16 }, { "QAM32", QAM_32 }, { "QAM64", QAM_64 }, { "QAM128", QAM_128 }, { "QAM256", QAM_256 }, { "AUTO", QAM_AUTO }, { "8VSB", VSB_8 }, { "16VSB", VSB_16 }, { NULL, 0 } }; return str2enum(qam, qamtab, QAM_AUTO);}static enum fe_bandwidth str2bandwidth(const char *bw){ struct strtab bwtab[] = { { "8MHz", BANDWIDTH_8_MHZ }, { "7MHz", BANDWIDTH_7_MHZ }, { "6MHz", BANDWIDTH_6_MHZ }, { "AUTO", BANDWIDTH_AUTO }, { NULL, 0 } }; return str2enum(bw, bwtab, BANDWIDTH_AUTO);}static enum fe_transmit_mode str2mode(const char *mode){ struct strtab modetab[] = { { "2k", TRANSMISSION_MODE_2K }, { "8k", TRANSMISSION_MODE_8K }, { "AUTO", TRANSMISSION_MODE_AUTO }, { NULL, 0 } }; return str2enum(mode, modetab, TRANSMISSION_MODE_AUTO);}static enum fe_guard_interval str2guard(const char *guard){ struct strtab guardtab[] = { { "1/32", GUARD_INTERVAL_1_32 }, { "1/16", GUARD_INTERVAL_1_16 }, { "1/8", GUARD_INTERVAL_1_8 }, { "1/4", GUARD_INTERVAL_1_4 }, { "AUTO", GUARD_INTERVAL_AUTO }, { NULL, 0 } }; return str2enum(guard, guardtab, GUARD_INTERVAL_AUTO);}static enum fe_hierarchy str2hier(const char *hier){ struct strtab hiertab[] = { { "NONE", HIERARCHY_NONE }, { "1", HIERARCHY_1 }, { "2", HIERARCHY_2 }, { "4", HIERARCHY_4 }, { "AUTO", HIERARCHY_AUTO }, { NULL, 0 } }; return str2enum(hier, hiertab, HIERARCHY_AUTO);}static const char * fe_type2str(fe_type_t t){ struct strtab typetab[] = { { "QPSK", FE_QPSK,}, { "QAM", FE_QAM, }, { "OFDM", FE_OFDM,}, { "ATSC", FE_ATSC,}, { NULL, 0 } }; return enum2str(t, typetab, "UNK");}static int tune_initial (int frontend_fd, const char *initial){ FILE *inif; unsigned int f, sr; char buf[200]; char pol[20], fec[20], qam[20], bw[20], fec2[20], mode[20], guard[20], hier[20]; struct transponder *t; inif = fopen(initial, "r"); if (!inif) { error("cannot open '%s': %d %m\n", initial, errno); return -1; } while (fgets(buf, sizeof(buf), inif)) { if (buf[0] == '#' || buf[0] == '\n') ; else if (sscanf(buf, "S %u %1[HVLR] %u %4s\n", &f, pol, &sr, fec) == 4) { t = alloc_transponder(f); t->type = FE_QPSK; switch(pol[0]) { case 'H': case 'L': t->polarisation = POLARISATION_HORIZONTAL; break; default: t->polarisation = POLARISATION_VERTICAL;; break; } t->param.inversion = spectral_inversion; t->param.u.qpsk.symbol_rate = sr; t->param.u.qpsk.fec_inner = str2fec(fec); info("initial transponder %u %c %u %d\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -