summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Boettcher <devnull@localhost>2005-04-22 18:06:32 +0000
committerPatrick Boettcher <devnull@localhost>2005-04-22 18:06:32 +0000
commite94f4020dfb24bb99bab9390d1d4ca10f21b7025 (patch)
tree524ddba52e7176004aa3a2e912d9463e856d41ce
parent62757cd413fbbab9388d649d52ca3c1fad642838 (diff)
downloadmediapointer-dvb-s2-e94f4020dfb24bb99bab9390d1d4ca10f21b7025.tar.gz
mediapointer-dvb-s2-e94f4020dfb24bb99bab9390d1d4ca10f21b7025.tar.bz2
corrected a typo in umt-010.c
Added a new driver for the µDigiTV USB2.0 DVB-T receiver made by Nebula Electronics. It isn't working yet, but with the help of Allan Third it will be very soon. Thanks.
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Kconfig6
-rw-r--r--linux/drivers/media/dvb/dvb-usb/Makefile3
-rw-r--r--linux/drivers/media/dvb/dvb-usb/digitv.c238
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h1
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c4
-rw-r--r--linux/drivers/media/dvb/dvb-usb/dvb-usb.h4
-rw-r--r--linux/drivers/media/dvb/dvb-usb/umt-010.c2
7 files changed, 255 insertions, 3 deletions
diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig
index 113f03d3b..18e2a0b61 100644
--- a/linux/drivers/media/dvb/dvb-usb/Kconfig
+++ b/linux/drivers/media/dvb/dvb-usb/Kconfig
@@ -69,6 +69,12 @@ config DVB_USB_UMT_010
help
Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
+config DVB_USB_DIGITV
+ tristate "Nebula Electronics µDigiTV DVB-T USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the Nebula Electronics µDigitV USB2.0 DVB-T receiver.
+
config DVB_USB_VP7045
tristate "Twinhan VP-7045 (Alpha) and VP-7046 (MagicBoxII) DVB-T USB2.0 support"
depends on DVB_USB
diff --git a/linux/drivers/media/dvb/dvb-usb/Makefile b/linux/drivers/media/dvb/dvb-usb/Makefile
index 4c8ccb11e..d65b50f9a 100644
--- a/linux/drivers/media/dvb/dvb-usb/Makefile
+++ b/linux/drivers/media/dvb/dvb-usb/Makefile
@@ -24,4 +24,7 @@ obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2
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/linux/drivers/media/dvb/dvb-usb/digitv.c b/linux/drivers/media/dvb/dvb-usb/digitv.c
new file mode 100644
index 000000000..1375446d5
--- /dev/null
+++ b/linux/drivers/media/dvb/dvb-usb/digitv.c
@@ -0,0 +1,238 @@
+/* DVB USB compliant linux driver for Nebula Electronics µDigiTV 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 "dvb-usb.h"
+
+#include "mt352.h"
+
+/* protocol: this is what I read of the USB log:
+ *
+ * Always 7 bytes control message(s),
+ *
+ * First byte at describes the command. Reads are 2 consecutive transfer (as always).
+ *
+ * I2C address is stored somewhere inside the device.
+ *
+ * 0x02 i2c reading (2 messages)
+ * 1st msg <reg> <len>
+ * 2nd msg <reg> <len> <value>
+ *
+ * 0x05 i2c writing
+ * <reg> <len> <value>
+ * len = 1 for the mt352
+ *
+ * Others:
+ *
+ * 0x03 remote control query (read 4 bytes)
+ * 1st msg: 0x00 0x04
+ * 2nd msg: 0x00 0x04 4 bytes key (probably NEC protocol)
+ *
+ * 0x08 stream control ?
+ * 0x00 0x04 0x01
+ *
+ * 0x07 unkown (maybe pid filter?)
+ */
+
+
+/* I2C */
+static int digitv_i2c_msg(struct dvb_usb_device *d,u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+ u8 sndbuf[7],rcvbuf[7]; /* <cmd> <reg> <len> <val[4]> */
+ int wo = (rbuf == NULL || rlen == 0); /* write-only */
+
+ memset(sndbuf,0,7); memset(rcvbuf,0,7);
+
+ sndbuf[0] = wo ? 0x05 : 0x03;
+ sndbuf[1] = wbuf[0]; /* register */
+ sndbuf[2] = wo ? wlen-1 : rlen;
+
+ if (wo)
+ memcpy(&sndbuf[3],&wbuf[1],wlen-1);
+
+ dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7);
+
+ if (!wo)
+ memcpy(rbuf,&rcvbuf[3],rlen);
+
+ return 0;
+}
+
+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_i2c_msg(d, msg[i].buf, msg[i].len,
+ msg[i+1].buf,msg[i+1].len) < 0)
+ break;
+ i++;
+ } else
+ if (digitv_i2c_msg(d, msg[i].buf,msg[i].len,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 probe_count;
+static int digitv_identify_state (struct usb_device *udev, struct
+ dvb_usb_properties *props, struct dvb_usb_device_description **desc,
+ int *cold)
+{
+
+ /* here we have to determine if the device is in cold state (pre firmware
+ * load) or in warm state therefore compare the 'lsusb -v' of each state.
+ * Most likely the number of endpoints or interfaces can be used to figure
+ * the real state out.
+ * For now we assume each odd call of this function (when the device is
+ * plugged in or virtually plugged in after the firmware load) is warm
+ * state and each even call is cold probe_count is set to 0 at module load.
+ */
+
+ *cold = (probe_count % 2) == 0;
+ probe_count++;
+ return 0;
+}
+
+static int digitv_frontend_attach(struct dvb_usb_device *d)
+{
+ struct mt352_config digitv_config;
+
+ memset(&digitv_config,0,sizeof(struct mt352_config));
+ digitv_config.demod_init = NULL; /* TODO maybe */
+ digitv_config.demod_address = 0x0; /* ignore by the digitv anyway */
+ digitv_config.pll_set = NULL; /* TODO */
+
+ d->fe = mt352_attach(&digitv_config, &d->i2c_adap);
+ 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, // digitv_streaming_ctrl,
+ .pid_filter = NULL,
+ .pid_filter_ctrl = NULL,
+ .power_ctrl = NULL, // digitv_power_ctrl,
+ .frontend_attach = digitv_frontend_attach,
+ .tuner_attach = NULL, // digitv_tuner_attach,
+ .read_mac_address = NULL,
+
+ .rc_interval = 0, // 150,
+ .init_rc = NULL, // digitv_rc_init,
+ .query_rc = NULL, // 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 µDigiTV DVB-T USB2.0)",
+ { &digitv_table[0], NULL },
+ { NULL },
+ },
+ }
+};
+
+static struct usb_driver digitv_driver = {
+ .owner = THIS_MODULE,
+ .name = "Nebula Electronics µDigiTV 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 µDigiTV DVB-T USB2.0");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 26de61e0a..fe3d6f464 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -69,5 +69,6 @@
#define USB_PID_DTT200U_WARM 0x0301
#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
+#define USB_PID_NEBULA_DIGITV 0x0201
#endif
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index beced1bd5..34dbcb836 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -114,8 +114,8 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
}
}
-/* if (desc != NULL && props->identify_desc_quirk != NULL)
- desc = props->identify_desc_quirk(udev,props,desc);*/
+ if (desc != NULL && props->identify_state != NULL)
+ props->identify_state(udev,props,&desc,cold);
return desc;
}
diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h
index e8d8136ef..239ff40c3 100644
--- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -88,6 +88,10 @@ struct dvb_usb_properties {
int (*frontend_attach) (struct dvb_usb_device *); /* each device has to know about its frontends */
int (*tuner_attach) (struct dvb_usb_device *); /* each device has to know about its tuners */
+ int (*identify_state) (struct usb_device *, struct dvb_usb_properties *, struct dvb_usb_device_description **, int *);
+ /* if the state (cold or warm) is not distinguishable by the USB IDs,
+ * the dvb-usb-device has to provie this callback to determine it*/
+
#define REMOTE_NO_KEY_PRESSED 0x00
#define REMOTE_KEY_PRESSED 0x01
#define REMOTE_KEY_REPEAT 0x02
diff --git a/linux/drivers/media/dvb/dvb-usb/umt-010.c b/linux/drivers/media/dvb/dvb-usb/umt-010.c
index f25db20b5..ab23759b2 100644
--- a/linux/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/linux/drivers/media/dvb/dvb-usb/umt-010.c
@@ -57,7 +57,7 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
memset(&umt_config,0,sizeof(struct mt352_config));
umt_config.demod_init = umt_mt352_demod_init;
umt_config.demod_address = 0xf;
- umt_config.pll_set = dibusb_pll_set,
+ umt_config.pll_set = dibusb_pll_set;
d->fe = mt352_attach(&umt_config, &d->i2c_adap);