[PATCH] media: vidtv: validate the frequency module parameters

From: Alberto Pimpo

Date: Sun Aug 30 2026 - 13:15:43 EST


The lists of frequencies the simulated tuner locks onto are module
parameters, and were handed over to the tuner module without being
checked first.

A terrestrial or cable frequency outside the range the demodulator
reports to the DVB core is unreachable, as dvb_frontend_check_parameters()
rejects such a tuning request before the tuner is ever asked about the
frequency. A satellite frequency outside the Ku-band covered by the
simulated LNBf is equally meaningless, since it is downconverted using
the LNBf local oscillators before reaching the tuner.

In both cases vidtv used to initialize successfully and then never lock
on anything, leaving no clue about the cause.

Check the terrestrial and cable frequencies against the range advertised
by the demodulator, and the satellite ones against the Ku-band covered by
the simulated LNBf, failing the probe with an explicit error message
otherwise.

Signed-off-by: Alberto Pimpo <me@xxxxxxxxxxxxxxxx>
---
.../media/test-drivers/vidtv/vidtv_bridge.c | 71 ++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c
index fd69b4ee16f4..37e9b1e8e793 100644
--- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c
@@ -44,6 +44,10 @@
#define LNB_LOW_FREQ 9750000 /* low IF frequency */
#define LNB_HIGH_FREQ 10600000 /* transition frequency */

+/* The Ku-band range covered by such an LNBf, in kHz */
+#define LNB_KU_BAND_MIN_FREQ 10700000
+#define LNB_KU_BAND_MAX_FREQ 12750000
+
static unsigned int drop_tslock_prob_on_low_snr;
module_param(drop_tslock_prob_on_low_snr, uint, 0444);
MODULE_PARM_DESC(drop_tslock_prob_on_low_snr,
@@ -367,6 +371,36 @@ static int vidtv_bridge_probe_demod(struct vidtv_dvb *dvb, u32 n)
return 0;
}

+/*
+ * Reject frequencies the simulation could never tune into, as the module
+ * would otherwise load just fine and then never lock on anything, leaving
+ * no clue about what went wrong.
+ */
+static int vidtv_bridge_check_freqs(struct vidtv_dvb *dvb,
+ const unsigned int *freqs,
+ u32 array_sz,
+ u32 min_freq,
+ u32 max_freq,
+ const char *name)
+{
+ u32 i;
+
+ for (i = 0; i < array_sz; i++) {
+ /* a zeroed entry means an unused slot */
+ if (!freqs[i])
+ continue;
+
+ if (freqs[i] < min_freq || freqs[i] > max_freq) {
+ dev_err(&dvb->pdev->dev,
+ "%s[%u]: %u is out of range (%u..%u)\n",
+ name, i, freqs[i], min_freq, max_freq);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int vidtv_bridge_probe_tuner(struct vidtv_dvb *dvb, u32 n)
{
struct vidtv_tuner_config cfg = {
@@ -374,10 +408,45 @@ static int vidtv_bridge_probe_tuner(struct vidtv_dvb *dvb, u32 n)
.mock_power_up_delay_msec = mock_power_up_delay_msec,
.mock_tune_delay_msec = mock_tune_delay_msec,
};
+ u32 min_freq = dvb->fe[n]->ops.info.frequency_min_hz;
+ u32 max_freq = dvb->fe[n]->ops.info.frequency_max_hz;
u32 freq;
+ int ret;
int i;

- /* TODO: check if the frequencies are at a valid range */
+ /*
+ * Terrestrial and cable frequencies are given in Hz and are used as
+ * is, so they have to fit within the range the demod reports to the
+ * DVB core: the core rejects a tuning request outside of it before
+ * the tuner is ever asked about the frequency.
+ */
+ ret = vidtv_bridge_check_freqs(dvb, vidtv_valid_dvb_t_freqs,
+ ARRAY_SIZE(vidtv_valid_dvb_t_freqs),
+ min_freq, max_freq,
+ "vidtv_valid_dvb_t_freqs");
+ if (ret)
+ return ret;
+
+ ret = vidtv_bridge_check_freqs(dvb, vidtv_valid_dvb_c_freqs,
+ ARRAY_SIZE(vidtv_valid_dvb_c_freqs),
+ min_freq, max_freq,
+ "vidtv_valid_dvb_c_freqs");
+ if (ret)
+ return ret;
+
+ /*
+ * Satellite frequencies are given in kHz at Ku-band and are
+ * downconverted below, so check them against the band the simulated
+ * LNBf covers instead. Doing so also ensures that the frequencies
+ * are above the LNBf local oscillators.
+ */
+ ret = vidtv_bridge_check_freqs(dvb, vidtv_valid_dvb_s_freqs,
+ ARRAY_SIZE(vidtv_valid_dvb_s_freqs),
+ LNB_KU_BAND_MIN_FREQ,
+ LNB_KU_BAND_MAX_FREQ,
+ "vidtv_valid_dvb_s_freqs");
+ if (ret)
+ return ret;

memcpy(cfg.vidtv_valid_dvb_t_freqs,
vidtv_valid_dvb_t_freqs,
--
2.53.0