On Fri, Oct 23, 2009 at 12:10 AM, Mauro Carvalho Chehab
<[email protected]> wrote:
> Em Thu, 22 Oct 2009 21:13:30 +0200
> Jean Delvare <[email protected]> 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_*/