[linux-dvb] [PATCH] Garbage diseqc messages emitted by bt8xx/dst
module
Yeasah Pell
yeasah at schwide.com
Fri Jun 9 20:36:27 CEST 2006
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.
-------------- next part --------------
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)
More information about the linux-dvb
mailing list