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

Bug#413238: Kernel 2.6.18 error regarding dibusb-mb driver (TwinHan Magic Box USB1.1)



Package: linux-2.6
Version: 2.6.18.dfsg.1-10

The standard kernel 2.6.18 (and also its debianized version) has a bug 
regarding the driver:

drivers/media/dvb/dvb-usb/dibusb-mb.c
and 
drivers/media/dvb/dvb-usb/dibusb-common.c

It results in using devices like the DVB-T TwinHan Magic box unusable
since it does not tune anymore. The driover does not complain in any way
while loading. It just does not work anymore. It worked in the kernels 
2.6.17 and lower and is reported to work aganin in 2.6.19.

The problem is in the first function of
drivers/media/dvb/dvb-usb/dibusb-mb.c:

stock 2.6.17 (also Debian)

static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = d->priv;

    demod_cfg.demod_address = 0x8;
    demod_cfg.pll_set = dvb_usb_pll_set_i2c;
    demod_cfg.pll_init = dvb_usb_pll_init_i2c;

    if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
        return -ENODEV;

    d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;

    return 0;
}

stock 2.6.18 (as Debian, does NOT tune)

static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = d->priv;

    demod_cfg.demod_address = 0x8;

    if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
        d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
        d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
        return -ENODEV;
    }

    d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;

    return 0;
}

stock 2.6.19 (here the error was recognized and the tuner commands were
moved outside the if-clause)

static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = adap->priv;

    demod_cfg.demod_address = 0x8;
     if ((adap->fe = dib3000mb_attach(&demod_cfg,&adap->dev->i2c_adap,&st->ops)) == NULL)
        return -ENODEV;

    adap->fe->ops.tuner_ops.init       = dvb_usb_tuner_init_i2c;
    adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;

    adap->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;

    return 0;
}

corrected version for 2.6.18:

static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = d->priv;

    demod_cfg.demod_address = 0x8;

    if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
        return -ENODEV;

    d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
    d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;


    d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;

    return 0;
}

In addition two lines in dibusb-common.c must be removed in the function 
dibusb_dib3000mc_frontend_attach. These are also new from 2.6.17 to .18
In 2.6.19 this function is completely changed. I have also a dib3000mc device 
(AverTV DVB-T USB2.0 A800) which still works fine after these changes.

kernel 2.6.17:

int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = d->priv;

    demod_cfg.pll_set = dvb_usb_pll_set_i2c;
    demod_cfg.pll_init = dvb_usb_pll_init_i2c;

    for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
        if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
            d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
            return 0;
        }

    return -ENODEV;
}




kernel 2.6.18 (also Debian)

int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = d->priv;

    for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)         
		if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
			d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
            d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
            d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
            return 0;
        }

    return -ENODEV;
}

correct version for 2.6.18:

int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
{
    struct dib3000_config demod_cfg;
    struct dibusb_state *st = d->priv;

    for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd;
demod_cfg.demod_address++)         
		if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
			d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
            return 0;
        }

    return -ENODEV;
}


I have attached a diff for the debian-kernel 2.6.18 If you have
questions pleas do not hesitate to mail me: hwahl (at) hwahl (dot) de

-- 
Hartmut Wahl <hwahl (at) hwahl (dot) de>
www: http://www.hwahl.de
PGP: http://www.hwahl.de/HartmutWahl.asc
diff -rc linux-source-2.6.18.org/drivers/media/dvb/dvb-usb/dibusb-common.c linux-source-2.6.18/drivers/media/dvb/dvb-usb/dibusb-common.c
*** linux-source-2.6.18.org/drivers/media/dvb/dvb-usb/dibusb-common.c	2007-02-28 22:22:06.000000000 +0100
--- linux-source-2.6.18/drivers/media/dvb/dvb-usb/dibusb-common.c	2007-02-27 20:00:28.000000000 +0100
***************
*** 175,182 ****
  
  	for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
  		if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
- 			d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
- 			d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
  			d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
  			return 0;
  		}
--- 175,180 ----
diff -rc linux-source-2.6.18.org/drivers/media/dvb/dvb-usb/dibusb-mb.c linux-source-2.6.18/drivers/media/dvb/dvb-usb/dibusb-mb.c
*** linux-source-2.6.18.org/drivers/media/dvb/dvb-usb/dibusb-mb.c	2007-02-28 22:22:06.000000000 +0100
--- linux-source-2.6.18/drivers/media/dvb/dvb-usb/dibusb-mb.c	2007-02-27 19:59:05.000000000 +0100
***************
*** 21,31 ****
  
  	demod_cfg.demod_address = 0x8;
  
! 	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
! 		d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
! 		d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
  		return -ENODEV;
! 	}
  
  	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
  
--- 21,31 ----
  
  	demod_cfg.demod_address = 0x8;
  
! 	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) 
  		return -ENODEV;
! 	
! 	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
! 	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
  
  	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
  

Reply to: