On Fri, Oct 23, 2009 at 12:10 AM, Mauro Carvalho Chehab <mchehab@xxxxxxxxxxxxx> wrote: > Em Thu, 22 Oct 2009 21:13:30 +0200 > Jean Delvare <khali@xxxxxxxxxxxx> escreveu: > >> Hi folks, >> >> I am looking for details regarding the DVB frontend API. I've read >> linux-dvb-api-1.0.0.pdf, it roughly explains what the FE_READ_BER, >> FE_READ_SNR, FE_READ_SIGNAL_STRENGTH and FE_READ_UNCORRECTED_BLOCKS >> commands return, however it does not give any information about how the >> returned values should be interpreted (or, seen from the other end, how >> the frontend kernel drivers should encode these values.) If there >> documentation available that would explain this? >> >> For example, the signal strength. All I know so far is that this is a >> 16-bit value. But then what? Do greater values represent stronger >> signal or weaker signal? Are 0x0000 and 0xffff special values? Is the >> returned value meaningful even when FE_HAS_SIGNAL is 0? When >> FE_HAS_LOCK is 0? Is the scale linear, or do some values have >> well-defined meanings, or is it arbitrary and each driver can have its >> own scale? What are the typical use cases by user-space application for >> this value? >> >> That's the kind of details I'd like to know, not only for the signal >> strength, but also for the SNR, BER and UB. Without this information, >> it seems a little difficult to have consistent frontend drivers. > > We all want to know about that ;) > > Seriously, the lack of a description of the meaning of the ranges for those > read values were already widely discussed at LMML and at the legacy dvb ML. > We should return this discussion again and decide what would be the better > way to describe those values. > > My suggestion is that someone summarize the proposals we had and give some time > for people vote. After that, we just commit the most voted one, and commit the > patches for it. A pending question that should also be discussed is what we will > do with those dvb devices where we simply don't know what scale it uses. There > are several of them. Sometime back, (some time in April) i proposed a patch which addressed the issue to scale "even those devices which have a weird scale or none". Though based on an older tree of mine, here is the patch again. If it looks good enough, i can port the patch to accomodate other devices as well. Regards, Manu
diff -r b5505a985f24 linux/drivers/media/dvb/dvb-core/dvb_frontend.c --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c Sat Feb 21 01:12:09 2009 +0400 +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c Tue Apr 07 18:19:22 2009 +0400 @@ -1004,8 +1004,8 @@ */ /* Legacy */ if (fe->legacy) { - if ((fepriv->state & FESTATE_LOSTLOCK) && - (fe->ops.info.caps & FE_CAN_RECOVER) && + if ((fepriv->state & FESTATE_LOSTLOCK) && + (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) { dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK); @@ -1487,6 +1487,13 @@ break; } + case FE_STATISTICS_CAPS: { + struct fecap_statistics *stats_cap = parg; + memcpy(stats_cap, &fe->ops.statistics_caps, sizeof (struct fecap_statistics)); + err = 0; + break; + } + case FE_READ_STATUS: { fe_status_t* status = parg; @@ -1502,6 +1509,17 @@ err = fe->ops.read_status(fe, status); break; } + + case FE_SIGNAL_LEVEL: + if (fe->ops.read_level) + err = fe->ops.read_level(fe, (__u32 *) parg); + break; + + case FE_SIGNAL_STATS: + if (fe->ops.read_stats) + err = fe->ops.read_stats(fe, (struct fesignal_stat *) parg); + break; + case FE_READ_BER: if (fe->ops.read_ber) err = fe->ops.read_ber(fe, (__u32*) parg); @@ -1645,7 +1663,7 @@ break; } - memcpy(&fepriv->parameters, parg, sizeof (struct dvb_frontend_parameters)); + memcpy(&fepriv->parameters, parg, sizeof (struct dvb_frontend_parameters)); memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); memcpy(&fetunesettings.parameters, parg, sizeof (struct dvb_frontend_parameters)); diff -r b5505a985f24 linux/drivers/media/dvb/dvb-core/dvb_frontend.h --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h Sat Feb 21 01:12:09 2009 +0400 +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h Tue Apr 07 18:19:22 2009 +0400 @@ -72,7 +72,7 @@ unsigned int audmode; u64 std; }; - + enum dvbfe_modcod { DVBFE_MODCOD_DUMMY_PLFRAME = 0, DVBFE_MODCOD_QPSK_1_4, @@ -250,6 +250,7 @@ struct dvb_frontend_ops { struct dvb_frontend_info info; + struct fecap_statistics statistics_caps; void (*release)(struct dvb_frontend* fe); void (*release_sec)(struct dvb_frontend* fe); @@ -304,6 +305,9 @@ enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvbfe_params *fe_params); int (*track)(struct dvb_frontend *fe, struct dvbfe_params *fe_params, int *delay); + int (*read_level)(struct dvb_frontend *fe, u32 *signal); /* Raw AGC level */ + int (*read_stats)(struct dvb_frontend *fe, struct fesignal_stat *stat); + struct dvb_tuner_ops tuner_ops; struct analog_demod_ops analog_ops; }; diff -r b5505a985f24 linux/drivers/media/dvb/frontends/stb0899_drv.c --- a/linux/drivers/media/dvb/frontends/stb0899_drv.c Sat Feb 21 01:12:09 2009 +0400 +++ b/linux/drivers/media/dvb/frontends/stb0899_drv.c Tue Apr 07 18:19:22 2009 +0400 @@ -1225,6 +1225,29 @@ return 0; } +static int stb0899_read_level(struct dvb_frontend *fe, u32 *signal) +{ + /* TODO! */ + return 0; +} + +static int stb0899_read_stats(struct dvb_frontend *fe, struct fesignal_stat *stats) +{ + u16 snr, strength; + u32 ber; + + stb0899_read_snr(fe, &snr); + stb0899_read_signal_strength(fe, &strength); + stb0899_read_ber(fe, &ber); + + stats->quality = snr; + stats->strength = strength; + stats->error = ber; + stats->unc = 0; + + return 0; +} + static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { struct stb0899_state *state = fe->demodulator_priv; @@ -2039,6 +2062,26 @@ .type = FE_QPSK, /* with old API */ }, + .statistics_caps = { + .quality = { + .params = FE_QUALITY_CNR, + .scale = FE_SCALE_dB, + .exponent = -4, + }, + + .strength = { + .params = FE_SCALE_dB, + .exponent = -4, + }, + + .error = { + .params = FE_ERROR_BER, + .exponent = 7, + }, + + .unc = FE_UNC_UNKNOWN, + }, + .release = stb0899_release, .init = stb0899_init, .sleep = stb0899_sleep, @@ -2059,6 +2102,9 @@ .read_signal_strength = stb0899_read_signal_strength, .read_status = stb0899_read_status, .read_ber = stb0899_read_ber, + + .read_level = stb0899_read_level, + .read_stats = stb0899_read_stats, .set_voltage = stb0899_set_voltage, .set_tone = stb0899_set_tone, diff -r b5505a985f24 linux/include/linux/dvb/frontend.h --- a/linux/include/linux/dvb/frontend.h Sat Feb 21 01:12:09 2009 +0400 +++ b/linux/include/linux/dvb/frontend.h Tue Apr 07 18:19:22 2009 +0400 @@ -645,4 +645,118 @@ }; #define DVBFE_GET_EVENT _IOR('o', 86, struct dvbfe_event) +/* Frontend General Statistics + * General parameters + * FE_*_UNKNOWN: + * Parameter is unknown to the frontend and doesn't really + * make any sense for an application. + * + * FE_*_RELATIVE: + * Parameter is relative on the basis of a ceil - floor basis + * Format is based on empirical test to determine + * the floor and ceiling values. This format is exactly the + * same format as the existing statistics implementation. + */ +enum fecap_quality_params { + FE_QUALITY_UNKNOWN = 0, + FE_QUALITY_SNR = (1 << 0), + FE_QUALITY_CNR = (1 << 1), + FE_QUALITY_EsNo = (1 << 2), + FE_QUALITY_EbNo = (1 << 3), + FE_QUALITY_RELATIVE = (1 << 31), +}; + +enum fecap_scale_params { + FE_SCALE_UNKNOWN = 0, + FE_SCALE_dB = (1 << 0), + FE_SCALE_RELATIVE = (1 << 31), +}; + +enum fecap_error_params { + FE_ERROR_UNKNOWN = 0, + FE_ERROR_BER = (1 << 0), + FE_ERROR_PER = (1 << 1), + FE_ERROR_RELATIVE = (1 << 31), +}; + +enum fecap_unc_params { + FE_UNC_UNKNOWN = 0, + FE_UNC_RELATIVE = (1 << 31), +}; + +/* General parameters + * width: + * Specifies the width of the field + * + * exponent: + * Specifies the multiplier for the respective field + * MSB:1bit indicates the signdness of the parameter + */ +struct fecap_quality { + enum fecap_quality_params params; + enum fecap_scale_params scale; + + __u32 width; + __s32 exponent; +}; + +struct fecap_strength { + enum fecap_scale_params params; + __u32 width; + __s32 exponent; +}; + +struct fecap_error { + enum fecap_error_params params; + __u32 width; + __s32 exponent; +}; + +struct fecap_statistics { + struct fecap_quality quality; + struct fecap_strength strength; + struct fecap_error error; + enum fecap_unc_params unc; +}; + +/* FE_STATISTICS_CAPS + * Userspace query for frontend signal statistics capabilities + */ +#define FE_STATISTICS_CAPS _IOR('o', 84, struct fecap_statistics) + + +/* FE_SIGNAL_LEVEL + * This system call provides a direct monitor of the signal, without + * passing through the relevant processing chains. In many cases, it + * is simply considered as direct AGC1 scaled values. This parameter + * can generally be used to position an antenna to while looking at + * a peak of this value. This parameter can be read back, even when + * a frontend LOCK has not been achieved. Some microntroller based + * demodulators do not provide a direct access to the AGC on the + * demodulator, hence this parameter will be Unsupported for such + * devices. + */ +#define FE_SIGNAL_LEVEL _IOR('o', 85, __u32) + + +struct fesignal_stat { + __u32 quality; + __u32 strength; + __u32 error; + __u32 unc; +}; + +/* FE_SIGNAL_STATS + * This system call provides a snapshot of all the receiver system + * at any given point of time. System signal statistics are always + * computed with respect to time and is best obtained the nearest + * to each of the individual parameters in a time domain. + * Signal statistics are assumed, "at any given instance of time". + * It is not possible to get a snapshot at the exact single instance + * and hence we look at the nearest instance, in the time domain. + * The statistics are described by the FE_STATISTICS_CAPS ioctl, + * ie. based on the device capabilities. + */ +#define FE_SIGNAL_STATS _IOR('o', 86, struct fesignal_stat) + #endif /*_DVBFRONTEND_H_*/