From 776338e121b9db3156bfb4e21622a0219bbab9d4 Mon Sep 17 00:00:00 2001
From: Johannes Stezenbach <js@linuxtv.org>
Date: Thu, 23 Jun 2005 22:02:35 -0700
Subject: [PATCH] dvb: Add generalized dvb-usb driver

Add generalized dvb-usb driver which supports a wide variety of devices.

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 Documentation/dvb/README.dvb-usb             | 308 ++++++++++++++++++++++++++
 drivers/media/dvb/Kconfig                    |   1 +
 drivers/media/dvb/Makefile                   |   2 +-
 drivers/media/dvb/dvb-usb/Kconfig            |  99 +++++++++
 drivers/media/dvb/dvb-usb/Makefile           |  30 +++
 drivers/media/dvb/dvb-usb/a800.c             | 176 +++++++++++++++
 drivers/media/dvb/dvb-usb/dibusb-common.c    | 272 +++++++++++++++++++++++
 drivers/media/dvb/dvb-usb/dibusb-mb.c        | 316 +++++++++++++++++++++++++++
 drivers/media/dvb/dvb-usb/dibusb-mc.c        | 116 ++++++++++
 drivers/media/dvb/dvb-usb/dibusb.h           | 122 +++++++++++
 drivers/media/dvb/dvb-usb/digitv.c           | 282 ++++++++++++++++++++++++
 drivers/media/dvb/dvb-usb/digitv.h           |  65 ++++++
 drivers/media/dvb/dvb-usb/dtt200u-fe.c       | 206 +++++++++++++++++
 drivers/media/dvb/dvb-usb/dtt200u.c          | 171 +++++++++++++++
 drivers/media/dvb/dvb-usb/dtt200u.h          |  66 ++++++
 drivers/media/dvb/dvb-usb/dvb-usb-common.h   |  44 ++++
 drivers/media/dvb/dvb-usb/dvb-usb-dvb.c      | 210 ++++++++++++++++++
 drivers/media/dvb/dvb-usb/dvb-usb-firmware.c | 100 +++++++++
 drivers/media/dvb/dvb-usb/dvb-usb-i2c.c      | 118 ++++++++++
 drivers/media/dvb/dvb-usb/dvb-usb-ids.h      |  83 +++++++
 drivers/media/dvb/dvb-usb/dvb-usb-init.c     | 211 ++++++++++++++++++
 drivers/media/dvb/dvb-usb/dvb-usb-remote.c   | 175 +++++++++++++++
 drivers/media/dvb/dvb-usb/dvb-usb-urb.c      | 211 ++++++++++++++++++
 drivers/media/dvb/dvb-usb/dvb-usb.h          | 315 ++++++++++++++++++++++++++
 drivers/media/dvb/dvb-usb/nova-t-usb2.c      | 236 ++++++++++++++++++++
 drivers/media/dvb/dvb-usb/umt-010.c          | 162 ++++++++++++++
 drivers/media/dvb/dvb-usb/vp7045-fe.c        | 196 +++++++++++++++++
 drivers/media/dvb/dvb-usb/vp7045.c           | 263 ++++++++++++++++++++++
 drivers/media/dvb/dvb-usb/vp7045.h           |  78 +++++++
 drivers/media/dvb/frontends/dib3000-common.c |   2 +-
 drivers/media/dvb/frontends/dib3000.h        |   5 +-
 drivers/media/dvb/frontends/dib3000mb.c      |  20 +-
 drivers/media/dvb/frontends/dib3000mb_priv.h |   2 +-
 drivers/media/dvb/frontends/dib3000mc.c      |  29 +--
 drivers/media/dvb/frontends/dvb-pll.c        |  94 +++++++-
 drivers/media/dvb/frontends/dvb-pll.h        |   9 +-
 36 files changed, 4743 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/dvb/README.dvb-usb
 create mode 100644 drivers/media/dvb/dvb-usb/Kconfig
 create mode 100644 drivers/media/dvb/dvb-usb/Makefile
 create mode 100644 drivers/media/dvb/dvb-usb/a800.c
 create mode 100644 drivers/media/dvb/dvb-usb/dibusb-common.c
 create mode 100644 drivers/media/dvb/dvb-usb/dibusb-mb.c
 create mode 100644 drivers/media/dvb/dvb-usb/dibusb-mc.c
 create mode 100644 drivers/media/dvb/dvb-usb/dibusb.h
 create mode 100644 drivers/media/dvb/dvb-usb/digitv.c
 create mode 100644 drivers/media/dvb/dvb-usb/digitv.h
 create mode 100644 drivers/media/dvb/dvb-usb/dtt200u-fe.c
 create mode 100644 drivers/media/dvb/dvb-usb/dtt200u.c
 create mode 100644 drivers/media/dvb/dvb-usb/dtt200u.h
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-common.h
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-ids.h
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-init.c
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-remote.c
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb-urb.c
 create mode 100644 drivers/media/dvb/dvb-usb/dvb-usb.h
 create mode 100644 drivers/media/dvb/dvb-usb/nova-t-usb2.c
 create mode 100644 drivers/media/dvb/dvb-usb/umt-010.c
 create mode 100644 drivers/media/dvb/dvb-usb/vp7045-fe.c
 create mode 100644 drivers/media/dvb/dvb-usb/vp7045.c
 create mode 100644 drivers/media/dvb/dvb-usb/vp7045.h

diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb
new file mode 100644
index 00000000000..c7ed01b9f8f
--- /dev/null
+++ b/Documentation/dvb/README.dvb-usb
@@ -0,0 +1,308 @@
+Documentation for dvb-usb-framework module and its devices
+
+Idea behind the dvb-usb-framework
+=================================
+
+In March 2005 I got the new Twinhan USB2.0 DVB-T device. They provided specs and a firmware.
+
+Quite keen I wanted to put the driver (with some quirks of course) into dibusb.
+After reading some specs and doing some USB snooping, it realized, that the
+dibusb-driver would be a complete mess afterwards. So I decided to do it in a
+different way: With the help of a dvb-usb-framework.
+
+The framework provides generic functions (mostly kernel API calls), such as:
+
+- Transport Stream URB handling in conjunction with dvb-demux-feed-control
+  (bulk and isoc (TODO) are supported)
+- registering the device for the DVB-API
+- registering an I2C-adapter if applicable
+- remote-control/input-device handling
+- firmware requesting and loading (currently just for the Cypress USB
+  controller)
+- other functions/methods which can be shared by several drivers (such as
+  functions for bulk-control-commands)
+
+The source code of the particular DVB USB devices does just the communication
+with the device via the bus. The connection between the DVB-API-functionality
+is done via callbacks, assigned in a static device-description (struct
+dvb_usb_device) each device-driver has to have.
+
+For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
+
+Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
+ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
+the dvb-usb-lib.
+
+TODO: dynamic enabling and disabling of the pid-filter in regard to number of
+feeds requested.
+
+Supported devices USB1.1
+========================
+
+Produced and reselled by Twinhan:
+---------------------------------
+- TwinhanDTV USB-Ter DVB-T Device (VP7041)
+	http://www.twinhan.com/product_terrestrial_3.asp
+
+- TwinhanDTV Magic Box (VP7041e)
+	http://www.twinhan.com/product_terrestrial_4.asp
+
+- HAMA DVB-T USB device
+	http://www.hama.de/portal/articleId*110620/action*2598
+
+- CTS Portable (Chinese Television System) (2)
+	http://www.2cts.tv/ctsportable/
+
+- Unknown USB DVB-T device with vendor ID Hyper-Paltek
+
+
+Produced and reselled by KWorld:
+--------------------------------
+- KWorld V-Stream XPERT DTV DVB-T USB
+	http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
+
+- JetWay DTV DVB-T USB
+	http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
+
+- ADSTech Instant TV DVB-T USB
+	http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
+
+
+Others:
+-------
+- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
+	http://82.161.246.249/products-tvbox.html
+
+- Compro Videomate DVB-U2000 - DVB-T USB (2)
+	http://www.comprousa.com/products/vmu2000.htm
+
+- Grandtec USB DVB-T
+	http://www.grand.com.tw/
+
+- AVerMedia AverTV DVBT USB
+	http://www.avermedia.com/
+
+- DiBcom USB DVB-T reference device (non-public)
+
+
+Supported devices USB2.0-only
+=============================
+- Twinhan MagicBox II
+	http://www.twinhan.com/product_terrestrial_7.asp
+
+- TwinhanDTV Alpha
+	http://www.twinhan.com/product_terrestrial_8.asp
+
+- DigitalNow TinyUSB 2 DVB-t Receiver
+	http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
+
+- Hanftek UMT-010
+	http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
+
+
+Supported devices USB2.0 and USB1.1
+=============================
+- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
+	http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
+	http://www.yuan.com.tw/en/products/vdo_ub300.html
+	http://www.hama.de/portal/articleId*114663/action*2563
+	http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
+
+- Artec T1 USB TVBOX (FX2) (2)
+
+- Hauppauge WinTV NOVA-T USB2
+	http://www.hauppauge.com/
+
+- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
+
+- DiBcom USB2.0 DVB-T reference device (non-public)
+
+- AVerMedia AverTV A800 DVB-T USB2.0
+
+1) It is working almost - work-in-progress.
+2) No test reports received yet.
+
+0. History & News:
+  2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
+  2005-04-02 - re-enabled and improved remote control code.
+  2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
+  2005-03-30 - first commit of the dvb-usb-module based on the dibusb-source. First device is a new driver for the
+               TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
+
+  (change from dvb-dibusb to dvb-usb)
+  2005-03-28 - added support for the AVerMedia AverTV DVB-T USB2.0 device (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia)
+  2005-03-14 - added support for the Typhoon/Yakumo/HAMA DVB-T mobile USB2.0
+  2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
+  2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
+  2005-01-31 - distorted streaming is gone for USB1.1 devices
+  2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
+             - first almost working version for HanfTek UMT-010
+             - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
+  2005-01-10 - refactoring completed, now everything is very delightful
+             - tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
+               Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
+  2004-12-29 - after several days of struggling around bug of no returning URBs fixed.
+  2004-12-26 - refactored the dibusb-driver, splitted into separate files
+             - i2c-probing enabled
+  2004-12-06 - possibility for demod i2c-address probing
+             - new usb IDs (Compro, Artec)
+  2004-11-23 - merged changes from DiB3000MC_ver2.1
+             - revised the debugging
+             - possibility to deliver the complete TS for USB2.0
+  2004-11-21 - first working version of the dib3000mc/p frontend driver.
+  2004-11-12 - added additional remote control keys. Thanks to Uwe Hanke.
+  2004-11-07 - added remote control support. Thanks to David Matthews.
+  2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec)
+             - merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
+             - moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
+               better settled there (added xfer_ops-struct)
+             - created a common files for frontends (mc/p/mb)
+  2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
+  2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
+               to Amaury Demol for reporting
+             - changed usb TS transfer method (several urbs, stopping transfer
+               before setting a new pid)
+  2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
+               to Christian Motschke for reporting
+  2004-09-05 - released the dibusb device and dib3000mb-frontend driver
+
+  (old news for vp7041.c)
+  2004-07-15 - found out, by accident, that the device has a TUA6010XS for
+               PLL
+  2004-07-12 - figured out, that the driver should also work with the
+               CTS Portable (Chinese Television System)
+  2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
+               properly with firmware extracted from 2.422
+             - #if for 2.6.4 (dvb), compile issue
+             - changed firmware handling, see vp7041.txt sec 1.1
+  2004-07-02 - some tuner modifications, v0.1, cleanups, first public
+  2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
+               runs fine now
+  2004-06-27 - able to watch and switching channels (pre-alpha)
+             - no section filtering yet
+  2004-06-06 - first TS received, but kernel oops :/
+  2004-05-14 - firmware loader is working
+  2004-05-11 - start writing the driver
+
+1. How to use?
+1.1. Firmware
+
+Most of the USB drivers need to download a firmware to start working.
+
+for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
+for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
+for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
+for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
+for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
+
+The files can be found on http://www.linuxtv.org/download/firmware/ .
+
+We do not have the permission (yet) to publish the following firmware-files.
+You'll need to extract them from the windows drivers.
+
+You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
+
+for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
+for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
+for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
+for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
+
+1.2. Compiling
+
+Since the driver is in the linux kernel, activating the driver in
+your favorite config-environment should sufficient. I recommend
+to compile the driver as module. Hotplug does the rest.
+
+If you use dvb-kernel enter the build-2.6 directory run 'make' and 'insmod.sh
+load' afterwards.
+
+1.3. Loading the drivers
+
+Hotplug is able to load the driver, when it is needed (because you plugged
+in the device).
+
+If you want to enable debug output, you have to load the driver manually and
+from withing the dvb-kernel cvs repository.
+
+first have a look, which debug level are available:
+
+modinfo dvb-usb
+modinfo dvb-usb-vp7045
+etc.
+
+modprobe dvb-usb debug=<level>
+modprobe dvb-usb-vp7045 debug=<level>
+etc.
+
+should do the trick.
+
+When the driver is loaded successfully, the firmware file was in
+the right place and the device is connected, the "Power"-LED should be
+turned on.
+
+At this point you should be able to start a dvb-capable application. I'm use
+(t|s)zap, mplayer and dvbscan to test the basics. VDR-xine provides the
+long-term test scenario.
+
+2. Known problems and bugs
+
+- Don't remove the USB device while running an DVB application, your system
+  will go crazy or die most likely.
+
+2.1. Adding support for devices
+
+TODO
+
+2.2. USB1.1 Bandwidth limitation
+
+A lot of the currently supported devices are USB1.1 and thus they have a
+maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
+This is not enough for receiving the complete transport stream of a
+DVB-T channel (which is about 16 MBit/s). Normally this is not a
+problem, if you only want to watch TV (this does not apply for HDTV),
+but watching a channel while recording another channel on the same
+frequency simply does not work very well. This applies to all USB1.1
+DVB-T devices, not just the dvb-usb-devices)
+
+The bug, where the TS is distorted by a heavy usage of the device is gone
+definitely. All dvb-usb-devices I was using (Twinhan, Kworld, DiBcom) are
+working like charm now with VDR. Sometimes I even was able to record a channel
+and watch another one.
+
+2.3. Comments
+
+Patches, comments and suggestions are very very welcome.
+
+3. Acknowledgements
+   Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
+    providing specs, code and help, on which the dvb-dibusb, dib3000mb and
+    dib3000mc are based.
+
+   David Matthews for identifying a new device type (Artec T1 with AN2235)
+    and for extending dibusb with remote control event handling. Thank you.
+
+   Alex Woods for frequently answering question about usb and dvb
+    stuff, a big thank you.
+
+   Bernd Wagner for helping with huge bug reports and discussions.
+
+   Gunnar Wittich and Joachim von Caron for their trust for providing
+    root-shells on their machines to implement support for new devices.
+
+   Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
+    Jung from AVerMedia who kindly provided a special firmware to get the device
+    up and running in Linux.
+
+   Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
+	writing the vp7045-driver.
+
+   Some guys on the linux-dvb mailing list for encouraging me
+
+   Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
+    user-level firmware loader, which saves a lot of time
+    (when writing the vp7041 driver)
+
+   Ulf Hermenau for helping me out with traditional chinese.
+
+   Andr� Smoktun and Christian Fr�mmel for supporting me with
+    hardware and listening to my problems very patient.
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index b81abdfde37..01387f883cd 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -27,6 +27,7 @@ source "drivers/media/dvb/ttpci/Kconfig"
 
 comment "Supported USB Adapters"
 	depends on DVB_CORE && USB
+source "drivers/media/dvb/dvb-usb/Kconfig"
 source "drivers/media/dvb/ttusb-budget/Kconfig"
 source "drivers/media/dvb/ttusb-dec/Kconfig"
 source "drivers/media/dvb/cinergyT2/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index d2dd914f777..3c6ff161910 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
new file mode 100644
index 00000000000..8aa32f6e447
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -0,0 +1,99 @@
+config DVB_USB
+	tristate "Support for various USB DVB devices"
+	depends on DVB_CORE && USB
+	select FW_LOADER
+	help
+	  By enabling this you will be able to choose the various USB 1.1 and
+	  USB2.0 DVB devices.
+
+	  Almost every USB device needs a firmware, please look into
+	  <file:Documentation/dvb/README.dvb-usb>
+
+	  Say Y if you own an USB DVB device.
+
+config DVB_USB_DEBUG
+	bool "Enable extended debug support for all DVB-USB devices"
+	depends on DVB_USB
+	help
+	  Say Y if you want to enable debuging. See modinfo dvb-usb (and the
+	  appropriate drivers) for debug levels.
+
+config DVB_USB_A800
+	tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
+	depends on DVB_USB
+	help
+	  Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
+
+config DVB_USB_DIBUSB_MB
+	tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
+	depends on DVB_USB
+	help
+	  Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
+	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
+
+	  Devices supported by this driver:
+	    TwinhanDTV USB-Ter (VP7041)
+	    TwinhanDTV Magic Box (VP7041e)
+	    KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
+	    Hama DVB-T USB1.1-Box
+	    DiBcom USB1.1 reference devices (non-public)
+	    Ultima Electronic/Artec T1 USB TVBOX
+	    Compro Videomate DVB-U2000 - DVB-T USB
+	    Grandtec DVB-T USB
+	    Avermedia AverTV DVBT USB1.1
+	    Artec T1 USB1.1 boxes
+
+	  The VP7041 seems to be identical to "CTS Portable" (Chinese
+	  Television System).
+
+	  Say Y if you own such a device and want to use it. You should build it as
+	  a module.
+
+config DVB_USB_DIBUSB_MC
+	tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
+	depends on DVB_USB
+	help
+	  Support for 2.0 DVB-T receivers based on reference designs made by
+	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
+
+	  Devices supported by this driver:
+	    DiBcom USB2.0 reference devices (non-public)
+	    Artec T1 USB2.0 boxes
+
+	  Say Y if you own such a device and want to use it. You should build it as
+	  a module.
+
+config DVB_USB_UMT_010
+	tristate "HanfTek UMT-010 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
+
+config DVB_USB_DIGITV
+	tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
+
+config DVB_USB_VP7045
+	tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the
+	    TwinhanDTV Alpha (stick) (VP-7045),
+		TwinhanDTV MagicBox II (VP-7046) and
+		DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
+
+config DVB_USB_NOVA_T_USB2
+	tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
+
+config DVB_USB_DTT200U
+	tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
+
+	  The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
new file mode 100644
index 00000000000..d65b50f9abb
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -0,0 +1,30 @@
+dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o
+obj-$(CONFIG_DVB_USB) += dvb-usb.o
+
+dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
+obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
+
+dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
+obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
+
+dvb-usb-dibusb-common-objs = dibusb-common.o
+
+dvb-usb-a800-objs = a800.o
+obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
+
+dvb-usb-dibusb-mb-objs = dibusb-mb.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
+
+dvb-usb-dibusb-mc-objs = dibusb-mc.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
+
+dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
+obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
+
+dvb-usb-umt-010-objs = umt-010.o
+obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
+
+dvb-usb-digitv-objs = digitv.o
+obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
new file mode 100644
index 00000000000..a3542935604
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -0,0 +1,176 @@
+/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
+ * USB2.0 (A800) DVB-T receiver.
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to
+ *   - AVerMedia who kindly provided information and
+ *   - Glen Harris who suffered from my mistakes during development.
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
+#define deb_rc(args...)   dprintk(debug,0x01,args)
+
+static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	/* do nothing for the AVerMedia */
+	return 0;
+}
+
+static struct dvb_usb_rc_key a800_rc_keys[] = {
+	{ 0x02, 0x01, KEY_PROG1 },       /* SOURCE */
+	{ 0x02, 0x00, KEY_POWER },       /* POWER */
+	{ 0x02, 0x05, KEY_1 },           /* 1 */
+	{ 0x02, 0x06, KEY_2 },           /* 2 */
+	{ 0x02, 0x07, KEY_3 },           /* 3 */
+	{ 0x02, 0x09, KEY_4 },           /* 4 */
+	{ 0x02, 0x0a, KEY_5 },           /* 5 */
+	{ 0x02, 0x0b, KEY_6 },           /* 6 */
+	{ 0x02, 0x0d, KEY_7 },           /* 7 */
+	{ 0x02, 0x0e, KEY_8 },           /* 8 */
+	{ 0x02, 0x0f, KEY_9 },           /* 9 */
+	{ 0x02, 0x12, KEY_LEFT },        /* L / DISPLAY */
+	{ 0x02, 0x11, KEY_0 },           /* 0 */
+	{ 0x02, 0x13, KEY_RIGHT },       /* R / CH RTN */
+	{ 0x02, 0x17, KEY_PROG2 },       /* SNAP SHOT */
+	{ 0x02, 0x10, KEY_PROG3 },       /* 16-CH PREV */
+	{ 0x02, 0x03, KEY_CHANNELUP },   /* CH UP */
+	{ 0x02, 0x1e, KEY_VOLUMEDOWN },  /* VOL DOWN */
+	{ 0x02, 0x0c, KEY_ZOOM },        /* FULL SCREEN */
+	{ 0x02, 0x1f, KEY_VOLUMEUP },    /* VOL UP */
+	{ 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
+	{ 0x02, 0x14, KEY_MUTE },        /* MUTE */
+	{ 0x02, 0x08, KEY_AUDIO },       /* AUDIO */
+	{ 0x02, 0x19, KEY_RECORD },      /* RECORD */
+	{ 0x02, 0x18, KEY_PLAY },        /* PLAY */
+	{ 0x02, 0x1b, KEY_STOP },        /* STOP */
+	{ 0x02, 0x1a, KEY_PLAYPAUSE },   /* TIMESHIFT / PAUSE */
+	{ 0x02, 0x1d, KEY_BACK },        /* << / RED */
+	{ 0x02, 0x1c, KEY_FORWARD },     /* >> / YELLOW */
+	{ 0x02, 0x03, KEY_TEXT },        /* TELETEXT */
+	{ 0x02, 0x01, KEY_FIRST },       /* |<< / GREEN */
+	{ 0x02, 0x00, KEY_LAST },        /* >>| / BLUE */
+	{ 0x02, 0x04, KEY_EPG },         /* EPG */
+	{ 0x02, 0x15, KEY_MENU },        /* MENU */
+};
+
+int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5];
+	if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
+				0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
+				2*HZ) != 5)
+		return -ENODEV;
+
+	/* call the universal NEC remote processor, to find out the key's state and event */
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties a800_properties;
+
+static int a800_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id a800_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
+/* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, a800_table);
+
+static struct dvb_usb_properties a800_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 32,
+
+	.usb_ctrl = CYPRESS_FX2,
+
+	.firmware = "dvb-usb-avertv-a800-02.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = a800_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = a800_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(a800_rc_keys),
+	.rc_query         = a800_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{   "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+			{ &a800_table[0], NULL },
+			{ &a800_table[1], NULL },
+		},
+	}
+};
+
+static struct usb_driver a800_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+	.probe		= a800_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= a800_table,
+};
+
+/* module stuff */
+static int __init a800_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&a800_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit a800_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&a800_driver);
+}
+
+module_init (a800_module_init);
+module_exit (a800_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
new file mode 100644
index 00000000000..63b626f70c8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -0,0 +1,272 @@
+/* Common methods for dibusb-based-receivers.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
+MODULE_LICENSE("GPL");
+
+#define deb_info(args...) dprintk(debug,0x01,args)
+
+/* common stuff used by the different dibusb modules */
+int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (d->priv != NULL) {
+		struct dib_fe_xfer_ops *ops = d->priv;
+		if (ops->fifo_ctrl != NULL)
+			if (ops->fifo_ctrl(d->fe,onoff)) {
+				err("error while controlling the fifo of the demod.");
+				return -ENODEV;
+			}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_streaming_ctrl);
+
+int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+	if (d->priv != NULL) {
+		struct dib_fe_xfer_ops *ops = d->priv;
+		if (d->pid_filtering && ops->pid_ctrl != NULL)
+			ops->pid_ctrl(d->fe,index,pid,onoff);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_pid_filter);
+
+int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (d->priv != NULL) {
+		struct dib_fe_xfer_ops *ops = d->priv;
+		if (ops->pid_parse != NULL)
+			if (ops->pid_parse(d->fe,onoff) < 0)
+				err("could not handle pid_parser");
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
+
+int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 b[3];
+	int ret;
+	b[0] = DIBUSB_REQ_SET_IOCTL;
+	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
+	b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
+	ret = dvb_usb_generic_write(d,b,3);
+	msleep(10);
+	return ret;
+}
+EXPORT_SYMBOL(dibusb_power_ctrl);
+
+int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 b[2];
+	b[0] = DIBUSB_REQ_SET_IOCTL;
+	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+
+	dvb_usb_generic_write(d,b,3);
+
+	return dibusb_streaming_ctrl(d,onoff);
+}
+EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
+
+int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (onoff) {
+		u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
+		return dvb_usb_generic_write(d,b,3);
+	} else
+		return 0;
+}
+EXPORT_SYMBOL(dibusb2_0_power_ctrl);
+
+static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
+			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
+	/* write only ? */
+	int wo = (rbuf == NULL || rlen == 0),
+		len = 2 + wlen + (wo ? 0 : 2);
+
+	sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
+	sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
+
+	memcpy(&sndbuf[2],wbuf,wlen);
+
+	if (!wo) {
+		sndbuf[wlen+2] = (rlen >> 8) & 0xff;
+		sndbuf[wlen+3] = rlen & 0xff;
+	}
+
+	return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
+}
+
+/*
+ * I2C master xfer function
+ */
+static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (down_interruptible(&d->i2c_sem) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
+						msg[i+1].buf,msg[i+1].len) < 0)
+				break;
+			i++;
+		} else
+			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
+				break;
+	}
+
+	up(&d->i2c_sem);
+	return i;
+}
+
+static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm dibusb_i2c_algo = {
+	.name          = "DiBcom USB I2C algorithm",
+	.id            = I2C_ALGO_BIT,
+	.master_xfer   = dibusb_i2c_xfer,
+	.functionality = dibusb_i2c_func,
+};
+EXPORT_SYMBOL(dibusb_i2c_algo);
+
+int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
+{
+	u8 wbuf[1] = { offs };
+	return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
+}
+EXPORT_SYMBOL(dibusb_read_eeprom_byte);
+
+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;
+}
+EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
+
+int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
+{
+	d->pll_addr = 0x60;
+	d->pll_desc = &dvb_pll_env57h1xd5;
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
+
+/*
+ * common remote control stuff
+ */
+struct dvb_usb_rc_key dibusb_rc_keys[] = {
+	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
+	{ 0x00, 0x16, KEY_POWER },
+	{ 0x00, 0x10, KEY_MUTE },
+	{ 0x00, 0x03, KEY_1 },
+	{ 0x00, 0x01, KEY_2 },
+	{ 0x00, 0x06, KEY_3 },
+	{ 0x00, 0x09, KEY_4 },
+	{ 0x00, 0x1d, KEY_5 },
+	{ 0x00, 0x1f, KEY_6 },
+	{ 0x00, 0x0d, KEY_7 },
+	{ 0x00, 0x19, KEY_8 },
+	{ 0x00, 0x1b, KEY_9 },
+	{ 0x00, 0x15, KEY_0 },
+	{ 0x00, 0x05, KEY_CHANNELUP },
+	{ 0x00, 0x02, KEY_CHANNELDOWN },
+	{ 0x00, 0x1e, KEY_VOLUMEUP },
+	{ 0x00, 0x0a, KEY_VOLUMEDOWN },
+	{ 0x00, 0x11, KEY_RECORD },
+	{ 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
+	{ 0x00, 0x14, KEY_PLAY },
+	{ 0x00, 0x1a, KEY_STOP },
+	{ 0x00, 0x40, KEY_REWIND },
+	{ 0x00, 0x12, KEY_FASTFORWARD },
+	{ 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
+	{ 0x00, 0x4c, KEY_PAUSE },
+	{ 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */
+	{ 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
+	/* additional keys TwinHan VisionPlus, the Artec seemingly not have */
+	{ 0x00, 0x0c, KEY_CANCEL }, /* Cancel */
+	{ 0x00, 0x1c, KEY_EPG }, /* EPG */
+	{ 0x00, 0x00, KEY_TAB }, /* Tab */
+	{ 0x00, 0x48, KEY_INFO }, /* Preview */
+	{ 0x00, 0x04, KEY_LIST }, /* RecordList */
+	{ 0x00, 0x0f, KEY_TEXT }, /* Teletext */
+	/* Key codes for the KWorld/ADSTech/JetWay remote. */
+	{ 0x86, 0x12, KEY_POWER },
+	{ 0x86, 0x0f, KEY_SELECT }, /* source */
+	{ 0x86, 0x0c, KEY_UNKNOWN }, /* scan */
+	{ 0x86, 0x0b, KEY_EPG },
+	{ 0x86, 0x10, KEY_MUTE },
+	{ 0x86, 0x01, KEY_1 },
+	{ 0x86, 0x02, KEY_2 },
+	{ 0x86, 0x03, KEY_3 },
+	{ 0x86, 0x04, KEY_4 },
+	{ 0x86, 0x05, KEY_5 },
+	{ 0x86, 0x06, KEY_6 },
+	{ 0x86, 0x07, KEY_7 },
+	{ 0x86, 0x08, KEY_8 },
+	{ 0x86, 0x09, KEY_9 },
+	{ 0x86, 0x0a, KEY_0 },
+	{ 0x86, 0x18, KEY_ZOOM },
+	{ 0x86, 0x1c, KEY_UNKNOWN }, /* preview */
+	{ 0x86, 0x13, KEY_UNKNOWN }, /* snap */
+	{ 0x86, 0x00, KEY_UNDO },
+	{ 0x86, 0x1d, KEY_RECORD },
+	{ 0x86, 0x0d, KEY_STOP },
+	{ 0x86, 0x0e, KEY_PAUSE },
+	{ 0x86, 0x16, KEY_PLAY },
+	{ 0x86, 0x11, KEY_BACK },
+	{ 0x86, 0x19, KEY_FORWARD },
+	{ 0x86, 0x14, KEY_UNKNOWN }, /* pip */
+	{ 0x86, 0x15, KEY_ESC },
+	{ 0x86, 0x1a, KEY_UP },
+	{ 0x86, 0x1e, KEY_DOWN },
+	{ 0x86, 0x1f, KEY_LEFT },
+	{ 0x86, 0x1b, KEY_RIGHT },
+};
+EXPORT_SYMBOL(dibusb_rc_keys);
+
+int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
+	dvb_usb_generic_rw(d,&cmd,1,key,5,0);
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_rc_query);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
new file mode 100644
index 00000000000..fd103e4746e
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -0,0 +1,316 @@
+/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
+ * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+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;
+}
+
+/* some of the dibusb 1.1 device aren't equipped with the default tuner
+ * (Thomson Cable), but with a Panasonic ENV77H11D5.  This function figures
+ * this out. */
+static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
+{
+	u8 b[2] = { 0,0 }, b2[1];
+	int ret = 0;
+	struct i2c_msg msg[2] = {
+		{ .flags = 0,        .buf = b,  .len = 2 },
+		{ .flags = I2C_M_RD, .buf = b2, .len = 1 },
+	};
+
+	/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
+	msg[0].addr = msg[1].addr = 0x60;
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(d->fe,1,msg[0].addr);
+
+	if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) {
+		err("tuner i2c write failed.");
+		ret = -EREMOTEIO;
+	}
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
+
+	if (b2[0] == 0xfe) {
+		info("this device has the Thomson Cable onboard. Which is default.");
+		d->pll_addr = 0x61;
+		d->pll_desc = &dvb_pll_tua6010xs;
+	} else {
+		u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
+		info("this device has the Panasonic ENV77H11D5 onboard.");
+		d->pll_addr = 0x60;
+		memcpy(d->pll_init,bpll,4);
+		d->pll_desc = &dvb_pll_tda665x;
+	}
+
+	return ret;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties dibusb1_1_properties;
+static struct dvb_usb_properties dibusb1_1_an2235_properties;
+static struct dvb_usb_properties dibusb2_0b_properties;
+
+static int dibusb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
+		dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) ||
+		dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
+		return 0;
+
+	return -EINVAL;
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id dibusb_dib3000mb_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA_UNK,	USB_PID_AVERMEDIA_DVBT_USB_COLD)},
+/* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA_UNK,	USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 02 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_COLD) },
+/* 03 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_WARM) },
+/* 04 */	{ USB_DEVICE(USB_VID_COMPRO_UNK,	USB_PID_COMPRO_DVBU2000_UNK_COLD) },
+/* 05 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_COLD) },
+/* 06 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_WARM) },
+/* 07 */	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_COLD) },
+/* 08 */	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_WARM) },
+/* 09 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_COLD) },
+/* 10 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_WARM) },
+/* 11 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_COLD) },
+/* 12 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_WARM) },
+/* 13 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD) },
+/* 14 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM) },
+/* 15 */	{ USB_DEVICE(USB_VID_VISIONPLUS,	USB_PID_TWINHAN_VP7041_COLD) },
+/* 16 */	{ USB_DEVICE(USB_VID_VISIONPLUS,	USB_PID_TWINHAN_VP7041_WARM) },
+/* 17 */	{ USB_DEVICE(USB_VID_TWINHAN,		USB_PID_TWINHAN_VP7041_COLD) },
+/* 18 */	{ USB_DEVICE(USB_VID_TWINHAN,		USB_PID_TWINHAN_VP7041_WARM) },
+/* 19 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+/* 20 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+/* 21 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+/* 22 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+/* 23 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_COLD) },
+/* 24 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_WARM) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
+
+static struct dvb_usb_properties dibusb1_1_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 16,
+
+	.usb_ctrl = CYPRESS_AN2135,
+
+	.firmware = "dvb-usb-dibusb-5.0.0.11.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mb_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 8,
+	.devices = {
+		{	"AVerMedia AverTV DVBT USB1.1",
+			{ &dibusb_dib3000mb_table[0],  NULL },
+			{ &dibusb_dib3000mb_table[1],  NULL },
+		},
+		{	"Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
+			{ &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL},
+			{ &dibusb_dib3000mb_table[3], NULL },
+		},
+		{	"DiBcom USB1.1 DVB-T reference design (MOD3000)",
+			{ &dibusb_dib3000mb_table[5],  NULL },
+			{ &dibusb_dib3000mb_table[6],  NULL },
+		},
+		{	"KWorld V-Stream XPERT DTV - DVB-T USB1.1",
+			{ &dibusb_dib3000mb_table[7], NULL },
+			{ &dibusb_dib3000mb_table[8], NULL },
+		},
+		{	"Grandtec USB1.1 DVB-T",
+			{ &dibusb_dib3000mb_table[9],  &dibusb_dib3000mb_table[11], NULL },
+			{ &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL },
+		},
+		{	"Unkown USB1.1 DVB-T device ???? please report the name to the author",
+			{ &dibusb_dib3000mb_table[13], NULL },
+			{ &dibusb_dib3000mb_table[14], NULL },
+		},
+		{	"TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
+			{ &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL},
+			{ &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL},
+		},
+		{	"Artec T1 USB1.1 TVBOX with AN2135",
+			{ &dibusb_dib3000mb_table[19], NULL },
+			{ &dibusb_dib3000mb_table[20], NULL },
+		},
+	}
+};
+
+static struct dvb_usb_properties dibusb1_1_an2235_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = CYPRESS_AN2235,
+
+	.firmware = "dvb-usb-dibusb-an2235-01.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mb_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{	"Artec T1 USB1.1 TVBOX with AN2235",
+			{ &dibusb_dib3000mb_table[20], NULL },
+			{ &dibusb_dib3000mb_table[21], NULL },
+		},
+	}
+};
+
+static struct dvb_usb_properties dibusb2_0b_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = CYPRESS_FX2,
+
+	.firmware = "dvb-usb-adstech-usb2-01.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb2_0_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mb_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{	"KWorld/ADSTech Instant DVB-T USB 2.0",
+			{ &dibusb_dib3000mb_table[23], NULL },
+			{ &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */
+		},
+	}
+};
+
+static struct usb_driver dibusb_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "DiBcom based USB DVB-T devices (DiB3000M-B based)",
+	.probe		= dibusb_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= dibusb_dib3000mb_table,
+};
+
+/* module stuff */
+static int __init dibusb_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&dibusb_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit dibusb_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&dibusb_driver);
+}
+
+module_init (dibusb_module_init);
+module_exit (dibusb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
new file mode 100644
index 00000000000..aad8ed3fe00
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -0,0 +1,116 @@
+/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
+ * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+/* USB Driver stuff */
+static struct dvb_usb_properties dibusb_mc_properties;
+
+static int dibusb_mc_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id dibusb_dib3000mc_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_COLD) },
+/* 01 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_WARM) },
+/* 02 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
+
+static struct dvb_usb_properties dibusb_mc_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 32,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb2_0_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* FIXME */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{   "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
+			{ &dibusb_dib3000mc_table[0], NULL },
+			{ &dibusb_dib3000mc_table[1], NULL },
+		},
+		{   "Artec T1 USB2.0 TVBOX (please report the warm ID)",
+			{ &dibusb_dib3000mc_table[2], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver dibusb_mc_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices",
+	.probe		= dibusb_mc_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= dibusb_dib3000mc_table,
+};
+
+/* module stuff */
+static int __init dibusb_mc_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&dibusb_mc_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit dibusb_mc_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&dibusb_mc_driver);
+}
+
+module_init (dibusb_mc_module_init);
+module_exit (dibusb_mc_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
new file mode 100644
index 00000000000..6611f62977c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -0,0 +1,122 @@
+/* Header file for all dibusb-based-receivers.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_DIBUSB_H_
+#define _DVB_USB_DIBUSB_H_
+
+#define DVB_USB_LOG_PREFIX "dibusb"
+#include "dvb-usb.h"
+
+#include "dib3000.h"
+
+/*
+ * protocol of all dibusb related devices
+ */
+
+/*
+ * bulk msg to/from endpoint 0x01
+ *
+ * general structure:
+ * request_byte parameter_bytes
+ */
+
+#define DIBUSB_REQ_START_READ			0x00
+#define DIBUSB_REQ_START_DEMOD			0x01
+
+/*
+ * i2c read
+ * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
+ * bulk read:  byte_buffer (length_word bytes)
+ */
+#define DIBUSB_REQ_I2C_READ			0x02
+
+/*
+ * i2c write
+ * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
+ */
+#define DIBUSB_REQ_I2C_WRITE			0x03
+
+/*
+ * polling the value of the remote control
+ * bulk write: 0x04
+ * bulk read:  byte_buffer (5 bytes)
+ */
+#define DIBUSB_REQ_POLL_REMOTE       0x04
+
+/* additional status values for Hauppauge Remote Control Protocol */
+#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED	0x01
+#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY	0x03
+
+/* streaming mode:
+ * bulk write: 0x05 mode_byte
+ *
+ * mode_byte is mostly 0x00
+ */
+#define DIBUSB_REQ_SET_STREAMING_MODE	0x05
+
+/* interrupt the internal read loop, when blocking */
+#define DIBUSB_REQ_INTR_READ			0x06
+
+/* io control
+ * 0x07 cmd_byte param_bytes
+ *
+ * param_bytes can be up to 32 bytes
+ *
+ * cmd_byte function    parameter name
+ * 0x00     power mode
+ *                      0x00      sleep
+ *                      0x01      wakeup
+ *
+ * 0x01     enable streaming
+ * 0x02     disable streaming
+ *
+ *
+ */
+#define DIBUSB_REQ_SET_IOCTL			0x07
+
+/* IOCTL commands */
+
+/* change the power mode in firmware */
+#define DIBUSB_IOCTL_CMD_POWER_MODE		0x00
+#define DIBUSB_IOCTL_POWER_SLEEP			0x00
+#define DIBUSB_IOCTL_POWER_WAKEUP			0x01
+
+/* modify streaming of the FX2 */
+#define DIBUSB_IOCTL_CMD_ENABLE_STREAM	0x01
+#define DIBUSB_IOCTL_CMD_DISABLE_STREAM	0x02
+
+struct dibusb_state {
+	struct dib_fe_xfer_ops ops;
+
+	/* for RC5 remote control */
+	int old_toggle;
+	int last_repeat_count;
+};
+
+extern struct i2c_algorithm dibusb_i2c_algo;
+
+extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *);
+extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *);
+
+extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int);
+extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
+extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int);
+extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
+
+#define DEFAULT_RC_INTERVAL 150
+//#define DEFAULT_RC_INTERVAL 100000
+
+extern struct dvb_usb_rc_key dibusb_rc_keys[];
+extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
+extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
new file mode 100644
index 00000000000..5acf3fde952
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -0,0 +1,282 @@
+/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
+ * receiver
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and
+ *                    Allan Third (allan.third@cs.man.ac.uk)
+ *
+ * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?)
+ *
+ *	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.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "digitv.h"
+
+#include "mt352.h"
+#include "nxt6000.h"
+
+/* debug */
+int dvb_usb_digitv_debug;
+module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int digitv_ctrl_msg(struct dvb_usb_device *d,
+		u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	int wo = (rbuf == NULL || rlen == 0); /* write-only */
+	u8 sndbuf[7],rcvbuf[7];
+	memset(sndbuf,0,7); memset(rcvbuf,0,7);
+
+	sndbuf[0] = cmd;
+	sndbuf[1] = vv;
+	sndbuf[2] = wo ? wlen : rlen;
+
+	if (!wo) {
+		memcpy(&sndbuf[3],wbuf,wlen);
+		dvb_usb_generic_write(d,sndbuf,7);
+	} else {
+		dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
+		memcpy(&rbuf,&rcvbuf[3],rlen);
+	}
+	return 0;
+}
+
+/* I2C */
+static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (down_interruptible(&d->i2c_sem) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
+						msg[i+1].buf,msg[i+1].len) < 0)
+				break;
+			i++;
+		} else
+			if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
+						&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
+				break;
+	}
+
+	up(&d->i2c_sem);
+	return i;
+}
+
+static u32 digitv_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm digitv_i2c_algo = {
+	.name          = "Nebula DigiTV USB I2C algorithm",
+	.id            = I2C_ALGO_BIT,
+	.master_xfer   = digitv_i2c_xfer,
+	.functionality = digitv_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int digitv_identify_state (struct usb_device *udev, struct
+		dvb_usb_properties *props, struct dvb_usb_device_description **desc,
+		int *cold)
+{
+	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+	return 0;
+}
+
+static int digitv_mt352_demod_init(struct dvb_frontend *fe)
+{
+	static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d };
+	static u8 mt352_reset[] = { 0x50, 0x80 };
+	static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
+
+	static u8 mt352_agc_cfg[] = { 0x68, 0xa0 };
+	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 };
+	static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
+	static u8 mt352_agc_target[] = { 0x67, 0x20 };
+
+	static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 };
+	static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 };
+
+	static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 };
+
+	static u8 mt352_scan_ctl[] = { 0x88, 0x0f };
+	static u8 mt352_capt_range[] = { 0x75, 0x32 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	msleep(1);
+	mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
+
+	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+	mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
+	mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target));
+
+
+	mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per));
+	mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select));
+
+	mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
+
+	mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl));
+	mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range));
+
+	return 0;
+}
+
+static struct mt352_config digitv_mt352_config = {
+	.demod_address = 0x0, /* ignored by the digitv anyway */
+	.demod_init = digitv_mt352_demod_init,
+	.pll_set = NULL, /* TODO */
+};
+
+static struct nxt6000_config digitv_nxt6000_config = {
+	.demod_address = 0x0, /* ignored by the digitv anyway */
+	.clock_inversion = 0x0,
+
+	.pll_init = NULL,
+	.pll_set = NULL,
+};
+
+static int digitv_frontend_attach(struct dvb_usb_device *d)
+{
+	if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL)
+		return 0;
+	if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) {
+
+		warn("nxt6000 support is not done yet, in fact you are one of the first "
+				"person who wants to use this device in Linux. Please report to "
+				"linux-dvb@linuxtv.org");
+
+		return 0;
+	}
+	return -EIO;
+}
+
+static struct dvb_usb_rc_key digitv_rc_keys[] = {
+	{ 0x00, 0x16, KEY_POWER }, /* dummy key */
+};
+
+/* TODO is it really the NEC protocol ? */
+int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5];
+
+	digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
+	/* TODO state, maybe it is VV ? */
+	if (key[1] != 0)
+		key[0] = 0x01; /* if something is inside the buffer, simulate key press */
+
+	/* call the universal NEC remote processor, to find out the key's state and event */
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_properties digitv_properties;
+
+static int digitv_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
+}
+
+static struct usb_device_id digitv_table [] = {
+		{ USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
+		{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, digitv_table);
+
+static struct dvb_usb_properties digitv_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-digitv-01.fw",
+
+	.size_of_priv     = 0,
+
+	.streaming_ctrl   = NULL,
+	.pid_filter       = NULL,
+	.pid_filter_ctrl  = NULL,
+	.power_ctrl       = NULL,
+	.frontend_attach  = digitv_frontend_attach,
+	.tuner_attach     = NULL, // digitv_tuner_attach,
+	.read_mac_address = NULL,
+
+	.rc_interval      = 1000,
+	.rc_key_map       = digitv_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(digitv_rc_keys),
+	.rc_query         = digitv_rc_query,
+
+	.identify_state   = digitv_identify_state,
+
+	.i2c_algo         = &digitv_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{   "Nebula Electronics uDigiTV DVB-T USB2.0)",
+			{ &digitv_table[0], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver digitv_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "Nebula Electronics uDigiTV DVB-T USB2.0 device",
+	.probe		= digitv_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= digitv_table,
+};
+
+/* module stuff */
+static int __init digitv_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&digitv_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit digitv_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&digitv_driver);
+}
+
+module_init (digitv_module_init);
+module_exit (digitv_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h
new file mode 100644
index 00000000000..477ee428a70
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.h
@@ -0,0 +1,65 @@
+#ifndef _DVB_USB_DIGITV_H_
+#define _DVB_USB_DIGITV_H_
+
+#define DVB_USB_LOG_PREFIX "digitv"
+#include "dvb-usb.h"
+
+extern int dvb_usb_digitv_debug;
+#define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
+
+/* protocol (from usblogging and the SDK:
+ *
+ * Always 7 bytes bulk message(s) for controlling
+ *
+ * First byte describes the command. Reads are 2 consecutive transfer (as always).
+ *
+ * General structure:
+ *
+ * write or first message of a read:
+ * <cmdbyte> VV <len> B0 B1 B2 B3
+ *
+ * second message of a read
+ * <cmdbyte> VV <len> R0 R1 R2 R3
+ *
+ * whereas 0 < len <= 4
+ *
+ * I2C address is stored somewhere inside the device.
+ *
+ * 0x01 read from EEPROM
+ *  VV = offset; B* = 0; R* = value(s)
+ *
+ * 0x02 read register of the COFDM
+ *  VV = register; B* = 0; R* = value(s)
+ *
+ * 0x05 write register of the COFDM
+ *  VV = register; B* = value(s);
+ *
+ * 0x06 write to the tuner (only for NXT6000)
+ *  VV = 0; B* = PLL data; len = 4;
+ *
+ * 0x03 read remote control
+ *  VV = 0; B* = 0; len = 4; R* = key
+ *
+ * 0x07 write to the remote (don't know why one should this, resetting ?)
+ *  VV = 0; B* = key; len = 4;
+ *
+ * 0x08 write remote type
+ *  VV = 0; B[0] = 0x01, len = 4
+ *
+ * 0x09 write device init
+ *  TODO
+ */
+#define USB_READ_EEPROM         1
+
+#define USB_READ_COFDM          2
+#define USB_WRITE_COFDM         5
+
+#define USB_WRITE_TUNER         6
+
+#define USB_READ_REMOTE         3
+#define USB_WRITE_REMOTE        7
+#define USB_WRITE_REMOTE_TYPE   8
+
+#define USB_DEV_INIT            9