diff options
author | Patrick Boettcher <devnull@localhost> | 2005-04-22 18:06:32 +0000 |
---|---|---|
committer | Patrick Boettcher <devnull@localhost> | 2005-04-22 18:06:32 +0000 |
commit | e94f4020dfb24bb99bab9390d1d4ca10f21b7025 (patch) | |
tree | 524ddba52e7176004aa3a2e912d9463e856d41ce | |
parent | 62757cd413fbbab9388d649d52ca3c1fad642838 (diff) | |
download | mediapointer-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/Kconfig | 6 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/Makefile | 3 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/digitv.c | 238 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb-init.c | 4 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/dvb-usb.h | 4 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dvb-usb/umt-010.c | 2 |
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); |