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; }
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_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); }
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_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; }
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; }
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_init(struct dvb_v5_fe_parms *parms, const uint8_t *buf, struct dvb_desc *desc) { struct isdb_desc_partial_reception *d = (void *)desc; unsigned char *p = (unsigned char *)buf; size_t len; int i; d->partial_reception = malloc(d->length); if (!d->partial_reception) { dvb_perror("Out of memory!"); return; } memcpy(d->partial_reception, p, d->length); len = d->length / sizeof(d->partial_reception); for (i = 0; i < len; i++) bswap16(d->partial_reception[i].service_id); }
int dvb_set_sys(struct dvb_v5_fe_parms *p, fe_delivery_system_t sys) { struct dvb_v5_fe_parms_priv *parms = (void *)p; struct dtv_property dvb_prop[1]; struct dtv_properties prop; int rc; if (sys != parms->p.current_sys) { /* Disable LNBf power */ if (dvb_fe_is_satellite(parms->p.current_sys) && !dvb_fe_is_satellite(sys)) dvb_fe_sec_voltage(&parms->p, 0, 0); /* Can't change standard with the legacy FE support */ if (parms->p.legacy_fe) return EINVAL; dvb_prop[0].cmd = DTV_DELIVERY_SYSTEM; dvb_prop[0].u.data = sys; prop.num = 1; prop.props = dvb_prop; if (xioctl(parms->fd, FE_SET_PROPERTY, &prop) == -1) { dvb_perror(_("Set delivery system")); return errno; } } rc = dvb_add_parms_for_sys(&parms->p, sys); if (rc < 0) return EINVAL; parms->p.current_sys = sys; parms->n_props = rc; return 0; }
int dvb_fe_set_parms(struct dvb_v5_fe_parms *p) { struct dvb_v5_fe_parms_priv *parms = (void *)p; /* Use a temporary copy of the parameters so we can safely perform * adjustments for satellite */ struct dvb_v5_fe_parms_priv tmp_parms = *parms; struct dtv_properties prop; struct dvb_frontend_parameters v3_parms; uint32_t bw; if (parms->p.lna != LNA_AUTO && !parms->p.legacy_fe) { struct dvb_v5_fe_parms_priv tmp_lna_parms; memset(&prop, 0, sizeof(prop)); prop.props = tmp_lna_parms.dvb_prop; prop.props[0].cmd = DTV_LNA; prop.props[0].u.data = parms->p.lna; prop.num = 1; if (xioctl(parms->fd, FE_SET_PROPERTY, &prop) == -1) { dvb_perror(_("Setting LNA")); parms->p.lna = LNA_AUTO; } else if (parms->p.lna != LNA_AUTO && parms->p.verbose) dvb_logdbg(_("LNA is %s"), parms->p.lna ? _("ON") : _("OFF")); } if (dvb_fe_is_satellite(tmp_parms.p.current_sys)) { dvb_sat_set_parms(&tmp_parms.p); /* * even though the frequncy prop is kept un-modified here, * a later call to dvb_fe_get_parms() issues FE_GET_PROPERTY * ioctl and overwrites it with the offset-ed value from * the FE. So we need to save the offset here and * re-add it in dvb_fe_get_parms(). * note that dvbv5-{scan,zap} utilities call dvb_fe_get_parms() * indirectly from check_frontend() via dvb_fe_get_stats(). */ parms->freq_offset = tmp_parms.freq_offset; } dvb_setup_delsys_default(p); /* Filter out any user DTV_foo property such as DTV_POLARIZATION */ tmp_parms.n_props = dvb_copy_fe_props(tmp_parms.dvb_prop, tmp_parms.n_props, tmp_parms.dvb_prop); memset(&prop, 0, sizeof(prop)); prop.props = tmp_parms.dvb_prop; prop.num = tmp_parms.n_props; prop.props[prop.num].cmd = DTV_TUNE; prop.num++; if (!parms->p.legacy_fe) { if (xioctl(parms->fd, FE_SET_PROPERTY, &prop) == -1) { dvb_perror("FE_SET_PROPERTY"); if (parms->p.verbose) dvb_fe_prt_parms(&parms->p); return -1; } return 0; } /* DVBv3 call */ dvb_fe_retrieve_parm(&tmp_parms.p, DTV_FREQUENCY, &v3_parms.frequency); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_INVERSION, &v3_parms.inversion); switch (tmp_parms.p.current_sys) { case SYS_DVBS: dvb_fe_retrieve_parm(&tmp_parms.p, DTV_SYMBOL_RATE, &v3_parms.u.qpsk.symbol_rate); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_INNER_FEC, &v3_parms.u.qpsk.fec_inner); break; case SYS_DVBC_ANNEX_AC: dvb_fe_retrieve_parm(&tmp_parms.p, DTV_SYMBOL_RATE, &v3_parms.u.qam.symbol_rate); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_INNER_FEC, &v3_parms.u.qam.fec_inner); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_MODULATION, &v3_parms.u.qam.modulation); break; case SYS_ATSC: case SYS_ATSCMH: case SYS_DVBC_ANNEX_B: dvb_fe_retrieve_parm(&tmp_parms.p, DTV_MODULATION, &v3_parms.u.vsb.modulation); break; case SYS_DVBT: for (bw = 0; fe_bandwidth_name[bw] != 0; bw++) { if (fe_bandwidth_name[bw] == v3_parms.u.ofdm.bandwidth) break; } dvb_fe_retrieve_parm(&tmp_parms.p, DTV_BANDWIDTH_HZ, &bw); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_CODE_RATE_HP, &v3_parms.u.ofdm.code_rate_HP); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_CODE_RATE_LP, &v3_parms.u.ofdm.code_rate_LP); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_MODULATION, &v3_parms.u.ofdm.constellation); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_TRANSMISSION_MODE, &v3_parms.u.ofdm.transmission_mode); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_GUARD_INTERVAL, &v3_parms.u.ofdm.guard_interval); dvb_fe_retrieve_parm(&tmp_parms.p, DTV_HIERARCHY, &v3_parms.u.ofdm.hierarchy_information); break; default: return -1; } if (xioctl(tmp_parms.fd, FE_SET_FRONTEND, &v3_parms) == -1) { dvb_perror("FE_SET_FRONTEND"); if (tmp_parms.p.verbose) dvb_fe_prt_parms(&tmp_parms.p); return -1; } return 0; }
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; }
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; }