All pastes #171690 Raw Edit

gp8psk-dvbs2-091506.

public text v1 · immutable
#171690 ·published 2006-09-15 15:51 UTC
rendered paste body
--- v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.c.orig   2006-09-15 09:40:29.000000000 -0400
+++ v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.c        2006-09-15 10:32:50.000000000 -0400
@@ -96,6 +96,7 @@
        /* 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;
@@ -111,6 +112,8 @@
        int tone;
        int voltage;

+       int current_standard_set;
+       fe_type_t current_standard;
        /* swzigzag values */
        unsigned int state;
        unsigned int bending;
@@ -262,13 +265,23 @@
        int autoinversion;
        int ready = 0;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       int original_inversion = fepriv->parameters.inversion;
-       u32 original_frequency = fepriv->parameters.frequency;
+        int original_inversion;
+        u32 original_frequency;
+
+        if (fepriv->current_standard_set) {
+                original_inversion = fepriv->parameters_new.inversion;
+                original_frequency = fepriv->parameters_new.frequency;
+        } else {
+                original_inversion = fepriv->parameters.inversion;
+                original_frequency = fepriv->parameters.frequency;
+        }

        /* are we using autoinversion? */
        autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-                        (fepriv->parameters.inversion == INVERSION_AUTO));
-
+                ((fepriv->current_standard_set &&
+                  fepriv->parameters_new.inversion == INVERSION_AUTO) ||
+                 (! fepriv->current_standard_set &&
+                   fepriv->parameters.inversion == INVERSION_AUTO)));
        /* setup parameters correctly */
        while(!ready) {
                /* calculate the lnb_drift */
@@ -333,14 +346,24 @@
                fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);

        /* set the frontend itself */
-       fepriv->parameters.frequency += fepriv->lnb_drift;
-       if (autoinversion)
-               fepriv->parameters.inversion = fepriv->inversion;
-       if (fe->ops.set_frontend) 
-               fe->ops.set_frontend(fe, &fepriv->parameters);
-
-       fepriv->parameters.frequency = original_frequency;
-       fepriv->parameters.inversion = original_inversion;
+        if (fepriv->current_standard_set) {
+                fepriv->parameters_new.frequency += fepriv->lnb_drift;
+                if (autoinversion)
+                        fepriv->parameters_new.inversion = fepriv->inversion;
+                if (fe->ops.set_frontend2)
+                        fe->ops.set_frontend2(fe, &fepriv->parameters_new);
+                fepriv->parameters_new.frequency = original_frequency;
+                fepriv->parameters_new.inversion = original_inversion;
+        } else {          
+                fepriv->parameters.frequency += fepriv->lnb_drift;
+                if (autoinversion)
+                        fepriv->parameters.inversion = fepriv->inversion;
+                if (fe->ops.set_frontend)
+                        fe->ops.set_frontend(fe, &fepriv->parameters);
+
+                fepriv->parameters.frequency = original_frequency;
+                fepriv->parameters.inversion = original_inversion;
+        }

        fepriv->auto_sub_step++;            
        return 0;
@@ -361,8 +384,13 @@
        /* in SCAN mode, we just set the frontend when asked and leave it alone */
        if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {      
                if (fepriv->state & FESTATE_RETUNE) {              
-                       if (fe->ops.set_frontend)
-                               fe->ops.set_frontend(fe, &fepriv->parameters);
+                        if (fepriv->current_standard_set) {
+                                if (fe->ops.set_frontend2)               
+                                        fe->ops.set_frontend2(fe, &fepriv->parameters_new);
+                        } else {
+                                if (fe->ops.set_frontend)
+                                        fe->ops.set_frontend(fe, &fepriv->parameters);
+                        }
                        fepriv->state = FESTATE_TUNED;                
                }
                fepriv->delay = 3*HZ;
@@ -937,18 +965,21 @@
                        /* 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;
@@ -958,6 +989,103 @@
                                fepriv->step_size = 0;
                                fepriv->max_drift = 0;
                                break;    
+                       case FE_DVB_S2:
+                               printk("dvb-core: ERROR FE_DVB_S2 is handled via FE_SET_FRONTEND2.\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;
+               break;
+       }
+       case FE_SET_FRONTEND2: {
+               struct dvb_frontend_tune_settings fetunesettings;
+               struct dvb_frontend_parameters_new *castedparg;
+                                
+               if (!fepriv->current_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 = castedparg->u;
+
+               /* 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_DVB_T || 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->current_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->current_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->current_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:
+                               if (fepriv->current_standard != FE_DVB_S2) {        
+                                       err = -EINVAL;
+                                       break;
+                               }
+                               fepriv->min_delay = HZ/20;
+                               fepriv->step_size = fepriv->parameters_new.u.qpsk2.symbol_rate / 16000;
+                               fepriv->max_drift = fepriv->parameters_new.u.qpsk2.symbol_rate / 2000;
+                               break;
+               
                        }
                }
                if (dvb_override_tune_delay > 0)
@@ -968,6 +1096,7 @@
                dvb_frontend_add_event(fe, 0);
                fepriv->status = 0;         
                err = 0;
+               /* if previously used delete old tuning params */
                break;                          
        }

@@ -981,6 +1110,48 @@
                        err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
                }
                break;
+       case FE_GET_FRONTEND2:
+               if (!fepriv->current_standard) {
+                       err = -EINVAL;
+                       break;      
+               }
+               if (fe->ops.get_frontend2) {                   
+                       memcpy (parg, &fepriv->parameters_new, sizeof (struct dvb_frontend_parameters_new));
+                       err = fe->ops.get_frontend2(fe, (struct dvb_frontend_parameters_new*) parg);
+               }
+               break;
+                               
+       case FE_SET_STANDARD:         
+               /*
+               * current_standard_set and current_standard are reset
+               * this prevents user from ignoring return value and        
+               * if current_standard would be kept as fallback, users may
+               * supply corrupted tuning data.
+               * if the new standard isn't supported no FE_SET_FRONTEND2
+               * is possible. it will return EINVAL      
+               */
+               fepriv->current_standard_set = 0;
+               fepriv->current_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->current_standard_set = 1;
+                                       fepriv->current_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;
@@ -1026,7 +1197,10 @@
                fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
                fepriv->tone = -1;
                fepriv->voltage = -1;
-
+                fepriv->current_standard_set = 0;
+                fepriv->current_standard = 0;  
+                if (fe->ops.set_standard)
+                        fe->ops.set_standard(fe, 0);
                ret = dvb_frontend_start (fe);
                if (ret)
                        dvb_generic_release (inode, file);
diff -r 436e56df57d3 v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
--- v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.h     Thu Apr 13 18:50:22 2006 -0300
+++ v4l-dvb/linux/drivers/media/dvb/dvb-core/dvb_frontend.h     Sat Apr 22 13:38:01 2006 -0700
@@ -45,6 +45,7 @@               
        int step_size;                
        int max_drift;
        struct dvb_frontend_parameters parameters;
+       struct dvb_frontend_parameters_new parameters_new;                 
 };

 struct dvb_frontend;
@@ -90,6 +91,7 @@
 struct dvb_frontend_ops {

        struct dvb_frontend_info info;       
+       struct dvb_fe_caps_extended extended_info;

        void (*release)(struct dvb_frontend* fe);

@@ -124,6 +126,10 @@
        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_frontend2)(struct dvb_frontend* fe, struct dvb_frontend_parameters_new* params);
+       int (*get_frontend2)(struct dvb_frontend* fe, struct dvb_frontend_parameters_new* params);

        struct dvb_tuner_ops tuner_ops;
 };
diff -r 436e56df57d3 v4l-dvb/linux/include/linux/dvb/frontend.h
--- v4l-dvb/linux/include/linux/dvb/frontend.h  Thu Apr 13 18:50:22 2006 -0300            
+++ v4l-dvb/linux/include/linux/dvb/frontend.h  Sat Apr 22 13:38:01 2006 -0700
@@ -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,45 @@ 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     = 0,
+       QPSK         = 0,
+       MOD_QAM_16   = 1,
+       QAM_16       = 1,
+       MOD_QAM_32   = 2,
+       QAM_32       = 2,
+       MOD_QAM_64   = 3,  
+       QAM_64       = 3,    
+       MOD_QAM_128  = 4,
+       QAM_128      = 4,
+       MOD_QAM_256  = 5,
+       QAM_256      = 5,
+       MOD_QAM_AUTO = 6,
+       QAM_AUTO     = 6,
+       MOD_8VSB     = 7,
+       VSB_8        = 7,                   
+       MOD_16VSB    = 8,
+       VSB_16       = 8,
+       MOD_2VSB     = 9,
+       MOD_4VSB     = 10,
+       MOD_BPSK     = 11,
+       MOD_16APSK   = 12,
+       MOD_32APSK   = 13,
+       MOD_8PSK     = 14,
+       MOD_16PSK    = 15,
 } fe_modulation_t;
+
+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 +226,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 +263,75 @@ 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 */
+};
+
+/* The following structure is used to allocate enough space in the union
+   for future expansion.
+*/
+struct dvb_private_parameters {
+       __u32           priv[64];
+};
+ 
+#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;
+               struct dvb_private_parameters priv;
+} 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;
+       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 +360,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_FRONTEND2          _IOW('o', 84, struct dvb_frontend_parameters_new)
+#define FE_GET_FRONTEND2          _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 */
--- v4l-dvb/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c.orig    2006-09-15 07:27:07.000000000 -0400
+++ v4l-dvb/linux/drivers/media/dvb/dvb-usb/gp8psk-fe.c 2006-09-15 07:29:11.000000000 -0400
@@ -41,6 +41,17 @@
        return 0;
 }

+static int gp8psk_set_standard(struct dvb_frontend* fe, u32 type)
+{ 
+       (void) fe;
+       if (type == FE_DVB_S2 || type == FE_DVB_S) {
+               fe->ops.info.type = type;
+               return 0;
+       } else {
+               fe->ops.info.type = FE_QPSK;    
+               return 1;
+       }
+}
 /* not supported by this Frontend */
 static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
 { 
@@ -90,8 +101,8 @@
        return 0;
 }  

-static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
-                                 struct dvb_frontend_parameters *fep)
+static int gp8psk_fe_set_frontend2(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters_new *fep)
 {              
        struct gp8psk_fe_state *state = fe->demodulator_priv;
        u8 cmd[10];
@@ -103,6 +114,7 @@
        cmd[7] = (freq >> 24) & 0xff;

        switch(fe->ops.info.type) {
+        case FE_DVB_S:
        case FE_QPSK:
                cmd[0] =  fep->u.qpsk.symbol_rate        & 0xff;
                cmd[1] = (fep->u.qpsk.symbol_rate >>  8) & 0xff;            
@@ -111,6 +123,17 @@
                cmd[8] = ADV_MOD_DVB_QPSK;
                cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
                break;
+       case FE_DVB_S2:
+               cmd[0] =  fep->u.qpsk2.symbol_rate        & 0xff;      
+               cmd[1] = (fep->u.qpsk2.symbol_rate >>  8) & 0xff;
+               cmd[2] = (fep->u.qpsk2.symbol_rate >> 16) & 0xff;
+               cmd[3] = (fep->u.qpsk2.symbol_rate >> 24) & 0xff;          
+               if (fep->u.qpsk2.modulation == MOD_8PSK)
+                       cmd[8] = ADV_MOD_TURBO_8PSK;
+               else
+                       cmd[8] = ADV_MOD_DVB_QPSK;
+               cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
+               break;
        default:
                // other modes are unsuported right now
                cmd[0] = 0;
@@ -129,6 +152,14 @@
        return 0;
 }

+static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
+                                 struct dvb_frontend_parameters *fep)
+{ 
+       return gp8psk_fe_set_frontend2(fe,
+                       (struct dvb_frontend_parameters_new *) fep);
+}
+                        
+               
 static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
                                  struct dvb_frontend_parameters *fep)
 {               
@@ -246,8 +277,15 @@
                .caps = FE_CAN_INVERSION_AUTO |
                                FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
                                FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-                               FE_CAN_QPSK                 
+                               FE_CAN_QPSK | FE_HAS_EXTENDED_INFO        
+       },      
+       .extended_info = {
+               .fecs           = FEC_1_2 | FEC_2_3 | FEC_3_4 | FEC_5_6 |
+                                        FEC_7_8 | FEC_AUTO,
+               .modulations    = MOD_QPSK | MOD_BPSK | MOD_8PSK,
+               .standards      = FE_DVB_S | FE_DVB_S2
        },
+       .set_standard = gp8psk_set_standard,

        .release = gp8psk_fe_release,

@@ -256,6 +294,10 @@

        .set_frontend = gp8psk_fe_set_frontend,   
        .get_frontend = gp8psk_fe_get_frontend,
+                      
+       .set_frontend2 = gp8psk_fe_set_frontend2,                      
+       .get_frontend2 = NULL,
+               
        .get_tune_settings = gp8psk_fe_get_tune_settings,                  

        .read_status = gp8psk_fe_read_status,