void dvb_desc_event_short_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_event_short *event = (const struct dvb_desc_event_short *) desc; dvb_log("| Name '%s'", event->name); dvb_log("| Language '%s'", event->language); dvb_log("| Description '%s'", event->text); }
void dvb_fe_prt_parms(const struct dvb_v5_fe_parms *p) { struct dvb_v5_fe_parms_priv *parms = (void *)p; int i; for (i = 0; i < parms->n_props; i++) { const char * const *attr_name = dvb_attr_names(parms->dvb_prop[i].cmd); if (attr_name) { int j; for (j = 0; j < parms->dvb_prop[i].u.data; j++) { if (!*attr_name) break; attr_name++; } } if (!attr_name || !*attr_name) dvb_log("%s = %u", dvb_cmd_name(parms->dvb_prop[i].cmd), parms->dvb_prop[i].u.data); else dvb_log("%s = %s", dvb_cmd_name(parms->dvb_prop[i].cmd), *attr_name); } };
int dvb_fe_get_event(struct dvb_v5_fe_parms *p) { struct dvb_v5_fe_parms_priv *parms = (void *)p; struct dvb_frontend_event event; fe_status_t status; int i; if (!parms->p.legacy_fe) { dvb_fe_get_parms(&parms->p); return dvb_fe_get_stats(&parms->p); } if (xioctl(parms->fd, FE_GET_EVENT, &event) == -1) { dvb_perror("FE_GET_EVENT"); return errno; } status = event.status; if (parms->p.verbose > 1) { dvb_log(_("Status: ")); for (i = 0; i < ARRAY_SIZE(fe_status_name); i++) { if (status & fe_status_name[i].idx) dvb_log (" %s", fe_status_name[i].name); } } dvb_fe_store_stats(parms, DTV_STATUS, FE_SCALE_RELATIVE, 0, status); dvb_fe_retrieve_parm(&parms->p, DTV_FREQUENCY, &event.parameters.frequency); dvb_fe_retrieve_parm(&parms->p, DTV_INVERSION, &event.parameters.inversion); switch (parms->p.current_sys) { case SYS_DVBS: dvb_fe_retrieve_parm(&parms->p, DTV_SYMBOL_RATE, &event.parameters.u.qpsk.symbol_rate); dvb_fe_retrieve_parm(&parms->p, DTV_INNER_FEC, &event.parameters.u.qpsk.fec_inner); break; case SYS_DVBC_ANNEX_AC: dvb_fe_retrieve_parm(&parms->p, DTV_SYMBOL_RATE, &event.parameters.u.qam.symbol_rate); dvb_fe_retrieve_parm(&parms->p, DTV_INNER_FEC, &event.parameters.u.qam.fec_inner); dvb_fe_retrieve_parm(&parms->p, DTV_MODULATION, &event.parameters.u.qam.modulation); break; case SYS_ATSC: case SYS_ATSCMH: case SYS_DVBC_ANNEX_B: dvb_fe_retrieve_parm(&parms->p, DTV_MODULATION, &event.parameters.u.vsb.modulation); break; case SYS_DVBT: dvb_fe_retrieve_parm(&parms->p, DTV_BANDWIDTH_HZ, &event.parameters.u.ofdm.bandwidth); dvb_fe_retrieve_parm(&parms->p, DTV_CODE_RATE_HP, &event.parameters.u.ofdm.code_rate_HP); dvb_fe_retrieve_parm(&parms->p, DTV_CODE_RATE_LP, &event.parameters.u.ofdm.code_rate_LP); dvb_fe_retrieve_parm(&parms->p, DTV_MODULATION, &event.parameters.u.ofdm.constellation); dvb_fe_retrieve_parm(&parms->p, DTV_TRANSMISSION_MODE, &event.parameters.u.ofdm.transmission_mode); dvb_fe_retrieve_parm(&parms->p, DTV_GUARD_INTERVAL, &event.parameters.u.ofdm.guard_interval); dvb_fe_retrieve_parm(&parms->p, DTV_HIERARCHY, &event.parameters.u.ofdm.hierarchy_information); break; default: return EINVAL; } return dvb_fe_get_stats(&parms->p); }
void dvb_desc_hierarchy_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_hierarchy *hierarchy = (const struct dvb_desc_hierarchy *) desc; dvb_log("| Hierarchy"); dvb_log("| type %d", hierarchy->hierarchy_type); dvb_log("| layer %d", hierarchy->layer); dvb_log("| embedded_layer %d", hierarchy->embedded_layer); dvb_log("| channel %d", hierarchy->channel); }
void dvb_desc_service_location_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_service_location *service_location = (const struct dvb_desc_service_location *) desc; struct dvb_desc_service_location_element *element = service_location->element; int i; dvb_log("| pcr pid %d", service_location->pcr_pid); dvb_log("| streams:"); for (i = 0; i < service_location->elements; i++) dvb_log("| pid %d, type %d: %s", element[i].elementary_pid, element[i].stream_type, element[i].language); dvb_log("| %d elements", service_location->elements); }
int dvb_fe_diseqc_reply(struct dvb_v5_fe_parms *p, unsigned *len, char *buf, int timeout) { struct dvb_v5_fe_parms_priv *parms = (void *)p; struct dvb_diseqc_slave_reply reply; int rc; if (*len > 4) *len = 4; reply.timeout = timeout; reply.msg_len = *len; if (parms->p.verbose) dvb_log("DiSEqC FE_DISEQC_RECV_SLAVE_REPLY"); rc = xioctl(parms->fd, FE_DISEQC_RECV_SLAVE_REPLY, reply); if (rc == -1) { dvb_perror("FE_DISEQC_RECV_SLAVE_REPLY"); return rc; } *len = reply.msg_len; memcpy(buf, reply.msg, reply.msg_len); return 0; }
int dvb_fe_diseqc_cmd(struct dvb_v5_fe_parms *p, const unsigned len, const unsigned char *buf) { struct dvb_v5_fe_parms_priv *parms = (void *)p; struct dvb_diseqc_master_cmd msg; int rc; if (len > 6) return -EINVAL; msg.msg_len = len; memcpy(msg.msg, buf, len); if (parms->p.verbose) { int i; char log[len * 3 + 20], *p = log; p += sprintf(p, _("DiSEqC command: ")); for (i = 0; i < len; i++) p += sprintf (p, "%02x ", buf[i]); dvb_log("%s", log); } rc = xioctl(parms->fd, FE_DISEQC_SEND_MASTER_CMD, &msg); if (rc == -1) dvb_perror("FE_DISEQC_SEND_MASTER_CMD"); return rc; }
void dvb_desc_sat_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_sat *sat = (const struct dvb_desc_sat *) desc; char pol; switch(sat->polarization) { case 0: pol = 'H'; break; case 1: pol = 'V'; break; case 2: pol = 'L'; break; case 3: pol = 'R'; break; } dvb_log("| modulation_system %s", sat->modulation_system ? "DVB-S2" : "DVB-S"); dvb_log("| frequency %d %c", sat->frequency, pol); dvb_log("| symbol_rate %d", sat->symbol_rate); dvb_log("| fec %d", sat->fec); dvb_log("| modulation_type %d", sat->modulation_type); dvb_log("| roll_off %d", sat->roll_off); dvb_log("| orbit %.1f %c", (float) sat->orbit / 10.0, sat->west_east ? 'E' : 'W'); }
int dvb_fe_set_default_country(struct dvb_v5_fe_parms *p, const char *cc) { struct dvb_v5_fe_parms_priv *parms = (void *)p; if (!cc) { parms->country = dvb_guess_user_country(); if (parms->p.verbose) { if (parms->country != COUNTRY_UNKNOWN) dvb_log(_("Assuming you're in %s.\n"), dvb_country_to_2letters(parms->country)); else dvb_log(_("Failed to guess country from the current locale setting.\n")); } return 0; } parms->country = dvb_country_a2_to_id(cc); return (parms->country == COUNTRY_UNKNOWN) ? -EINVAL : 0; }
int dvb_fe_sec_tone(struct dvb_v5_fe_parms *p, fe_sec_tone_mode_t tone) { struct dvb_v5_fe_parms_priv *parms = (void *)p; int rc; if (parms->p.verbose) dvb_log( _("DiSEqC TONE: %s"), fe_tone_name[tone] ); rc = xioctl(parms->fd, FE_SET_TONE, tone); if (rc == -1) dvb_perror("FE_SET_TONE"); return rc; }
int dvb_fe_sec_voltage(struct dvb_v5_fe_parms *p, int on, int v18) { struct dvb_v5_fe_parms_priv *parms = (void *)p; fe_sec_voltage_t v; int rc; if (!on) { v = SEC_VOLTAGE_OFF; if (parms->p.verbose) dvb_log(_("DiSEqC VOLTAGE: OFF")); } else { v = v18 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13; if (parms->p.verbose) dvb_log(_("DiSEqC VOLTAGE: %s"), v18 ? "18" : "13"); } rc = xioctl(parms->fd, FE_SET_VOLTAGE, v); if (rc == -1) dvb_perror("FE_SET_VOLTAGE"); return rc; }
void isdb_desc_partial_reception_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { struct isdb_desc_partial_reception *d = (void *)desc; int i; size_t len; len = d->length / sizeof(d->partial_reception); for (i = 0; i < len; i++) { dvb_log("| service ID[%d] %d", i, d->partial_reception[i].service_id); } }
void dvb_desc_cable_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_cable_delivery *cable = (const struct dvb_desc_cable_delivery *) desc; dvb_log("| cable delivery"); dvb_log("| length %d", cable->length); dvb_log("| frequency %d", cable->frequency); dvb_log("| fec outer %d", cable->fec_outer); dvb_log("| modulation %d", cable->modulation); dvb_log("| symbol_rate %d", cable->symbol_rate); dvb_log("| fec inner %d", cable->fec_inner); }
int dvb_fe_lnb_high_voltage(struct dvb_v5_fe_parms *p, int on) { struct dvb_v5_fe_parms_priv *parms = (void *)p; int rc; if (on) on = 1; if (parms->p.verbose) dvb_log( _("DiSEqC HIGH LNB VOLTAGE: %s"), on ? _("ON") : _("OFF") ); rc = xioctl(parms->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, on); if (rc == -1) dvb_perror("FE_ENABLE_HIGH_LNB_VOLTAGE"); return rc; }
void dvb_table_sdt_print(struct dvb_v5_fe_parms *parms, struct dvb_table_sdt *sdt) { dvb_log("SDT"); dvb_table_header_print(parms, &sdt->header); dvb_log("|- network_id %d", sdt->network_id); dvb_log("|\\ service_id"); const struct dvb_table_sdt_service *service = sdt->service; uint16_t services = 0; while(service) { dvb_log("|- %7d", service->service_id); dvb_log("| EIT schedule %d", service->EIT_schedule); dvb_log("| EIT present following %d", service->EIT_present_following); dvb_log("| free CA mode %d", service->free_CA_mode); dvb_log("| running status %d", service->running_status); dvb_print_descriptors(parms, service->descriptor); service = service->next; services++; } dvb_log("|_ %d services", services); }
int dvb_fe_diseqc_burst(struct dvb_v5_fe_parms *p, int mini_b) { struct dvb_v5_fe_parms_priv *parms = (void *)p; fe_sec_mini_cmd_t mini; int rc; mini = mini_b ? SEC_MINI_B : SEC_MINI_A; if (parms->p.verbose) dvb_log( _("DiSEqC BURST: %s"), mini_b ? "SEC_MINI_B" : "SEC_MINI_A" ); rc = xioctl(parms->fd, FE_DISEQC_SEND_BURST, mini); if (rc == -1) dvb_perror("FE_DISEQC_SEND_BURST"); return rc; }
struct dvb_v5_fe_parms *dvb_fe_open_flags(int adapter, int frontend, unsigned verbose, unsigned use_legacy_call, dvb_logfunc logfunc, int flags) { int fd, i, r; char *fname; struct dtv_properties dtv_prop; struct dvb_v5_fe_parms_priv *parms = NULL; libdvbv5_initialize(); if (logfunc == NULL) logfunc = dvb_default_log; r = asprintf(&fname, "/dev/dvb/adapter%i/frontend%i", adapter, frontend); if (r < 0) { logfunc(LOG_ERR, _("asprintf error")); return NULL; } if (!fname) { logfunc(LOG_ERR, _("fname calloc: %s"), strerror(errno)); return NULL; } fd = open(fname, flags, 0); if (fd == -1) { logfunc(LOG_ERR, _("%s while opening %s"), strerror(errno), fname); free(fname); return NULL; } parms = calloc(sizeof(*parms), 1); if (!parms) { logfunc(LOG_ERR, _("parms calloc: %s"), strerror(errno)); close(fd); free(fname); return NULL; } parms->fname = fname; parms->fd = fd; parms->fe_flags = flags; parms->p.verbose = verbose; parms->p.default_charset = "iso-8859-1"; parms->p.output_charset = "utf-8"; parms->p.logfunc = logfunc; parms->p.lna = LNA_AUTO; parms->p.sat_number = -1; parms->p.abort = 0; parms->country = COUNTRY_UNKNOWN; if (xioctl(fd, FE_GET_INFO, &parms->p.info) == -1) { dvb_perror("FE_GET_INFO"); dvb_v5_free(parms); close(fd); free(fname); return NULL; } if (verbose) { fe_caps_t caps = parms->p.info.caps; dvb_log(_("Device %s (%s) capabilities:"), parms->p.info.name, fname); for (i = 0; i < ARRAY_SIZE(fe_caps_name); i++) { if (caps & fe_caps_name[i].idx) dvb_log (" %s", fe_caps_name[i].name); } } parms->dvb_prop[0].cmd = DTV_API_VERSION; parms->dvb_prop[1].cmd = DTV_DELIVERY_SYSTEM; dtv_prop.num = 2; dtv_prop.props = parms->dvb_prop; /* Detect a DVBv3 device */ if (xioctl(fd, FE_GET_PROPERTY, &dtv_prop) == -1) { parms->dvb_prop[0].u.data = 0x300; parms->dvb_prop[1].u.data = SYS_UNDEFINED; } parms->p.version = parms->dvb_prop[0].u.data; parms->p.current_sys = parms->dvb_prop[1].u.data; if (verbose) dvb_log (_("DVB API Version %d.%d%s, Current v5 delivery system: %s"), parms->p.version / 256, parms->p.version % 256, use_legacy_call ? _(" (forcing DVBv3 calls)") : "", delivery_system_name[parms->p.current_sys]); if (parms->p.version < 0x500) use_legacy_call = 1; if (parms->p.version >= 0x50a) parms->p.has_v5_stats = 1; else parms->p.has_v5_stats = 0; if (use_legacy_call || parms->p.version < 0x505) { parms->p.legacy_fe = 1; switch(parms->p.info.type) { case FE_QPSK: parms->p.current_sys = SYS_DVBS; parms->p.systems[parms->p.num_systems++] = parms->p.current_sys; if (parms->p.version < 0x0500) break; if (parms->p.info.caps & FE_CAN_2G_MODULATION) parms->p.systems[parms->p.num_systems++] = SYS_DVBS2; if (parms->p.info.caps & FE_CAN_TURBO_FEC) parms->p.systems[parms->p.num_systems++] = SYS_TURBO; break; case FE_QAM: parms->p.current_sys = SYS_DVBC_ANNEX_A; parms->p.systems[parms->p.num_systems++] = parms->p.current_sys; break; case FE_OFDM: parms->p.current_sys = SYS_DVBT; parms->p.systems[parms->p.num_systems++] = parms->p.current_sys; if (parms->p.version < 0x0500) break; if (parms->p.info.caps & FE_CAN_2G_MODULATION) parms->p.systems[parms->p.num_systems++] = SYS_DVBT2; break; case FE_ATSC: if (parms->p.info.caps & (FE_CAN_8VSB | FE_CAN_16VSB)) parms->p.systems[parms->p.num_systems++] = SYS_ATSC; if (parms->p.info.caps & (FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO)) parms->p.systems[parms->p.num_systems++] = SYS_DVBC_ANNEX_B; parms->p.current_sys = parms->p.systems[0]; break; } if (!parms->p.num_systems) { dvb_logerr(_("delivery system not detected")); dvb_v5_free(parms); close(fd); return NULL; } } else { parms->dvb_prop[0].cmd = DTV_ENUM_DELSYS; parms->n_props = 1; dtv_prop.num = 1; dtv_prop.props = parms->dvb_prop; if (xioctl(fd, FE_GET_PROPERTY, &dtv_prop) == -1) { dvb_perror("FE_GET_PROPERTY"); dvb_v5_free(parms); close(fd); return NULL; } parms->p.num_systems = parms->dvb_prop[0].u.buffer.len; for (i = 0; i < parms->p.num_systems; i++) parms->p.systems[i] = parms->dvb_prop[0].u.buffer.data[i]; if (parms->p.num_systems == 0) { dvb_logerr(_("driver returned 0 supported delivery systems!")); dvb_v5_free(parms); close(fd); return NULL; } } if (verbose) { dvb_log(_("Supported delivery system%s: "), (parms->p.num_systems > 1) ? "s" : ""); for (i = 0; i < parms->p.num_systems; i++) { if (parms->p.systems[i] == parms->p.current_sys) dvb_log (" [%s]", delivery_system_name[parms->p.systems[i]]); else dvb_log (" %s", delivery_system_name[parms->p.systems[i]]); } if (use_legacy_call || parms->p.version < 0x505) dvb_log(_("Warning: new delivery systems like ISDB-T, ISDB-S, DMB-TH, DSS, ATSC-MH will be miss-detected by a DVBv5.4 or earlier API call")); } /* * Fix a bug at some DVB drivers */ if (parms->p.current_sys == SYS_UNDEFINED) parms->p.current_sys = parms->p.systems[0]; /* Prepare to use the delivery system */ parms->n_props = dvb_add_parms_for_sys(&parms->p, parms->p.current_sys); if ((flags & O_ACCMODE) == O_RDWR) dvb_set_sys(&parms->p, parms->p.current_sys); /* * Prepare the status struct - DVBv5.10 parameters should * come first, as they'll be read together. */ parms->stats.prop[0].cmd = DTV_STAT_SIGNAL_STRENGTH; parms->stats.prop[1].cmd = DTV_STAT_CNR; parms->stats.prop[2].cmd = DTV_STAT_PRE_ERROR_BIT_COUNT; parms->stats.prop[3].cmd = DTV_STAT_PRE_TOTAL_BIT_COUNT; parms->stats.prop[4].cmd = DTV_STAT_POST_ERROR_BIT_COUNT; parms->stats.prop[5].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT; parms->stats.prop[6].cmd = DTV_STAT_ERROR_BLOCK_COUNT; parms->stats.prop[7].cmd = DTV_STAT_TOTAL_BLOCK_COUNT; /* Now, status and the calculated stats */ parms->stats.prop[8].cmd = DTV_STATUS; parms->stats.prop[9].cmd = DTV_BER; parms->stats.prop[10].cmd = DTV_PER; parms->stats.prop[11].cmd = DTV_QUALITY; parms->stats.prop[12].cmd = DTV_PRE_BER; return &parms->p; }
static int run_scan(struct arguments *args, struct dvb_v5_fe_parms *parms) { struct dvb_file *dvb_file = NULL, *dvb_file_new = NULL; struct dvb_entry *entry; int i, rc, count = 0, dmx_fd, shift; uint32_t freq, sys; /* This is used only when reading old formats */ switch (parms->current_sys) { case SYS_DVBT: case SYS_DVBS: case SYS_DVBC_ANNEX_A: case SYS_ATSC: sys = parms->current_sys; break; case SYS_DVBC_ANNEX_C: sys = SYS_DVBC_ANNEX_A; break; case SYS_DVBC_ANNEX_B: sys = SYS_ATSC; break; case SYS_ISDBT: sys = SYS_DVBT; break; default: sys = SYS_UNDEFINED; break; } dvb_file = dvb_read_file_format(args->confname, sys, args->input_format); if (!dvb_file) return -2; dmx_fd = open(args->demux_dev, O_RDWR); if (dmx_fd < 0) { perror("openening pat demux failed"); return -3; } for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) { struct dvb_v5_descriptors *dvb_desc = NULL; /* First of all, set the delivery system */ for (i = 0; i < entry->n_props; i++) if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM) dvb_set_compat_delivery_system(parms, entry->props[i].u.data); /* Copy data into parms */ for (i = 0; i < entry->n_props; i++) { uint32_t data = entry->props[i].u.data; /* Don't change the delivery system */ if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM) continue; dvb_fe_store_parm(parms, entry->props[i].cmd, data); if (parms->current_sys == SYS_ISDBT) { dvb_fe_store_parm(parms, DTV_ISDBT_PARTIAL_RECEPTION, 0); dvb_fe_store_parm(parms, DTV_ISDBT_SOUND_BROADCASTING, 0); dvb_fe_store_parm(parms, DTV_ISDBT_LAYER_ENABLED, 0x07); if (entry->props[i].cmd == DTV_CODE_RATE_HP) { dvb_fe_store_parm(parms, DTV_ISDBT_LAYERA_FEC, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERB_FEC, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERC_FEC, data); } else if (entry->props[i].cmd == DTV_MODULATION) { dvb_fe_store_parm(parms, DTV_ISDBT_LAYERA_MODULATION, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERB_MODULATION, data); dvb_fe_store_parm(parms, DTV_ISDBT_LAYERC_MODULATION, data); } } if (parms->current_sys == SYS_ATSC && entry->props[i].cmd == DTV_MODULATION) { if (data != VSB_8 && data != VSB_16) dvb_fe_store_parm(parms, DTV_DELIVERY_SYSTEM, SYS_DVBC_ANNEX_B); } } /* * If the channel file has duplicated frequencies, or some * entries without any frequency at all, discard. */ freq = 0; for (i = 0; i < entry->n_props; i++) { if (entry->props[i].cmd == DTV_FREQUENCY) { freq = entry->props[i].u.data; break; } } if (!freq) continue; shift = estimate_freq_shift(parms); if (dvb_desc && !new_freq_is_needed(dvb_file->first_entry, entry, freq, dvb_desc->nit_table.pol, shift)) continue; rc = dvb_fe_set_parms(parms); if (rc < 0) { PERROR("dvb_fe_set_parms failed"); return -1; } /* As the DVB core emulates it, better to always use auto */ dvb_fe_store_parm(parms, DTV_INVERSION, INVERSION_AUTO); dvb_fe_retrieve_parm(parms, DTV_FREQUENCY, &freq); count++; dvb_log("Scanning frequency #%d %d", count, freq); if (verbose) dvb_fe_prt_parms(parms); rc = check_frontend(args, parms); if (rc < 0) continue; dvb_desc = dvb_get_ts_tables(parms, dmx_fd, parms->current_sys, args->other_nit, args->timeout_multiply, verbose); if (!dvb_desc) continue; for (i = 0; i < dvb_desc->sdt_table.service_table_len; i++) { struct service_table *service_table = &dvb_desc->sdt_table.service_table[i]; entry->vchannel = dvb_vchannel(dvb_desc, i); printf("Service #%d (%d)", i, service_table->service_id); if (service_table->service_name) printf(" %s", service_table->service_name); if (entry->vchannel) printf(" channel %s", entry->vchannel); printf("\n"); } store_dvb_channel(&dvb_file_new, parms, dvb_desc, args->get_detected, args->get_nit); if (!args->dont_add_new_freqs) add_other_freq_entries(dvb_file, parms, dvb_desc); dvb_free_ts_tables(dvb_desc); } if (dvb_file_new) write_file_format(args->output, dvb_file_new, parms->current_sys, args->output_format); dvb_file_free(dvb_file); if (dvb_file_new) dvb_file_free(dvb_file_new); close(dmx_fd); return 0; }
static int run_scan(struct arguments *args, struct dvb_v5_fe_parms *parms) { struct dvb_file *dvb_file = NULL, *dvb_file_new = NULL; struct dvb_entry *entry; int count = 0, dmx_fd, shift; uint32_t freq, sys; enum dvb_sat_polarization pol; /* This is used only when reading old formats */ switch (parms->current_sys) { case SYS_DVBT: case SYS_DVBS: case SYS_DVBC_ANNEX_A: case SYS_ATSC: sys = parms->current_sys; break; case SYS_DVBC_ANNEX_C: sys = SYS_DVBC_ANNEX_A; break; case SYS_DVBC_ANNEX_B: sys = SYS_ATSC; break; case SYS_ISDBT: case SYS_DTMB: sys = SYS_DVBT; break; default: sys = SYS_UNDEFINED; break; } dvb_file = dvb_read_file_format(args->confname, sys, args->input_format); if (!dvb_file) return -2; dmx_fd = open(args->demux_dev, O_RDWR); if (dmx_fd < 0) { perror(_("openening pat demux failed")); return -3; } for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) { struct dvb_v5_descriptors *dvb_scan_handler = NULL; uint32_t stream_id; /* * If the channel file has duplicated frequencies, or some * entries without any frequency at all, discard. */ if (dvb_retrieve_entry_prop(entry, DTV_FREQUENCY, &freq)) continue; shift = dvb_estimate_freq_shift(parms); if (dvb_retrieve_entry_prop(entry, DTV_POLARIZATION, &pol)) pol = POLARIZATION_OFF; if (dvb_retrieve_entry_prop(entry, DTV_STREAM_ID, &stream_id)) stream_id = NO_STREAM_ID_FILTER; if (!dvb_new_entry_is_needed(dvb_file->first_entry, entry, freq, shift, pol, stream_id)) continue; count++; dvb_log(_("Scanning frequency #%d %d"), count, freq); /* * update params->lnb only if it differs from entry->lnb * (and "--lnbf" option was not provided), * to avoid linear search of LNB types for every entries. */ if (!args->lnb_name && entry->lnb && (!parms->lnb || strcasecmp(entry->lnb, parms->lnb->alias))) parms->lnb = dvb_sat_get_lnb(dvb_sat_search_lnb(entry->lnb)); /* * Run the scanning logic */ dvb_scan_handler = dvb_scan_transponder(parms, entry, dmx_fd, &check_frontend, args, args->other_nit, args->timeout_multiply); if (parms->abort) { dvb_scan_free_handler_table(dvb_scan_handler); break; } if (!dvb_scan_handler) continue; /* * Store the service entry */ dvb_store_channel(&dvb_file_new, parms, dvb_scan_handler, args->get_detected, args->get_nit); /* * Add new transponders based on NIT table information */ if (!args->dont_add_new_freqs) dvb_add_scaned_transponders(parms, dvb_scan_handler, dvb_file->first_entry, entry); /* * Free the scan handler associated with the transponder */ dvb_scan_free_handler_table(dvb_scan_handler); } if (dvb_file_new) dvb_write_file_format(args->output, dvb_file_new, parms->current_sys, args->output_format); dvb_file_free(dvb_file); if (dvb_file_new) dvb_file_free(dvb_file_new); close(dmx_fd); return 0; }
static int run_scan(struct arguments *args, struct dvb_v5_fe_parms *parms) { struct dvb_file *dvb_file = NULL, *dvb_file_new = NULL; struct dvb_entry *entry; int count = 0, dmx_fd, shift; uint32_t freq, sys; enum dvb_sat_polarization pol; /* This is used only when reading old formats */ switch (parms->current_sys) { case SYS_DVBT: case SYS_DVBS: case SYS_DVBC_ANNEX_A: case SYS_ATSC: sys = parms->current_sys; break; case SYS_DVBC_ANNEX_C: sys = SYS_DVBC_ANNEX_A; break; case SYS_DVBC_ANNEX_B: sys = SYS_ATSC; break; case SYS_ISDBT: sys = SYS_DVBT; break; default: sys = SYS_UNDEFINED; break; } dvb_file = dvb_read_file_format(args->confname, sys, args->input_format); if (!dvb_file) return -2; dmx_fd = open(args->demux_dev, O_RDWR); if (dmx_fd < 0) { perror("openening pat demux failed"); return -3; } for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) { struct dvb_v5_descriptors *dvb_scan_handler = NULL; /* * If the channel file has duplicated frequencies, or some * entries without any frequency at all, discard. */ if (retrieve_entry_prop(entry, DTV_FREQUENCY, &freq)) continue; shift = estimate_freq_shift(parms); if (retrieve_entry_prop(entry, DTV_POLARIZATION, &pol)) pol = POLARIZATION_OFF; if (!new_freq_is_needed(dvb_file->first_entry, entry, freq, pol, shift)) continue; count++; dvb_log("Scanning frequency #%d %d", count, freq); /* * Run the scanning logic */ dvb_scan_handler = dvb_scan_transponder(parms, entry, dmx_fd, &check_frontend, args, args->other_nit, args->timeout_multiply); if (parms->abort) { dvb_scan_free_handler_table(dvb_scan_handler); break; } if (!dvb_scan_handler) continue; /* * Store the service entry */ store_dvb_channel(&dvb_file_new, parms, dvb_scan_handler, args->get_detected, args->get_nit); /* * Add new transponders based on NIT table information */ if (!args->dont_add_new_freqs) dvb_add_scaned_transponders(parms, dvb_scan_handler, dvb_file->first_entry, entry); /* * Free the scan handler associated with the transponder */ dvb_scan_free_handler_table(dvb_scan_handler); } if (dvb_file_new) write_file_format(args->output, dvb_file_new, parms->current_sys, args->output_format); dvb_file_free(dvb_file); if (dvb_file_new) dvb_file_free(dvb_file_new); close(dmx_fd); return 0; }
void dvb_desc_default_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { dvb_log("| %s (%d)", dvb_descriptors[desc->type].name, desc->type); hexdump(parms, "| ", desc->data, desc->length); }
void atsc_table_header_print(struct dvb_v5_fe_parms *parms, const struct atsc_table_header *t) { dvb_log("| table_id %02x", t->table_id); dvb_log("| section_length %d", t->section_length); dvb_log("| syntax %d", t->syntax); dvb_log("| priv %d", t->priv); dvb_log("| one %d", t->one); dvb_log("| id %d", t->id); dvb_log("| one2 %d", t->one2); dvb_log("| version %d", t->version); dvb_log("| current_next %d", t->current_next); dvb_log("| section_id %d", t->section_id); dvb_log("| last_section %d", t->last_section); dvb_log("| protocol_version %d", t->protocol_version); }
void dvb_desc_event_extended_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_event_extended *event = (const struct dvb_desc_event_extended *) desc; dvb_log("| Description '%s'", event->text); }
int dvb_set_compat_delivery_system(struct dvb_v5_fe_parms *p, uint32_t desired_system) { struct dvb_v5_fe_parms_priv *parms = (void *)p; int i; uint32_t delsys = SYS_UNDEFINED; enum dvbv3_emulation_type type; /* Check if the desired delivery system is supported */ for (i = 0; i < parms->p.num_systems; i++) { if (parms->p.systems[i] == desired_system) { dvb_set_sys(&parms->p, desired_system); return 0; } } /* * Find the closest DVBv3 system that matches the delivery * system. */ type = dvbv3_type(desired_system); /* * Get the last non-DVBv3 delivery system that has the same type * of the desired system */ for (i = 0; i < parms->p.num_systems; i++) { if ((dvbv3_type(parms->p.systems[i]) == type) && !is_dvbv3_delsys(parms->p.systems[i])) delsys = parms->p.systems[i]; } if (delsys == SYS_UNDEFINED) return EINVAL; dvb_log(_("Using a DVBv3 compat file for %s"), delivery_system_name[delsys]); dvb_set_sys(&parms->p, delsys); /* Put ISDB-T into auto mode */ if (delsys == SYS_ISDBT) { dvb_fe_store_parm(&parms->p, DTV_BANDWIDTH_HZ, 6000000); dvb_fe_store_parm(&parms->p, DTV_ISDBT_PARTIAL_RECEPTION, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_SOUND_BROADCASTING, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_SB_SUBCHANNEL_ID, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_SB_SEGMENT_IDX, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_SB_SEGMENT_COUNT, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYER_ENABLED, 7); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERA_FEC, FEC_AUTO); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERB_FEC, FEC_AUTO); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERC_FEC, FEC_AUTO); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERA_MODULATION, QAM_AUTO); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERB_MODULATION, QAM_AUTO); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERC_MODULATION, QAM_AUTO); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERA_SEGMENT_COUNT, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERB_SEGMENT_COUNT, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERC_SEGMENT_COUNT, 0); dvb_fe_store_parm(&parms->p, DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0); } return 0; }
void atsc_table_vct_print(struct dvb_v5_fe_parms *parms, struct atsc_table_vct *vct) { if (vct->header.table_id == ATSC_TABLE_CVCT) dvb_log("CVCT"); else dvb_log("TVCT"); atsc_table_header_print(parms, &vct->header); dvb_log("|- Protocol version %d", vct->ATSC_protocol_version); dvb_log("|- #channels %d", vct->num_channels_in_section); dvb_log("|\\ channel_id"); const struct atsc_table_vct_channel *channel = vct->channel; uint16_t channels = 0; while(channel) { dvb_log("|- Channel %d.%d: %s", channel->major_channel_number, channel->minor_channel_number, channel->short_name); dvb_log("| modulation mode %d", channel->modulation_mode); dvb_log("| carrier frequency %d", channel->carrier_frequency); dvb_log("| TS ID %d", channel->channel_tsid); dvb_log("| program number %d", channel->program_number); dvb_log("| ETM location %d", channel->ETM_location); dvb_log("| access controlled %d", channel->access_controlled); dvb_log("| hidden %d", channel->hidden); if (vct->header.table_id == ATSC_TABLE_CVCT) { dvb_log("| path select %d", channel->path_select); dvb_log("| out of band %d", channel->out_of_band); } dvb_log("| hide guide %d", channel->hide_guide); dvb_log("| service type %d", channel->service_type); dvb_log("| source id %d", channel->source_id); dvb_print_descriptors(parms, channel->descriptor); channel = channel->next; channels++; } dvb_log("|_ %d channels", channels); }
void dvb_desc_terrestrial_delivery_print(struct dvb_v5_fe_parms *parms, const struct dvb_desc *desc) { const struct dvb_desc_terrestrial_delivery *tdel = (const struct dvb_desc_terrestrial_delivery *) desc; dvb_log("| terrestrial delivery"); dvb_log("| length %d", tdel->length); dvb_log("| centre frequency %d", tdel->centre_frequency * 10); dvb_log("| mpe_fec_indicator %d", tdel->mpe_fec_indicator); dvb_log("| time_slice_indicator %d", tdel->time_slice_indicator); dvb_log("| priority %d", tdel->priority); dvb_log("| bandwidth %d", tdel->bandwidth); dvb_log("| code_rate_hp_stream %d", tdel->code_rate_hp_stream); dvb_log("| hierarchy_information %d", tdel->hierarchy_information); dvb_log("| constellation %d", tdel->constellation); dvb_log("| other_frequency_flag %d", tdel->other_frequency_flag); dvb_log("| transmission_mode %d", tdel->transmission_mode); dvb_log("| guard_interval %d", tdel->guard_interval); dvb_log("| code_rate_lp_stream %d", tdel->code_rate_lp_stream); }
int dvb_fe_get_parms(struct dvb_v5_fe_parms *p) { struct dvb_v5_fe_parms_priv *parms = (void *)p; int i, n = 0; const unsigned int *sys_props; struct dtv_properties prop; struct dvb_frontend_parameters v3_parms; uint32_t bw; sys_props = dvb_v5_delivery_system[parms->p.current_sys]; if (!sys_props) return EINVAL; while (sys_props[n]) { parms->dvb_prop[n].cmd = sys_props[n]; n++; } parms->dvb_prop[n].cmd = DTV_DELIVERY_SYSTEM; parms->dvb_prop[n].u.data = parms->p.current_sys; n++; /* Keep it ready for set */ parms->dvb_prop[n].cmd = DTV_TUNE; parms->n_props = n; struct dtv_property fe_prop[DTV_MAX_COMMAND]; n = dvb_copy_fe_props(parms->dvb_prop, n, fe_prop); prop.props = fe_prop; prop.num = n; if (!parms->p.legacy_fe) { if (xioctl(parms->fd, FE_GET_PROPERTY, &prop) == -1) { dvb_perror("FE_GET_PROPERTY"); return errno; } /* copy back params from temporary fe_prop */ for (i = 0; i < n; i++) { if (dvb_fe_is_satellite(p->current_sys) && fe_prop[i].cmd == DTV_FREQUENCY) fe_prop[i].u.data += parms->freq_offset; dvb_fe_store_parm(&parms->p, fe_prop[i].cmd, fe_prop[i].u.data); } if (parms->p.verbose) { dvb_log(_("Got parameters for %s:"), delivery_system_name[parms->p.current_sys]); dvb_fe_prt_parms(&parms->p); } return 0; } /* DVBv3 call */ if (xioctl(parms->fd, FE_GET_FRONTEND, &v3_parms) == -1) { dvb_perror("FE_GET_FRONTEND"); return EINVAL; } dvb_fe_store_parm(&parms->p, DTV_FREQUENCY, v3_parms.frequency); dvb_fe_store_parm(&parms->p, DTV_INVERSION, v3_parms.inversion); switch (parms->p.current_sys) { case SYS_DVBS: dvb_fe_store_parm(&parms->p, DTV_SYMBOL_RATE, v3_parms.u.qpsk.symbol_rate); dvb_fe_store_parm(&parms->p, DTV_INNER_FEC, v3_parms.u.qpsk.fec_inner); break; case SYS_DVBC_ANNEX_A: dvb_fe_store_parm(&parms->p, DTV_SYMBOL_RATE, v3_parms.u.qam.symbol_rate); dvb_fe_store_parm(&parms->p, DTV_INNER_FEC, v3_parms.u.qam.fec_inner); dvb_fe_store_parm(&parms->p, DTV_MODULATION, v3_parms.u.qam.modulation); break; case SYS_ATSC: case SYS_ATSCMH: case SYS_DVBC_ANNEX_B: dvb_fe_store_parm(&parms->p, DTV_MODULATION, v3_parms.u.vsb.modulation); break; case SYS_DVBT: if (v3_parms.u.ofdm.bandwidth < ARRAY_SIZE(fe_bandwidth_name) -1) bw = fe_bandwidth_name[v3_parms.u.ofdm.bandwidth]; else bw = 0; dvb_fe_store_parm(&parms->p, DTV_BANDWIDTH_HZ, bw); dvb_fe_store_parm(&parms->p, DTV_CODE_RATE_HP, v3_parms.u.ofdm.code_rate_HP); dvb_fe_store_parm(&parms->p, DTV_CODE_RATE_LP, v3_parms.u.ofdm.code_rate_LP); dvb_fe_store_parm(&parms->p, DTV_MODULATION, v3_parms.u.ofdm.constellation); dvb_fe_store_parm(&parms->p, DTV_TRANSMISSION_MODE, v3_parms.u.ofdm.transmission_mode); dvb_fe_store_parm(&parms->p, DTV_GUARD_INTERVAL, v3_parms.u.ofdm.guard_interval); dvb_fe_store_parm(&parms->p, DTV_HIERARCHY, v3_parms.u.ofdm.hierarchy_information); break; default: return EINVAL; } return 0; }
int dvb_fe_get_stats(struct dvb_v5_fe_parms *p) { struct dvb_v5_fe_parms_priv *parms = (void *)p; fe_status_t status = 0; uint32_t ber= 0, ucb = 0; uint16_t strength = 0, snr = 0; int i; enum fecap_scale_params scale; if (xioctl(parms->fd, FE_READ_STATUS, &status) == -1) { dvb_perror("FE_READ_STATUS"); return EINVAL; } dvb_fe_store_stats(parms, DTV_STATUS, FE_SCALE_RELATIVE, 0, status); /* if lock has obtained, get DVB parameters */ if (status != parms->stats.prev_status) { if ((status & FE_HAS_LOCK) && parms->stats.prev_status != status) dvb_fe_get_parms(&parms->p); parms->stats.prev_status = status; } if (parms->p.has_v5_stats) { struct dtv_properties props; props.num = DTV_NUM_KERNEL_STATS; props.props = parms->stats.prop; /* Do a DVBv5.10 stats call */ if (ioctl(parms->fd, FE_GET_PROPERTY, &props) == -1) { if (errno == EAGAIN) return 0; goto dvbv3_fallback; } /* * All props with len=0 mean that this device doesn't have any * dvbv5 stats. Try the legacy stats instead. */ for (i = 0; i < props.num; i++) if (parms->stats.prop[i].u.st.len) break; if (i == props.num) goto dvbv3_fallback; dvb_fe_update_counters(parms); return 0; } dvbv3_fallback: /* DVB v3 stats */ parms->p.has_v5_stats = 0; if (ioctl(parms->fd, FE_READ_BER, &ber) == -1) scale = FE_SCALE_NOT_AVAILABLE; else scale = FE_SCALE_RELATIVE; /* * BER scale on DVBv3 is not defined - different drivers use * different scales, even weird ones, like multiples of 1/65280 */ dvb_fe_store_stats(parms, DTV_BER, scale, 0, ber); if (ioctl(parms->fd, FE_READ_SIGNAL_STRENGTH, &strength) == -1) scale = FE_SCALE_NOT_AVAILABLE; else scale = FE_SCALE_RELATIVE; dvb_fe_store_stats(parms, DTV_STAT_SIGNAL_STRENGTH, scale, 0, strength); if (ioctl(parms->fd, FE_READ_SNR, &snr) == -1) scale = FE_SCALE_NOT_AVAILABLE; else scale = FE_SCALE_RELATIVE; dvb_fe_store_stats(parms, DTV_STAT_CNR, scale, 0, snr); if (ioctl(parms->fd, FE_READ_UNCORRECTED_BLOCKS, &ucb) == -1) scale = FE_SCALE_NOT_AVAILABLE; else scale = FE_SCALE_COUNTER; dvb_fe_store_stats(parms, DTV_STAT_ERROR_BLOCK_COUNT, scale, 0, snr); if (parms->p.verbose > 1) { dvb_log(_("Status: ")); for (i = 0; i < ARRAY_SIZE(fe_status_name); i++) { if (status & fe_status_name[i].idx) dvb_log (" %s", fe_status_name[i].name); } dvb_log(_("BER: %d, Strength: %d, SNR: %d, UCB: %d"), ber, strength, snr, ucb); } return 0; }