Re: [PATCH] Garbage diseqc messages emitted by bt8xx/dst module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Gnome42 Gnome42 wrote:

Sorry, yeah -- I didn't realize anybody was using that patch. That part
was actually an attempt to resolve another issue with the card, but it
didn't work very well as you discovered. The problem is that the dst
can't actually change voltage between 18V and 13V without issuing a
tuning command (it can only turn the voltage off or back to whatever the
last tuning command set it at), but the software I'm working on wants to
be able to control the voltage without actually tuning.


No prob, I thought it might me something like that. :)

So I put an extra tuning command in there to try to get the voltage
switch to happen immediately, but the dst bridge really doesn't like it
when you send multiple tuning requests in rapid succession, which is
what happens in the normal case -- i.e. the software sets the voltage
and shortly thereafter issues a tuning request.

You should definitely leave in the set_polarization line though (just
take out the write_tuna), or alternatively I have an updated patch with
some more stuff fixed if you're interested.


Yes please! Send it along, I'm interested in testing.

Thanks for your efforts.

Here's the latest patch I've got. List of changes:

* 5-byte diseqc for supporting cards (USALS support)
* Fixes garbage commands caused by tone/power and tuner command buffer conflict.
* Mini-DiSEqC commands corrected based on observations with a scope.
* More reliable about changing desired LNB voltage (though it still won't switch it until tuning) * Error reporting is much more thorough -- any failed commands should now return a failure code for the ioctl. If you see applications erroring out with failed ioctls, this is why. But it's much better this way -- the command would have failed either way, but now the application is told about it, and can retry, etc. -- or even better, we can actually fix any problems that are revealed. * Doesn't update internal state on unsuccessful commands to avoid cached state diverging from real state.
* Avoids resending redundant tone/power commands.

diff -r b6b2d7591d38 linux/drivers/media/dvb/bt8xx/dst.c
--- a/linux/drivers/media/dvb/bt8xx/dst.c	Thu Jun 08 18:00:33 2006 -0300
+++ b/linux/drivers/media/dvb/bt8xx/dst.c	Fri Jun 09 14:04:51 2006 -0400
@@ -374,7 +374,7 @@ static int dst_set_bandwidth(struct dst_
 	state->bandwidth = bandwidth;
 
 	if (state->dst_type != DST_TYPE_IS_TERR)
-		return 0;
+		return -EOPNOTSUPP;
 
 	switch (bandwidth) {
 	case BANDWIDTH_6_MHZ:
@@ -441,10 +441,10 @@ static int dst_set_symbolrate(struct dst
 	u32 symcalc;
 	u64 sval;
 
+	if (state->dst_type == DST_TYPE_IS_TERR)
+		return -EOPNOTSUPP;
+
 	state->symbol_rate = srate;
-	if (state->dst_type == DST_TYPE_IS_TERR) {
-		return 0;
-	}
 	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 	srate /= 1000;
 	if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
@@ -473,7 +473,7 @@ static int dst_set_modulation(struct dst
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 {
 	if (state->dst_type != DST_TYPE_IS_CABLE)
-		return 0;
+		return -EOPNOTSUPP;
 
 	state->modulation = modulation;
 	switch (modulation) {
@@ -1058,15 +1058,42 @@ static int dst_tone_power_cmd(struct dst
 {
 	u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
 
-	if (state->dst_type == DST_TYPE_IS_TERR)
-		return 0;
-	paket[4] = state->tx_tuna[4];
-	paket[2] = state->tx_tuna[2];
-	paket[3] = state->tx_tuna[3];
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+
+	switch (state->tone) {
+	case SEC_TONE_OFF:
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+			paket[2] = 0x00;
+		else
+			paket[2] = 0xff;
+		break;
+	case SEC_TONE_ON:
+		paket[2] = 0x02;
+		break;
+	}
+
+	switch (state->minicmd) {
+	case SEC_MINI_A:
+		paket[3] = 0x00;
+		break;
+	case SEC_MINI_B:
+		paket[3] = 0x01;
+		break;
+	}
+	state->minicmd = (fe_sec_mini_cmd_t)0;
+
+	switch (state->voltage) {
+	case SEC_VOLTAGE_OFF:
+		paket[4] = 0x00;
+		break;
+	default:
+		paket[4] = 0x01;
+		break;
+	}
+
 	paket[7] = dst_check_sum (paket, 7);
-	dst_command(state, paket, 8);
-
-	return 0;
+	return dst_command(state, paket, 8);
 }
 
 static int dst_get_tuna(struct dst_state *state)
@@ -1188,94 +1215,92 @@ static int dst_set_diseqc(struct dvb_fro
 	u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
 
 	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+
+	if (cmd->msg_len > 0 && cmd->msg_len < 5)
+		memcpy(&paket[3], cmd->msg, cmd->msg_len);
+	else if(cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
+		memcpy(&paket[2], cmd->msg, cmd->msg_len);
+	else
+		return -EINVAL;
+
+	paket[7] = dst_check_sum(&paket[0], 7);
+	return dst_command(state, paket, 8);
+}
+
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct dst_state *state = fe->demodulator_priv;
+	int retval;
+
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+        if (voltage == state->voltage)
 		return 0;
-	if (cmd->msg_len == 0 || cmd->msg_len > 4)
-		return -EINVAL;
-	memcpy(&paket[3], cmd->msg, cmd->msg_len);
-	paket[7] = dst_check_sum(&paket[0], 7);
-	dst_command(state, paket, 8);
-	return 0;
-}
-
-static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	int need_cmd;
-	struct dst_state *state = fe->demodulator_priv;
-
-	state->voltage = voltage;
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
-
-	need_cmd = 0;
 
 	switch (voltage) {
 	case SEC_VOLTAGE_13:
 	case SEC_VOLTAGE_18:
-		if ((state->diseq_flags & HAS_POWER) == 0)
-			need_cmd = 1;
-		state->diseq_flags |= HAS_POWER;
-		state->tx_tuna[4] = 0x01;
-		break;
 	case SEC_VOLTAGE_OFF:
-		need_cmd = 1;
-		state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
-		state->tx_tuna[4] = 0x00;
+		dst_set_polarization(state);
+		retval = dst_tone_power_cmd(state);
+		if(retval == 0)
+		{
+			state->voltage = voltage;
+			if(voltage == SEC_VOLTAGE_OFF)
+				state->diseq_flags |= HAS_POWER;
+			else
+				state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
+		}
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+	return retval;
+}
+
+static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct dst_state *state = fe->demodulator_priv;
+	int retval;
+
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+        if (tone == state->tone)
+		return 0;
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+	case SEC_TONE_ON:
+		retval = dst_tone_power_cmd(state);
+		if(retval == 0)
+			state->tone = tone;
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+	return retval;
+}
+
+static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+
+	switch (minicmd) {
+	case SEC_MINI_A:
+	case SEC_MINI_B:
+		state->minicmd = minicmd;
+		return dst_tone_power_cmd(state);
 		break;
 	default:
 		return -EINVAL;
 	}
-
-	if (need_cmd)
-		dst_tone_power_cmd(state);
-
-	return 0;
-}
-
-static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	state->tone = tone;
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
-
-	switch (tone) {
-	case SEC_TONE_OFF:
-		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
-		    state->tx_tuna[2] = 0x00;
-		else
-		    state->tx_tuna[2] = 0xff;
-		break;
-
-	case SEC_TONE_ON:
-		state->tx_tuna[2] = 0x02;
-		break;
-	default:
-		return -EINVAL;
-	}
-	dst_tone_power_cmd(state);
-
-	return 0;
-}
-
-static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return 0;
-	state->minicmd = minicmd;
-	switch (minicmd) {
-	case SEC_MINI_A:
-		state->tx_tuna[3] = 0x02;
-		break;
-	case SEC_MINI_B:
-		state->tx_tuna[3] = 0xff;
-		break;
-	}
-	dst_tone_power_cmd(state);
-
-	return 0;
 }
 
 
@@ -1293,6 +1318,7 @@ static int dst_init(struct dvb_frontend 
 	state->inversion = INVERSION_OFF;
 	state->voltage = SEC_VOLTAGE_13;
 	state->tone = SEC_TONE_OFF;
+	state->minicmd = 0;
 	state->diseq_flags = 0;
 	state->k22 = 0x02;
 	state->bandwidth = BANDWIDTH_7_MHZ;
@@ -1325,20 +1351,20 @@ static int dst_read_signal_strength(stru
 {
 	struct dst_state *state = fe->demodulator_priv;
 
-	dst_get_signal(state);
+	int retval = dst_get_signal(state);
 	*strength = state->decode_strength;
 
-	return 0;
+	return retval;
 }
 
 static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
 	struct dst_state *state = fe->demodulator_priv;
 
-	dst_get_signal(state);
+	int retval = dst_get_signal(state);
 	*snr = state->decode_snr;
 
-	return 0;
+	return retval;
 }
 
 static int dst_set_frontend(struct dvb_frontend* fe,
@@ -1347,10 +1373,12 @@ static int dst_set_frontend(struct dvb_f
 			    int *delay,
 			    fe_status_t *status)
 {
+	int retval = -EINVAL;
 	struct dst_state *state = fe->demodulator_priv;
 
 	if (p != NULL) {
-		dst_set_freq(state, p->frequency);
+		if ((retval = dst_set_freq(state, p->frequency)) != 0)
+			return retval;
 		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
 
 		if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1368,14 +1396,15 @@ static int dst_set_frontend(struct dvb_f
 			dst_set_symbolrate(state, p->u.qam.symbol_rate);
 			dst_set_modulation(state, p->u.qam.modulation);
 		}
-		dst_write_tuna(fe);
+		if(retval == 0)
+			retval = dst_write_tuna(fe);
 	}
 
 	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
 		dst_read_status(fe, status);
 
 	*delay = HZ/10;
-	return 0;
+	return retval;
 }
 
 static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
_______________________________________________

linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux