Exemple #1
0
void DVBChannel::CheckOptions(DTVMultiplex &tuning) const
{
    if ((tuning.inversion == DTVInversion::kInversionAuto) &&
        !(capabilities & FE_CAN_INVERSION_AUTO))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "'Auto' inversion parameter unsupported by this driver, "
            "falling back to 'off'.");
        tuning.inversion = DTVInversion::kInversionOff;
    }

    // DVB-S needs a fully initialized diseqc tree and is checked later in Tune
    if (!diseqc_tree)
        CheckFrequency(tuning.frequency);

    if (tunerType.IsFECVariable() &&
        symbol_rate_minimum && symbol_rate_maximum &&
        (symbol_rate_minimum <= symbol_rate_maximum) &&
        (tuning.symbolrate < symbol_rate_minimum ||
         tuning.symbolrate > symbol_rate_maximum))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            QString("Symbol Rate setting (%1) is out of range (min/max:%2/%3)")
                .arg(tuning.symbolrate)
                .arg(symbol_rate_minimum).arg(symbol_rate_maximum));
    }

    if (tunerType.IsFECVariable() && !CheckCodeRate(tuning.fec))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "Selected fec_inner parameter unsupported by this driver.");
    }

    if (tunerType.IsModulationVariable() && !CheckModulation(tuning.modulation))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
           "Selected modulation parameter unsupported by this driver.");
    }

    if (DTVTunerType::kTunerTypeDVBT != tunerType)
    {
        LOG(VB_CHANNEL, LOG_INFO, LOC + tuning.toString());
        return;
    }

    // Check OFDM Tuning params

    if (!CheckCodeRate(tuning.hp_code_rate))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "Selected code_rate_hp parameter unsupported by this driver.");
    }

    if (!CheckCodeRate(tuning.lp_code_rate))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "Selected code_rate_lp parameter unsupported by this driver.");
    }

    if ((tuning.bandwidth == DTVBandwidth::kBandwidthAuto) &&
        !(capabilities & FE_CAN_BANDWIDTH_AUTO))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "'Auto' bandwidth parameter unsupported by this driver.");
    }

    if ((tuning.trans_mode == DTVTransmitMode::kTransmissionModeAuto) &&
        !(capabilities & FE_CAN_TRANSMISSION_MODE_AUTO))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "'Auto' transmission_mode parameter unsupported by this driver.");
    }

    if ((tuning.guard_interval == DTVGuardInterval::kGuardIntervalAuto) &&
        !(capabilities & FE_CAN_GUARD_INTERVAL_AUTO))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "'Auto' guard_interval parameter unsupported by this driver.");
    }

    if ((tuning.hierarchy == DTVHierarchy::kHierarchyAuto) &&
        !(capabilities & FE_CAN_HIERARCHY_AUTO))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "'Auto' hierarchy parameter unsupported by this driver. ");
    }

    if (!CheckModulation(tuning.modulation))
    {
        LOG(VB_GENERAL, LOG_WARNING, LOC +
            "Selected modulation parameter unsupported by this driver.");
    }

    LOG(VB_CHANNEL, LOG_INFO, LOC + tuning.toString());
}
Exemple #2
0
/**
 *  \brief Tunes the card to a frequency but does not deal with PIDs.
 *
 *   This is used by DVB Channel Scanner, the EIT Parser, and by TVRec.
 *
 *  \param tuning      Info on transport to tune to
 *  \param inputid     Optional, forces specific input (for DiSEqC)
 *  \param force_reset If true, frequency tuning is done
 *                     even if it should not be needed.
 *  \param same_input  Optional, doesn't change input (for retuning).
 *  \return true on success, false on failure
 */
bool DVBChannel::Tune(const DTVMultiplex &tuning,
                      uint inputid,
                      bool force_reset,
                      bool same_input)
{
    QMutexLocker lock(&tune_lock);
    QMutexLocker locker(&hw_lock);

    DVBChannel *master = GetMasterLock();
    if (master != this)
    {
        LOG(VB_CHANNEL, LOG_INFO, LOC + "tuning on slave channel");
        SetSIStandard(tuning.sistandard);
        bool ok = master->Tune(tuning, inputid, force_reset, false);
        ReturnMasterLock(master);
        return ok;
    }
    ReturnMasterLock(master); // if we're the master we don't need this lock..


    int intermediate_freq = 0;
    bool can_fec_auto = false;
    bool reset = (force_reset || first_tune);

    if (tunerType.IsDiSEqCSupported() && !diseqc_tree)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC +
            "DVB-S needs device tree for LNB handling");
        return false;
    }

    desired_tuning = tuning;

    if (fd_frontend < 0)
    {
        LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Card not open!");

        return false;
    }

    // Remove any events in queue before tuning.
    drain_dvb_events(fd_frontend);

    // send DVB-S setup
    if (diseqc_tree)
    {
        // configure for new input
        if (!same_input)
            diseqc_settings.Load(inputid);

        // execute diseqc commands
        if (!diseqc_tree->Execute(diseqc_settings, tuning))
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Tune(): Failed to setup DiSEqC devices");
            return false;
        }

        // retrieve actual intermediate frequency
        DiSEqCDevLNB *lnb = diseqc_tree->FindLNB(diseqc_settings);
        if (!lnb)
        {
            LOG(VB_GENERAL, LOG_ERR, LOC +
                "Tune(): No LNB for this configuration");
            return false;
        }

        if (lnb->GetDeviceID() != last_lnb_dev_id)
        {
            last_lnb_dev_id = lnb->GetDeviceID();
            // make sure we tune to frequency, if the lnb has changed
            reset = first_tune = true;
        }

        intermediate_freq = lnb->GetIntermediateFrequency(
            diseqc_settings, tuning);

        // if card can auto-FEC, use it -- sometimes NITs are inaccurate
        if (capabilities & FE_CAN_FEC_AUTO)
            can_fec_auto = true;

        // Check DVB-S intermediate frequency here since it requires a fully
        // initialized diseqc tree
        CheckFrequency(intermediate_freq);
    }

    LOG(VB_CHANNEL, LOG_INFO, LOC + "Old Params: " + prev_tuning.toString() +
            "\n\t\t\t" + LOC + "New Params: " + tuning.toString());

    // DVB-S is in kHz, other DVB is in Hz
    bool is_dvbs = ((DTVTunerType::kTunerTypeDVBS1 == tunerType) ||
                    (DTVTunerType::kTunerTypeDVBS2 == tunerType));
    int     freq_mult = (is_dvbs) ? 1 : 1000;
    QString suffix    = (is_dvbs) ? "kHz" : "Hz";

    if (reset || !prev_tuning.IsEqual(tunerType, tuning, 500 * freq_mult))
    {
        LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2")
                .arg(intermediate_freq ? intermediate_freq : tuning.frequency)
                .arg(suffix));

#if DVB_API_VERSION >=5
        if (DTVTunerType::kTunerTypeDVBS2 == tunerType)
        {
            struct dtv_property p_clear;
            struct dtv_properties cmdseq_clear;

            p_clear.cmd        = DTV_CLEAR;
            cmdseq_clear.num   = 1;
            cmdseq_clear.props = &p_clear;

            if ((ioctl(fd_frontend, FE_SET_PROPERTY, &cmdseq_clear)) < 0)
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "Tune(): Clearing DTV properties cache failed." + ENO);
                return false;
            }

            struct dtv_properties *cmds = dtvmultiplex_to_dtvproperties(
                tunerType, tuning, intermediate_freq, can_fec_auto);

            if (!cmds) {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "Failed to convert DTVMultiplex to DTV_PROPERTY sequence");
                return false;
            }

            if (VERBOSE_LEVEL_CHECK(VB_CHANNEL, LOG_DEBUG))
            {
                for (uint i = 0; i < cmds->num; i++)
                {
                    LOG(VB_CHANNEL, LOG_DEBUG, LOC +
                        QString("prop %1: cmd = %2, data %3")
                            .arg(i).arg(cmds->props[i].cmd)
                            .arg(cmds->props[i].u.data));
                }
            }

            int res = ioctl(fd_frontend, FE_SET_PROPERTY, cmds);

            free(cmds->props);
            free(cmds);

            if (res < 0)
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "Tune(): Setting Frontend tuning parameters failed." + ENO);
                return false;
            }
        }
        else
#endif
        {
            struct dvb_frontend_parameters params = dtvmultiplex_to_dvbparams(
                tunerType, tuning, intermediate_freq, can_fec_auto);

            if (ioctl(fd_frontend, FE_SET_FRONTEND, &params) < 0)
            {
                LOG(VB_GENERAL, LOG_ERR, LOC +
                    "Tune(): Setting Frontend tuning parameters failed." + ENO);
                return false;
            }
        }

        // Extra delay to add for broken DVB drivers
        if (tuning_delay)
            usleep(tuning_delay * 1000);

        wait_for_backend(fd_frontend, 5 /* msec */);

        prev_tuning = tuning;
        first_tune = false;
    }

    SetSIStandard(tuning.sistandard);

    LOG(VB_CHANNEL, LOG_INFO, LOC + "Tune(): Frequency tuning successful.");

    return true;
}