Notes Apr 29 14:56:17 mythtv kernel: [ 2385.788462] cxusb: No IR receiver detected on this device. Apr 29 14:56:17 mythtv kernel: [ 2385.788472] usb 3-2: DVB: registering adapter 2 frontend 0 (Zarlink ZL10353 DVB-T)... Apr 29 14:56:17 mythtv kernel: [ 2385.788565] xc2028 11-0061: creating new instance Apr 29 14:56:17 mythtv kernel: [ 2385.788568] xc2028 11-0061: type set to XCeive xc2028/xc3028 tuner Apr 29 14:56:17 mythtv kernel: [ 2385.790357] xc2028 11-0061: Loading 80 firmware images from xc3028-v27.fw, type: xc2028 firmware, ver 2.7 Apr 29 14:56:17 mythtv kernel: [ 2385.790714] dvb-usb: DViCO FusionHDTV DVB-T Dual Digital 4 successfully initialized and connected. Apr 29 14:56:17 mythtv kernel: [ 2385.790760] usbcore: registered new interface driver dvb_usb_cxusb Apr 29 14:58:32 mythtv kernel: [ 2520.932221] xc2028 10-0061: Loading firmware for type=BASE F8MHZ (3), id 0000000000000000. Apr 29 14:58:32 mythtv kernel: [ 2520.944221] cxusb: i2c wr: len=64 is too big! Apr 29 14:58:32 mythtv kernel: [ 2520.944221] Apr 29 14:58:32 mythtv kernel: [ 2520.944226] xc2028 10-0061: i2c output error: rc = -95 (should be 64) Apr 29 14:58:32 mythtv kernel: [ 2520.944228] xc2028 10-0061: -95 returned from send Apr 29 14:58:32 mythtv kernel: [ 2520.944231] xc2028 10-0061: Error -22 while loading base firmware I have located the origin of each of these messages: Apr 29 14:58:32 mythtv kernel: [ 2520.932221] xc2028 10-0061: Loading firmware for type=BASE F8MHZ (3), id 0000000000000000. drivers/media/tuners/tuner-xc2028.c static int load_firmware(struct dvb_frontend *fe, unsigned int type, v4l2_std_id *id) tuner_info("Loading firmware for type="); dump_firm_type(priv->firm[pos].type); printk("(%x), id %016llx.\n", priv->firm[pos].type, (unsigned long long)*id); further down /* Sends message chunks */ while (size > 0) { int len = (size < priv->ctrl.max_len - 1) ? size : priv->ctrl.max_len - 1; memcpy(buf + 1, p, len); rc = i2c_send(priv, buf, len + 1); if (rc < 0) { tuner_err("%d returned from send\n", rc); return -EINVAL; } p += len; size -= len; } i2c_send is a macro, defined near the top of tuner-xc2028.c #define i2c_send(priv, buf, size) ({ \ int _rc; \ _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \ if (size != _rc) \ tuner_info("i2c output error: rc = %d (should be %d)\n",\ _rc, (int)size); \ if (priv->ctrl.msleep) \ msleep(priv->ctrl.msleep); \ _rc; \ }) tuner_i2c_xfer_send drivers/media/tuners/tuner-i2c.h static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) { struct i2c_msg msg = { .addr = props->addr, .flags = 0, .buf = buf, .len = len }; int ret = i2c_transfer(props->adap, &msg, 1); return (ret == 1) ? len : ret; } drivers/i2c/i2c-core.c int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ... ret = __i2c_transfer(adap, msgs, num); int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ... ret = adap->algo->master_xfer(adap, msgs, num); drivers/media/usb/dvb-usb/cxusb.c static struct i2c_algorithm cxusb_i2c_algo = { .master_xfer = cxusb_i2c_xfer, .functionality = cxusb_i2c_func, }; static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = { ... .i2c_algo = &cxusb_i2c_algo, ... .devices = { { "DViCO FusionHDTV DVB-T Dual Digital 4", { NULL }, { &cxusb_table[13], NULL }, }, } }; Apr 29 14:58:32 mythtv kernel: [ 2520.944221] cxusb: i2c wr: len=64 is too big! drivers/media/usb/dvb-usb/cxusb.c static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) /* write only */ u8 obuf[MAX_XFER_SIZE], ibuf; if (2 + msg[i].len > sizeof(obuf)) { warn("i2c wr: len=%d is too big!\n", msg[i].len); ret = -EOPNOTSUPP; goto unlock; } Apr 29 14:58:32 mythtv kernel: [ 2520.944221] Note that warn supplies its own \n, so the \n in the call to warn is superfluous. drivers/media/usb/dvb-usb/dvb-usb.h #define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) Apr 29 14:58:32 mythtv kernel: [ 2520.944226] xc2028 10-0061: i2c output error: rc = -95 (should be 64) drivers/media/tuners/tuner-xc2028.c #define i2c_send(priv, buf, size) ({ \ int _rc; \ _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size); \ if (size != _rc) \ tuner_info("i2c output error: rc = %d (should be %d)\n",\ _rc, (int)size); \ if (priv->ctrl.msleep) \ msleep(priv->ctrl.msleep); \ _rc; \ }) -95 is the return code of tuner_i2c_xfer_send, which came from the return code of i2c_transfer, which came from the return code of cxusb_i2c_transfer. include/uapi/asm-generic/errno.h #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ Apr 29 14:58:32 mythtv kernel: [ 2520.944228] xc2028 10-0061: -95 returned from send drivers/media/tuners/tuner-xc2028.c load_firmware /* Sends message chunks */ while (size > 0) { int len = (size < priv->ctrl.max_len - 1) ? size : priv->ctrl.max_len - 1; memcpy(buf + 1, p, len); rc = i2c_send(priv, buf, len + 1); if (rc < 0) { tuner_err("%d returned from send\n", rc); return -EINVAL; } p += len; size -= len; } Apr 29 14:58:32 mythtv kernel: [ 2520.944231] xc2028 10-0061: Error -22 while loading base firmware include/uapi/asm-generic/errno-base.h #define EINVAL 22 /* Invalid argument */ It seems that the MAX_XFER_SIZE is inconsistent between several places: drivers/media/tuners/tuner-xc2028.c /* Max transfer size done by I2C transfer functions */ #define MAX_XFER_SIZE 80 drivers/media/usb/dvb-usb/cxusb.c /* Max transfer size done by I2C transfer functions */ #define MAX_XFER_SIZE 64 In fact, it would seem that tuner-xc2028.c should have /* Max transfer size done by I2C transfer functions */ #define MAX_XFER_SIZE 62 because cxusb_i2c_xfer requires 2 extra bytes for its own purposes. There are a great many definitions of MAX_XFER_SIZE under drivers/media . Many are 64, some are 128, some are 256! There needs to be consistency!!! It seems that the macro should be defined in ONE place instead of separately in every .c file! After making this change, #define MAX_XFER_SIZE 64 the system logs appear as follows: ============================================================= Apr 29 21:06:35 mythtv kernel: [ 155.767660] dvb-usb: found a 'DViCO FusionHDTV DVB-T Dual Digital 4' in warm state. Apr 29 21:06:35 mythtv kernel: [ 155.767793] dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer. Apr 29 21:06:35 mythtv kernel: [ 155.798893] DVB: registering new adapter (DViCO FusionHDTV DVB-T Dual Digital 4) Apr 29 21:06:35 mythtv kernel: [ 155.949154] usb 3-1: DVB: registering adapter 1 frontend 0 (Zarlink ZL10353 DVB-T)... Apr 29 21:06:35 mythtv kernel: [ 155.964139] xc2028 10-0061: creating new instance Apr 29 21:06:35 mythtv kernel: [ 155.964143] xc2028 10-0061: type set to XCeive xc2028/xc3028 tuner Apr 29 21:06:35 mythtv kernel: [ 155.964714] input: IR-receiver inside an USB DVB receiver as /devices/pci0000:00/0000:00:1e.0/0000:05:01.2/usb3/3-1/input/input16 Apr 29 21:06:35 mythtv kernel: [ 155.964838] dvb-usb: schedule remote query interval to 100 msecs. Apr 29 21:06:35 mythtv kernel: [ 155.964901] dvb-usb: DViCO FusionHDTV DVB-T Dual Digital 4 successfully initialized and connected. Apr 29 21:06:35 mythtv kernel: [ 155.964923] dvb-usb: found a 'DViCO FusionHDTV DVB-T Dual Digital 4' in warm state. Apr 29 21:06:35 mythtv kernel: [ 155.965068] dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer. Apr 29 21:06:35 mythtv kernel: [ 155.973845] xc2028 10-0061: Loading 80 firmware images from xc3028-v27.fw, type: xc2028 firmware, ver 2.7 Apr 29 21:06:35 mythtv kernel: [ 155.996183] DVB: registering new adapter (DViCO FusionHDTV DVB-T Dual Digital 4) Apr 29 21:06:35 mythtv kernel: [ 156.044540] cxusb: No IR receiver detected on this device. Apr 29 21:06:35 mythtv kernel: [ 156.044549] usb 3-2: DVB: registering adapter 2 frontend 0 (Zarlink ZL10353 DVB-T)... Apr 29 21:06:35 mythtv kernel: [ 156.044633] xc2028 11-0061: creating new instance Apr 29 21:06:35 mythtv kernel: [ 156.044636] xc2028 11-0061: type set to XCeive xc2028/xc3028 tuner Apr 29 21:06:35 mythtv kernel: [ 156.045705] xc2028 11-0061: Loading 80 firmware images from xc3028-v27.fw, type: xc2028 firmware, ver 2.7 Apr 29 21:06:35 mythtv kernel: [ 156.046917] dvb-usb: DViCO FusionHDTV DVB-T Dual Digital 4 successfully initialized and connected. Apr 29 21:06:35 mythtv kernel: [ 156.046957] usbcore: registered new interface driver dvb_usb_cxusb ============================================================= It appears that the firmware has been loaded successfully. Unfortunately, when tested using me-tv, the error messages seen previously return. Changing the size to 62 produces very similar errors: Apr 30 10:04:52 mythtv kernel: [ 8605.800219] xc2028 10-0061: Loading firmware for type=BASE F8MHZ (3), id 0000000000000000. Apr 30 10:04:52 mythtv kernel: [ 8605.813347] cxusb: i2c wr: len=64 is too big! Apr 30 10:04:52 mythtv kernel: [ 8605.813347] Apr 30 10:04:52 mythtv kernel: [ 8605.813353] xc2028 10-0061: i2c output error: rc = -121 (should be 62) Apr 30 10:04:52 mythtv kernel: [ 8605.813355] xc2028 10-0061: -121 returned from send Apr 30 10:04:52 mythtv kernel: [ 8605.813358] xc2028 10-0061: Error -22 while loading base firmware include/uapi/asm-generic/errno.h #define EREMOTEIO 121 /* Remote I/O error */ Now this is turning into a wild goose chase... This is returned by drivers/media/usb/dvb-usb/cxusb.c static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num) if (i == num) ret = num; else ret = -EREMOTEIO; drivers/media/usb/dvb-usb/cxusb.c static int cxusb_ctrl_msg(struct dvb_usb_device *d, u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen) { info("%s wlen=%d rlen=%d\n",wlen,rlen); int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 sndbuf[MAX_XFER_SIZE]; if (1 + wlen > sizeof(sndbuf)) { warn("%s i2c wr: len=%d is too big! sizeof(sndbuf)=%lu\n", __func__,wlen,sizeof(sndbuf)); return -EOPNOTSUPP; } memset(sndbuf, 0, 1+wlen); sndbuf[0] = cmd; memcpy(&sndbuf[1], wbuf, wlen); if (wo) return dvb_usb_generic_write(d, sndbuf, 1+wlen); else return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); } Need to allow 2 bytes for cxusb_i2c_xfer overhead 1 byte for cxusb_ctrl_msg overhead So the correct maximum value for MAX_XFER_SIZE in tuner-xc2028 is 61! Notes on re-building and testing the kernel modules: cd /home/ben/kernel/linux-3.13.0 cp /lib/modules/3.13.0-24-generic/build/Module.symvers . make SUBDIRS=drivers/media/tuners modules make SUBDIRS=drivers/media/usb/dvb-usb modules sudo cp drivers/media/tuners/tuner-xc2028.ko /lib/modules/3.13.0-24-generic/kernel/drivers/media/tuners sudo cp drivers/media/usb/dvb-usb/dvb-usb-cxusb.ko /lib/modules/3.13.0-24-generic/kernel/drivers/media/usb/dvb-usb sudo depmod 3.13.0-24-generic sudo modprobe tuner-xc2028 debug=1 sudo modprobe dvb_usb_cxusb dvb_usb_cxusb_debug=1 After Testing sudo rmmod dvb_usb_cxusb tuner-xc2028