summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
authorPatrick Boettcher <devnull@localhost>2004-12-26 21:36:25 +0000
committerPatrick Boettcher <devnull@localhost>2004-12-26 21:36:25 +0000
commita6f918f6a12f1f47ee17ec62a0844dea8c3ab33b (patch)
tree1f6e7ec0623e3ff3b30d456a339845cd5ed6d3c5 /linux/drivers
parentec61b5437a9c1b58d31e84eb725d08f4bd4fbeac (diff)
downloadmediapointer-dvb-s2-a6f918f6a12f1f47ee17ec62a0844dea8c3ab33b.tar.gz
mediapointer-dvb-s2-a6f918f6a12f1f47ee17ec62a0844dea8c3ab33b.tar.bz2
- enabled i2c-address probing for frontends
- refactored the dibusb driver, split into separate, code-dependent files, should have done this from the beginning, sorry for possible inconveniences in advance; I'm still learning
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/dvb/dibusb/Kconfig4
-rw-r--r--linux/drivers/media/dvb/dibusb/Makefile7
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c462
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c205
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c252
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c95
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c185
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c216
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb.c1034
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb.h345
10 files changed, 1525 insertions, 1280 deletions
diff --git a/linux/drivers/media/dvb/dibusb/Kconfig b/linux/drivers/media/dvb/dibusb/Kconfig
index 69efde08d..a6d41043a 100644
--- a/linux/drivers/media/dvb/dibusb/Kconfig
+++ b/linux/drivers/media/dvb/dibusb/Kconfig
@@ -19,7 +19,8 @@ config DVB_DIBUSB
Compro Videomate DVB-U2000 - DVB-T USB
Grandtec DVB-T USB
Avermedia AverTV DVBT USB
- Yakumo DVB-T mobile USB2.0
+ Artec T1 USB1.1 and USB2.0 boxes
+ Yakumo/Typhoon DVB-T USB2.0
The VP7041 seems to be identical to "CTS Portable" (Chinese
Television System).
@@ -46,6 +47,7 @@ config DVB_DIBUSB_MISDESIGNED_DEVICES
0x0574:0x2235 (Artec T1 USB1.1, cold)
0x04b4:0x8613 (Artec T1 USB2.0, cold)
0x0574:0x1002 (Artec T1 USB2.0, warm)
+ 0x0574:0x2131 (aged DiBcom USB1.1 test device)
Say Y if your device has one of the mentioned IDs.
diff --git a/linux/drivers/media/dvb/dibusb/Makefile b/linux/drivers/media/dvb/dibusb/Makefile
index ab990cd3b..aeb896fe2 100644
--- a/linux/drivers/media/dvb/dibusb/Makefile
+++ b/linux/drivers/media/dvb/dibusb/Makefile
@@ -1,3 +1,10 @@
+dvb-dibusb-objs = dvb-dibusb-core.o \
+ dvb-dibusb-dvb.o \
+ dvb-dibusb-fe-i2c.o \
+ dvb-dibusb-firmware.o \
+ dvb-dibusb-remote.o \
+ dvb-dibusb-usb.o
+
obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c
new file mode 100644
index 000000000..9cbfede7d
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-core.c
@@ -0,0 +1,462 @@
+/*
+ * Driver for mobile USB Budget DVB-T devices based on reference
+ * design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * dvb-dibusb-core.c
+ *
+ * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * 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.
+ *
+ * Acknowledgements
+ *
+ * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
+ * sources, on which this driver (and the dib3000mb/mc/p frontends) are based.
+ *
+ * see Documentation/dvb/README.dibusb for more information
+ */
+#include "dvb-dibusb.h"
+
+#include <linux/moduleparam.h>
+
+/* debug */
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+int debug;
+module_param(debug, int, 0x644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able)).");
+#endif
+
+int pid_parse;
+module_param(pid_parse, int, 0x644);
+MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0");
+
+int rc_query_interval;
+module_param(rc_query_interval, int, 0x644);
+MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)");
+
+/* Version information */
+#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"
+
+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"
+};
+
+static const char * dibusb_fw_filenames2_0[] = {
+ "dvb-dibusb-6.0.0.5.fw"
+};
+
+int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct
+ dvb_frontend_parameters *params);
+
+int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct
+ dvb_frontend_parameters* params);
+
+static struct dibusb_device_parameter dibusb_dev_parm[3] = {
+ { .type = DIBUSB1_1,
+ .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 = 0x01,
+ .data_pipe = 0x02,
+
+ .pll_set = thomson_cable_eu_pll_set,
+ .pll_addr = 194,
+ .demod_i2c_addrs = { 0x10, 0, 0, 0 },
+ },
+ { .type = DIBUSB2_0,
+ .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 = 0x01,
+ .data_pipe = 0x06,
+
+ .pll_set = panasonic_cofdm_env57h1xd5_pll_set,
+ .pll_addr = 192,
+ .demod_i2c_addrs = { 0x12, 0x14, 0x16, 0x18 },
+ },
+ { .type = DIBUSB1_1_AN2235,
+ .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 = 0x01,
+ .data_pipe = 0x02,
+
+ .pll_set = thomson_cable_eu_pll_set,
+ .pll_addr = 194,
+ .demod_i2c_addrs = { 0x10, 0, 0, 0 },
+ }
+};
+
+/* Vendor IDs */
+#define USB_VID_ANCHOR 0x0547
+#define USB_VID_AVERMEDIA 0x14aa
+#define USB_VID_COMPRO 0x185b
+#define USB_VID_COMPRO_UNK 0x145f
+#define USB_VID_CYPRESS 0x04b4
+#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_COMPRO_DVBU2000_UNK_COLD 0x010c
+#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
+#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_DIBCOM_ANCHOR_2135_COLD 0x2131
+#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_ULTIMA_TVBOX_USB2_COLD 0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
+#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 16
+
+/* USB Driver stuff */
+static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
+ { .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 = "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs",
+ .cold_product_id = USB_PID_DIBCOM_ANCHOR_2135_COLD,
+ .warm_product_id = 0, /* undefined, let's see what comes out */
+ .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 = "Artec T1 USB2.0 TVBOX (please report the warm ID)",
+ .cold_product_id = USB_PID_ULTIMA_TVBOX_USB2_COLD,
+ .warm_product_id = 0, /* don't know, it is most likely that the device will get another USB ID in warm state */
+ .parm = &dibusb_dev_parm[1],
+ },
+ { .name = "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)",
+ .cold_product_id = USB_PID_ULTIMA_TVBOX_USB2_FX_COLD,
+ .warm_product_id = USB_PID_ULTIMA_TVBOX_USB2_FX_WARM, /* undefined, it could be that the device will get another USB ID in warm state */
+ .parm = &dibusb_dev_parm[1],
+ },
+ { .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 = "Compro Videomate DVB-U2000 - DVB-T USB1.1 (really ?? please report the name!)",
+ .cold_product_id = USB_PID_COMPRO_DVBU2000_UNK_COLD,
+ .warm_product_id = USB_PID_COMPRO_DVBU2000_UNK_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/Typhoon 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 this driver is working with */
+static struct usb_device_id dibusb_table [] = {
+ { 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) },
+ { USB_DEVICE(USB_PID_COMPRO_DVBU2000_UNK_COLD, USB_VID_COMPRO_UNK) },
+ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+
+/*
+ * activate the following define when you have one of the devices and want to
+ * build it from build-2.6 in dvb-kernel
+ */
+// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
+#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
+ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
+ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
+ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
+ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) },
+#endif
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, dibusb_table);
+
+static int dibusb_exit(struct usb_dibusb *dib)
+{
+ dibusb_remote_exit(dib);
+ dibusb_fe_exit(dib);
+ dibusb_i2c_exit(dib);
+ dibusb_dvb_exit(dib);
+ dibusb_usb_exit(dib);
+ kfree(dib);
+ return 0;
+}
+
+static int dibusb_init(struct usb_dibusb *dib)
+{
+ int ret = 0;
+ sema_init(&dib->usb_sem, 1);
+ sema_init(&dib->i2c_sem, 1);
+
+ if ((ret = dibusb_usb_init(dib)) ||
+ (ret = dibusb_dvb_init(dib)) ||
+ (ret = dibusb_i2c_init(dib))) {
+ dibusb_exit(dib);
+ return ret;
+ }
+
+ dibusb_hw_wakeup(dib);
+ dibusb_set_streaming_mode(dib,0);
+ dibusb_streaming(dib,1);
+
+ if ((ret = dibusb_fe_init(dib)))
+ err("could not initialize a frontend.");
+
+ if ((ret = dibusb_remote_init(dib)))
+ err("could not initialize remote control.");
+
+ return 0;
+}
+
+/*
+ * USB
+ */
+static int dibusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_dibusb *dib = NULL;
+ struct dibusb_device *dibdev = NULL;
+
+ int ret = -ENOMEM,i,cold=0;
+
+ for (i = 0; i < DIBUSB_SUPPORTED_DEVICES; i++)
+ if (dibusb_devices[i].cold_product_id == udev->descriptor.idProduct ||
+ dibusb_devices[i].warm_product_id == udev->descriptor.idProduct) {
+ dibdev = &dibusb_devices[i];
+
+ cold = dibdev->cold_product_id == udev->descriptor.idProduct;
+
+ if (cold)
+ info("found a '%s' in cold state, will try to load a firmware",dibdev->name);
+ else
+ info("found a '%s' in warm state.",dibdev->name);
+ }
+
+ if (dibdev == NULL) {
+ err("something went very wrong, "
+ "unknown product ID: %.4x",udev->descriptor.idProduct);
+ return -ENODEV;
+ }
+
+ if (cold)
+ ret = dibusb_loadfirmware(udev,dibdev);
+ else {
+ dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL);
+ if (dib == NULL) {
+ err("no memory");
+ return ret;
+ }
+ memset(dib,0,sizeof(struct usb_dibusb));
+
+ dib->pid_parse = 1;
+ 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 parsing.");
+ break;
+ case USB_SPEED_HIGH:
+ if (!pid_parse) {
+ dib->pid_parse = 0;
+ info("running at HIGH speed, will deliver the complete TS.");
+ } else
+ info("running at HIGH speed, will use pid_parsing anyway.");
+ break;
+ case USB_SPEED_UNKNOWN: /* fall through */
+ default:
+ err("cannot handle USB speed because it is unkown.");
+ break;
+ }
+ dib->udev = udev;
+ dib->dibdev = dibdev;
+
+ usb_set_intfdata(intf, dib);
+
+ ret = dibusb_init(dib);
+ }
+
+ if (ret == 0)
+ info("%s successfully initialized and connected.",dibdev->name);
+ else
+ info("%s error while loading driver (%d)",dibdev->name,ret);
+ return ret;
+}
+
+static void dibusb_disconnect(struct usb_interface *intf)
+{
+ struct usb_dibusb *dib = usb_get_intfdata(intf);
+ const char *name = DRIVER_DESC;
+
+ usb_set_intfdata(intf,NULL);
+ if (dib != NULL && dib->dibdev != NULL) {
+ name = dib->dibdev->name;
+ dibusb_exit(dib);
+ }
+ info("%s successfully deinitialized and disconnected.",name);
+
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver dibusb_driver = {
+ .owner = THIS_MODULE,
+ .name = "dvb_dibusb",
+ .probe = dibusb_probe,
+ .disconnect = dibusb_disconnect,
+ .id_table = dibusb_table,
+};
+
+/* module stuff */
+static int __init usb_dibusb_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 usb_dibusb_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&dibusb_driver);
+}
+
+module_init (usb_dibusb_init);
+module_exit (usb_dibusb_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
new file mode 100644
index 000000000..3d35ad322
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
@@ -0,0 +1,205 @@
+/*
+ * dvb-dibusb-dvb.c is part of the driver for mobile USB Budget DVB-T devices
+ * based on reference design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * see dvb-dibusb-core.c for more copyright details.
+ *
+ * This file contains functions for initializing and handling the
+ * linux-dvb API.
+ */
+#include "dvb-dibusb.h"
+
+#include <linux/usb.h>
+#include <linux/version.h>
+
+/*
+ * MPEG2 TS DVB stuff
+ */
+void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+ struct usb_dibusb *dib = urb->context;
+ int ret;
+
+ deb_ts("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status);
+
+ switch (urb->status) {
+ case 0: /* success */
+ case -ETIMEDOUT: /* NAK */
+ break;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* error */
+ warn("urb completition error %d.", urb->status);
+ }
+
+ if (dib->feedcount > 0) {
+ deb_ts("URB return len: %d\n",urb->actual_length);
+ if (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, at least for USB1.1
+ */
+ 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 "
+ "actual_length or !dvb_is_ready (%d).\n",dib->dvb_is_ready);
+ } else
+ deb_ts("URB dropped because of feedcount.\n");
+
+ ret = usb_submit_urb(urb,GFP_ATOMIC);
+ deb_ts("urb resubmitted, (%d)\n",ret);
+}
+
+static int dibusb_ctrl_feed(struct usb_dibusb *dib, int pid, int onoff)
+{
+ int newfeedcount = dib->feedcount + (onoff ? 1 : -1);
+ /*
+ * stop feed before setting a new pid and firmware_bug
+ * or if there will be no pid anymore
+ */
+ if ((dib->dibdev->parm->firmware_bug && dib->feedcount) || newfeedcount == 0) {
+ 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;
+ }
+ }
+
+ dib->feedcount = newfeedcount;
+
+ if (dib->pid_parse) {
+ 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;
+ }
+ } 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 and there is still a pid for
+ * reception.
+ */
+ if ((dib->dibdev->parm->firmware_bug || dib->feedcount == onoff) &&
+ dib->feedcount > 0) {
+
+ deb_ts("controlling pid parser\n");
+ if (dib->xfer_ops.pid_parse != NULL) {
+ if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) {
+ err("could not handle pid_parser");
+ }
+ }
+
+ 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;
+ }
+ dibusb_streaming(dib,1);
+ }
+ return 0;
+}
+
+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);
+}
+
+static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ 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);
+}
+
+int dibusb_dvb_init(struct usb_dibusb *dib)
+{
+ int ret;
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,4)
+ if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC)) < 0) {
+#else
+ if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC ,
+ THIS_MODULE)) < 0) {
+#endif
+ deb_info("dvb_register_adapter failed: error %d", ret);
+ goto err;
+ }
+ dib->adapter->priv = dib;
+
+/* i2c is done in dibusb_i2c_init */
+
+ dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+
+ dib->demux.priv = (void *)dib;
+ /* get pidcount from demod */
+ dib->demux.feednum = dib->demux.filternum = 24;
+ dib->demux.start_feed = dibusb_start_feed;
+ dib->demux.stop_feed = dibusb_stop_feed;
+ dib->demux.write_to_decoder = NULL;
+ if ((ret = dvb_dmx_init(&dib->demux)) < 0) {
+ err("dvb_dmx_init failed: error %d",ret);
+ goto err_dmx;
+ }
+
+ dib->dmxdev.filternum = dib->demux.filternum;
+ dib->dmxdev.demux = &dib->demux.dmx;
+ dib->dmxdev.capabilities = 0;
+ if ((ret = dvb_dmxdev_init(&dib->dmxdev, dib->adapter)) < 0) {
+ err("dvb_dmxdev_init failed: error %d",ret);
+ goto err_dmx_dev;
+ }
+
+ dvb_net_init(dib->adapter, &dib->dvb_net, &dib->demux.dmx);
+
+ goto success;
+err_dmx_dev:
+ dvb_dmx_release(&dib->demux);
+err_dmx:
+ dvb_unregister_adapter(dib->adapter);
+err:
+ return ret;
+success:
+ dib->dvb_is_ready = 1;
+ return 0;
+}
+
+int dibusb_dvb_exit(struct usb_dibusb *dib)
+{
+ 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);
+ dvb_unregister_adapter(dib->adapter);
+ return 0;
+}
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
new file mode 100644
index 000000000..dc60a6a92
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
@@ -0,0 +1,252 @@
+/*
+ * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
+ * based on reference design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * see dvb-dibusb-core.c for more copyright details.
+ *
+ * This file contains functions for attaching, initializing of an appropriate
+ * demodulator/frontend. I2C-stuff is also located here.
+ *
+ */
+#include "dvb-dibusb.h"
+
+#include <linux/usb.h>
+
+static int dibusb_i2c_msg(struct usb_dibusb *dib, 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 & 0xfe) | (wo ? 0 : 1);
+
+ memcpy(&sndbuf[2],wbuf,wlen);
+
+ if (!wo) {
+ sndbuf[wlen+2] = (rlen >> 8) & 0xff;
+ sndbuf[wlen+3] = rlen & 0xff;
+ }
+
+ return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
+}
+
+/*
+ * I2C master xfer function
+ */
+static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+ struct usb_dibusb *dib = i2c_get_adapdata(adap);
+ int i;
+
+ if (down_interruptible(&dib->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(dib, 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(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
+ break;
+ }
+
+ up(&dib->i2c_sem);
+ return i;
+}
+
+static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dibusb_algo = {
+ .name = "DiBcom USB i2c algorithm",
+ .id = I2C_ALGO_BIT,
+ .master_xfer = dibusb_i2c_xfer,
+ .functionality = dibusb_i2c_func,
+};
+
+int dibusb_fe_init(struct usb_dibusb* dib)
+{
+ struct dib3000_config demod_cfg;
+ int i;
+
+ for (i = 0; i < sizeof(dib->dibdev->parm->demod_i2c_addrs) / sizeof(unsigned char) &&
+ dib->dibdev->parm->demod_i2c_addrs[i] != 0; i++) {
+
+ demod_cfg.demod_address = dib->dibdev->parm->demod_i2c_addrs[i];
+ demod_cfg.pll_addr = dib->dibdev->parm->pll_addr;
+ demod_cfg.pll_set = dib->dibdev->parm->pll_set;
+ demod_cfg.pll_init = NULL;
+
+ switch (dib->dibdev->parm->type) {
+ case DIBUSB1_1:
+ case DIBUSB1_1_AN2235:
+ dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
+ break;
+ case DIBUSB2_0:
+ dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
+ break;
+ }
+ if (dib->fe != NULL) {
+ info("found demodulator at i2c address 0x%x",demod_cfg.demod_address);
+ break;
+ }
+ }
+
+ if (dib->fe == NULL) {
+ err("A frontend driver was not found for device '%s'.",
+ dib->dibdev->name);
+ return -ENODEV;
+ } else {
+ if (dvb_register_frontend(dib->adapter, dib->fe)) {
+ err("Frontend registration failed.");
+ if (dib->fe->ops->release)
+ dib->fe->ops->release(dib->fe);
+ dib->fe = NULL;
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+
+int dibusb_fe_exit(struct usb_dibusb *dib)
+{
+ if (dib->fe != NULL)
+ dvb_unregister_frontend(dib->fe);
+ return 0;
+}
+
+int dibusb_i2c_init(struct usb_dibusb *dib)
+{
+ int ret = 0;
+
+ dib->adapter->priv = dib;
+
+ strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+ dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
+#else
+ dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
+#endif
+ dib->i2c_adap.algo = &dibusb_algo;
+ dib->i2c_adap.algo_data = NULL;
+ dib->i2c_adap.id = I2C_ALGO_BIT;
+
+ i2c_set_adapdata(&dib->i2c_adap, dib);
+
+ if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)
+ err("could not add i2c adapter");
+
+ return ret;
+}
+
+int dibusb_i2c_exit(struct usb_dibusb *dib)
+{
+ i2c_del_adapter(&dib->i2c_adap);
+ return 0;
+}
+
+
+
+/* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */
+int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct
+ dvb_frontend_parameters* params)
+{
+ struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
+ u8 buf[4];
+ struct i2c_msg msg = {
+ .addr = dib->dibdev->parm->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;
+}
+
+int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct
+ dvb_frontend_parameters *params)
+{
+ struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
+ u8 buf[4];
+ u32 freq = params->frequency;
+ u32 tfreq = (freq + 36125000) / 1000000 * 6 + 1;
+ u8 TA, T210, R210, ctrl1, cp210, p4321;
+ struct i2c_msg msg = {
+ .addr = dib->dibdev->parm->pll_addr,
+ .flags = 0,
+ .buf = buf,
+ .len = sizeof(buf)
+ };
+
+ if (freq > 858000000) {
+ err("frequency cannot be larger than 858 MHz.");
+ return -EINVAL;
+ }
+
+ // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
+ TA = 1;
+ T210 = 0;
+ R210 = 0x2;
+ ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
+
+// ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
+ if (freq < 470000000)
+ cp210 = 2; // VHF Low and High band ch E12 to E4 to E12
+ else if (freq < 526000000)
+ cp210 = 4; // UHF band Ch E21 to E27
+ else // if (freq < 862000000)
+ cp210 = 5; // UHF band ch E28 to E69
+
+//********************* BW select *******************************
+ if (freq < 153000000)
+ p4321 = 1; // BW selected for VHF low
+ else if (freq < 470000000)
+ p4321 = 2; // BW selected for VHF high E5 to E12
+ else // if (freq < 862000000)
+ p4321 = 4; // BW selection for UHF E21 to E69
+
+ buf[0] = (tfreq >> 8) & 0xff;
+ buf[1] = (tfreq >> 0) & 0xff;
+ buf[2] = 0xff & ctrl1;
+ buf[3] = (cp210 << 5) | (p4321);
+
+ if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+
+ msleep(1);
+ return 0;
+}
+
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
new file mode 100644
index 000000000..a6585e87e
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
@@ -0,0 +1,95 @@
+/*
+ * dvb-dibusb-firmware.c is part of the driver for mobile USB Budget DVB-T devices
+ * based on reference design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * see dvb-dibusb-core.c for more copyright details.
+ *
+ * This file contains functions for downloading the firmware to the device.
+ */
+#include "dvb-dibusb.h"
+
+#include <linux/firmware.h>
+#include <linux/usb.h>
+
+/*
+ * load a firmware packet to the device
+ */
+static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
+ 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+}
+
+int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_device *dibdev)
+{
+ const struct firmware *fw = NULL;
+ const char **fws;
+ u16 addr;
+ u8 *b,*p;
+ int ret = 0,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",
+ fws[i],ret);
+ }
+
+ if (fw == NULL) {
+ err("did not find a valid firmware file. "
+ "Please see linux/Documentation/dvb/ for more details on firmware-problems.");
+ return -EINVAL;
+ }
+ p = kmalloc(fw->size,GFP_KERNEL);
+ if (p != NULL) {
+ u8 reset;
+ /*
+ * you cannot use the fw->data as buffer for
+ * usb_control_msg, a new buffer has to be
+ * created
+ */
+ memcpy(p,fw->data,fw->size);
+
+ /* stop the CPU */
+ reset = 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];
+ addr = *((u16 *) &b[1]);
+
+ ret = dibusb_writemem(udev,addr,&b[4],b[0]);
+
+ if (ret != b[0]) {
+ err("error while transferring firmware "
+ "(transferred size: %d, block size: %d)",
+ ret,b[0]);
+ ret = -EINVAL;
+ break;
+ }
+ i += 5 + b[0];
+ }
+ /* length in ret */
+ if (ret > 0)
+ ret = 0;
+ /* restart the CPU */
+ reset = 0;
+ if (ret || dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1) != 1) {
+ err("could not restart the USB controller CPU.");
+ ret = -EINVAL;
+ }
+
+ kfree(p);
+ } else {
+ ret = -ENOMEM;
+ }
+ release_firmware(fw);
+
+ return ret;
+}
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
new file mode 100644
index 000000000..fc670c499
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
@@ -0,0 +1,185 @@
+/*
+ * dvb-dibusb-remote.c is part of the driver for mobile USB Budget DVB-T devices
+ * based on reference design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * see dvb-dibusb-core.c for more copyright details.
+ *
+ * This file contains functions for handling the event device on the software
+ * side and the remote control on the hardware side.
+ */
+#include "dvb-dibusb.h"
+
+/* 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. */
+ /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
+ { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */
+ { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */
+ { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */
+ { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */
+ { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */
+ { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */
+ /* 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 },
+};
+
+/*
+ * 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_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;
+ }
+ return 0;
+}
+
+/* Remote-control poll function - called every dib->rc_query_interval ms to see
+ whether the remote control has received anything. */
+static void dibusb_remote_query(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));
+}
+
+int dibusb_remote_init(struct usb_dibusb *dib)
+{
+ int i;
+
+ /* 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_remote_query, dib);
+
+ /* Start the remote-control polling. */
+ if (rc_query_interval < 40)
+ rc_query_interval = 100; /* default */
+
+ info("schedule remote query interval to %d msecs.",rc_query_interval);
+ schedule_delayed_work(&dib->rc_query_work,msecs_to_jiffies(rc_query_interval));
+ return 0;
+}
+
+int dibusb_remote_exit(struct usb_dibusb *dib)
+{
+ cancel_delayed_work(&dib->rc_query_work);
+ flush_scheduled_work();
+ input_unregister_device(&dib->rc_input_dev);
+ return 0;
+}
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
new file mode 100644
index 000000000..7176859fe
--- /dev/null
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
@@ -0,0 +1,216 @@
+/*
+ * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
+ * based on reference design made by DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * see dvb-dibusb-core.c for more copyright details.
+ *
+ * This file contains functions for initializing and handling the
+ * usb specific stuff.
+ */
+#include "dvb-dibusb.h"
+
+#include <linux/version.h>
+#include <linux/pci.h>
+
+int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
+ u16 rlen)
+{
+ int actlen,ret = -ENOMEM;
+
+ if (wbuf == NULL || wlen == 0)
+ return -EINVAL;
+
+ if ((ret = down_interruptible(&dib->usb_sem)))
+ return ret;
+
+ 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)\n", wbuf[0],wbuf[2],wbuf[3]);
+
+ debug_dump(wbuf,wlen);
+
+ 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, and no error before */
+ if (!ret && rbuf && rlen) {
+ 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);
+ else {
+ deb_alot("rlen: %d\n",rlen);
+ debug_dump(rbuf,actlen);
+ }
+ }
+
+ up(&dib->usb_sem);
+ return ret;
+}
+
+/*
+ * Cypress controls
+ */
+
+#if 0
+/*
+ * #if 0'ing the following functions as they are not in use _now_,
+ * but probably will be sometime.
+ */
+
+/*
+ * do not use this, just a workaround for a bug,
+ * which will hopefully never occur :).
+ */
+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 power control
+ */
+int dibusb_hw_sleep(struct usb_dibusb *dib)
+{
+ u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
+}
+
+#endif
+static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
+{
+ return dibusb_readwrite_usb(dib,buf,len,NULL,0);
+}
+
+/*
+ * ioctl for the firmware
+ */
+static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
+{
+ u8 b[34];
+ int size = plen > 32 ? 32 : plen;
+ b[0] = DIBUSB_REQ_SET_IOCTL;
+ b[1] = cmd;
+
+ if (size > 0)
+ memcpy(&b[2],param,size);
+
+ return dibusb_write_usb(dib,b,34); //2+size);
+}
+
+int dibusb_hw_wakeup(struct usb_dibusb *dib)
+{
+ u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
+}
+
+int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
+{
+ u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
+ return dibusb_readwrite_usb(dib,b,2,NULL,0);
+}
+
+int dibusb_streaming(struct usb_dibusb *dib,int onoff)
+{
+ if (onoff)
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
+ else
+ return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
+}
+
+int dibusb_usb_init(struct usb_dibusb *dib)
+{
+ int ret,i,bufsize;
+
+ /*
+ * when reloading the driver w/o replugging the device
+ * a timeout occures, this helps
+ */
+ 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 *));
+
+ 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) {
+ deb_info("not enough memory.\n");
+ return -ENOMEM;
+ }
+ deb_info("allocation complete\n");
+ 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_ATOMIC))) {
+ return -ENOMEM;
+ }
+ deb_info("submitting URB no. %d\n",i);
+
+ 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->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_ATOMIC))) {
+ err("could not submit buffer urb no. %d\n",i);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int dibusb_usb_exit(struct usb_dibusb *dib)
+{
+ int i;
+ 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);
+
+ /* 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);
+ /* free the URBs */
+ usb_free_urb(dib->urb_list[i]);
+ }
+ }
+ /* 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;
+}
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb.c
deleted file mode 100644
index c94684b5b..000000000
--- a/linux/drivers/media/dvb/dibusb/dvb-dibusb.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*
- * Driver for mobile USB Budget DVB-T devices based on reference
- * design made by DiBcom (http://www.dibcom.fr/)
- *
- * dvb-dibusb.c
- *
- * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DiBcom, which has
- * 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.
- *
- * Acknowledgements
- *
- * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- * sources, on which this driver (and the dib3000mb/mc/p frontends) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/firmware.h>
-#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 */
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk(level,args...) \
- do { if ((debug & level)) { printk(args); } } while (0)
-
-#define debug_dump(b,l) if (debug) {\
- int i; deb_xfer("%s: %d > ",__FUNCTION__,l); \
- for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
- deb_xfer("\n");\
-}
-
-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,32=rc (|-able)).");
-#else
-#define dprintk(args...)
-#define debug_dump(b,l)
-#endif
-
-#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)
-
-static int pid_parse;
-module_param(pid_parse, int, 0x644);
-MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0");
-
-/* Version information */
-#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"
-
-static int dibusb_readwrite_usb(struct usb_dibusb *dib,
- u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
- int actlen,ret = -ENOMEM;
-
- if (wbuf == NULL || wlen == 0)
- return -EINVAL;
-
- if ((ret = down_interruptible(&dib->usb_sem)))
- return ret;
-
- 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)\n", wbuf[0],wbuf[2],wbuf[3]);
-
- debug_dump(wbuf,wlen);
-
- 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, and no error before */
- if (!ret && rbuf && rlen) {
- 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);
- else {
- deb_alot("rlen: %d\n",rlen);
- debug_dump(rbuf,actlen);
- }
- }
-
- up(&dib->usb_sem);
- return ret;
-}
-
-static int dibusb_i2c_msg(struct usb_dibusb *dib, 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);
-
- deb_alot("wo: %d, wlen: %d, len: %d\n",wo,wlen,len);
-
- sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
- sndbuf[1] = (addr & 0xfe) | (wo ? 0 : 1);
-
- memcpy(&sndbuf[2],wbuf,wlen);
-
- if (!wo) {
- sndbuf[wlen+2] = (rlen >> 8) & 0xff;
- sndbuf[wlen+3] = rlen & 0xff;
- }
-
- return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
-}
-
-/*
- * DVB stuff
- */
-static void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
-{
- struct usb_dibusb *dib = urb->context;
-
- deb_ts("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status);
-
- if (dib->feedcount > 0 && urb->status == 0) {
- deb_ts("URB return len: %d\n",urb->actual_length);
- if (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 == 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 "
- "actual_length or !dvb_is_ready (%d).\n",dib->dvb_is_ready);
- } else
- deb_ts("URB dropped because of feedcount or status.\n");
-
- usb_submit_urb(urb,GFP_KERNEL);
-}
-
-static int dibusb_ctrl_feed(struct usb_dibusb *dib, int pid, int onoff)
-{
- 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;
- }
- }
-
- dib->feedcount += onoff ? 1 : -1;
-
- if (dib->pid_parse) {
- 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;
- }
- } 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("controlling pid parser\n");
- if (dib->xfer_ops.pid_parse != NULL) {
- if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) {
- err("could not handle pid_parser");
- }
- }
-
- 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;
- }
-
-
- }
- return 0;
-}
-
-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);
-}
-
-static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- 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. */
- /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
- { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */
- { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */
- { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */
- { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */
- { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */
- { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */
- /* 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 },
-};
-
-/*
- * 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_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;
- }
- 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 functions as they are not in use _now_,
- * but probably will be sometime.
- */
-
-/*
- * 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 power control
- */
-static int dibusb_hw_sleep(struct usb_dibusb *dib)
-{
- u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
- return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
-}
-
-#endif
-static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
-{
- return dibusb_readwrite_usb(dib,buf,len,NULL,0);
-}
-
-/*
- * ioctl for the firmware
- */
-static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
-{
- u8 b[34];
- int size = plen > 32 ? 32 : plen;
- b[0] = DIBUSB_REQ_SET_IOCTL;
- b[1] = cmd;
- memcpy(&b[2],param,size);
-
- return dibusb_write_usb(dib,b,2+size);
-}
-
-static int dibusb_hw_wakeup(struct usb_dibusb *dib)
-{
- u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
- return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
-}
-
-/*
- * I2C
- */
-static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
-{
- struct usb_dibusb *dib = i2c_get_adapdata(adap);
- int i;
-
- if (down_interruptible(&dib->i2c_sem) < 0)
- return -EAGAIN;
-
- for (i = 0; i < num; i++) {
- /* write/read request */
- if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
- if (dibusb_i2c_msg(dib, 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(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
- break;
- }
-
- up(&dib->i2c_sem);
- return i;
-}
-
-static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct
- dvb_frontend_parameters* params);
-
-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 = (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;
-}
-
-static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct
- dvb_frontend_parameters *params);
-
-static struct dib3000_config panasonic_cofdm_env57h1xd5 = {
- .demod_address = 0x18,
- .pll_addr = 192,
- .pll_set = panasonic_cofdm_env57h1xd5_pll_set,
-};
-
-static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend *fe, struct
- dvb_frontend_parameters *params)
-{
- struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
- u8 buf[4];
- u32 freq = params->frequency;
- u32 tfreq = (freq + 36125000) / 1000000 * 6 + 1;
- u8 TA, T210, R210, ctrl1, cp210, p4321;
- struct i2c_msg msg = {
- .addr = panasonic_cofdm_env57h1xd5.pll_addr,
- .flags = 0,
- .buf = buf,
- .len = sizeof(buf)
- };
-
- if (freq > 858000000) {
- err("frequency cannot be larger than 858 MHz.");
- return -EINVAL;
- }
-
- // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
- TA = 1;
- T210 = 0;
- R210 = 0x2;
- ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
-
-// ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
- if (freq < 470000000)
- cp210 = 2; // VHF Low and High band ch E12 to E4 to E12
- else if (freq < 526000000)
- cp210 = 4; // UHF band Ch E21 to E27
- else // if (freq < 862000000)
- cp210 = 5; // UHF band ch E28 to E69
-
-//********************* BW select *******************************
- if (freq < 153000000)
- p4321 = 1; // BW selected for VHF low
- else if (freq < 470000000)
- p4321 = 2; // BW selected for VHF high E5 to E12
- else // if (freq < 862000000)
- p4321 = 4; // BW selection for UHF E21 to E69
-
- buf[0] = (tfreq >> 8) & 0xff;
- buf[1] = (tfreq >> 0) & 0xff;
- buf[2] = 0xff & ctrl1;
- buf[3] = (cp210 << 5) | (p4321);
-
- if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
- return -EIO;
-
- msleep(1);
- return 0;
-}
-
-static struct i2c_algorithm dibusb_algo = {
- .name = "DiBcom USB i2c algorithm",
- .id = I2C_ALGO_BIT,
- .master_xfer = dibusb_i2c_xfer,
- .functionality = dibusb_i2c_func,
-};
-
-static void frontend_init(struct usb_dibusb* dib)
-{
- switch (dib->dibdev->parm->type) {
- case DIBUSB1_1:
- case DIBUSB1_1_AN2235:
- dib->fe = dib3000mb_attach(&thomson_cable_eu_config,&dib->i2c_adap,&dib->xfer_ops);
- break;
- case DIBUSB2_0:
- dib->fe = dib3000mc_attach(&panasonic_cofdm_env57h1xd5,&dib->i2c_adap, &dib->xfer_ops);
- break;
- }
-
- 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;
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,4)
- if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC)) < 0) {
-#else
- if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC ,
- THIS_MODULE)) < 0) {
-#endif
- 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
- dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
-#else
- dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
-#endif
- dib->i2c_adap.algo = &dibusb_algo;
- dib->i2c_adap.algo_data = NULL;
- dib->i2c_adap.id = I2C_ALGO_BIT;
-
- i2c_set_adapdata(&dib->i2c_adap, dib);
-
- if ((i2c_add_adapter(&dib->i2c_adap) < 0)) {
- err("could not add i2c adapter");
- goto err_i2c;
- }
-
- dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-
- dib->demux.priv = (void *)dib;
- /* 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;
- if ((ret = dvb_dmx_init(&dib->demux)) < 0) {
- err("dvb_dmx_init failed: error %d",ret);
- goto err_dmx;
- }
-
- dib->dmxdev.filternum = dib->demux.filternum;
- dib->dmxdev.demux = &dib->demux.dmx;
- dib->dmxdev.capabilities = 0;
- if ((ret = dvb_dmxdev_init(&dib->dmxdev, dib->adapter)) < 0) {
- err("dvb_dmxdev_init failed: error %d",ret);
- goto err_dmx_dev;
- }
-
- 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);
-err_dmx:
- i2c_del_adapter(&dib->i2c_adap);
-err_i2c:
- dvb_unregister_adapter(dib->adapter);
-err:
- return ret;
-success:
- dib->dvb_is_ready = 1;
- return 0;
-}
-
-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);
-
- return 0;
-}
-
-static int dibusb_exit(struct usb_dibusb *dib)
-{
- int i;
- 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);
-
- /* 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);
- /* free the URBs */
- usb_free_urb(dib->urb_list[i]);
- }
- }
- /* 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,bufsize;
- sema_init(&dib->usb_sem, 1);
- sema_init(&dib->i2c_sem, 1);
-
- /*
- * when reloading the driver w/o replugging the device
- * a timeout occures, this helps
- */
- 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 *));
-
- 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) {
- deb_info("not enough memory.\n");
- dibusb_exit(dib);
- return -ENOMEM;
- }
- deb_info("allocation complete\n");
- 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->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->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;
- }
- }
-
- 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);
-
- dibusb_hw_wakeup(dib);
-
- if ((ret = dibusb_dvb_init(dib))) {
- dibusb_exit(dib);
- return ret;
- }
- return 0;
-}
-
-/*
- * load a firmware packet to the device
- */
-static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
-{
- return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
-}
-
-static int dibusb_loadfirmware(struct usb_device *udev,
- struct dibusb_device *dibdev)
-{
- const struct firmware *fw = NULL;
- const char **fws;
- u16 addr;
- u8 *b,*p;
- int ret = 0,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",
- fws[i],ret);
- }
-
- if (fw == NULL) {
- err("did not find a valid firmware file. "
- "Please see linux/Documentation/dvb/ for more details on firmware-problems.");
- return -EINVAL;
- }
- p = kmalloc(fw->size,GFP_KERNEL);
- if (p != NULL) {
- u8 reset;
- /*
- * you cannot use the fw->data as buffer for
- * usb_control_msg, a new buffer has to be
- * created
- */
- memcpy(p,fw->data,fw->size);
-
- /* stop the CPU */
- reset = 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];
- addr = *((u16 *) &b[1]);
-
- ret = dibusb_writemem(udev,addr,&b[4],b[0]);
-
- if (ret != b[0]) {
- err("error while transferring firmware "
- "(transferred size: %d, block size: %d)",
- ret,b[0]);
- ret = -EINVAL;
- break;
- }
- i += 5 + b[0];
- }
- /* length in ret */
- if (ret > 0)
- ret = 0;
- /* restart the CPU */
- reset = 0;
- if (ret || dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1) != 1) {
- err("could not restart the USB controller CPU.");
- ret = -EINVAL;
- }
-
- kfree(p);
- } else {
- ret = -ENOMEM;
- }
- release_firmware(fw);
-
- return ret;
-}
-
-/*
- * USB
- */
-static int dibusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_dibusb *dib = NULL;
- struct dibusb_device *dibdev = NULL;
-
- int ret = -ENOMEM,i,cold=0;
-
- for (i = 0; i < DIBUSB_SUPPORTED_DEVICES; i++)
- if (dibusb_devices[i].cold_product_id == udev->descriptor.idProduct ||
- dibusb_devices[i].warm_product_id == udev->descriptor.idProduct) {
- dibdev = &dibusb_devices[i];
-
- cold = dibdev->cold_product_id == udev->descriptor.idProduct;
-
- if (cold)
- info("found a '%s' in cold state, will try to load a firmware",dibdev->name);
- else
- info("found a '%s' in warm state.",dibdev->name);
- }
-
- if (dibdev == NULL) {
- err("something went very wrong, "
- "unknown product ID: %.4x",udev->descriptor.idProduct);
- return -ENODEV;
- }
-
- if (cold)
- ret = dibusb_loadfirmware(udev,dibdev);
- else {
- dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL);
- if (dib == NULL) {
- err("no memory");
- return ret;
- }
- memset(dib,0,sizeof(struct usb_dibusb));
-
- dib->pid_parse = 1;
- 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 parsing.");
- break;
- case USB_SPEED_HIGH:
- if (!pid_parse) {
- dib->pid_parse = 0;
- info("running at HIGH speed, will deliver the complete TS.");
- } else
- info("running at HIGH speed, will use pid_parsing anyway.");
- break;
- case USB_SPEED_UNKNOWN: /* fall through */
- default:
- err("cannot handle USB speed because it is unkown.");
- break;
- }
-
- dib->udev = udev;
- dib->dibdev = dibdev;
-
- usb_set_intfdata(intf, dib);
-
- ret = dibusb_init(dib);
-
- }
-
- if (ret == 0)
- info("%s successfully initialized and connected.",dibdev->name);
- else
- info("%s error while loading driver (%d)",dibdev->name,ret);
- return ret;
-}
-
-static void dibusb_disconnect(struct usb_interface *intf)
-{
- struct usb_dibusb *dib = usb_get_intfdata(intf);
- const char *name = DRIVER_DESC;
-
- usb_set_intfdata(intf,NULL);
- if (dib != NULL) {
- name = dib->dibdev->name;
- dibusb_dvb_exit(dib);
- dibusb_exit(dib);
- kfree(dib);
- }
- info("%s successfully deinitialized and disconnected.",name);
-
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver dibusb_driver = {
- .owner = THIS_MODULE,
- .name = "dvb_dibusb",
- .probe = dibusb_probe,
- .disconnect = dibusb_disconnect,
- .id_table = dibusb_table,
-};
-
-/* module stuff */
-static int __init usb_dibusb_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 usb_dibusb_exit(void)
-{
- /* deregister this driver from the USB subsystem */
- usb_deregister(&dibusb_driver);
-}
-
-module_init (usb_dibusb_init);
-module_exit (usb_dibusb_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb.h b/linux/drivers/media/dvb/dibusb/dvb-dibusb.h
index b6f106019..bac7d0921 100644
--- a/linux/drivers/media/dvb/dibusb/dvb-dibusb.h
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb.h
@@ -7,35 +7,71 @@
* 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 .
+ * for more information see dvb-dibusb-core.c .
*/
-
#ifndef __DVB_DIBUSB_H__
#define __DVB_DIBUSB_H__
+#include <linux/input.h>
+#include <linux/config.h>
+#include <linux/usb.h>
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+
#include "dib3000.h"
+/* debug */
+#ifdef CONFIG_DVB_DIBCOM_DEBUG
+#define dprintk(level,args...) \
+ do { if ((debug & level)) { printk(args); } } while (0)
+
+#define debug_dump(b,l) if (debug) {\
+ int i; deb_xfer("%s: %d > ",__FUNCTION__,l); \
+ for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
+ deb_xfer("\n");\
+}
+
+/* module parameters - declared in -core.c */
+extern int debug;
+
+#else
+#define dprintk(args...)
+#define debug_dump(b,l)
+#endif
+
+/* module parameters - declared in -core.c */
+extern int pid_parse;
+extern int rc_query_interval;
+
+#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)
+
+/* generic log methods - taken from usb.h */
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n" , __FILE__ , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n" , __FILE__ , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n" , __FILE__ , ## arg)
+
+/* Version information */
+#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"
+
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"
-};
-
-static const char * dibusb_fw_filenames2_0[] = {
- "dvb-dibusb-6.0.0.5.fw"
-};
-
+/* struct for holding properties of the different dibusb device models */
struct dibusb_device_parameter {
dibusb_type type;
- u8 demod_addr;
const char **fw_filenames;
const char *usb_controller;
u16 usb_cpu_csreg;
@@ -48,56 +84,17 @@ struct dibusb_device_parameter {
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 = 0x18,
- .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,
- }
+ int (*pll_set) (struct dvb_frontend *,struct dvb_frontend_parameters *);
+ unsigned char pll_addr;
+ unsigned char demod_i2c_addrs[4];
};
+/*
+ * for each warm/cold product id a name is stored, this is just beautification,
+ * it could easily done by an PID-array, but then the real names of the devices
+ * would get lost.
+ */
struct dibusb_device {
const char *name;
u16 cold_product_id;
@@ -105,187 +102,6 @@ struct dibusb_device {
struct dibusb_device_parameter *parm;
};
-/* Vendor IDs */
-#define USB_VID_ANCHOR 0x0547
-#define USB_VID_AVERMEDIA 0x14aa
-#define USB_VID_COMPRO 0x185b
-#define USB_VID_COMPRO_UNK 0x145f
-#define USB_VID_CYPRESS 0x04b4
-#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_COMPRO_DVBU2000_UNK_COLD 0x010c
-#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
-#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_DIBCOM_ANCHOR_2135_COLD 0x2131
-#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_ULTIMA_TVBOX_USB2_COLD 0x8109
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
-#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 16
-
-/* USB Driver stuff */
-static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
- { .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 = "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs",
- .cold_product_id = USB_PID_DIBCOM_ANCHOR_2135_COLD,
- .warm_product_id = 0, /* undefined, let's see what comes out */
- .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 = "Artec T1 USB2.0 TVBOX (please report the warm ID)",
- .cold_product_id = USB_PID_ULTIMA_TVBOX_USB2_COLD,
- .warm_product_id = 0, /* don't know, it is most likely that the device will get another USB ID in warm state */
- .parm = &dibusb_dev_parm[1],
- },
- { .name = "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)",
- .cold_product_id = USB_PID_ULTIMA_TVBOX_USB2_FX_COLD,
- .warm_product_id = USB_PID_ULTIMA_TVBOX_USB2_FX_WARM, /* undefined, it could be that the device will get another USB ID in warm state */
- .parm = &dibusb_dev_parm[1],
- },
- { .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 = "Compro Videomate DVB-U2000 - DVB-T USB1.1 (really ?? please report the name!)",
- .cold_product_id = USB_PID_COMPRO_DVBU2000_UNK_COLD,
- .warm_product_id = USB_PID_COMPRO_DVBU2000_UNK_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_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) },
- { USB_DEVICE(USB_PID_COMPRO_DVBU2000_UNK_COLD, USB_VID_COMPRO_UNK) },
- { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-
-/*
- * activate the following define when you have one of the devices and want to
- * build it from build-2.6 in dvb-kernel
- */
-// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
- { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
- { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
- { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
- { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) },
-#endif
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dibusb_table);
-
-#define DIBUSB_I2C_TIMEOUT HZ*5
-
struct usb_dibusb {
/* usb */
struct usb_device * udev;
@@ -302,7 +118,6 @@ struct usb_dibusb {
/* I2C */
struct i2c_adapter i2c_adap;
- struct i2c_client i2c_client;
/* locking */
struct semaphore usb_sem;
@@ -322,8 +137,44 @@ struct usb_dibusb {
int rc_input_event;
};
+/* commonly used functions in the separated files */
+
+/* dvb-dibusb-firmware.c */
+int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_device *dibdev);
-/* types of first byte of each buffer */
+/* dvb-dibusb-remote.c */
+int dibusb_remote_exit(struct usb_dibusb *dib);
+int dibusb_remote_init(struct usb_dibusb *dib);
+
+/* dvb-dibusb-fe-i2c.c */
+int dibusb_fe_init(struct usb_dibusb* dib);
+int dibusb_fe_exit(struct usb_dibusb *dib);
+int dibusb_i2c_init(struct usb_dibusb *dib);
+int dibusb_i2c_exit(struct usb_dibusb *dib);
+
+/* dvb-dibusb-dvb.c */
+void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs);
+int dibusb_dvb_init(struct usb_dibusb *dib);
+int dibusb_dvb_exit(struct usb_dibusb *dib);
+
+/* dvb-dibusb-usb.c */
+int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
+ u16 rlen);
+
+int dibusb_hw_wakeup(struct usb_dibusb *dib);
+int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode);
+int dibusb_streaming(struct usb_dibusb *dib,int onoff);
+
+int dibusb_usb_init(struct usb_dibusb *dib);
+int dibusb_usb_exit(struct usb_dibusb *dib);
+
+/* i2c and transfer stuff */
+#define DIBUSB_I2C_TIMEOUT HZ*5
+
+/*
+ * types of first byte of each buffer send to USB, applying for
+ * USB1.1 and USB2.0
+ */
#define DIBUSB_REQ_START_READ 0x00
#define DIBUSB_REQ_START_DEMOD 0x01
@@ -355,4 +206,8 @@ struct usb_dibusb {
#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
+
#endif