summaryrefslogtreecommitdiff
path: root/drivers/media/common
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-03-10 02:26:28 +0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-21 14:47:31 +0400
commitd42f1cb25334bbcddf213a00bb67083414027933 (patch)
tree698df33b58aa2d1a5486afb4c9f3d7050e51124e /drivers/media/common
parentff702eb8d9c8ca293e7f0343dd38b718d58815b0 (diff)
downloadlinux-d42f1cb25334bbcddf213a00bb67083414027933.tar.xz
[media] siano: Convert it to report DVBv5 stats
While this frontend provides a nice set of statistics, the way it is currently reported to userspace is poor. Worse than that, instead of using quality indicators that range from 0 to 65535, as expected by userspace, most indicators range from 0 to 100. Improve it by using DVBv5 statistics API. The legacy indicators are still reported using the very same old way, but they're now using a proper range (0 to 65535 for quality indicadors; 0.1 dB for SNR). Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/siano/smsdvb.c826
1 files changed, 468 insertions, 358 deletions
diff --git a/drivers/media/common/siano/smsdvb.c b/drivers/media/common/siano/smsdvb.c
index 04544f591df5..a5f52721154c 100644
--- a/drivers/media/common/siano/smsdvb.c
+++ b/drivers/media/common/siano/smsdvb.c
@@ -49,7 +49,10 @@ struct smsdvb_client_t {
struct completion tune_done;
struct completion stats_done;
- struct SMSHOSTLIB_STATISTICS_DVB_EX_S sms_stat_dvb;
+ int last_per;
+
+ int legacy_ber, legacy_per;
+
int event_fe_state;
int event_unc_state;
};
@@ -61,6 +64,82 @@ static int sms_dbg;
module_param_named(debug, sms_dbg, int, 0644);
MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
+/*
+ * This struct is a mix of RECEPTION_STATISTICS_EX_S and SRVM_SIGNAL_STATUS_S.
+ * It was obtained by comparing the way it was filled by the original code
+ */
+struct RECEPTION_STATISTICS_PER_SLICES_S {
+ u32 result;
+ u32 snr;
+ s32 inBandPower;
+ u32 tsPackets;
+ u32 etsPackets;
+ u32 constellation;
+ u32 hpCode;
+ u32 tpsSrvIndLP;
+ u32 tpsSrvIndHP;
+ u32 cellId;
+ u32 reason;
+ u32 requestId;
+ u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+
+ u32 BER; /* Post Viterbi BER [1E-5] */
+ s32 RSSI; /* dBm */
+ s32 CarrierOffset; /* Carrier Offset in bin/1024 */
+
+ u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+ u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+
+ u32 BERBitCount; /* Total number of SYNC bits. */
+ u32 BERErrorCount; /* Number of erronous SYNC bits. */
+
+ s32 MRC_SNR; /* dB */
+ s32 MRC_InBandPwr; /* In band power in dBM */
+ s32 MRC_RSSI; /* dBm */
+};
+
+u32 sms_to_bw_table[] = {
+ [BW_8_MHZ] = 8000000,
+ [BW_7_MHZ] = 7000000,
+ [BW_6_MHZ] = 6000000,
+ [BW_5_MHZ] = 5000000,
+ [BW_2_MHZ] = 2000000,
+ [BW_1_5_MHZ] = 1500000,
+ [BW_ISDBT_1SEG] = 6000000,
+ [BW_ISDBT_3SEG] = 6000000,
+ [BW_ISDBT_13SEG] = 6000000,
+};
+
+u32 sms_to_guard_interval_table[] = {
+ [0] = GUARD_INTERVAL_1_32,
+ [1] = GUARD_INTERVAL_1_16,
+ [2] = GUARD_INTERVAL_1_8,
+ [3] = GUARD_INTERVAL_1_4,
+};
+
+u32 sms_to_code_rate_table[] = {
+ [0] = FEC_1_2,
+ [1] = FEC_2_3,
+ [2] = FEC_3_4,
+ [3] = FEC_5_6,
+ [4] = FEC_7_8,
+};
+
+
+u32 sms_to_hierarchy_table[] = {
+ [0] = HIERARCHY_NONE,
+ [1] = HIERARCHY_1,
+ [2] = HIERARCHY_2,
+ [3] = HIERARCHY_4,
+};
+
+u32 sms_to_modulation_table[] = {
+ [0] = QPSK,
+ [1] = QAM_16,
+ [2] = QAM_64,
+ [3] = DQPSK,
+};
+
static void smsdvb_print_dvb_stats(struct SMSHOSTLIB_STATISTICS_ST *p)
{
if (!(sms_dbg & 2))
@@ -244,93 +323,350 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
}
}
-static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
+static void smsdvb_stats_not_ready(struct dvb_frontend *fe)
+{
+ struct smsdvb_client_t *client =
+ container_of(fe, struct smsdvb_client_t, frontend);
+ struct smscore_device_t *coredev = client->coredev;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ int i, n_layers;
+
+ switch (smscore_get_device_mode(coredev)) {
+ case DEVICE_MODE_ISDBT:
+ case DEVICE_MODE_ISDBT_BDA:
+ n_layers = 4;
+ default:
+ n_layers = 1;
+ }
+
+ /* Fill the length of each status counter */
+
+ /* Only global stats */
+ c->strength.len = 1;
+ c->cnr.len = 1;
+
+ /* Per-layer stats */
+ c->post_bit_error.len = n_layers;
+ c->post_bit_count.len = n_layers;
+ c->block_error.len = n_layers;
+ c->block_count.len = n_layers;
+
+ /* Signal is always available */
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = 0;
+
+ /* Put all of them at FE_SCALE_NOT_AVAILABLE */
+ for (i = 0; i < n_layers; i++) {
+ c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+}
+
+static inline int sms_to_mode(u32 mode)
+{
+ switch (mode) {
+ case 2:
+ return TRANSMISSION_MODE_2K;
+ case 4:
+ return TRANSMISSION_MODE_4K;
+ case 8:
+ return TRANSMISSION_MODE_8K;
+ }
+ return TRANSMISSION_MODE_AUTO;
+}
+
+static inline int sms_to_status(u32 is_demod_locked, u32 is_rf_locked)
+{
+ if (is_demod_locked)
+ return FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+ FE_HAS_SYNC | FE_HAS_LOCK;
+
+ if (is_rf_locked)
+ return FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ return 0;
+}
+
+
+#define convert_from_table(value, table, defval) ({ \
+ u32 __ret; \
+ if (value < ARRAY_SIZE(table)) \
+ __ret = table[value]; \
+ else \
+ __ret = defval; \
+ __ret; \
+})
+
+#define sms_to_bw(value) \
+ convert_from_table(value, sms_to_bw_table, 0);
+
+#define sms_to_guard_interval(value) \
+ convert_from_table(value, sms_to_guard_interval_table, \
+ GUARD_INTERVAL_AUTO);
+
+#define sms_to_code_rate(value) \
+ convert_from_table(value, sms_to_code_rate_table, \
+ FEC_NONE);
+
+#define sms_to_hierarchy(value) \
+ convert_from_table(value, sms_to_hierarchy_table, \
+ FEC_NONE);
+
+#define sms_to_modulation(value) \
+ convert_from_table(value, sms_to_modulation_table, \
+ FEC_NONE);
+
+static void smsdvb_update_tx_params(struct smsdvb_client_t *client,
+ struct TRANSMISSION_STATISTICS_S *p)
+{
+ struct dvb_frontend *fe = &client->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ c->frequency = p->Frequency;
+ client->fe_status = sms_to_status(p->IsDemodLocked, 0);
+ c->bandwidth_hz = sms_to_bw(p->Bandwidth);
+ c->transmission_mode = sms_to_mode(p->TransmissionMode);
+ c->guard_interval = sms_to_guard_interval(p->GuardInterval);
+ c->code_rate_HP = sms_to_code_rate(p->CodeRate);
+ c->code_rate_LP = sms_to_code_rate(p->LPCodeRate);
+ c->hierarchy = sms_to_hierarchy(p->Hierarchy);
+ c->modulation = sms_to_modulation(p->Constellation);
+}
+
+static void smsdvb_update_per_slices(struct smsdvb_client_t *client,
+ struct RECEPTION_STATISTICS_PER_SLICES_S *p)
+{
+ struct dvb_frontend *fe = &client->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ client->fe_status = sms_to_status(p->IsDemodLocked, p->IsRfLocked);
+ c->modulation = sms_to_modulation(p->constellation);
+
+ /* TS PER */
+ client->last_per = c->block_error.stat[0].uvalue;
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue += p->etsPackets;
+ c->block_count.stat[0].uvalue += p->etsPackets + p->tsPackets;
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue += p->BERErrorCount;
+ c->post_bit_count.stat[0].uvalue += p->BERBitCount;
+
+ /* Legacy PER/BER */
+ client->legacy_per = (p->etsPackets * 65535) /
+ (p->tsPackets + p->etsPackets);
+
+ /* Signal Strength, in DBm */
+ c->strength.stat[0].uvalue = p->RSSI * 1000;
+
+ /* Carrier to Noise ratio, in DB */
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = p->snr * 1000;
+}
+
+static void smsdvb_update_dvb_stats(struct smsdvb_client_t *client,
struct SMSHOSTLIB_STATISTICS_ST *p)
{
+ struct dvb_frontend *fe = &client->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
smsdvb_print_dvb_stats(p);
+ client->fe_status = sms_to_status(p->IsDemodLocked, p->IsRfLocked);
+
+ /* Update DVB modulation parameters */
+ c->frequency = p->Frequency;
+ client->fe_status = sms_to_status(p->IsDemodLocked, 0);
+ c->bandwidth_hz = sms_to_bw(p->Bandwidth);
+ c->transmission_mode = sms_to_mode(p->TransmissionMode);
+ c->guard_interval = sms_to_guard_interval(p->GuardInterval);
+ c->code_rate_HP = sms_to_code_rate(p->CodeRate);
+ c->code_rate_LP = sms_to_code_rate(p->LPCodeRate);
+ c->hierarchy = sms_to_hierarchy(p->Hierarchy);
+ c->modulation = sms_to_modulation(p->Constellation);
+
/* update reception data */
- pReceptionData->IsRfLocked = p->IsRfLocked;
- pReceptionData->IsDemodLocked = p->IsDemodLocked;
- pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
- pReceptionData->ModemState = p->ModemState;
- pReceptionData->SNR = p->SNR;
- pReceptionData->BER = p->BER;
- pReceptionData->BERErrorCount = p->BERErrorCount;
- pReceptionData->BERBitCount = p->BERBitCount;
- pReceptionData->RSSI = p->RSSI;
- CORRECT_STAT_RSSI(*pReceptionData);
- pReceptionData->InBandPwr = p->InBandPwr;
- pReceptionData->CarrierOffset = p->CarrierOffset;
- pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
- pReceptionData->TotalTSPackets = p->TotalTSPackets;
+ c->lna = p->IsExternalLNAOn ? 1 : 0;
+
+ /* Carrier to Noise ratio, in DB */
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = p->SNR * 1000;
+
+ /* Signal Strength, in DBm */
+ c->strength.stat[0].uvalue = p->RSSI * 1000;
+
+ /* TS PER */
+ client->last_per = c->block_error.stat[0].uvalue;
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue += p->ErrorTSPackets;
+ c->block_count.stat[0].uvalue += p->TotalTSPackets;
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue += p->BERErrorCount;
+ c->post_bit_count.stat[0].uvalue += p->BERBitCount;
+
+ /* Legacy PER/BER */
+ client->legacy_ber = p->BER;
};
-static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
+static void smsdvb_update_isdbt_stats(struct smsdvb_client_t *client,
struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
{
+ struct dvb_frontend *fe = &client->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST *lr;
+ int i, n_layers;
+
smsdvb_print_isdb_stats(p);
+ /* Update ISDB-T transmission parameters */
+ c->frequency = p->Frequency;
+ client->fe_status = sms_to_status(p->IsDemodLocked, 0);
+ c->bandwidth_hz = sms_to_bw(p->Bandwidth);
+ c->transmission_mode = sms_to_mode(p->TransmissionMode);
+ c->guard_interval = sms_to_guard_interval(p->GuardInterval);
+ c->isdbt_partial_reception = p->PartialReception ? 1 : 0;
+ n_layers = p->NumOfLayers;
+ if (n_layers < 1)
+ n_layers = 1;
+ if (n_layers > 3)
+ n_layers = 3;
+ c->isdbt_layer_enabled = 0;
+
/* update reception data */
- pReceptionData->IsRfLocked = p->IsRfLocked;
- pReceptionData->IsDemodLocked = p->IsDemodLocked;
- pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
- pReceptionData->ModemState = p->ModemState;
- pReceptionData->SNR = p->SNR;
- pReceptionData->BER = p->LayerInfo[0].BER;
- pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
- pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
- pReceptionData->RSSI = p->RSSI;
- CORRECT_STAT_RSSI(*pReceptionData);
- pReceptionData->InBandPwr = p->InBandPwr;
-
- pReceptionData->CarrierOffset = p->CarrierOffset;
- pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
- pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
- pReceptionData->MFER = 0;
+ c->lna = p->IsExternalLNAOn ? 1 : 0;
- /* TS PER */
- if ((p->LayerInfo[0].TotalTSPackets +
- p->LayerInfo[0].ErrorTSPackets) > 0) {
- pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
- * 100) / (p->LayerInfo[0].TotalTSPackets
- + p->LayerInfo[0].ErrorTSPackets);
- } else {
- pReceptionData->TS_PER = 0;
+ /* Carrier to Noise ratio, in DB */
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = p->SNR * 1000;
+
+ /* Signal Strength, in DBm */
+ c->strength.stat[0].uvalue = p->RSSI * 1000;
+
+ client->last_per = c->block_error.stat[0].uvalue;
+
+ /* Clears global counters, as the code below will sum it again */
+ c->block_error.stat[0].uvalue = 0;
+ c->block_count.stat[0].uvalue = 0;
+ c->post_bit_error.stat[0].uvalue = 0;
+ c->post_bit_count.stat[0].uvalue = 0;
+
+ for (i = 0; i < n_layers; i++) {
+ lr = &p->LayerInfo[i];
+
+ /* Update per-layer transmission parameters */
+ if (lr->NumberOfSegments > 0 && lr->NumberOfSegments < 13) {
+ c->isdbt_layer_enabled |= 1 << i;
+ c->layer[i].segment_count = lr->NumberOfSegments;
+ } else {
+ continue;
+ }
+ c->layer[i].modulation = sms_to_modulation(lr->Constellation);
+
+ /* TS PER */
+ c->block_error.stat[i].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[i].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[i].uvalue += lr->ErrorTSPackets;
+ c->block_count.stat[i].uvalue += lr->TotalTSPackets;
+
+ /* Update global PER counter */
+ c->block_error.stat[0].uvalue += lr->ErrorTSPackets;
+ c->block_count.stat[0].uvalue += lr->TotalTSPackets;
+
+ /* BER */
+ c->post_bit_error.stat[i].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[i].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[i].uvalue += lr->BERErrorCount;
+ c->post_bit_count.stat[i].uvalue += lr->BERBitCount;
+
+ /* Update global BER counter */
+ c->post_bit_error.stat[0].uvalue += lr->BERErrorCount;
+ c->post_bit_count.stat[0].uvalue += lr->BERBitCount;
}
}
-static void smsdvb_update_isdbt_stats_ex(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
- struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
+static void smsdvb_update_isdbt_stats_ex(struct smsdvb_client_t *client,
+ struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
{
+ struct dvb_frontend *fe = &client->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST *lr;
+ int i, n_layers;
+
smsdvb_print_isdb_stats_ex(p);
+ /* Update ISDB-T transmission parameters */
+ c->frequency = p->Frequency;
+ client->fe_status = sms_to_status(p->IsDemodLocked, 0);
+ c->bandwidth_hz = sms_to_bw(p->Bandwidth);
+ c->transmission_mode = sms_to_mode(p->TransmissionMode);
+ c->guard_interval = sms_to_guard_interval(p->GuardInterval);
+ c->isdbt_partial_reception = p->PartialReception ? 1 : 0;
+ n_layers = p->NumOfLayers;
+ if (n_layers < 1)
+ n_layers = 1;
+ if (n_layers > 3)
+ n_layers = 3;
+ c->isdbt_layer_enabled = 0;
+
/* update reception data */
- pReceptionData->IsRfLocked = p->IsRfLocked;
- pReceptionData->IsDemodLocked = p->IsDemodLocked;
- pReceptionData->IsExternalLNAOn = p->IsExternalLNAOn;
- pReceptionData->ModemState = p->ModemState;
- pReceptionData->SNR = p->SNR;
- pReceptionData->BER = p->LayerInfo[0].BER;
- pReceptionData->BERErrorCount = p->LayerInfo[0].BERErrorCount;
- pReceptionData->BERBitCount = p->LayerInfo[0].BERBitCount;
- pReceptionData->RSSI = p->RSSI;
- CORRECT_STAT_RSSI(*pReceptionData);
- pReceptionData->InBandPwr = p->InBandPwr;
-
- pReceptionData->CarrierOffset = p->CarrierOffset;
- pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
- pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
- pReceptionData->MFER = 0;
+ c->lna = p->IsExternalLNAOn ? 1 : 0;
- /* TS PER */
- if ((p->LayerInfo[0].TotalTSPackets +
- p->LayerInfo[0].ErrorTSPackets) > 0) {
- pReceptionData->TS_PER = (p->LayerInfo[0].ErrorTSPackets
- * 100) / (p->LayerInfo[0].TotalTSPackets
- + p->LayerInfo[0].ErrorTSPackets);
- } else {
- pReceptionData->TS_PER = 0;
+ /* Carrier to Noise ratio, in DB */
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = p->SNR * 1000;
+
+ /* Signal Strength, in DBm */
+ c->strength.stat[0].uvalue = p->RSSI * 1000;
+
+ client->last_per = c->block_error.stat[0].uvalue;
+
+ /* Clears global counters, as the code below will sum it again */
+ c->block_error.stat[0].uvalue = 0;
+ c->block_count.stat[0].uvalue = 0;
+ c->post_bit_error.stat[0].uvalue = 0;
+ c->post_bit_count.stat[0].uvalue = 0;
+
+ for (i = 0; i < n_layers; i++) {
+ lr = &p->LayerInfo[i];
+
+ /* Update per-layer transmission parameters */
+ if (lr->NumberOfSegments > 0 && lr->NumberOfSegments < 13) {
+ c->isdbt_layer_enabled |= 1 << i;
+ c->layer[i].segment_count = lr->NumberOfSegments;
+ } else {
+ continue;
+ }
+ c->layer[i].modulation = sms_to_modulation(lr->Constellation);
+
+ /* TS PER */
+ c->block_error.stat[i].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[i].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[i].uvalue += lr->ErrorTSPackets;
+ c->block_count.stat[i].uvalue += lr->TotalTSPackets;
+
+ /* Update global PER counter */
+ c->block_error.stat[0].uvalue += lr->ErrorTSPackets;
+ c->block_count.stat[0].uvalue += lr->TotalTSPackets;
+
+ /* BER */
+ c->post_bit_error.stat[i].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[i].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[i].uvalue += lr->BERErrorCount;
+ c->post_bit_count.stat[i].uvalue += lr->BERBitCount;
+
+ /* Update global BER counter */
+ c->post_bit_error.stat[0].uvalue += lr->BERErrorCount;
+ c->post_bit_count.stat[0].uvalue += lr->BERBitCount;
}
}
@@ -339,13 +675,14 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
+ cb->offset);
- u32 *pMsgData = (u32 *) phdr + 1;
- /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
+ void *p = phdr + 1;
+ struct dvb_frontend *fe = &client->frontend;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
bool is_status_update = false;
switch (phdr->msgType) {
case MSG_SMS_DVBT_BDA_DATA:
- dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
+ dvb_dmx_swfilter(&client->demux, p,
cb->size - sizeof(struct SmsMsgHdr_ST));
break;
@@ -355,166 +692,64 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
break;
case MSG_SMS_SIGNAL_DETECTED_IND:
- client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
+ client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+ FE_HAS_VITERBI | FE_HAS_SYNC |
+ FE_HAS_LOCK;
+
is_status_update = true;
break;
case MSG_SMS_NO_SIGNAL_IND:
- client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
+ client->fe_status = 0;
+
is_status_update = true;
break;
- case MSG_SMS_TRANSMISSION_IND: {
-
- pMsgData++;
- memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
- sizeof(struct TRANSMISSION_STATISTICS_S));
+ case MSG_SMS_TRANSMISSION_IND:
+ smsdvb_update_tx_params(client, p);
-#if 1
- /*
- * FIXME: newer driver doesn't have those fixes
- * Are those firmware-specific stuff?
- */
-
- /* Mo need to correct guard interval
- * (as opposed to old statistics message).
- */
- CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
- CORRECT_STAT_TRANSMISSON_MODE(
- client->sms_stat_dvb.TransmissionData);
-#endif
is_status_update = true;
break;
- }
- case MSG_SMS_HO_PER_SLICES_IND: {
- struct RECEPTION_STATISTICS_EX_S *pReceptionData =
- &client->sms_stat_dvb.ReceptionData;
- struct SRVM_SIGNAL_STATUS_S SignalStatusData;
-
- pMsgData++;
- SignalStatusData.result = pMsgData[0];
- SignalStatusData.snr = pMsgData[1];
- SignalStatusData.inBandPower = (s32) pMsgData[2];
- SignalStatusData.tsPackets = pMsgData[3];
- SignalStatusData.etsPackets = pMsgData[4];
- SignalStatusData.constellation = pMsgData[5];
- SignalStatusData.hpCode = pMsgData[6];
- SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
- SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
- SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
- SignalStatusData.reason = pMsgData[10];
- SignalStatusData.requestId = pMsgData[11];
- pReceptionData->IsRfLocked = pMsgData[16];
- pReceptionData->IsDemodLocked = pMsgData[17];
- pReceptionData->ModemState = pMsgData[12];
- pReceptionData->SNR = pMsgData[1];
- pReceptionData->BER = pMsgData[13];
- pReceptionData->RSSI = pMsgData[14];
- CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
-
- pReceptionData->InBandPwr = (s32) pMsgData[2];
- pReceptionData->CarrierOffset = (s32) pMsgData[15];
- pReceptionData->TotalTSPackets = pMsgData[3];
- pReceptionData->ErrorTSPackets = pMsgData[4];
- /* TS PER */
- if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
- > 0) {
- pReceptionData->TS_PER = (SignalStatusData.etsPackets
- * 100) / (SignalStatusData.tsPackets
- + SignalStatusData.etsPackets);
- } else {
- pReceptionData->TS_PER = 0;
- }
-
- pReceptionData->BERBitCount = pMsgData[18];
- pReceptionData->BERErrorCount = pMsgData[19];
-
- pReceptionData->MRC_SNR = pMsgData[20];
- pReceptionData->MRC_InBandPwr = pMsgData[21];
- pReceptionData->MRC_RSSI = pMsgData[22];
+ case MSG_SMS_HO_PER_SLICES_IND:
+ smsdvb_update_per_slices(client, p);
is_status_update = true;
break;
- }
- case MSG_SMS_GET_STATISTICS_RES: {
- union {
- struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt;
- struct SmsMsgStatisticsInfo_ST dvb;
- } *p = (void *) (phdr + 1);
- struct RECEPTION_STATISTICS_EX_S *pReceptionData =
- &client->sms_stat_dvb.ReceptionData;
-
- is_status_update = true;
+ case MSG_SMS_GET_STATISTICS_RES:
switch (smscore_get_device_mode(client->coredev)) {
case DEVICE_MODE_ISDBT:
case DEVICE_MODE_ISDBT_BDA:
- smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
+ smsdvb_update_isdbt_stats(client, p);
break;
default:
- smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
- }
- if (!pReceptionData->IsDemodLocked) {
- pReceptionData->SNR = 0;
- pReceptionData->BER = 0;
- pReceptionData->BERErrorCount = 0;
- pReceptionData->InBandPwr = 0;
- pReceptionData->ErrorTSPackets = 0;
+ smsdvb_update_dvb_stats(client, p);
}
+ is_status_update = true;
break;
- }
- case MSG_SMS_GET_STATISTICS_EX_RES: {
- union {
- struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST isdbt;
- struct SMSHOSTLIB_STATISTICS_ST dvb;
- } *p = (void *) (phdr + 1);
- struct RECEPTION_STATISTICS_EX_S *pReceptionData =
- &client->sms_stat_dvb.ReceptionData;
+ /* Only for ISDB-T */
+ case MSG_SMS_GET_STATISTICS_EX_RES:
+ smsdvb_update_isdbt_stats_ex(client, p);
is_status_update = true;
-
- switch (smscore_get_device_mode(client->coredev)) {
- case DEVICE_MODE_ISDBT:
- case DEVICE_MODE_ISDBT_BDA:
- smsdvb_update_isdbt_stats_ex(pReceptionData, &p->isdbt);
- break;
- default:
- smsdvb_update_dvb_stats(pReceptionData, &p->dvb);
- }
- if (!pReceptionData->IsDemodLocked) {
- pReceptionData->SNR = 0;
- pReceptionData->BER = 0;
- pReceptionData->BERErrorCount = 0;
- pReceptionData->InBandPwr = 0;
- pReceptionData->ErrorTSPackets = 0;
- }
-
break;
- }
default:
sms_info("message not handled");
}
smscore_putbuffer(client->coredev, cb);
if (is_status_update) {
- if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
- client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
- | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (client->fe_status == FE_HAS_LOCK) {
sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
- if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
- == 0)
+ if (client->last_per == c->block_error.stat[0].uvalue)
sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
else
- sms_board_dvb3_event(client,
- DVB3_EVENT_UNC_ERR);
-
+ sms_board_dvb3_event(client, DVB3_EVENT_UNC_ERR);
} else {
- if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
- client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
- else
- client->fe_status = 0;
+ smsdvb_stats_not_ready(fe);
+
sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
}
complete(&client->stats_done);
@@ -612,13 +847,20 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
Msg.msgFlags = 0;
Msg.msgLength = sizeof(Msg);
- /*
- * Check for firmware version, to avoid breaking for old cards
- */
- if (client->coredev->fw_version >= 0x800)
- Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ;
- else
+ switch (smscore_get_device_mode(client->coredev)) {
+ case DEVICE_MODE_ISDBT:
+ case DEVICE_MODE_ISDBT_BDA:
+ /*
+ * Check for firmware version, to avoid breaking for old cards
+ */
+ if (client->coredev->fw_version >= 0x800)
+ Msg.msgType = MSG_SMS_GET_STATISTICS_EX_REQ;
+ else
+ Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
+ break;
+ default:
Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;
+ }
rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
&client->stats_done);
@@ -628,12 +870,12 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
static inline int led_feedback(struct smsdvb_client_t *client)
{
- if (client->fe_status & FE_HAS_LOCK)
- return sms_board_led_feedback(client->coredev,
- (client->sms_stat_dvb.ReceptionData.BER
- == 0) ? SMS_LED_HI : SMS_LED_LO);
- else
+ if (!(client->fe_status & FE_HAS_LOCK))
return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+
+ return sms_board_led_feedback(client->coredev,
+ (client->legacy_ber == 0) ?
+ SMS_LED_HI : SMS_LED_LO);
}
static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
@@ -655,11 +897,12 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
{
int rc;
struct smsdvb_client_t *client;
+
client = container_of(fe, struct smsdvb_client_t, frontend);
rc = smsdvb_send_statistics_request(client);
- *ber = client->sms_stat_dvb.ReceptionData.BER;
+ *ber = client->legacy_ber;
led_feedback(client);
@@ -668,21 +911,21 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc;
-
+ s32 power = (s32) c->strength.stat[0].uvalue;
struct smsdvb_client_t *client;
+
client = container_of(fe, struct smsdvb_client_t, frontend);
rc = smsdvb_send_statistics_request(client);
- if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
+ if (power < -95)
*strength = 0;
- else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
- *strength = 100;
+ else if (power > -29)
+ *strength = 65535;
else
- *strength =
- (client->sms_stat_dvb.ReceptionData.InBandPwr
- + 95) * 3 / 2;
+ *strength = (power + 95) * 65535 / 66;
led_feedback(client);
@@ -691,13 +934,16 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc;
struct smsdvb_client_t *client;
+
client = container_of(fe, struct smsdvb_client_t, frontend);
rc = smsdvb_send_statistics_request(client);
- *snr = client->sms_stat_dvb.ReceptionData.SNR;
+ /* Preferred scale for SNR with legacy API: 0.1 dB */
+ *snr = c->cnr.stat[0].svalue / 100;
led_feedback(client);
@@ -707,12 +953,14 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
{
int rc;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct smsdvb_client_t *client;
+
client = container_of(fe, struct smsdvb_client_t, frontend);
rc = smsdvb_send_statistics_request(client);
- *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
+ *ucblocks = c->block_error.stat[0].uvalue;
led_feedback(client);
@@ -743,7 +991,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
int ret;
- client->fe_status = FE_HAS_SIGNAL;
+ client->fe_status = 0;
client->event_fe_state = -1;
client->event_unc_state = -1;
fe->dtv_property_cache.delivery_system = SYS_DVBT;
@@ -871,6 +1119,8 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe)
container_of(fe, struct smsdvb_client_t, frontend);
struct smscore_device_t *coredev = client->coredev;
+ smsdvb_stats_not_ready(fe);
+
switch (smscore_get_device_mode(coredev)) {
case DEVICE_MODE_DVBT:
case DEVICE_MODE_DVBT_BDA:
@@ -883,150 +1133,10 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe)
}
}
-static int smsdvb_get_frontend_dvb(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
- struct smsdvb_client_t *client =
- container_of(fe, struct smsdvb_client_t, frontend);
- struct TRANSMISSION_STATISTICS_S *td =
- &client->sms_stat_dvb.TransmissionData;
-
- fep->frequency = td->Frequency;
-
- switch (td->Bandwidth) {
- case 6:
- fep->bandwidth_hz = 6000000;
- break;
- case 7:
- fep->bandwidth_hz = 7000000;
- break;
- case 8:
- fep->bandwidth_hz = 8000000;
- break;
- }
-
- switch (td->TransmissionMode) {
- case 2:
- fep->transmission_mode = TRANSMISSION_MODE_2K;
- break;
- case 8:
- fep->transmission_mode = TRANSMISSION_MODE_8K;
- }
-
- switch (td->GuardInterval) {
- case 0:
- fep->guard_interval = GUARD_INTERVAL_1_32;
- break;
- case 1:
- fep->guard_interval = GUARD_INTERVAL_1_16;
- break;
- case 2:
- fep->guard_interval = GUARD_INTERVAL_1_8;
- break;
- case 3:
- fep->guard_interval = GUARD_INTERVAL_1_4;
- break;
- }
-
- switch (td->CodeRate) {
- case 0:
- fep->code_rate_HP = FEC_1_2;
- break;
- case 1:
- fep->code_rate_HP = FEC_2_3;
- break;
- case 2:
- fep->code_rate_HP = FEC_3_4;
- break;
- case 3:
- fep->code_rate_HP = FEC_5_6;
- break;
- case 4:
- fep->code_rate_HP = FEC_7_8;
- break;
- }
-
- switch (td->LPCodeRate) {
- case 0:
- fep->code_rate_LP = FEC_1_2;
- break;
- case 1:
- fep->code_rate_LP = FEC_2_3;
- break;
- case 2:
- fep->code_rate_LP = FEC_3_4;
- break;
- case 3:
- fep->code_rate_LP = FEC_5_6;
- break;
- case 4:
- fep->code_rate_LP = FEC_7_8;
- break;
- }
-
- switch (td->Constellation) {
- case 0:
- fep->modulation = QPSK;
- break;
- case 1:
- fep->modulation = QAM_16;
- break;
- case 2:
- fep->modulation = QAM_64;
- break;
- }
-
- switch (td->Hierarchy) {
- case 0:
- fep->hierarchy = HIERARCHY_NONE;
- break;
- case 1:
- fep->hierarchy = HIERARCHY_1;
- break;
- case 2:
- fep->hierarchy = HIERARCHY_2;
- break;
- case 3:
- fep->hierarchy = HIERARCHY_4;
- break;
- }
-
- fep->inversion = INVERSION_AUTO;
-
- return 0;
-}
-
-static int smsdvb_get_frontend_isdb(struct dvb_frontend *fe)
-{
- struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
- struct smsdvb_client_t *client =
- container_of(fe, struct smsdvb_client_t, frontend);
- struct TRANSMISSION_STATISTICS_S *td =
- &client->sms_stat_dvb.TransmissionData;
-
- fep->frequency = td->Frequency;
- fep->bandwidth_hz = 6000000;
- /* todo: retrive the other parameters */
-
- return 0;
-}
-
+/* Nothing to do here, as stats are automatically updated */
static int smsdvb_get_frontend(struct dvb_frontend *fe)
{
- struct smsdvb_client_t *client =
- container_of(fe, struct smsdvb_client_t, frontend);
- struct smscore_device_t *coredev = client->coredev;
-
- switch (smscore_get_device_mode(coredev)) {
- case DEVICE_MODE_DVBT:
- case DEVICE_MODE_DVBT_BDA:
- return smsdvb_get_frontend_dvb(fe);
- case DEVICE_MODE_ISDBT:
- case DEVICE_MODE_ISDBT_BDA:
- return smsdvb_get_frontend_isdb(fe);
- default:
- return -EINVAL;
- }
+ return 0;
}
static int smsdvb_init(struct dvb_frontend *fe)