linux/drivers/media/dvb-core/dvb_frontend.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * dvb_frontend.c: DVB frontend tuning interface/thread
 *
 * Copyright (C) 1999-2001 Ralph  Metzler
 *			   Marcus Metzler
 *			   Holger Waechtler
 *				      for convergence integrated media GmbH
 *
 * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
 */

/* Enables DVBv3 compatibility bits at the headers */
#define __DVB_CORE__

#define pr_fmt(fmt)

#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/semaphore.h>
#include <linux/module.h>
#include <linux/nospec.h>
#include <linux/list.h>
#include <linux/freezer.h>
#include <linux/jiffies.h>
#include <linux/kthread.h>
#include <linux/ktime.h>
#include <linux/compat.h>
#include <asm/processor.h>

#include <media/dvb_frontend.h>
#include <media/dvbdev.h>
#include <linux/dvb/version.h>

static int dvb_frontend_debug;
static int dvb_shutdown_timeout;
static int dvb_force_auto_inversion;
static int dvb_override_tune_delay;
static int dvb_powerdown_on_sleep =;
static int dvb_mfe_wait_time =;

module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
MODULE_PARM_DESC();
module_param(dvb_shutdown_timeout, int, 0644);
MODULE_PARM_DESC();
module_param(dvb_force_auto_inversion, int, 0644);
MODULE_PARM_DESC();
module_param(dvb_override_tune_delay, int, 0644);
MODULE_PARM_DESC();
module_param(dvb_powerdown_on_sleep, int, 0644);
MODULE_PARM_DESC();
module_param(dvb_mfe_wait_time, int, 0644);
MODULE_PARM_DESC();

#define dprintk(fmt, arg...)

#define FESTATE_IDLE
#define FESTATE_RETUNE
#define FESTATE_TUNING_FAST
#define FESTATE_TUNING_SLOW
#define FESTATE_TUNED
#define FESTATE_ZIGZAG_FAST
#define FESTATE_ZIGZAG_SLOW
#define FESTATE_DISEQC
#define FESTATE_ERROR
#define FESTATE_WAITFORLOCK
#define FESTATE_SEARCHING_FAST
#define FESTATE_SEARCHING_SLOW
#define FESTATE_LOSTLOCK

/*
 * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
 * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
 * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress.
 * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower.
 * FESTATE_TUNED. The frontend has successfully locked on.
 * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
 * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
 * FESTATE_DISEQC. A DISEQC command has just been issued.
 * FESTATE_WAITFORLOCK. When we're waiting for a lock.
 * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
 * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
 * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
 */

static DEFINE_MUTEX(frontend_mutex);

struct dvb_frontend_private {};

static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
					void (*release)(struct dvb_frontend *fe));

static void __dvb_frontend_free(struct dvb_frontend *fe)
{}

static void dvb_frontend_free(struct kref *ref)
{}

static void dvb_frontend_put(struct dvb_frontend *fe)
{}

static void dvb_frontend_get(struct dvb_frontend *fe)
{}

static void dvb_frontend_wakeup(struct dvb_frontend *fe);
static int dtv_get_frontend(struct dvb_frontend *fe,
			    struct dtv_frontend_properties *c,
			    struct dvb_frontend_parameters *p_out);
static int
dtv_property_legacy_params_sync(struct dvb_frontend *fe,
				const struct dtv_frontend_properties *c,
				struct dvb_frontend_parameters *p);

static bool has_get_frontend(struct dvb_frontend *fe)
{}

/*
 * Due to DVBv3 API calls, a delivery system should be mapped into one of
 * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
 * otherwise, a DVBv3 call will fail.
 */
enum dvbv3_emulation_type {};

static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
{}

static void dvb_frontend_add_event(struct dvb_frontend *fe,
				   enum fe_status status)
{}

static int dvb_frontend_test_event(struct dvb_frontend_private *fepriv,
				   struct dvb_fe_events *events)
{}

static int dvb_frontend_get_event(struct dvb_frontend *fe,
				  struct dvb_frontend_event *event, int flags)
{}

static void dvb_frontend_clear_events(struct dvb_frontend *fe)
{}

static void dvb_frontend_init(struct dvb_frontend *fe)
{}

void dvb_frontend_reinitialise(struct dvb_frontend *fe)
{}
EXPORT_SYMBOL();

static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
{}

/**
 * dvb_frontend_swzigzag_autotune - Performs automatic twiddling of frontend
 *	parameters.
 *
 * @fe: The frontend concerned.
 * @check_wrapped: Checks if an iteration has completed.
 *		   DO NOT SET ON THE FIRST ATTEMPT.
 *
 * return: Number of complete iterations that have been performed.
 */
static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
{}

static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
{}

static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{}

static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
{}

static void dvb_frontend_wakeup(struct dvb_frontend *fe)
{}

static int dvb_frontend_thread(void *data)
{}

static void dvb_frontend_stop(struct dvb_frontend *fe)
{}

/*
 * Sleep for the amount of time given by add_usec parameter
 *
 * This needs to be as precise as possible, as it affects the detection of
 * the dish tone command at the satellite subsystem. The precision is improved
 * by using a scheduled msleep followed by udelay for the remainder.
 */
void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec)
{}
EXPORT_SYMBOL();

static int dvb_frontend_start(struct dvb_frontend *fe)
{}

static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
					      u32 *freq_min, u32 *freq_max,
					      u32 *tolerance)
{}

static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe)
{}

static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
{}

static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
{}

#define _DTV_CMD(n)

static char *dtv_cmds[DTV_MAX_COMMAND + 1] =;

static char *dtv_cmd_name(u32 cmd)
{}

/* Synchronise the legacy tuning parameters into the cache, so that demodulator
 * drivers can use a single set_frontend tuning function, regardless of whether
 * it's being used for the legacy or new API, reducing code and complexity.
 */
static int dtv_property_cache_sync(struct dvb_frontend *fe,
				   struct dtv_frontend_properties *c,
				   const struct dvb_frontend_parameters *p)
{}

/* Ensure the cached values are set correctly in the frontend
 * legacy tuning structures, for the advanced tuning API.
 */
static int
dtv_property_legacy_params_sync(struct dvb_frontend *fe,
				const struct dtv_frontend_properties *c,
				struct dvb_frontend_parameters *p)
{}

/**
 * dtv_get_frontend - calls a callback for retrieving DTV parameters
 * @fe:		struct dvb_frontend pointer
 * @c:		struct dtv_frontend_properties pointer (DVBv5 cache)
 * @p_out:	struct dvb_frontend_parameters pointer (DVBv3 FE struct)
 *
 * This routine calls either the DVBv3 or DVBv5 get_frontend call.
 * If c is not null, it will update the DVBv5 cache struct pointed by it.
 * If p_out is not null, it will update the DVBv3 params pointed by it.
 */
static int dtv_get_frontend(struct dvb_frontend *fe,
			    struct dtv_frontend_properties *c,
			    struct dvb_frontend_parameters *p_out)
{}

static int dvb_frontend_handle_ioctl(struct file *file,
				     unsigned int cmd, void *parg);

static int dtv_property_process_get(struct dvb_frontend *fe,
				    const struct dtv_frontend_properties *c,
				    struct dtv_property *tvp,
				    struct file *file)
{}

static int dtv_set_frontend(struct dvb_frontend *fe);

static bool is_dvbv3_delsys(u32 delsys)
{}

/**
 * emulate_delivery_system - emulate a DVBv5 delivery system with a DVBv3 type
 * @fe:			struct frontend;
 * @delsys:			DVBv5 type that will be used for emulation
 *
 * Provides emulation for delivery systems that are compatible with the old
 * DVBv3 call. Among its usages, it provices support for ISDB-T, and allows
 * using a DVB-S2 only frontend just like it were a DVB-S, if the frontend
 * parameters are compatible with DVB-S spec.
 */
static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys)
{}

/**
 * dvbv5_set_delivery_system - Sets the delivery system for a DVBv5 API call
 * @fe:			frontend struct
 * @desired_system:	delivery system requested by the user
 *
 * A DVBv5 call know what's the desired system it wants. So, set it.
 *
 * There are, however, a few known issues with early DVBv5 applications that
 * are also handled by this logic:
 *
 * 1) Some early apps use SYS_UNDEFINED as the desired delivery system.
 *    This is an API violation, but, as we don't want to break userspace,
 *    convert it to the first supported delivery system.
 * 2) Some apps might be using a DVBv5 call in a wrong way, passing, for
 *    example, SYS_DVBT instead of SYS_ISDBT. This is because early usage of
 *    ISDB-T provided backward compat with DVB-T.
 */
static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
				     u32 desired_system)
{}

/**
 * dvbv3_set_delivery_system - Sets the delivery system for a DVBv3 API call
 * @fe:	frontend struct
 *
 * A DVBv3 call doesn't know what's the desired system it wants. It also
 * doesn't allow to switch between different types. Due to that, userspace
 * should use DVBv5 instead.
 * However, in order to avoid breaking userspace API, limited backward
 * compatibility support is provided.
 *
 * There are some delivery systems that are incompatible with DVBv3 calls.
 *
 * This routine should work fine for frontends that support just one delivery
 * system.
 *
 * For frontends that support multiple frontends:
 * 1) It defaults to use the first supported delivery system. There's an
 *    userspace application that allows changing it at runtime;
 *
 * 2) If the current delivery system is not compatible with DVBv3, it gets
 *    the first one that it is compatible.
 *
 * NOTE: in order for this to work with applications like Kaffeine that
 *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
 *	DVB-S, drivers that support both DVB-S and DVB-S2 should have the
 *	SYS_DVBS entry before the SYS_DVBS2, otherwise it won't switch back
 *	to DVB-S.
 */
static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
{}

static void prepare_tuning_algo_parameters(struct dvb_frontend *fe)
{}

/**
 * dtv_property_process_set -  Sets a single DTV property
 * @fe:		Pointer to &struct dvb_frontend
 * @file:	Pointer to &struct file
 * @cmd:	Digital TV command
 * @data:	An unsigned 32-bits number
 *
 * This routine assigns the property
 * value to the corresponding member of
 * &struct dtv_frontend_properties
 *
 * Returns:
 * Zero on success, negative errno on failure.
 */
static int dtv_property_process_set(struct dvb_frontend *fe,
				    struct file *file,
				    u32 cmd, u32 data)
{}

static int dvb_frontend_do_ioctl(struct file *file, unsigned int cmd,
				 void *parg)
{}

static long dvb_frontend_ioctl(struct file *file, unsigned int cmd,
			       unsigned long arg)
{}

#ifdef CONFIG_COMPAT
struct compat_dtv_property {} __attribute__ ((packed));

struct compat_dtv_properties {};

#define COMPAT_FE_SET_PROPERTY
#define COMPAT_FE_GET_PROPERTY

static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,
					    unsigned long arg)
{}

static long dvb_frontend_compat_ioctl(struct file *file, unsigned int cmd,
				      unsigned long arg)
{}
#endif

static int dtv_set_frontend(struct dvb_frontend *fe)
{}

static int dvb_get_property(struct dvb_frontend *fe, struct file *file,
			    struct dtv_properties *tvps)
{}

static int dvb_get_frontend(struct dvb_frontend *fe,
			    struct dvb_frontend_parameters *p_out)
{}

static int dvb_frontend_handle_ioctl(struct file *file,
				     unsigned int cmd, void *parg)
{}

static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{}

static int dvb_frontend_open(struct inode *inode, struct file *file)
{}

static int dvb_frontend_release(struct inode *inode, struct file *file)
{}

static const struct file_operations dvb_frontend_fops =;

int dvb_frontend_suspend(struct dvb_frontend *fe)
{}
EXPORT_SYMBOL();

int dvb_frontend_resume(struct dvb_frontend *fe)
{}
EXPORT_SYMBOL();

int dvb_register_frontend(struct dvb_adapter *dvb,
			  struct dvb_frontend *fe)
{}
EXPORT_SYMBOL();

int dvb_unregister_frontend(struct dvb_frontend *fe)
{}
EXPORT_SYMBOL();

static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
					void (*release)(struct dvb_frontend *fe))
{}

void dvb_frontend_detach(struct dvb_frontend *fe)
{}
EXPORT_SYMBOL();