
From: Michael Hunold <hunold@linuxtv.org>

- [DVB] dibusb: added remote control event handling, thanks to David
  Matthews.

- [DVB] dibusb: added support for special Artec devices (with AN2235 usb
  controller)

- [DVB] dibusb: enable several new devices (even the broken Artec T1)

- [DVB] dibusb: #if 0'ing unused code

- [DVB] dibusb: follow frontend changes

Signed-off-by: Michael Hunold <hunold@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.c |  578 +++++++++++++++++---------
 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.h |  348 ++++++++++-----
 2 files changed, 603 insertions(+), 323 deletions(-)

diff -puN drivers/media/dvb/dibusb/dvb-dibusb.c~dvb-dibusb-driver-update drivers/media/dvb/dibusb/dvb-dibusb.c
--- 25/drivers/media/dvb/dibusb/dvb-dibusb.c~dvb-dibusb-driver-update	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.c	Thu Nov 18 15:18:06 2004
@@ -11,6 +11,8 @@
  * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
  *
  *
+ * Remote control code added by David Matthews (dm@prolingua.co.uk)
+ *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
@@ -18,9 +20,7 @@
  * Acknowledgements
  *
  *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dib3000mb frontend) are based.
- *
- * 
+ *  sources, on which this driver (and the dib3000mb/mc/p frontends) are based.
  *
  * see Documentation/dvb/README.dibusb for more information
  */
@@ -32,19 +32,21 @@
 #include <linux/version.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <linux/input.h>
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
 #include "dvb_filter.h"
 #include "dvb_net.h"
 #include "dvb_frontend.h"
+#include "dib3000.h"
 
 #include "dvb-dibusb.h"
 
-/* debug */
 
+/* debug */
 #ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk_new(level,args...) \
+#define dprintk(level,args...) \
 	    do { if ((debug & level)) { printk(args); } } while (0)
 
 #define debug_dump(b,l) if (debug) {\
@@ -55,20 +57,22 @@
 
 static int debug;
 module_param(debug, int, 0x644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err (|-able)).");
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able)).");
 #else
-#define dprintk_new(args...)
+#define dprintk(args...)
 #define debug_dump(b,l)
 #endif
 
-#define deb_info(args...) dprintk_new(0x01,args)
-#define deb_xfer(args...) dprintk_new(0x02,args)
-#define deb_alot(args...) dprintk_new(0x04,args)
-#define deb_ts(args...)   dprintk_new(0x08,args)
-#define deb_err(args...)   dprintk_new(0x10,args)
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_xfer(args...) dprintk(0x02,args)
+#define deb_alot(args...) dprintk(0x04,args)
+#define deb_ts(args...)   dprintk(0x08,args)
+#define deb_err(args...)   dprintk(0x10,args)
+#define deb_rc(args...)   dprintk(0x20,args)
+
 
 /* Version information */
-#define DRIVER_VERSION "0.0"
+#define DRIVER_VERSION "0.1"
 #define DRIVER_DESC "Driver for DiBcom based USB Budget DVB-T device"
 #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
 
@@ -83,25 +87,28 @@ static int dibusb_readwrite_usb(struct u
 	if ((ret = down_interruptible(&dib->usb_sem)))
 		return ret;
 
-	if (dib->streaming && wbuf[0] == DIBUSB_REQ_I2C_WRITE)
-		deb_err("BUG: writing to i2c, while TS-streaming destroys the stream. What"
-			" did you do ? Please enable debugging and send the syslog to the author. (%x reg: %x %x)",
-			wbuf[0],wbuf[2],wbuf[3]);
+	if (dib->feedcount &&
+		wbuf[0] == DIBUSB_REQ_I2C_WRITE &&
+		dib->dibdev->parm->type == DIBUSB1_1)
+		deb_err("BUG: writing to i2c, while TS-streaming destroys the stream."
+				"(%x reg: %x %x)", wbuf[0],wbuf[2],wbuf[3]);
 			
 	debug_dump(wbuf,wlen);
 
-	ret = usb_bulk_msg(dib->udev,COMMAND_PIPE,
-			wbuf,wlen,&actlen,DIBUSB_I2C_TIMEOUT);
+	ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
+			dib->dibdev->parm->cmd_pipe), wbuf,wlen,&actlen,
+			DIBUSB_I2C_TIMEOUT);
 
 	if (ret)
 		err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
 	else
 		ret = actlen != wlen ? -1 : 0;
 
-	/* an answer is expected */
+	/* an answer is expected, and no error before */
 	if (!ret && rbuf && rlen) {
-		ret = usb_bulk_msg(dib->udev,RESULT_PIPE,rbuf,rlen,
-				&actlen,DIBUSB_I2C_TIMEOUT);
+		ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
+				dib->dibdev->parm->result_pipe),rbuf,rlen,&actlen,
+				DIBUSB_I2C_TIMEOUT);
 
 		if (ret)
 			err("recv bulk message failed: %d",ret);
@@ -115,11 +122,6 @@ static int dibusb_readwrite_usb(struct u
 	return ret;
 }
 
-static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
-{
-	return dibusb_readwrite_usb(dib,buf,len,NULL,0);
-}
-
 static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
@@ -146,97 +148,21 @@ static int dibusb_i2c_msg(struct usb_dib
 /*
  * DVB stuff
  */
-
-static struct dibusb_pid * dibusb_get_free_pid(struct usb_dibusb *dib)
-{
-	int i;
-	unsigned long flags;
-	struct dibusb_pid *dpid = NULL;
-
-	spin_lock_irqsave(&dib->pid_list_lock,flags);
-	for (i=0; i < DIBUSB_MAX_PIDS; i++)
-		if (!dib->pid_list[i].active) {
-			dpid = dib->pid_list + i;
-			dpid->active = 1;
-			break;
-		}
-	spin_unlock_irqrestore(&dib->pid_list_lock,flags);
-	return dpid;
-}
-
-static int dibusb_start_xfer(struct usb_dibusb *dib)
-{
-	u8 b[4] = {
-		(DIB3000MB_REG_FIFO >> 8) & 0xff,
-		(DIB3000MB_REG_FIFO) & 0xff,
-		(DIB3000MB_FIFO_ACTIVATE >> 8) & 0xff,
-		(DIB3000MB_FIFO_ACTIVATE) & 0xff
-	};
-	dib->streaming = 1;
-	deb_ts("start streaming\n");
-	return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
-}
-
-static int dibusb_stop_xfer(struct usb_dibusb *dib)
-{
-	u8 b[4] = {
-		(DIB3000MB_REG_FIFO >> 8) & 0xff,
-		(DIB3000MB_REG_FIFO) & 0xff,
-		(DIB3000MB_FIFO_INHIBIT >> 8) & 0xff,
-		(DIB3000MB_FIFO_INHIBIT) & 0xff
-	};
-	dib->streaming = 0;
-	deb_ts("stop streaming\n");
-	return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
-}
-
-static int dibusb_set_pid(struct dibusb_pid *dpid)
-{
-	struct usb_dibusb *dib = dpid->dib;
-	u16 pid = dpid->pid | (dpid->active ? DIB3000MB_ACTIVATE_FILTERING : 0);
-	u8 b[4] = {
-		(dpid->reg >> 8) & 0xff,
-		(dpid->reg) & 0xff,
-		(pid >> 8) & 0xff,
-		(pid) & 0xff
-	};
-	int ret;
-	
-	/* firmware bug, i2c write during mpeg transfer */
-	if (dib->feedcount) {
-		deb_info("stop streaming\n");
-		ret = dibusb_stop_xfer(dib);
-	}
-	
-	if (dpid->active) 
-		dib->feedcount++;
-	else
-		dib->feedcount--;
-
-	ret = dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
-
-	if (ret == 0 && dib->feedcount) {
-		deb_info("start streaming\n");
-		ret = dibusb_start_xfer(dib);
-	}
-	return ret;
-}
-
 static void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
 {
 	struct usb_dibusb *dib = urb->context;
 
-	deb_xfer("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status);
+	deb_ts("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status);
 
 	if (dib->feedcount > 0 && urb->status == 0) {
-		deb_xfer("URB return len: %d\n",urb->actual_length);
+		deb_ts("URB return len: %d\n",urb->actual_length);
 		if (urb->actual_length % 188)
-			deb_xfer("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
+			deb_ts("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
 
 		/* Francois recommends to drop not full-filled packets, even if they may 
 		 * contain valid TS packets
 		 */
-		if (urb->actual_length == DIBUSB_TS_DEFAULT_SIZE && dib->dvb_is_ready)
+		if (urb->actual_length == dib->dibdev->parm->default_size && dib->dvb_is_ready)
 		dvb_dmx_swfilter_packets(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length/188);
 		else
 			deb_ts("URB dropped because of the " 
@@ -247,78 +173,181 @@ static void dibusb_urb_complete(struct u
 		usb_submit_urb(urb,GFP_KERNEL);
 }
 
-
-static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+static int dibusb_ctrl_feed(struct usb_dibusb *dib, int pid, int onoff)
 {
-//	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
-	struct dibusb_pid *dpid;
+	if (dib->dibdev->parm->firmware_bug && dib->feedcount) {
+		deb_ts("stop feeding\n");
+		if (dib->xfer_ops.fifo_ctrl != NULL) {
+			if (dib->xfer_ops.fifo_ctrl(dib->fe,0)) {
+				err("error while inhibiting fifo.");
+				return -ENODEV;
+			}
+		} else {
+			err("fifo_ctrl is not set.");
+			return -ENODEV;
+		}
+	}
 
-	deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
+	dib->feedcount += onoff ? 1 : -1;
 
-	if ((dpid = dibusb_get_free_pid(dib)) == NULL) {
+	if (dib->xfer_ops.pid_ctrl != NULL) {
+		if (dib->xfer_ops.pid_ctrl(dib->fe,pid,onoff) < 0) {
 		err("no free pid in list.");
 		return -ENODEV;
 	}
-	dvbdmxfeed->priv = dpid;
-	dpid->pid = dvbdmxfeed->pid;
-
-	dibusb_set_pid(dpid);
-
-	return 0;
+	} else {
+		err("no pid ctrl callback.");
+		return -ENODEV;
+	}
+	/*
+	 * start the feed, either if there is the firmware bug or
+	 * if this was the first pid to set.
+	 */
+	if (dib->dibdev->parm->firmware_bug || dib->feedcount == onoff) {
+		deb_ts("start feeding\n");
+		if (dib->xfer_ops.fifo_ctrl != NULL) {
+			if (dib->xfer_ops.fifo_ctrl(dib->fe,1)) {
+				err("error while enabling fifo.");
+				return -ENODEV;
+			}
+		} else {
+			err("fifo_ctrl is not set.");
+			return -ENODEV;
 }
-
-static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dibusb_pid *dpid = (struct dibusb_pid *) dvbdmxfeed->priv;
-
-	deb_ts("stopfeed pid: 0x%04x, feedtype: %d\n",dvbdmxfeed->pid, dvbdmxfeed->type);
-
-	if (dpid == NULL)
-		err("channel in dmxfeed->priv was NULL");
-	else {
-		dpid->active = 0;
-		dpid->pid = 0;
-		dibusb_set_pid(dpid);
 	}
-
 	return 0;
 }
 
-/*
- * firmware transfers
- */
+static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
+	deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
+	dvbdmxfeed->priv = dib;
+	return dibusb_ctrl_feed(dib,dvbdmxfeed->pid,1);
+}
 
-/*
- * do not use this, just a workaround for a bug,
- * which will hopefully never occur :).
- */
-static int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
+static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-	u8 b[1] = { DIBUSB_REQ_INTR_READ };
-	return dibusb_write_usb(dib,b,1);
+	struct usb_dibusb *dib = (struct usb_dibusb *) dvbdmxfeed->priv;
+	if (dib == NULL) {
+		err("dib in dmxfeed->priv was NULL");
+		return -EINVAL;
 }
+	deb_ts("dvbdmxfeed pid: 0x%04x, feedtype: %d\n",
+			dvbdmxfeed->pid, dvbdmxfeed->type);
+	return dibusb_ctrl_feed(dib,dvbdmxfeed->pid,0);
+}
+
+/* Table to map raw key codes to key events.  This should not be hard-wired
+   into the kernel.  */
+static const struct { u8 c0, c1, c2; uint32_t key; } rc_keys [] =
+{
+	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
+	{ 0x00, 0xff, 0x16, KEY_POWER },
+	{ 0x00, 0xff, 0x10, KEY_MUTE },
+	{ 0x00, 0xff, 0x03, KEY_1 },
+	{ 0x00, 0xff, 0x01, KEY_2 },
+	{ 0x00, 0xff, 0x06, KEY_3 },
+	{ 0x00, 0xff, 0x09, KEY_4 },
+	{ 0x00, 0xff, 0x1d, KEY_5 },
+	{ 0x00, 0xff, 0x1f, KEY_6 },
+	{ 0x00, 0xff, 0x0d, KEY_7 },
+	{ 0x00, 0xff, 0x19, KEY_8 },
+	{ 0x00, 0xff, 0x1b, KEY_9 },
+	{ 0x00, 0xff, 0x15, KEY_0 },
+	{ 0x00, 0xff, 0x05, KEY_CHANNELUP },
+	{ 0x00, 0xff, 0x02, KEY_CHANNELDOWN },
+	{ 0x00, 0xff, 0x1e, KEY_VOLUMEUP },
+	{ 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN },
+	{ 0x00, 0xff, 0x11, KEY_RECORD },
+	{ 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
+	{ 0x00, 0xff, 0x14, KEY_PLAY },
+	{ 0x00, 0xff, 0x1a, KEY_STOP },
+	{ 0x00, 0xff, 0x40, KEY_REWIND },
+	{ 0x00, 0xff, 0x12, KEY_FASTFORWARD },
+	{ 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
+	{ 0x00, 0xff, 0x4c, KEY_PAUSE },
+	{ 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */
+	{ 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
+	/* Key codes for the KWorld/ADSTech/JetWay remote. */
+	{ 0x86, 0x6b, 0x12, KEY_POWER },
+	{ 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */
+	{ 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */
+	{ 0x86, 0x6b, 0x0b, KEY_EPG },
+	{ 0x86, 0x6b, 0x10, KEY_MUTE },
+	{ 0x86, 0x6b, 0x01, KEY_1 },
+	{ 0x86, 0x6b, 0x02, KEY_2 },
+	{ 0x86, 0x6b, 0x03, KEY_3 },
+	{ 0x86, 0x6b, 0x04, KEY_4 },
+	{ 0x86, 0x6b, 0x05, KEY_5 },
+	{ 0x86, 0x6b, 0x06, KEY_6 },
+	{ 0x86, 0x6b, 0x07, KEY_7 },
+	{ 0x86, 0x6b, 0x08, KEY_8 },
+	{ 0x86, 0x6b, 0x09, KEY_9 },
+	{ 0x86, 0x6b, 0x0a, KEY_0 },
+	{ 0x86, 0x6b, 0x18, KEY_ZOOM },
+	{ 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */
+	{ 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */
+	{ 0x86, 0x6b, 0x00, KEY_UNDO },
+	{ 0x86, 0x6b, 0x1d, KEY_RECORD },
+	{ 0x86, 0x6b, 0x0d, KEY_STOP },
+	{ 0x86, 0x6b, 0x0e, KEY_PAUSE },
+	{ 0x86, 0x6b, 0x16, KEY_PLAY },
+	{ 0x86, 0x6b, 0x11, KEY_BACK },
+	{ 0x86, 0x6b, 0x19, KEY_FORWARD },
+	{ 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */
+	{ 0x86, 0x6b, 0x15, KEY_ESC },
+	{ 0x86, 0x6b, 0x1a, KEY_UP },
+	{ 0x86, 0x6b, 0x1e, KEY_DOWN },
+	{ 0x86, 0x6b, 0x1f, KEY_LEFT },
+	{ 0x86, 0x6b, 0x1b, KEY_RIGHT },
+};
 
 /*
- * TODO: a tasklet should run with a delay of 1/10 second
- * and feed an appropriate event device ?
- * NEC protocol is used for remote controlls
+ * Read the remote control and feed the appropriate event.
+ * NEC protocol is used for remote controls
  */
 static int dibusb_read_remote_control(struct usb_dibusb *dib)
 {
 	u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5];
 	int ret;
+	int i;
 	if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
 		return ret;
 
-
-	
 	switch (rb[0]) {
 		case DIBUSB_RC_NEC_KEY_PRESSED:
+			/* rb[1-3] is the actual key, rb[4] is a checksum */
+			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+				rb[1], rb[2], rb[3], rb[4]);
 
+			if ((0xff - rb[3]) != rb[4]) {
+				deb_rc("remote control checksum failed.\n");
+				break;
+			}
+
+			/* See if we can match the raw key code. */
+			for (i = 0; i < sizeof(rc_keys)/sizeof(rc_keys[0]); i++) {
+				if (rc_keys[i].c0 == rb[1] &&
+					rc_keys[i].c1 == rb[2] &&
+				    rc_keys[i].c2 == rb[3]) {
+					dib->rc_input_event = rc_keys[i].key;
+					deb_rc("Translated key 0x%04x\n", dib->rc_input_event);
+					/* Signal down and up events for this key. */
+					input_report_key(&dib->rc_input_dev, dib->rc_input_event, 1);
+					input_report_key(&dib->rc_input_dev, dib->rc_input_event, 0);
+					input_sync(&dib->rc_input_dev);
+					break;
+				}
+			}
+			break;
+		case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */
 			break;
-		case DIBUSB_RC_NEC_EMPTY:
 		case DIBUSB_RC_NEC_KEY_REPEATED:
+			/* rb[1]..rb[4] are always zero.*/
+			/* Repeats often seem to occur so for the moment just ignore this. */
+			deb_rc("Key repeat\n");
+			break;
 		default:
 			break;
 	}
@@ -326,6 +355,46 @@ static int dibusb_read_remote_control(st
 	return 0;
 }
 
+#define RC_QUERY_INTERVAL (100)	/* milliseconds */
+
+/* Remote-control poll function - called every RC_QUERY_INTERVAL ms to see
+   whether the remote control has received anything. */
+static void dibusb_query_rc (void *data)
+{
+	struct usb_dibusb *dib = (struct usb_dibusb *) data;
+	/* TODO: need a lock here.  We can simply skip checking for the remote control
+	   if we're busy. */
+	dibusb_read_remote_control(dib);
+	schedule_delayed_work(&dib->rc_query_work,
+			      msecs_to_jiffies(RC_QUERY_INTERVAL));
+}
+
+/*
+ * Cypress controls
+ */
+
+#if 0
+
+/*
+ * #if 0'ing the following 5 functions as they are not in use _now_,
+ * but probably will be sometime.
+ */
+
+static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
+{
+	return dibusb_readwrite_usb(dib,buf,len,NULL,0);
+}
+
+/*
+ * do not use this, just a workaround for a bug,
+ * which will hopefully never occur :).
+ */
+static int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
+{
+	u8 b[1] = { DIBUSB_REQ_INTR_READ };
+	return dibusb_write_usb(dib,b,1);
+}
+
 /*
  * ioctl for the firmware
  */
@@ -355,6 +424,8 @@ static int dibusb_hw_wakeup(struct usb_d
 	return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
 }
 
+#endif
+
 /*
  * I2C
  */
@@ -387,19 +458,44 @@ static u32 dibusb_i2c_func(struct i2c_ad
 	return I2C_FUNC_I2C;
 }
 
-static int dibusb_i2c_client_register (struct i2c_client *i2c)
-{
-	struct usb_dibusb *dib = i2c_get_adapdata(i2c->adapter);
-	if (i2c->driver->command)
-		return i2c->driver->command(i2c,FE_REGISTER,dib->adapter);
-	return 0;
-}
+static int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 
-static int dibusb_i2c_client_unregister (struct i2c_client *i2c)
+static struct dib3000_config thomson_cable_eu_config = {
+	.demod_address = 0x10,
+	.pll_addr = 194,
+	.pll_set = thomson_cable_eu_pll_set,
+};
+
+static int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
-	struct usb_dibusb *dib = i2c_get_adapdata(i2c->adapter);
-	if (i2c->driver->command)
-		return i2c->driver->command(i2c,FE_UNREGISTER,dib->adapter);
+	struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
+	u8 buf[4];
+	struct i2c_msg msg = {
+		.addr = thomson_cable_eu_config.pll_addr,
+		.flags = 0,
+		.buf = buf,
+		.len = sizeof(buf)
+	};
+	u32 tfreq = (params->frequency + 36125000) / 62500;
+	int vu,p0,p1,p2;
+
+	if (params->frequency > 403250000)
+		vu = 1, p2 = 1, p1 = 0, p0 = 1;
+	else if (params->frequency > 115750000)
+		vu = 0, p2 = 1, p1 = 1, p0 = 0;
+	else if (params->frequency > 44250000)
+		vu = 0, p2 = 0, p1 = 1, p0 = 1;
+	else
+		return -EINVAL;
+
+	buf[0] = (tfreq >> 8) & 0x7f;
+	buf[1] = tfreq & 0xff;
+   	buf[2] = 0x8e;
+   	buf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
+
+	if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1) return -EIO;
+
+	msleep(1);
 	return 0;
 }
 
@@ -410,6 +506,24 @@ static struct i2c_algorithm dibusb_algo 
 	.functionality	= dibusb_i2c_func,
 };
 
+static void frontend_init(struct usb_dibusb* dib)
+{
+	dib->fe = dib3000mb_attach(&thomson_cable_eu_config, &dib->i2c_adap,&dib->xfer_ops);
+
+	if (dib->fe == NULL) {
+		printk("dvb-dibusb: A frontend driver was not found for device %04x/%04x\n",
+		       dib->udev->descriptor.idVendor,
+		       dib->udev->descriptor.idProduct);
+	} else {
+		if (dvb_register_frontend(dib->adapter, dib->fe)) {
+			printk("dvb-dibusb: Frontend registration failed!\n");
+			if (dib->fe->ops->release)
+				dib->fe->ops->release(dib->fe);
+			dib->fe = NULL;
+		}
+	}
+}
+
 static int dibusb_dvb_init(struct usb_dibusb *dib)
 {
 	int ret;
@@ -423,6 +537,7 @@ static int dibusb_dvb_init(struct usb_di
 		deb_info("dvb_register_adapter failed: error %d", ret);
 		goto err;
 	}
+	dib->adapter->priv = dib;
 
 	strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
 #ifdef I2C_ADAP_CLASS_TV_DIGITAL
@@ -433,8 +548,6 @@ static int dibusb_dvb_init(struct usb_di
 	dib->i2c_adap.algo 		= &dibusb_algo;
 	dib->i2c_adap.algo_data = NULL;
 	dib->i2c_adap.id		= I2C_ALGO_BIT;
-	dib->i2c_adap.client_register   = dibusb_i2c_client_register,
-	dib->i2c_adap.client_unregister = dibusb_i2c_client_unregister,
 
 	i2c_set_adapdata(&dib->i2c_adap, dib);
 
@@ -446,8 +559,8 @@ static int dibusb_dvb_init(struct usb_di
 	dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
 
 	dib->demux.priv = (void *)dib;
-	dib->demux.filternum = DIBUSB_MAX_PIDS;
-	dib->demux.feednum = DIBUSB_MAX_PIDS;
+	/* get pidcount from demod */
+	dib->demux.feednum = dib->demux.filternum = 16;
 	dib->demux.start_feed = dibusb_start_feed;
 	dib->demux.stop_feed = dibusb_stop_feed;
 	dib->demux.write_to_decoder = NULL;
@@ -466,6 +579,11 @@ static int dibusb_dvb_init(struct usb_di
 
 	dvb_net_init(dib->adapter, &dib->dvb_net, &dib->demux.dmx);
 
+	frontend_init(dib);
+
+	/* Start the remote-control polling. */
+	schedule_delayed_work(&dib->rc_query_work, msecs_to_jiffies(RC_QUERY_INTERVAL));
+
 	goto success;
 err_dmx_dev:
 	dvb_dmx_release(&dib->demux);
@@ -482,12 +600,17 @@ success:
 
 static int dibusb_dvb_exit(struct usb_dibusb *dib)
 {
+	cancel_delayed_work(&dib->rc_query_work);
+	flush_scheduled_work();
+	input_unregister_device(&dib->rc_input_dev);
+
 	dib->dvb_is_ready = 0;
 	deb_info("unregistering DVB part\n");
 	dvb_net_release(&dib->dvb_net);
 	dib->demux.dmx.close(&dib->demux.dmx);
 	dvb_dmxdev_release(&dib->dmxdev);
 	dvb_dmx_release(&dib->demux);
+	if (dib->fe != NULL) dvb_unregister_frontend(dib->fe);
 	i2c_del_adapter(&dib->i2c_adap);
 	dvb_unregister_adapter(dib->adapter);
 
@@ -497,21 +620,36 @@ static int dibusb_dvb_exit(struct usb_di
 static int dibusb_exit(struct usb_dibusb *dib)
 {
 	int i;
-	for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) 
-		if (dib->buf_urb[i] != NULL) {
+	if (dib->urb_list != NULL) {
+		for (i = 0; i < dib->dibdev->parm->num_urbs; i++) {
+			if (dib->urb_list[i] != NULL) {
 			deb_info("killing URB no. %d.\n",i);
-			usb_kill_urb(dib->buf_urb[i]); // TODO kernel version ifdef for unlink_urb
+
+				/* stop the URBs */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
+				usb_unlink_urb(dib->urb_list[i]);
+#else
+				usb_kill_urb(dib->urb_list[i]);
+#endif
 			
 			deb_info("freeing URB no. %d.\n",i);
-			usb_free_urb(dib->buf_urb[i]);
+				/* free the URBs */
+				usb_free_urb(dib->urb_list[i]);
+			}
 		}
-	pci_free_consistent(NULL,DIBUSB_TS_BUFFER_SIZE,dib->buffer,dib->dma_handle);
+		/* free the urb array */
+		kfree(dib->urb_list);
+		}
+
+	pci_free_consistent(NULL,
+		dib->dibdev->parm->urb_buf_size*dib->dibdev->parm->num_urbs,dib->buffer,
+		dib->dma_handle);
 	return 0;
 }
 
 static int dibusb_init(struct usb_dibusb *dib)
 {
-	int ret,i;
+	int ret,i,bufsize;
 	sema_init(&dib->usb_sem, 1);
 	sema_init(&dib->i2c_sem, 1);
 
@@ -519,46 +657,70 @@ static int dibusb_init(struct usb_dibusb
 	 * when reloading the driver w/o replugging the device
 	 * a timeout occures, this helps
 	 */
-	usb_clear_halt(dib->udev,COMMAND_PIPE);
-	usb_clear_halt(dib->udev,RESULT_PIPE);
-	usb_clear_halt(dib->udev,DATA_PIPE);
-
-	/* dibusb_reset_cpu(dib); */
+	usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->parm->cmd_pipe));
+	usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->result_pipe));
+	usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->data_pipe));
+
+	/* allocate the array for the data transfer URBs */
+	dib->urb_list = kmalloc(dib->dibdev->parm->num_urbs*sizeof(struct urb *),GFP_KERNEL);
+	if (dib->urb_list == NULL)
+		return -ENOMEM;
+	memset(dib->urb_list,0,dib->dibdev->parm->num_urbs*sizeof(struct urb *));
 
-	if ((dib->buffer = pci_alloc_consistent(NULL,DIBUSB_TS_BUFFER_SIZE, &dib->dma_handle)) == NULL) {
+	bufsize = dib->dibdev->parm->num_urbs*dib->dibdev->parm->urb_buf_size;
+	deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
+	/* allocate the actual buffer for the URBs */
+	if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
+		dibusb_exit(dib);
 		return -ENOMEM;
 	}
-	memset(dib->buffer,0,DIBUSB_TS_BUFFER_SIZE);
-	for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) {
-		if (!(dib->buf_urb[i] = usb_alloc_urb(0,GFP_KERNEL))) {
+	memset(dib->buffer,0,bufsize);
+
+	/* allocate and submit the URBs */
+	for (i = 0; i < dib->dibdev->parm->num_urbs; i++) {
+		if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_KERNEL))) {
 		dibusb_exit(dib);
 		return -ENOMEM;
 	}
 		deb_info("submitting URB no. %d\n",i);
 
-		usb_fill_bulk_urb( dib->buf_urb[i], dib->udev, DATA_PIPE,
-				&dib->buffer[i*DIBUSB_TS_URB_BUFFER_SIZE], DIBUSB_TS_URB_BUFFER_SIZE, 
+		usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
+				usb_rcvbulkpipe(dib->udev,dib->dibdev->parm->data_pipe),
+				&dib->buffer[i*dib->dibdev->parm->urb_buf_size],
+				dib->dibdev->parm->urb_buf_size,
 				dibusb_urb_complete, dib);
-		dib->buf_urb[i]->transfer_flags = 0;
 
-		if ((ret = usb_submit_urb(dib->buf_urb[i],GFP_KERNEL))) {
+		dib->urb_list[i]->transfer_flags = 0;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
+		dib->urb_list[i]->timeout = 0;
+#endif
+
+		if ((ret = usb_submit_urb(dib->urb_list[i],GFP_KERNEL))) {
 			err("could not submit buffer urb no. %d\n",i);
 			dibusb_exit(dib);
 			return ret;
 		}
 	}
 
-	for (i=0; i < DIBUSB_MAX_PIDS; i++) {
-		dib->pid_list[i].reg = i+DIB3000MB_REG_FIRST_PID;
-		dib->pid_list[i].pid = 0;
-		dib->pid_list[i].active = 0;
-		dib->pid_list[i].dib = dib;
-	}
-
-	dib->feedcount = 0;
-	dib->streaming = 0;
 	dib->dvb_is_ready = 0;
 
+	/* Initialise the remote-control structures.*/
+	init_input_dev(&dib->rc_input_dev);
+
+	dib->rc_input_dev.evbit[0] = BIT(EV_KEY);
+	dib->rc_input_dev.keycodesize = sizeof(unsigned char);
+	dib->rc_input_dev.keycodemax = KEY_MAX;
+	dib->rc_input_dev.name = DRIVER_DESC " remote control";
+
+	for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i++)
+		set_bit(rc_keys[i].key, dib->rc_input_dev.keybit);
+
+	input_register_device(&dib->rc_input_dev);
+
+	dib->rc_input_event = KEY_MAX;
+
+	INIT_WORK(&dib->rc_query_work, dibusb_query_rc, dib);
+
 	if ((ret = dibusb_dvb_init(dib))) {
 		dibusb_exit(dib);
 		return ret;
@@ -579,17 +741,20 @@ static int dibusb_loadfirmware(struct us
 		struct dibusb_device *dibdev)
 {
 	const struct firmware *fw = NULL;
+	const char **fws;
 	u16 addr;
 	u8 *b,*p;
 	int ret = 0,i;
 
-	for (i = 0; i < sizeof(valid_firmware_filenames)/sizeof(const char*); i++) {
-		if ((ret = request_firmware(&fw, valid_firmware_filenames[i], &udev->dev)) == 0) {
-			info("using firmware file (%s).",valid_firmware_filenames[i]);
+	fws = dibdev->parm->fw_filenames;
+
+	for (i = 0; i < sizeof(fws)/sizeof(const char*); i++) {
+		if ((ret = request_firmware(&fw, fws[i], &udev->dev)) == 0) {
+			info("using firmware file (%s).",fws[i]);
 			break;
 		}
 		deb_info("tried to find '%s' firmware - unsuccessful. (%d)\n",
-				valid_firmware_filenames[i],ret);
+				fws[i],ret);
 	}
 
 	if (fw == NULL) {
@@ -609,7 +774,7 @@ static int dibusb_loadfirmware(struct us
 
 		/* stop the CPU */
 		reset = 1;
-		if ((ret = dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1)) != 1)
+		if ((ret = dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1)) != 1)
 			err("could not stop the USB controller CPU.");
 		for(i = 0; p[i+3] == 0 && i < fw->size; ) {
 			b = (u8 *) &p[i];
@@ -631,7 +796,7 @@ static int dibusb_loadfirmware(struct us
 			ret = 0;
 		/* restart the CPU */
 		reset = 0;
-		if (ret || dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1) != 1) {
+		if (ret || dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1) != 1) {
 			err("could not restart the USB controller CPU.");
 			ret = -EINVAL;
 		}
@@ -679,6 +844,21 @@ static int dibusb_probe(struct usb_inter
 	if (cold)
 		ret = dibusb_loadfirmware(udev,dibdev);
 	else {
+		switch (udev->speed) {
+			case USB_SPEED_LOW:
+				err("cannot handle USB speed because it is to sLOW.");
+				break;
+			case USB_SPEED_FULL:
+				info("running at FULL speed, will use pid filter.");
+				break;
+			case USB_SPEED_HIGH:
+				info("running at HIGH speed, will deliver the complete TS.");
+				break;
+			case USB_SPEED_UNKNOWN: /* fall through */
+			default:
+				err("cannot handle USB speed because it is unkown.");
+				break;
+		}
 		dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL);
 		if (dib == NULL) {
 			err("no memory");
diff -puN drivers/media/dvb/dibusb/dvb-dibusb.h~dvb-dibusb-driver-update drivers/media/dvb/dibusb/dvb-dibusb.h
--- 25/drivers/media/dvb/dibusb/dvb-dibusb.h~dvb-dibusb-driver-update	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.h	Thu Nov 18 15:18:06 2004
@@ -7,136 +7,252 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  *
- * 
- *
  * for more information see dvb-dibusb.c .
  */
 
 #ifndef __DVB_DIBUSB_H__
 #define __DVB_DIBUSB_H__
 
-#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT	0x10
+#include "dib3000.h"
 
-/* Vendor IDs */
-#define USB_VID_TWINHAN_ID					0x1822
-#define USB_VID_IMC_NETWORKS_ID				0x13d3
-#define USB_VID_EMPIA_ID					0xeb1a
-#define USB_VID_DIBCOM_ID					0x10b8
-#define USB_VID_ULTIMA_ELECTRONIC_ID		0x05d8
-#define USB_VID_COMPRO_ID					0x185b
-#define USB_VID_HYPER_PALTEK				0x1025
+typedef enum {
+	DIBUSB1_1 = 0,
+	DIBUSB2_0,
+	DIBUSB1_1_AN2235,
+} dibusb_type;
+
+static const char * dibusb_fw_filenames1_1[] = {
+	"dvb-dibusb-5.0.0.11.fw"
+};
+
+static const char * dibusb_fw_filenames1_1_an2235[] = {
+	"dvb-dibusb-an2235-1.fw"
+};
 
-/* Product IDs before loading the firmware */
-#define USB_PID_TWINHAN_VP7041_COLD_ID		0x3201
-#define USB_PID_KWORLD_VSTREAM_COLD_ID		0x17de
-#define USB_PID_DIBCOM_MOD3000_COLD_ID		0x0bb8
-#define USB_PID_ULTIMA_TVBOX_COLD_ID		0x8105
-#define USB_PID_COMPRO_DVBU2000_COLD_ID		0xd000
-#define USB_PID_UNK_HYPER_PALTEK_COLD_ID	0x005e
-
-/* product ID afterwards */
-#define USB_PID_TWINHAN_VP7041_WARM_ID		0x3202
-#define USB_PID_KWORLD_VSTREAM_WARM_ID		0x17df
-#define USB_PID_DIBCOM_MOD3000_WARM_ID		0x0bb9
-#define USB_PID_ULTIMA_TVBOX_WARM_ID		0x8106
-#define USB_PID_COMPRO_DVBU2000_WARM_ID		0xd001
-#define USB_PID_UNK_HYPER_PALTEK_WARM_ID	0x005f
-
-/* static array of valid firmware names, the best one first */
-static const char * valid_firmware_filenames[] = {
-	"dvb-dibusb-5.0.0.11.fw",
+static const char * dibusb_fw_filenames2_0[] = {
+	"dvb-dibusb-6.0.0.5.fw"
+};
+
+struct dibusb_device_parameter {
+	dibusb_type type;
+	u8 demod_addr;
+	const char **fw_filenames;
+	const char *usb_controller;
+	u16 usb_cpu_csreg;
+
+	int num_urbs;
+	int urb_buf_size;
+	int default_size;
+	int firmware_bug;
+
+	int cmd_pipe;
+	int result_pipe;
+	int data_pipe;
+};
+
+static struct dibusb_device_parameter dibusb_dev_parm[3] = {
+	{	.type = DIBUSB1_1,
+		.demod_addr = 0x10,
+		.fw_filenames = dibusb_fw_filenames1_1,
+		.usb_controller = "Cypress AN2135",
+		.usb_cpu_csreg = 0x7f92,
+
+		.num_urbs = 3,
+		.urb_buf_size = 4096,
+		.default_size = 188*21,
+		.firmware_bug = 1,
+
+		.cmd_pipe = 0x01,
+		.result_pipe = 0x81,
+		.data_pipe = 0x82,
+	},
+	{	.type = DIBUSB2_0,
+		.demod_addr = 0x10,
+		.fw_filenames = dibusb_fw_filenames2_0,
+		.usb_controller = "Cypress FX2",
+		.usb_cpu_csreg = 0xe600,
+
+		.num_urbs = 3,
+		.urb_buf_size = 40960,
+		.default_size = 188*210,
+		.firmware_bug = 0,
+
+		.cmd_pipe = 0x01,
+		.result_pipe = 0x81,
+		.data_pipe = 0x86,
+	},
+	{	.type = DIBUSB1_1_AN2235,
+		.demod_addr = 0x10,
+		.fw_filenames = dibusb_fw_filenames1_1_an2235,
+		.usb_controller = "Cypress CY7C64613 (AN2235)",
+		.usb_cpu_csreg = 0x7f92,
+
+		.num_urbs = 3,
+		.urb_buf_size = 4096,
+		.default_size = 188*21,
+		.firmware_bug = 1,
+
+		.cmd_pipe = 0x01,
+		.result_pipe = 0x81,
+		.data_pipe = 0x82,
+	}
 };
 
 struct dibusb_device {
+	const char *name;
 	u16 cold_product_id;
 	u16 warm_product_id;
-	u8 demod_addr;
-	const char *name;
+	struct dibusb_device_parameter *parm;
 };
 
-#define DIBUSB_SUPPORTED_DEVICES	6
+/* Vendor IDs */
+#define USB_VID_ANCHOR						0x0547
+#define USB_VID_AVERMEDIA					0x14aa
+#define USB_VID_COMPRO						0x185b
+#define USB_VID_DIBCOM						0x10b8
+#define USB_VID_EMPIA						0xeb1a
+#define USB_VID_GRANDTEC					0x5032
+#define USB_VID_HYPER_PALTEK				0x1025
+#define USB_VID_IMC_NETWORKS				0x13d3
+#define USB_VID_TWINHAN						0x1822
+#define USB_VID_ULTIMA_ELECTRONIC			0x05d8
+
+/* Product IDs */
+#define USB_PID_AVERMEDIA_DVBT_USB_COLD		0x0001
+#define USB_PID_AVERMEDIA_DVBT_USB_WARM		0x0002
+#define USB_PID_COMPRO_DVBU2000_COLD		0xd000
+#define USB_PID_COMPRO_DVBU2000_WARM		0xd001
+#define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
+#define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
+#define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
+#define USB_PID_DIBCOM_MOD3001_WARM			0x0bc7
+#define USB_PID_GRANDTEC_DVBT_USB_COLD		0x0fa0
+#define USB_PID_GRANDTEC_DVBT_USB_WARM		0x0fa1
+#define USB_PID_KWORLD_VSTREAM_COLD			0x17de
+#define USB_PID_KWORLD_VSTREAM_WARM			0x17df
+#define USB_PID_TWINHAN_VP7041_COLD			0x3201
+#define USB_PID_TWINHAN_VP7041_WARM			0x3202
+#define USB_PID_ULTIMA_TVBOX_COLD			0x8105
+#define USB_PID_ULTIMA_TVBOX_WARM			0x8106
+#define USB_PID_ULTIMA_TVBOX_AN2235_COLD	0x8107
+#define USB_PID_ULTIMA_TVBOX_AN2235_WARM	0x8108
+#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD	0x2235
+#define USB_PID_UNK_HYPER_PALTEK_COLD		0x005e
+#define USB_PID_UNK_HYPER_PALTEK_WARM		0x005f
+#define USB_PID_YAKUMO_DTT200U_COLD			0x0201
+#define USB_PID_YAKUMO_DTT200U_WARM			0x0301
+
+#define DIBUSB_SUPPORTED_DEVICES	12
 
 /* USB Driver stuff */
 static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
-	{	.cold_product_id = USB_PID_TWINHAN_VP7041_COLD_ID, 
-		.warm_product_id = USB_PID_TWINHAN_VP7041_WARM_ID,
-		.name = "TwinhanDTV USB-Ter/Magic Box / HAMA USB DVB-T device", 
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_PID_KWORLD_VSTREAM_COLD_ID,
-		.warm_product_id = USB_PID_KWORLD_VSTREAM_WARM_ID,
-		.name = "KWorld V-Stream XPERT DTV - DVB-T USB",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_PID_DIBCOM_MOD3000_COLD_ID,
-		.warm_product_id = USB_PID_DIBCOM_MOD3000_WARM_ID,
-		.name = "DiBcom USB DVB-T reference design (MOD300)",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_PID_ULTIMA_TVBOX_COLD_ID,
-		.warm_product_id = USB_PID_ULTIMA_TVBOX_WARM_ID,
-		.name = "Ultima Electronic/Artec T1 USB TVBOX",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_PID_COMPRO_DVBU2000_COLD_ID,
-		.warm_product_id = USB_PID_COMPRO_DVBU2000_WARM_ID,
-		.name = "Compro Videomate DVB-U2000 - DVB-T USB",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
-	},
-	{	.cold_product_id = USB_PID_UNK_HYPER_PALTEK_COLD_ID,
-		.warm_product_id = USB_PID_UNK_HYPER_PALTEK_WARM_ID,
-		.name = "Unkown USB DVB-T device ???? please report the name to linux-dvb or to the author",
-		.demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+	{	.name = "TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device",
+		.cold_product_id = USB_PID_TWINHAN_VP7041_COLD,
+		.warm_product_id = USB_PID_TWINHAN_VP7041_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
+		.cold_product_id = USB_PID_KWORLD_VSTREAM_COLD,
+		.warm_product_id = USB_PID_KWORLD_VSTREAM_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "Grandtec USB1.1 DVB-T/DiBcom USB1.1 DVB-T reference design (MOD3000)",
+		.cold_product_id = USB_PID_DIBCOM_MOD3000_COLD,
+		.warm_product_id = USB_PID_DIBCOM_MOD3000_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "Artec T1 USB1.1 TVBOX with AN2135",
+		.cold_product_id = USB_PID_ULTIMA_TVBOX_COLD,
+		.warm_product_id = USB_PID_ULTIMA_TVBOX_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "Artec T1 USB1.1 TVBOX with AN2235",
+		.cold_product_id = USB_PID_ULTIMA_TVBOX_AN2235_COLD,
+		.warm_product_id = USB_PID_ULTIMA_TVBOX_AN2235_WARM,
+		.parm = &dibusb_dev_parm[2],
+	},
+	{	.name = "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)",
+		.cold_product_id = USB_PID_ULTIMA_TVBOX_ANCHOR_COLD,
+		.warm_product_id = 0, /* undefined, this design becomes USB_PID_DIBCOM_MOD3000_WARM in warm state */
+		.parm = &dibusb_dev_parm[2],
+	},
+	{	.name = "Compro Videomate DVB-U2000 - DVB-T USB1.1",
+		.cold_product_id = USB_PID_COMPRO_DVBU2000_COLD,
+		.warm_product_id = USB_PID_COMPRO_DVBU2000_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "Unkown USB1.1 DVB-T device ???? please report the name to the author",
+		.cold_product_id = USB_PID_UNK_HYPER_PALTEK_COLD,
+		.warm_product_id = USB_PID_UNK_HYPER_PALTEK_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
+		.cold_product_id = USB_PID_DIBCOM_MOD3001_COLD,
+		.warm_product_id = USB_PID_DIBCOM_MOD3001_WARM,
+		.parm = &dibusb_dev_parm[1],
+	},
+	{	.name = "Grandtec DVB-T USB1.1",
+		.cold_product_id = USB_PID_GRANDTEC_DVBT_USB_COLD,
+		.warm_product_id = USB_PID_GRANDTEC_DVBT_USB_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "Avermedia AverTV DVBT USB1.1",
+		.cold_product_id = USB_PID_AVERMEDIA_DVBT_USB_COLD,
+		.warm_product_id = USB_PID_AVERMEDIA_DVBT_USB_WARM,
+		.parm = &dibusb_dev_parm[0],
+	},
+	{	.name = "Yakumo DVB-T mobile USB2.0",
+		.cold_product_id = USB_PID_YAKUMO_DTT200U_COLD,
+		.warm_product_id = USB_PID_YAKUMO_DTT200U_WARM,
+		.parm = &dibusb_dev_parm[1],
 	}
 };
 
 /* USB Driver stuff */
 /* table of devices that work with this driver */
 static struct usb_device_id dibusb_table [] = {
-	{ USB_DEVICE(USB_VID_TWINHAN_ID, 	USB_PID_TWINHAN_VP7041_COLD_ID) },
-	{ USB_DEVICE(USB_VID_TWINHAN_ID, 	USB_PID_TWINHAN_VP7041_WARM_ID) },
-	{ USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_COLD_ID) },
-	{ USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_WARM_ID) },
-	{ USB_DEVICE(USB_VID_EMPIA_ID,		USB_PID_KWORLD_VSTREAM_COLD_ID) },
-	{ USB_DEVICE(USB_VID_EMPIA_ID,		USB_PID_KWORLD_VSTREAM_WARM_ID) },
-	{ USB_DEVICE(USB_VID_DIBCOM_ID,		USB_PID_DIBCOM_MOD3000_COLD_ID) },
-	{ USB_DEVICE(USB_VID_DIBCOM_ID,		USB_PID_DIBCOM_MOD3000_WARM_ID) },
-	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_COLD_ID) },
-	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_WARM_ID) },
-	{ USB_DEVICE(USB_VID_COMPRO_ID,		USB_PID_COMPRO_DVBU2000_COLD_ID) },
-	{ USB_DEVICE(USB_VID_COMPRO_ID,		USB_PID_COMPRO_DVBU2000_WARM_ID) },
-	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD_ID) },
-	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM_ID) },
+	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_AVERMEDIA_DVBT_USB_COLD)},
+	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_COLD) },
+	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_WARM) },
+	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_COLD) },
+	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_WARM) },
+	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_COLD) },
+	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_WARM) },
+	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_COLD) },
+	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_WARM) },
+	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_COLD) },
+	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_WARM) },
+	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_COLD) },
+	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_WARM) },
+	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD) },
+	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM) },
+	{ USB_DEVICE(USB_VID_IMC_NETWORKS,	USB_PID_TWINHAN_VP7041_COLD) },
+	{ USB_DEVICE(USB_VID_IMC_NETWORKS,	USB_PID_TWINHAN_VP7041_WARM) },
+	{ USB_DEVICE(USB_VID_TWINHAN, 		USB_PID_TWINHAN_VP7041_COLD) },
+	{ USB_DEVICE(USB_VID_TWINHAN, 		USB_PID_TWINHAN_VP7041_WARM) },
+	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_YAKUMO_DTT200U_COLD) },
+	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_YAKUMO_DTT200U_WARM) },
+
+/*
+ * activate the following define when you have the device and want to compile
+ * build from build-2.6 in dvb-kernel
+ */
+// #define CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235
+#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235
+	{ USB_DEVICE(USB_VID_ANCHOR,		USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+#endif
 	{ }                 /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, dibusb_table);
 
-/* CS register start/stop the usb controller cpu */
-#define DIBUSB_CPU_CSREG				0x7F92
-
-// 0x10 is the I2C address of the first demodulator on the board
-#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT	0x10
 #define DIBUSB_I2C_TIMEOUT 				HZ*5
 
-#define DIBUSB_MAX_PIDS					16
-
-#define DIB3000MB_REG_FIRST_PID			(   153)
-
-struct usb_dibusb;
-
-struct dibusb_pid {
-	u16 reg;
-	u16 pid;
-	int active;
-	struct usb_dibusb *dib;
-};
-
-#define DIBUSB_TS_NUM_URBS			3
-#define DIBUSB_TS_URB_BUFFER_SIZE	4096
-#define DIBUSB_TS_BUFFER_SIZE		(DIBUSB_TS_NUM_URBS * DIBUSB_TS_URB_BUFFER_SIZE)
-#define DIBUSB_TS_DEFAULT_SIZE		(188*21)
-
 struct usb_dibusb {
 	/* usb */
 	struct usb_device * udev;
@@ -144,14 +260,12 @@ struct usb_dibusb {
 	struct dibusb_device * dibdev;
 
 	int feedcount;
-	int streaming;
-	struct urb * buf_urb[DIBUSB_TS_NUM_URBS];
+	struct dib3000_xfer_ops xfer_ops;
+
+	struct urb **urb_list;
 	u8 *buffer;
 	dma_addr_t dma_handle;
 
-	spinlock_t pid_list_lock;
-	struct dibusb_pid pid_list[DIBUSB_MAX_PIDS];
-
 	/* I2C */
 	struct i2c_adapter i2c_adap;
 	struct i2c_client i2c_client;
@@ -166,16 +280,14 @@ struct usb_dibusb {
 	struct dmxdev dmxdev;
 	struct dvb_demux demux;
 	struct dvb_net dvb_net;
+	struct dvb_frontend* fe;
+
+	/* remote control */
+	struct input_dev rc_input_dev;
+	struct work_struct rc_query_work;
+	int rc_input_event;
 };
 
-#define COMMAND_PIPE	usb_sndbulkpipe(dib->udev, 0x01)
-#define RESULT_PIPE		usb_rcvbulkpipe(dib->udev, 0x81)
-#define DATA_PIPE		usb_rcvbulkpipe(dib->udev, 0x82)
-/*
- * last endpoint 0x83 only used for chaining the buffers
- * of the endpoints in the cypress
- */
-#define CHAIN_PIPE_DO_NOT_USE	usb_rcvbulkpipe(dib->udev, 0x83)
 
 /* types of first byte of each buffer */
 
@@ -209,16 +321,4 @@ struct usb_dibusb {
 #define DIBUSB_IOCTL_POWER_SLEEP			0x00
 #define DIBUSB_IOCTL_POWER_WAKEUP			0x01
 
-
-/*
- * values from the demodulator which are needed in
- * the usb driver as well
- */
-
-#define DIB3000MB_REG_FIFO              (   145)
-#define DIB3000MB_FIFO_INHIBIT              (     1)
-#define DIB3000MB_FIFO_ACTIVATE             (     0)
-
-#define DIB3000MB_ACTIVATE_FILTERING            (0x2000)
-
 #endif
_
