[PATCH/RFC] add dvb-s2 support to frontend.h and dvb_frontend.[h|c]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



hi all,

it starts to become a never ending story, but
due to compilation tests ect., the last version had to 
be reworked.


From: Marcel Siegert <mws@xxxxxxxxxxx>

dvb-s2 support in dvb_frontend.c/h and frontend.h

new FE_DVB_X frontend types added 
provided backward compat defines

fixed comment on FE_REINIT

added new fec_modes that dvb-s2 supports
added new modulations that dvb-s2 supports
added fe_rolloff_factor enums needed for dvb-s2

renamed modulation names. 
added backward compat defines

added  dvb_fe_caps_extended struct
 this struct will be filled by the FE_GET_EXTENDED_INFO ioctl.
 it is a extension to the normal frontend capabilities and provided
 if the dvb_fe_info.caps is having the FE_HAS_EXTENDED_INFO bit set.
 added fe_type_t member to this struct, thus now we are able to detect 
 combined frontends and their according types also

renamed dvb_[qpsk|quam|ofdm|vsb]_parameters to their system matching name 
dvb_[dvbs|dvbc|dvbt|atsc]_parameters
added dvb_dvbs2_parameters struct
provided backward compat defines

added recommendation on dvb_frontend_event how this struct should be used via
the FE_GET_EVENT ioctl. marked the struct as deprecated

added FE_SET_STANDARD ioctl - used to set combined frontends to a specific mode.
drivers should report mode matching capabilities. other frontends more are determined via
the FE_GET_EXTENDED_INFO ioctl.

added FE_GET_EXTEND_INFO ioctl that reports more specific capabilities. we do get more 
enum values due to seperated struct members.

added new FE_[GET|SET]_FRONTEND_NEW ioctls for new applications.

added a future safe dvb_frontend_parameters_new struct, that is passing the union of tuning parameters
as a pointer to a union instead of passing the union itself. this keeps future extensions of the union possible
without any thinking about loosing backwards compatibility - it just will be there.


 drivers/media/dvb/dvb-core/dvb_frontend.c |  148 +++++++++++++++++++++++
 drivers/media/dvb/dvb-core/dvb_frontend.h |    6
 include/linux/dvb/frontend.h              |  190 ++++++++++++++++++++++++------
 3 files changed, 306 insertions(+), 38 deletions(-)

  Signed-off-by: Marcel Siegert <mws@xxxxxxxxxxx>

just wondering if the size member ( or a fe_type_t member ) or could be automatically assigned after FE_SET_STANDARD

just have a look, and feel free to place any comments or to bash me down :)

best regards
marcel

diff -r 7d8b443a95d6 linux/drivers/media/dvb/dvb-core/dvb_frontend.c
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c	Thu Mar 30 19:52:23 2006 -0300
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c	Fri Mar 31 21:17:52 2006 +0200
@@ -94,6 +94,7 @@ struct dvb_frontend_private {
 	/* thread/frontend values */
 	struct dvb_device *dvbdev;
 	struct dvb_frontend_parameters parameters;
+	struct dvb_frontend_parameters_new parameters_new;
 	struct dvb_fe_events events;
 	struct semaphore sem;
 	struct list_head list_head;
@@ -106,7 +107,8 @@ struct dvb_frontend_private {
 	unsigned long tune_mode_flags;
 	unsigned int delay;
 	unsigned int reinitialise;
-
+	int act_standard_set;
+	fe_type_t act_standard;
 	/* swzigzag values */
 	unsigned int state;
 	unsigned int bending;
@@ -911,18 +913,21 @@ static int dvb_frontend_ioctl(struct ino
 			/* default values */
 			switch(fe->ops->info.type) {
 			case FE_QPSK:
+			case FE_DVB_S:
 				fepriv->min_delay = HZ/20;
 				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
 				fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;
 				break;
 
 			case FE_QAM:
+			case FE_DVB_C:
 				fepriv->min_delay = HZ/20;
 				fepriv->step_size = 0; /* no zigzag */
 				fepriv->max_drift = 0;
 				break;
 
 			case FE_OFDM:
+			case FE_DVB_T:
 				fepriv->min_delay = HZ/20;
 				fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
 				fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
@@ -930,6 +935,9 @@ static int dvb_frontend_ioctl(struct ino
 			case FE_ATSC:
 				printk("dvb-core: FE_ATSC not handled yet.\n");
 				break;
+			case FE_DVB_S2:
+				printk("dvb-core: ERROR FE_DVB_S2 is handled via FE_SET_FRONTEND_NEW.\n");
+				break;
 			}
 		}
 		if (dvb_override_tune_delay > 0)
@@ -942,6 +950,102 @@ static int dvb_frontend_ioctl(struct ino
 		err = 0;
 		break;
 	}
+	case FE_SET_FRONTEND_NEW: {
+		struct dvb_frontend_tune_settings fetunesettings;
+		struct dvb_frontend_parameters_new *castedparg;
+
+		if (!fepriv->act_standard_set) {
+			err = -EINVAL;
+			break;
+		}
+
+		castedparg = (struct dvb_frontend_parameters_new *)parg;
+		memcpy (&fepriv->parameters_new, parg,
+			 sizeof (struct dvb_frontend_parameters_new));
+
+		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+
+		/* be sure struct union pointer is set - even if it is NULL */
+		fetunesettings.parameters_new.u = (struct frontend_parameters_union *) kmalloc(castedparg->size, GFP_KERNEL);
+		if ( !fetunesettings.parameters_new.u ) {
+
+			err = -ENOMEM;
+			break;
+		}
+		memcpy(fetunesettings.parameters_new.u, castedparg->u, castedparg->size);
+
+		/* force auto frequency inversion if requested */
+		if (dvb_force_auto_inversion) {
+			fepriv->parameters_new.inversion = INVERSION_AUTO;
+			fetunesettings.parameters_new.inversion = INVERSION_AUTO;
+		}
+		if (fe->ops->info.type == FE_OFDM) {
+			/* without hierachical coding code_rate_LP is irrelevant,
+			* so we tolerate the otherwise invalid FEC_NONE setting */
+			if (fepriv->parameters_new.u->ofdm.hierarchy_information == HIERARCHY_NONE &&
+						 fepriv->parameters_new.u->ofdm.code_rate_LP == FEC_NONE)
+				fepriv->parameters_new.u->ofdm.code_rate_LP = FEC_AUTO;
+		}
+
+		/* get frontend-specific tuning settings */
+		if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {
+			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+			fepriv->max_drift = fetunesettings.max_drift;
+			fepriv->step_size = fetunesettings.step_size;
+		} else {
+			/* default values */
+			switch(fe->ops->info.type) {
+			case FE_DVB_S:
+			case FE_QPSK:
+				if (fepriv->act_standard != FE_DVB_S) {
+					err = -EINVAL;
+					break;
+				}
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = fepriv->parameters_new.u->qpsk.symbol_rate / 16000;
+				fepriv->max_drift = fepriv->parameters_new.u->qpsk.symbol_rate / 2000;
+				break;
+			case FE_DVB_C:
+			case FE_QAM:
+				if (fepriv->act_standard != FE_DVB_C) {
+					err = -EINVAL;
+					break;
+				}
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = 0; /* no zigzag */
+				fepriv->max_drift = 0;
+				break;
+			case FE_DVB_T:
+			case FE_OFDM:
+				if (fepriv->act_standard != FE_DVB_T) {
+					err = -EINVAL;
+					break;
+				}
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
+				fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
+				break;
+			case FE_ATSC:
+				printk("dvb-core: FE_ATSC not handled yet.\n");
+				break;
+			case FE_DVB_S2:
+				printk("dvb-core: FE_DVB_S2 not handled yet.\n");
+				break;
+
+			}
+		}
+		if (dvb_override_tune_delay > 0)
+			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+		fepriv->state = FESTATE_RETUNE;
+		dvb_frontend_wakeup(fe);
+		dvb_frontend_add_event(fe, 0);
+		fepriv->status = 0;
+		err = 0;
+		/* if previously used delete old tuning params */
+		kfree(fetunesettings.parameters_new.u);
+		break;
+	}
 
 	case FE_GET_EVENT:
 		err = dvb_frontend_get_event (fe, parg, file->f_flags);
@@ -953,6 +1057,48 @@ static int dvb_frontend_ioctl(struct ino
 			err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
 		}
 		break;
+	case FE_GET_FRONTEND_NEW:
+		if (!fepriv->act_standard_set) {
+			err = -EINVAL;
+			break;
+		}
+		if (fe->ops->get_frontend_new) {
+			memcpy (parg, &fepriv->parameters_new, sizeof (struct dvb_frontend_parameters_new));
+			err = fe->ops->get_frontend_new(fe, (struct dvb_frontend_parameters_new*) parg);
+		}
+		break;
+
+	case FE_SET_STANDARD:
+		/*
+		* act_standard_set and act_standard are reset
+		* this prevents user from ignoring return value and
+		* if act_standard would be kept as fallback, users may
+		* supply corrupted tuning data.
+		* if the new standard isn't supported no FE_SET_FRONTEND_NEW
+		* is possible. it will return EINVAL
+		*/
+		fepriv->act_standard_set = 0;
+		fepriv->act_standard = 0;
+		{
+			fe_type_t fetype = (fe_type_t) parg;
+			if (fetype != FE_DVB_S && fetype != FE_DVB_C && fetype != FE_DVB_T && fetype != FE_DVB_S2 && fetype != FE_ATSC) {
+				err = -EINVAL;
+			} else if (fe->ops->set_standard) {
+				err = fe->ops->set_standard(fe, fetype);
+				if (!err) {
+					fepriv->act_standard_set = 1;
+					fepriv->act_standard = fetype;
+				}
+			}
+		}
+		break;
+
+	case FE_GET_EXTENDED_INFO: {
+		struct dvb_fe_caps_extended* info = parg;
+		memcpy(info, &fe->ops->extended_info, sizeof(struct dvb_fe_caps_extended));
+		err = 0;
+		break;
+	}
 
 	case FE_SET_FRONTEND_TUNE_MODE:
 		fepriv->tune_mode_flags = (unsigned long) parg;
diff -r 7d8b443a95d6 linux/drivers/media/dvb/dvb-core/dvb_frontend.h
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h	Thu Mar 30 19:52:23 2006 -0300
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h	Fri Mar 31 21:17:52 2006 +0200
@@ -45,6 +45,7 @@ struct dvb_frontend_tune_settings {
 	int step_size;
 	int max_drift;
 	struct dvb_frontend_parameters parameters;
+	struct dvb_frontend_parameters_new parameters_new;
 };
 
 struct dvb_frontend;
@@ -52,6 +53,7 @@ struct dvb_frontend_ops {
 struct dvb_frontend_ops {
 
 	struct dvb_frontend_info info;
+	struct dvb_fe_caps_extended extended_info;
 
 	void (*release)(struct dvb_frontend* fe);
 
@@ -86,6 +88,10 @@ struct dvb_frontend_ops {
 	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
 	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+	int (*set_standard)(struct dvb_frontend* fe, fe_type_t type);
+	int (*get_extended_info)(struct dvb_frontend* fe, struct dvb_fe_caps_extended* extendedinfo);
+	int (*set_frontend_new)(struct dvb_frontend* fe, struct dvb_frontend_parameters_new* params);
+	int (*get_frontend_new)(struct dvb_frontend* fe, struct dvb_frontend_parameters_new* params);
 };
 
 #define MAX_EVENT 8
diff -r 7d8b443a95d6 linux/include/linux/dvb/frontend.h
--- a/linux/include/linux/dvb/frontend.h	Thu Mar 30 19:52:23 2006 -0300
+++ b/linux/include/linux/dvb/frontend.h	Fri Mar 31 21:17:52 2006 +0200
@@ -28,14 +28,23 @@
 
 #include <asm/types.h>
 
-
+/**
+ * Usage of fe_type_t enumerations:
+ * Don't use FE_QPSK, FE_QAM, FE_OFDM any longer in new applications.
+ * If the FE_HAS_EXTENDED_INFO is set within the fe_caps,
+ * applications should ignore the fe_type_t returned by the FE_GET_INFO ioctl.
+ *
+ */
 typedef enum fe_type {
-	FE_QPSK,
-	FE_QAM,
-	FE_OFDM,
-	FE_ATSC
+	FE_QPSK = 0,
+	FE_QAM = 1,
+	FE_OFDM = 2,
+	FE_ATSC = 3,
+	FE_DVB_S = (1 << 2),
+	FE_DVB_C = (1 << 3),
+	FE_DVB_T = (1 << 4),
+	FE_DVB_S2 = (1 << 5),
 } fe_type_t;
-
 
 typedef enum fe_caps {
 	FE_IS_STUPID			= 0,
@@ -62,11 +71,11 @@ typedef enum fe_caps {
 	FE_CAN_HIERARCHY_AUTO		= 0x100000,
 	FE_CAN_8VSB			= 0x200000,
 	FE_CAN_16VSB			= 0x400000,
+	FE_HAS_EXTENDED_INFO		= 0x10000000,
 	FE_NEEDS_BENDING		= 0x20000000, // not supported anymore, don't use (frontend requires frequency bending)
 	FE_CAN_RECOVER			= 0x40000000, // frontend can recover from a cable unplug automatically
 	FE_CAN_MUTE_TS			= 0x80000000  // frontend can stop spurious TS data output
 } fe_caps_t;
-
 
 struct dvb_frontend_info {
 	char       name[128];
@@ -82,7 +91,6 @@ struct dvb_frontend_info {
 	fe_caps_t  caps;
 };
 
-
 /**
  *  Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
  *  the meaning of this struct...
@@ -126,9 +134,9 @@ typedef enum fe_status {
 	FE_HAS_SYNC	= 0x08,   /*  found sync bytes  */
 	FE_HAS_LOCK	= 0x10,   /*  everything's working... */
 	FE_TIMEDOUT	= 0x20,   /*  no lock within the last ~2 seconds */
-	FE_REINIT	= 0x40    /*  frontend was reinitialized,  */
-} fe_status_t;			  /*  application is recommended to reset */
-				  /*  DiSEqC, tone and parameters */
+	FE_REINIT	= 0x40    /*  legacy cruft, do not use */
+} fe_status_t;
+
 
 typedef enum fe_spectral_inversion {
 	INVERSION_OFF,
@@ -147,21 +155,48 @@ typedef enum fe_code_rate {
 	FEC_6_7,
 	FEC_7_8,
 	FEC_8_9,
-	FEC_AUTO
+	FEC_AUTO,
+	FEC_3_5,
+	FEC_9_10
 } fe_code_rate_t;
 
 
 typedef enum fe_modulation {
-	QPSK,
-	QAM_16,
-	QAM_32,
-	QAM_64,
-	QAM_128,
-	QAM_256,
-	QAM_AUTO,
-	VSB_8,
-	VSB_16
+	MOD_QPSK,
+	MOD_QAM_16,
+	MOD_QAM_32,
+	MOD_QAM_64,
+	MOD_QAM_128,
+	MOD_QAM_256,
+	MOD_QAM_AUTO,
+	MOD_8VSB,
+	MOD_16VSB,
+	MOD_2VSB,
+	MOD_4VSB,
+	MOD_BPSK,
+	MOD_16APSK,
+	MOD_32APSK,
+	MOD_8PSK,
+	MOD_16PSK
 } fe_modulation_t;
+
+// backward defines
+#define	QPSK 		MOD_QPSK
+#define	QAM_16 		MOD_QAM_16
+#define	QAM_32 		MOD_QAM_32
+#define	QAM_64		MOD_QAM_64
+#define	QAM_128 	MOD_QAM_128
+#define	QAM_256 	MOD_QAM_256
+#define	QAM_AUTO 	MOD_QAM_AUTO
+#define	VSB_8		MOD_8VSB
+#define	VSB_16		MOD_16VSB
+
+
+typedef enum fe_rolloff_factor {
+	ROLLOFF_ALPHA_0_35,
+	ROLLOFF_ALPHA_0_25,
+	ROLLOFF_ALPHA_0_20
+} fe_rolloff_factor_t;
 
 typedef enum fe_transmit_mode {
 	TRANSMISSION_MODE_2K,
@@ -194,23 +229,34 @@ typedef enum fe_hierarchy {
 	HIERARCHY_AUTO
 } fe_hierarchy_t;
 
-
-struct dvb_qpsk_parameters {
-	__u32		symbol_rate;  /* symbol rate in Symbols per second */
+/**
+ *  this struct will be filled by the FE_GET_EXTENDED_INFO ioctl.
+ *  it is a extension to the normal frontend capabilities and provided
+ *  if the dvb_fe_info.caps is having the FE_HAS_EXTENDED_INFO bit set.
+ */
+struct dvb_fe_caps_extended {
+	__u32	fecs;		/* supported fecs */
+	__u32	modulations;	/* supported modulations */
+	__u32	standards;	/* supported frontend_types */
+};
+
+
+struct dvb_dvbs_parameters {
+	__u32		symbol_rate;  /* symbol rate in symbols per second */
 	fe_code_rate_t	fec_inner;    /* forward error correction (see above) */
 };
 
-struct dvb_qam_parameters {
-	__u32		symbol_rate; /* symbol rate in Symbols per second */
+struct dvb_dvbc_parameters {
+	__u32		symbol_rate; /* symbol rate in symbols per second */
 	fe_code_rate_t	fec_inner;   /* forward error correction (see above) */
 	fe_modulation_t	modulation;  /* modulation type (see above) */
 };
 
-struct dvb_vsb_parameters {
+struct dvb_atsc_parameters {
 	fe_modulation_t	modulation;  /* modulation type (see above) */
 };
 
-struct dvb_ofdm_parameters {
+struct dvb_dvbt_parameters {
 	fe_bandwidth_t      bandwidth;
 	fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
 	fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
@@ -220,25 +266,68 @@ struct dvb_ofdm_parameters {
 	fe_hierarchy_t      hierarchy_information;
 };
 
-
+struct dvb_dvbs2_parameters {
+	__u32			symbol_rate;    /* symbol rate in symbols per second */
+	fe_code_rate_t		fec_inner;      /* forward error correction (see above) */
+	fe_modulation_t		modulation;     /* modulation type (see above) */
+	fe_rolloff_factor_t	rolloff_factor; /* rolloff factor needed for dvb-s2 */
+};
+
+#define dvb_qpsk_parameters dvb_dvbs_parameters
+#define dvb_qam_parameters dvb_dvbc_parameters
+#define dvb_ofdm_parameters dvb_dvbt_parameters
+#define dvb_vsb_parameters dvb_atsc_parameters
+
+/* just kept for backwards binary compatibility
+ * deprecated for usage in actual applications
+ */
 struct dvb_frontend_parameters {
 	__u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
 			     /* intermediate frequency in kHz for QPSK */
 	fe_spectral_inversion_t inversion;
 	union {
-		struct dvb_qpsk_parameters qpsk;
-		struct dvb_qam_parameters  qam;
-		struct dvb_ofdm_parameters ofdm;
-		struct dvb_vsb_parameters vsb;
+		struct dvb_dvbs_parameters qpsk;
+		struct dvb_dvbc_parameters  qam;
+		struct dvb_dvbt_parameters ofdm;
+		struct dvb_atsc_parameters vsb;
 	} u;
-};
-
+} __attribute((__deprecated__));
+
+typedef union {
+		struct dvb_dvbs_parameters qpsk;
+		struct dvb_dvbc_parameters qam;
+		struct dvb_dvbt_parameters ofdm;
+		struct dvb_atsc_parameters vsb;
+		struct dvb_dvbs2_parameters qpsk2;
+} frontend_parameters_union;
+
+struct dvb_frontend_parameters_new {
+	__u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
+			     /* intermediate frequency in kHz for QPSK */
+	fe_spectral_inversion_t inversion;
+	__u32 size;
+	frontend_parameters_union *u;
+};
+
+/**
+ * Important:
+ * FE_GET_EVENT and struct dvb_frontend_event
+ * are deprecated due to:
+ * FE_GET_EVENT is a mis-designed ioctl
+ * informations within dvb_frontend_event will
+ * always return stale information.
+ * Applications should:
+ * - open the frontend device with O_NONBLOCK
+ * - poll() for events
+ * - FE_GET_EVENT all pending events to clear the POLLPRI status,
+ *   and throw them away
+ * - FE_READ_STATUS etc. to get current information
+ */
 
 struct dvb_frontend_event {
 	fe_status_t status;
 	struct dvb_frontend_parameters parameters;
-};
-
+} __attribute((__deprecated__));
 
 /**
  * When set, this flag will disable any zigzagging or other "normal" tuning
@@ -267,9 +356,36 @@ struct dvb_frontend_event {
 #define FE_READ_SNR		   _IOR('o', 72, __u16)
 #define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
 
+#define FE_SET_FRONTEND_NEW	   _IOW('o', 84, struct dvb_frontend_parameters_new)
+#define FE_GET_FRONTEND_NEW        _IOR('o', 85, struct dvb_frontend_parameters_new)
+
+/**
+ * next two IOCTLs are deprecated for further use in applications
+ */
 #define FE_SET_FRONTEND		   _IOW('o', 76, struct dvb_frontend_parameters)
 #define FE_GET_FRONTEND		   _IOR('o', 77, struct dvb_frontend_parameters)
+
+
 #define FE_SET_FRONTEND_TUNE_MODE  _IO('o', 81) /* unsigned int */
+
+/**
+ * use to set the FE_STANDARD - if a tuner supports more than one type.
+ * e.g. DVB-C/T or DVB-S/S2 combi frontends. after FE_SET_STANDARD was set,
+ * the drivers has to make sure still to reflect the standards available,
+ * but capabilities should be adjusted to the selected standard
+ */
+#define FE_SET_STANDARD		   _IO('o', 82) /* fe_type_t */
+
+/**
+ * used to query the extended frontend capabilities (see above for details)
+ */
+#define FE_GET_EXTENDED_INFO	   _IOR('o', 83, struct dvb_fe_caps_extended)
+
+/**
+ * FE_GET_EVENT is deprecated for applications.
+ * you should use FE_READ_STATUS and if needed the FE_GET_FRONTEND_NEW
+ * IOCTLs.
+ */
 #define FE_GET_EVENT		   _IOR('o', 78, struct dvb_frontend_event)
 
 #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */

Attachment: pgpeB2YXRlrAD.pgp
Description: PGP signature

_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux