Commit b4059095 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] siano: use the newer stats message for recent firmwares

The old statistics request don't work with newer firmwares.
Add a logic to use the newer stats if firmware major is 8.
Note that I have only 2 devices here, one with firmware 2.1
(Hauppauge model 55009 Rev B1F7) and another one with
firmware 8.1. We may need to adjust the firmware minimal
version for the *_EX message variants, as we start finding
firmware versions between 2.x and 8.x.
This patch was based on Doron Cohen patch:
	http://patchwork.linuxtv.org/patch/7886/



Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0c189fa6
Loading
Loading
Loading
Loading
+103 −0
Original line number Diff line number Diff line
@@ -800,6 +800,66 @@ struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
	u32 SmsToHostTxErrors; /* Total number of transmission errors. */
};

struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST {
	u32 StatisticsType; /* Enumerator identifying the type of the
				* structure.  Values are the same as
				* SMSHOSTLIB_DEVICE_MODES_E
				*
				* This field MUST always be first in any
				* statistics structure */

	u32 FullSize; /* Total size of the structure returned by the modem.
		       * If the size requested by the host is smaller than
		       * FullSize, the struct will be truncated */

	/* Common parameters */
	u32 IsRfLocked; /* 0 - not locked, 1 - locked */
	u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
	u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */

	/* Reception quality */
	s32  SNR; /* dB */
	s32  RSSI; /* dBm */
	s32  InBandPwr; /* In band power in dBM */
	s32  CarrierOffset; /* Carrier Offset in Hz */

	/* Transmission parameters */
	u32 Frequency; /* Frequency in Hz */
	u32 Bandwidth; /* Bandwidth in MHz */
	u32 TransmissionMode; /* ISDB-T transmission mode */
	u32 ModemState; /* 0 - Acquisition, 1 - Locked */
	u32 GuardInterval; /* Guard Interval, 1 divided by value */
	u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
	u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
	u32 NumOfLayers; /* Number of ISDB-T layers in the network */

	u32 SegmentNumber; /* Segment number for ISDB-Tsb */
	u32 TuneBW;	   /* Tuned bandwidth - BW_ISDBT_1SEG / BW_ISDBT_3SEG */

	/* Per-layer information */
	/* Layers A, B and C */
	struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST	LayerInfo[3];
	/* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */

	/* Interface information */
	u32 Reserved1;    /* Was SmsToHostTxErrors - obsolete . */
 /* Proprietary information */
	u32 ExtAntenna;    /* Obsolete field. */
	u32 ReceptionQuality;
	u32 EwsAlertActive;   /* Signals if EWS alert is currently on */
	u32 LNAOnOff;	/* Internal LNA state: 0: OFF, 1: ON */

	u32 RfAgcLevel;	 /* RF AGC Level [linear units], full gain = 65535 (20dB) */
	u32 BbAgcLevel;    /* Baseband AGC level [linear units], full gain = 65535 (71.5dB) */
	u32 FwErrorsCounter;   /* Application errors - should be always zero */
	u8 FwErrorsHistoryArr[8]; /* Last FW errors IDs - first is most recent, last is oldest */

	s32  MRC_SNR;     /* dB */
	u32 SNRFullRes;    /* dB x 65536 */
	u32 Reserved4[4];
};


struct PID_STATISTICS_DATA_S {
	struct PID_BURST_S {
		u32 size;
@@ -880,6 +940,35 @@ struct RECEPTION_STATISTICS_S {
	s32 MRC_InBandPwr;	/* In band power in dBM */
};

struct RECEPTION_STATISTICS_EX_S {
	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */

	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
	s32 SNR;		/* dB */
	u32 BER;		/* Post Viterbi BER [1E-5] */
	u32 BERErrorCount;	/* Number of erronous SYNC bits. */
	u32 BERBitCount;	/* Total number of SYNC bits. */
	u32 TS_PER;		/* Transport stream PER,
	0xFFFFFFFF indicate N/A */
	u32 MFER;		/* DVB-H frame error rate in percentage,
	0xFFFFFFFF indicate N/A, valid only for DVB-H */
	s32 RSSI;		/* dBm */
	s32 InBandPwr;		/* In band power in dBM */
	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
	u32 ErrorTSPackets;	/* Number of erroneous
	transport-stream packets */
	u32 TotalTSPackets;	/* Total number of transport-stream packets */

	s32  RefDevPPM;
	s32  FreqDevHz;

	s32 MRC_SNR;		/* dB */
	s32 MRC_RSSI;		/* dBm */
	s32 MRC_InBandPwr;	/* In band power in dBM */
};


/* Statistics information returned as response for
 * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
@@ -895,6 +984,20 @@ struct SMSHOSTLIB_STATISTICS_DVB_S {
	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
};

/* Statistics information returned as response for
 * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
struct SMSHOSTLIB_STATISTICS_DVB_EX_S {
	/* Reception */
	struct RECEPTION_STATISTICS_EX_S ReceptionData;

	/* Transmission parameters */
	struct TRANSMISSION_STATISTICS_S TransmissionData;

	/* Burst parameters, valid only for DVB-H */
#define	SRVM_MAX_PID_FILTERS 8
	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
};

struct SRVM_SIGNAL_STATUS_S {
	u32 result;
	u32 snr;
+157 −20
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ struct smsdvb_client_t {
	struct completion       tune_done;
	struct completion       stats_done;

	struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
	struct SMSHOSTLIB_STATISTICS_DVB_EX_S sms_stat_dvb;
	int event_fe_state;
	int event_unc_state;
};
@@ -115,12 +115,10 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
	}
}


static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
				   struct SMSHOSTLIB_STATISTICS_ST *p)
{
	if (sms_dbg & 2) {
		printk(KERN_DEBUG "Reserved = %d", p->Reserved);
		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
@@ -132,6 +130,7 @@ static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionDat
		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
@@ -163,17 +162,24 @@ static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionDat
		printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
	}

	/* 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;
};


static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
				    struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
{
	int i;
@@ -212,18 +218,100 @@ static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionD
		}
	}

	/* 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->ErrorTSPackets = 0;
	pReceptionData->BER = 0;
	pReceptionData->BERErrorCount = 0;
	pReceptionData->CarrierOffset = p->CarrierOffset;
	pReceptionData->ErrorTSPackets = p->LayerInfo[0].ErrorTSPackets;
	pReceptionData->TotalTSPackets = p->LayerInfo[0].TotalTSPackets;
	pReceptionData->MFER = 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;
	}
}

static void smsdvb_update_isdbt_stats_ex(struct RECEPTION_STATISTICS_EX_S *pReceptionData,
				    struct SMSHOSTLIB_STATISTICS_ISDBT_EX_ST *p)
{
	int i;

	if (sms_dbg & 2) {
		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
		printk(KERN_DEBUG "SNR = %d", p->SNR);
		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
		printk(KERN_DEBUG "SystemType = %d", p->SystemType);
		printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
		printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
		printk(KERN_DEBUG "SegmentNumber = %d", p->SegmentNumber);
		printk(KERN_DEBUG "TuneBW = %d", p->TuneBW);
		for (i = 0; i < 3; i++) {
		pReceptionData->BER += p->LayerInfo[i].BER;
		pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
		pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
			printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
			printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
			printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
			printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
			printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
			printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
			printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
			printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
			printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
			printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
			printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
			printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
		}
	}

	/* 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;

	/* 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;
	}
}

@@ -260,21 +348,29 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
		break;

	case MSG_SMS_TRANSMISSION_IND: {

		pMsgData++;
		memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
				sizeof(struct TRANSMISSION_STATISTICS_S));

#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_S *pReceptionData =
		struct RECEPTION_STATISTICS_EX_S *pReceptionData =
				&client->sms_stat_dvb.ReceptionData;
		struct SRVM_SIGNAL_STATUS_S SignalStatusData;

@@ -329,7 +425,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
			struct SMSHOSTLIB_STATISTICS_ISDBT_ST  isdbt;
			struct SmsMsgStatisticsInfo_ST         dvb;
		} *p = (void *) (phdr + 1);
		struct RECEPTION_STATISTICS_S *pReceptionData =
		struct RECEPTION_STATISTICS_EX_S *pReceptionData =
				&client->sms_stat_dvb.ReceptionData;

		is_status_update = true;
@@ -352,6 +448,34 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)

		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;
		}

		break;
	}
	default:
		sms_info("message not handled");
	}
@@ -466,10 +590,23 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
{
	int rc;
	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
				    DVBT_BDA_CONTROL_MSG_ID,
				    HIF_TASK,
				    sizeof(struct SmsMsgHdr_ST), 0 };
	struct SmsMsgHdr_ST Msg;


	Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
	Msg.msgDstId = HIF_TASK;
	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
		Msg.msgType = MSG_SMS_GET_STATISTICS_REQ;

	smsendian_handle_tx_message((struct SmsMsgHdr_S *)&Msg);

	rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
					 &client->stats_done);