Re: Garbage diseqc messages emitted by bt8xx/dst module

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

 



linuxtv@xxxxxxxxxxxxxx wrote:

There is some fairly strange code in bt8xx/dst.c which
generates garbage diseqc messages because of wrongly initialized data.

For some strange reason the diseqc messages share the tx_tuna[] array
which has absolutely nothing to do with diseqc, but which is used for
complete distinct and unfrelated tuning messages.

And because the tx_tuna[] array gets initialized for tuning messages
the first few times the dst_tone_power_cmd() function is invoked
unrelated garbage frequency data gets sent to diseqc.

Has anyone actually tested this code and looked at the messages
that get written to cards?  Just run it once, with debugging turned
on, and look at the garbage bytes that get written to the card!

Regards
LinuxTV
I agree, this is bogus. Here's a patch that should solve this. It replaces the 18V/13V patch I sent earlier (but not the 5-byte diseqc patch I sent, that one's still good)

diff -r c993e945fcea linux/drivers/media/dvb/bt8xx/dst.c
--- a/linux/drivers/media/dvb/bt8xx/dst.c	Fri May 19 13:08:09 2006 -0300
+++ b/linux/drivers/media/dvb/bt8xx/dst.c	Sun May 21 11:20:13 2006 -0400
@@ -1058,11 +1058,47 @@ 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)
+	if (state->dst_type != DST_TYPE_IS_SAT)
 		return 0;
-	paket[4] = state->tx_tuna[4];
-	paket[2] = state->tx_tuna[2];
-	paket[3] = state->tx_tuna[3];
+
+	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;
+	default:
+		break;
+	}
+
+	switch (state->minicmd) {
+	case SEC_MINI_A:
+		paket[3] = 0x02;
+		break;
+	case SEC_MINI_B:
+		paket[3] = 0xff;
+		break;
+	default:
+		break;
+	}
+
+	switch (state->voltage) {
+	case SEC_VOLTAGE_13:
+	case SEC_VOLTAGE_18:
+		paket[4] = 0x01;
+		break;
+	case SEC_VOLTAGE_OFF:
+		paket[4] = 0x00;
+		break;
+	default:
+		break;
+	}
+
 	paket[7] = dst_check_sum (paket, 7);
 	dst_command(state, paket, 8);
 
@@ -1112,8 +1148,6 @@ static int dst_get_tuna(struct dst_state
 	return 1;
 }
 
-static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-
 static int dst_write_tuna(struct dvb_frontend *fe)
 {
 	struct dst_state *state = fe->demodulator_priv;
@@ -1123,9 +1157,10 @@ static int dst_write_tuna(struct dvb_fro
 	dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
 	state->decode_freq = 0;
 	state->decode_lock = state->decode_strength = state->decode_snr = 0;
-	if (state->dst_type == DST_TYPE_IS_SAT) {
-		if (!(state->diseq_flags & HAS_POWER))
-			dst_set_voltage(fe, SEC_VOLTAGE_13);
+	if (state->dst_type == DST_TYPE_IS_SAT &&
+	    !(state->diseq_flags & HAS_POWER)) {
+		state->voltage = SEC_VOLTAGE_13;
+		dst_tone_power_cmd(state);
 	}
 	state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
 	mutex_lock(&state->dst_mutex);
@@ -1199,34 +1239,32 @@ static int dst_set_diseqc(struct dvb_fro
 
 static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
-	int need_cmd;
+	int need_cmd = 0;
 	struct dst_state *state = fe->demodulator_priv;
 
-	state->voltage = voltage;
 	if (state->dst_type != DST_TYPE_IS_SAT)
 		return 0;
 
-	need_cmd = 0;
+	/* a command is needed if voltage is changing */
+	if (state->voltage != voltage)
+		need_cmd = 1;
 
 	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;
+		state->voltage = voltage;
+		dst_tone_power_cmd(state);
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	if (need_cmd)
-		dst_tone_power_cmd(state);
+	/* apparently the actual voltage is set in the tuner command. ugh. */
+	if (need_cmd) {
+		dst_set_polarization(state);
+		dst_write_tuna(fe);
+	}
 
 	return 0;
 }
@@ -1235,25 +1273,18 @@ static int dst_set_tone(struct dvb_front
 {
 	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;
+		state->tone = tone;
+		dst_tone_power_cmd(state);
 		break;
 	default:
 		return -EINVAL;
 	}
-	dst_tone_power_cmd(state);
 
 	return 0;
 }
@@ -1264,16 +1295,16 @@ static int dst_send_burst(struct dvb_fro
 
 	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);
+		state->minicmd = minicmd;
+		dst_tone_power_cmd(state);
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	return 0;
 }
_______________________________________________

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