Commit d42f1cb2 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[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: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ff702eb8
......@@ -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);
/* 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 {
pReceptionData->TS_PER = 0;
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,
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);
/* 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 {
pReceptionData->TS_PER = 0;
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);
}
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;
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;
}
/* Only for ISDB-T */
case MSG_SMS_GET_STATISTICS_EX_RES:
smsdvb_update_isdbt_stats_ex(client, p);
is_status_update = true;
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,6 +847,9 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
Msg.msgFlags = 0;
Msg.msgLength = sizeof(Msg);
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
*/
......@@ -619,6 +857,10 @@ static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment