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