summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorPatrick Boettcher <devnull@localhost>2004-09-20 15:25:11 +0000
committerPatrick Boettcher <devnull@localhost>2004-09-20 15:25:11 +0000
commit0c68f2871259818657693bdf2d82ac92bd70600e (patch)
tree3b9d1f9a2dcab7384f49a99f675e92e001a63c2c /linux
parentf0ef0b54a60a050a2cfaf014524495710a299f89 (diff)
downloadmediapointer-dvb-s2-0c68f2871259818657693bdf2d82ac92bd70600e.tar.gz
mediapointer-dvb-s2-0c68f2871259818657693bdf2d82ac92bd70600e.tar.bz2
- added Compro Videomate USB DVB-T USB ids
- changed vendor and product id defines - several URB's are now submitted for TS-transfer - usb_kill_urb - i2c writes during ts feed is now paused
Diffstat (limited to 'linux')
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb.c151
-rw-r--r--linux/drivers/media/dvb/dibusb/dvb-dibusb.h145
2 files changed, 170 insertions, 126 deletions
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb.c b/linux/drivers/media/dvb/dibusb/dvb-dibusb.c
index 30db454bc..f1e6fd418 100644
--- a/linux/drivers/media/dvb/dibusb/dvb-dibusb.c
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb.c
@@ -57,7 +57,7 @@
static int debug;
module_param(debug, int, 0x644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore (|-able)).");
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts (|-able)).");
#else
#define dprintk_new(args...)
#define debug_dump(b,l)
@@ -66,31 +66,13 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore (|-able))
#define deb_info(args...) dprintk_new(0x01,args)
#define deb_xfer(args...) dprintk_new(0x02,args)
#define deb_alot(args...) dprintk_new(0x04,args)
+#define deb_ts(args...) dprintk_new(0x08,args)
/* Version information */
#define DRIVER_VERSION "0.0"
-#define DRIVER_DESC "DiBcom based USB Budget DVB-T device"
+#define DRIVER_DESC "Driver for DiBcom based USB Budget DVB-T device"
#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-/* USB Driver stuff */
-
-/* table of devices that work with this driver */
-static struct usb_device_id dibusb_table [] = {
- { USB_DEVICE(USB_TWINHAN_VENDOR_ID, USB_VP7041_PRODUCT_PREFW_ID) },
- { USB_DEVICE(USB_TWINHAN_VENDOR_ID, USB_VP7041_PRODUCT_ID) },
- { USB_DEVICE(USB_IMC_NETWORKS_VENDOR_ID, USB_VP7041_PRODUCT_PREFW_ID) },
- { USB_DEVICE(USB_IMC_NETWORKS_VENDOR_ID, USB_VP7041_PRODUCT_ID) },
- { USB_DEVICE(USB_KWORLD_VENDOR_ID, USB_VSTREAM_PRODUCT_PREFW_ID) },
- { USB_DEVICE(USB_KWORLD_VENDOR_ID, USB_VSTREAM_PRODUCT_ID) },
- { USB_DEVICE(USB_DIBCOM_VENDOR_ID, USB_DIBCOM_PRODUCT_PREFW_ID) },
- { USB_DEVICE(USB_DIBCOM_VENDOR_ID, USB_DIBCOM_PRODUCT_ID) },
- { USB_DEVICE(USB_ULTIMA_ELECTRONIC_ID, USB_ULTIMA_ELEC_PROD_PREFW_ID) },
- { USB_DEVICE(USB_ULTIMA_ELECTRONIC_ID, USB_ULTIMA_ELEC_PROD_ID) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dibusb_table);
-
static int dibusb_readwrite_usb(struct usb_dibusb *dib,
u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
{
@@ -205,6 +187,7 @@ static int dibusb_stop_xfer(struct usb_dibusb *dib)
static int dibusb_set_pid(struct dibusb_pid *dpid)
{
+ struct usb_dibusb *dib = dpid->dib;
u16 pid = dpid->pid | (dpid->active ? DIB3000MB_ACTIVATE_FILTERING : 0);
u8 b[4] = {
(dpid->reg >> 8) & 0xff,
@@ -212,26 +195,51 @@ static int dibusb_set_pid(struct dibusb_pid *dpid)
(pid >> 8) & 0xff,
(pid) & 0xff
};
+ int ret;
+
+ /* firmware bug, i2c write during mpeg transfer */
+ if (dib->feedcount) {
+ deb_info("stop streaming\n");
+ ret = dibusb_stop_xfer(dib);
+ }
+
+ if (dpid->active)
+ dib->feedcount++;
+ else
+ dib->feedcount--;
+
+ ret = dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
- return dibusb_i2c_msg(dpid->dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0);
+ if (ret == 0 && dib->feedcount) {
+ deb_info("start streaming\n");
+ ret = dibusb_start_xfer(dib);
+ }
+ return ret;
}
static void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
{
struct usb_dibusb *dib = urb->context;
- if (!dib->streaming)
- return;
-
- if (urb->status == 0) {
- deb_info("URB return len: %d\n",urb->actual_length);
- if (urb->actual_length % 188)
- deb_info("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
- dvb_dmx_swfilter_packets(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length/188);
- }
+ 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_xfer("TS Packets: %d, %d\n", urb->actual_length/188,urb->actual_length % 188);
- if (dib->streaming)
- usb_submit_urb(urb,GFP_KERNEL);
+ /* Francois recommends to drop not full-filled packets, even if they may
+ * contain valid TS packets
+ */
+ if (urb->actual_length == DIBUSB_TS_DEFAULT_SIZE && dib->dvb_is_ready)
+ 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);
}
@@ -240,9 +248,8 @@ static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
// struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
struct dibusb_pid *dpid;
- int ret = 0;
- deb_info("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
+ deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
if ((dpid = dibusb_get_free_pid(dib)) == NULL) {
err("no free pid in list.");
@@ -253,33 +260,15 @@ static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
dibusb_set_pid(dpid);
- if (0 == dib->feed_count++) {
- usb_fill_bulk_urb( dib->buf_urb, dib->udev, DATA_PIPE,
- dib->buffer, 8192, dibusb_urb_complete, dib);
- dib->buf_urb->transfer_flags = 0;
- dib->buf_urb->timeout = 0;
-
- if ((ret = usb_submit_urb(dib->buf_urb,GFP_KERNEL))) {
- dibusb_stop_xfer(dib);
- err("could not submit buffer urb.");
- return ret;
- }
-
- if ((ret = dibusb_start_xfer(dib)))
- return ret;
-
- dib->streaming = 1;
- }
return 0;
}
static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
{
- struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
struct dibusb_pid *dpid = (struct dibusb_pid *) dvbdmxfeed->priv;
- deb_info("stopfeed pid: 0x%04x, feedtype: %d",dvbdmxfeed->pid, dvbdmxfeed->type);
-
+ deb_ts("stopfeed pid: 0x%04x, feedtype: %d\n",dvbdmxfeed->pid, dvbdmxfeed->type);
+
if (dpid == NULL)
err("channel in dmxfeed->priv was NULL");
else {
@@ -288,11 +277,6 @@ static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
dibusb_set_pid(dpid);
}
- if (--dib->feed_count == 0) {
- dib->streaming = 0;
- usb_unlink_urb(dib->buf_urb);
- dibusb_stop_xfer(dib);
- }
return 0;
}
@@ -302,7 +286,7 @@ static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
/*
* do not use this, just a workaround for a bug,
- * which will never occur :).
+ * which will hopefully never occur :).
*/
static int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
{
@@ -312,7 +296,7 @@ static int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
/*
* TODO: a tasklet should run with a delay of 1/10 second
- * and fill an appropriate event device ?
+ * and feed an appropriate event device ?
*/
static int dibusb_read_remote_control(struct usb_dibusb *dib)
{
@@ -474,11 +458,13 @@ err_i2c:
err:
return ret;
success:
+ dib->dvb_is_ready = 1;
return 0;
}
static 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);
@@ -492,8 +478,16 @@ static int dibusb_dvb_exit(struct usb_dibusb *dib)
static int dibusb_exit(struct usb_dibusb *dib)
{
- usb_free_urb(dib->buf_urb);
- pci_free_consistent(NULL,8192,dib->buffer,dib->dma_handle);
+ int i;
+ for (i = 0; i < DIBUSB_TS_NUM_URBS; i++)
+ if (dib->buf_urb[i] != NULL) {
+ deb_info("killing URB no. %d.\n",i);
+ usb_kill_urb(dib->buf_urb[i]); // TODO kernel version ifdef for unlink_urb
+
+ deb_info("freeing URB no. %d.\n",i);
+ usb_free_urb(dib->buf_urb[i]);
+ }
+ pci_free_consistent(NULL,DIBUSB_TS_BUFFER_SIZE,dib->buffer,dib->dma_handle);
return 0;
}
@@ -513,12 +507,29 @@ static int dibusb_init(struct usb_dibusb *dib)
/* dibusb_reset_cpu(dib); */
- dib->buffer = pci_alloc_consistent(NULL,8192, &dib->dma_handle);
- memset(dib->buffer,0,8192);
- if (!(dib->buf_urb = usb_alloc_urb(0,GFP_KERNEL))) {
- dibusb_exit(dib);
+ if ((dib->buffer = pci_alloc_consistent(NULL,DIBUSB_TS_BUFFER_SIZE, &dib->dma_handle)) == NULL) {
return -ENOMEM;
}
+ memset(dib->buffer,0,DIBUSB_TS_BUFFER_SIZE);
+ for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) {
+ if (!(dib->buf_urb[i] = usb_alloc_urb(0,GFP_KERNEL))) {
+ dibusb_exit(dib);
+ return -ENOMEM;
+ }
+ deb_info("submitting URB no. %d\n",i);
+
+ usb_fill_bulk_urb( dib->buf_urb[i], dib->udev, DATA_PIPE,
+ &dib->buffer[i*DIBUSB_TS_URB_BUFFER_SIZE], DIBUSB_TS_URB_BUFFER_SIZE,
+ dibusb_urb_complete, dib);
+ dib->buf_urb[i]->transfer_flags = 0;
+ dib->buf_urb[i]->timeout = 0;
+
+ if ((ret = usb_submit_urb(dib->buf_urb[i],GFP_KERNEL))) {
+ err("could not submit buffer urb no. %d\n",i);
+ dibusb_exit(dib);
+ return ret;
+ }
+ }
for (i=0; i < DIBUSB_MAX_PIDS; i++) {
dib->pid_list[i].reg = i+DIB3000MB_REG_FIRST_PID;
@@ -527,8 +538,8 @@ static int dibusb_init(struct usb_dibusb *dib)
dib->pid_list[i].dib = dib;
}
- dib->streaming = 0;
- dib->feed_count = 0;
+ dib->feedcount = 0;
+ dib->dvb_is_ready = 0;
if ((ret = dibusb_dvb_init(dib))) {
dibusb_exit(dib);
diff --git a/linux/drivers/media/dvb/dibusb/dvb-dibusb.h b/linux/drivers/media/dvb/dibusb/dvb-dibusb.h
index a04e8d8cf..331f85d3c 100644
--- a/linux/drivers/media/dvb/dibusb/dvb-dibusb.h
+++ b/linux/drivers/media/dvb/dibusb/dvb-dibusb.h
@@ -14,24 +14,92 @@
#ifndef __DVB_DIBUSB_H__
#define __DVB_DIBUSB_H__
+#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT 0x10
+
/* Vendor IDs */
-#define USB_TWINHAN_VENDOR_ID 0x1822
-#define USB_IMC_NETWORKS_VENDOR_ID 0x13d3
-#define USB_KWORLD_VENDOR_ID 0xeb1a
-#define USB_DIBCOM_VENDOR_ID 0x10b8
-#define USB_ULTIMA_ELECTRONIC_ID 0x05d8
+#define USB_VID_TWINHAN_ID 0x1822
+#define USB_VID_IMC_NETWORKS_ID 0x13d3
+#define USB_VID_KWORLD_ID 0xeb1a
+#define USB_VID_DIBCOM_ID 0x10b8
+#define USB_VID_ULTIMA_ELECTRONIC_ID 0x05d8
+#define USB_VID_COMPRO_ID 0x185b
/* Product IDs before loading the firmware */
-#define USB_VP7041_PRODUCT_PREFW_ID 0x3201
-#define USB_VSTREAM_PRODUCT_PREFW_ID 0x17de
-#define USB_DIBCOM_PRODUCT_PREFW_ID 0x0bb8
-#define USB_ULTIMA_ELEC_PROD_PREFW_ID 0x8105
+#define USB_PID_TWINHAN_VP7041_COLD_ID 0x3201
+#define USB_PID_KWORLD_VSTREAM_COLD_ID 0x17de
+#define USB_PID_DIBCOM_MOD3000_COLD_ID 0x0bb8
+#define USB_PID_ULTIMA_TVBOX_COLD_ID 0x8105
+#define USB_PID_COMPRO_DVBU2000_COLD_ID 0xd000
/* product ID afterwards */
-#define USB_VP7041_PRODUCT_ID 0x3202
-#define USB_VSTREAM_PRODUCT_ID 0x17df
-#define USB_DIBCOM_PRODUCT_ID 0x0bb9
-#define USB_ULTIMA_ELEC_PROD_ID 0x8106
+#define USB_PID_TWINHAN_VP7041_WARM_ID 0x3202
+#define USB_PID_KWORLD_VSTREAM_WARM_ID 0x17df
+#define USB_PID_DIBCOM_MOD3000_WARM_ID 0x0bb9
+#define USB_PID_ULTIMA_TVBOX_WARM_ID 0x8106
+#define USB_PID_COMPRO_DVBU2000_WARM_ID 0xd001
+
+/* static array of valid firmware names, the best one first */
+static const char * valid_firmware_filenames[] = {
+ "dvb-dibusb-5.0.0.11.fw",
+};
+
+struct dibusb_device {
+ u16 cold_product_id;
+ u16 warm_product_id;
+ u8 demod_addr;
+ const char *name;
+};
+
+#define DIBUSB_SUPPORTED_DEVICES 5
+
+/* USB Driver stuff */
+static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
+ { .cold_product_id = USB_PID_TWINHAN_VP7041_COLD_ID,
+ .warm_product_id = USB_PID_TWINHAN_VP7041_WARM_ID,
+ .name = "Twinhan VisionDTV USB-Ter/HAMA USB DVB-T device",
+ .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+ },
+ { .cold_product_id = USB_PID_KWORLD_VSTREAM_COLD_ID,
+ .warm_product_id = USB_PID_KWORLD_VSTREAM_WARM_ID,
+ .name = "KWorld V-Stream XPERT DTV - DVB-T USB",
+ .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+ },
+ { .cold_product_id = USB_PID_DIBCOM_MOD3000_COLD_ID,
+ .warm_product_id = USB_PID_DIBCOM_MOD3000_WARM_ID,
+ .name = "DiBcom USB reference design",
+ .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+ },
+ { .cold_product_id = USB_PID_ULTIMA_TVBOX_COLD_ID,
+ .warm_product_id = USB_PID_ULTIMA_TVBOX_WARM_ID,
+ .name = "Ultima Electronic/Artec T1 USB TVBOX",
+ .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+ },
+ { .cold_product_id = USB_PID_COMPRO_DVBU2000_COLD_ID,
+ .warm_product_id = USB_PID_COMPRO_DVBU2000_WARM_ID,
+ .name = "Compro Videomate DVB-U2000 - DVB-T USB",
+ .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
+ }
+};
+
+/* USB Driver stuff */
+/* table of devices that work with this driver */
+static struct usb_device_id dibusb_table [] = {
+ { USB_DEVICE(USB_VID_TWINHAN_ID, USB_PID_TWINHAN_VP7041_COLD_ID) },
+ { USB_DEVICE(USB_VID_TWINHAN_ID, USB_PID_TWINHAN_VP7041_WARM_ID) },
+ { USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_COLD_ID) },
+ { USB_DEVICE(USB_VID_IMC_NETWORKS_ID,USB_PID_TWINHAN_VP7041_WARM_ID) },
+ { USB_DEVICE(USB_VID_KWORLD_ID, USB_PID_KWORLD_VSTREAM_COLD_ID) },
+ { USB_DEVICE(USB_VID_KWORLD_ID, USB_PID_KWORLD_VSTREAM_WARM_ID) },
+ { USB_DEVICE(USB_VID_DIBCOM_ID, USB_PID_DIBCOM_MOD3000_COLD_ID) },
+ { USB_DEVICE(USB_VID_DIBCOM_ID, USB_PID_DIBCOM_MOD3000_WARM_ID) },
+ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_COLD_ID) },
+ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC_ID, USB_PID_ULTIMA_TVBOX_WARM_ID) },
+ { USB_DEVICE(USB_VID_COMPRO_ID, USB_PID_COMPRO_DVBU2000_COLD_ID) },
+ { USB_DEVICE(USB_VID_COMPRO_ID, USB_PID_COMPRO_DVBU2000_WARM_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, dibusb_table);
/* CS register start/stop the usb controller cpu */
#define DIBUSB_CPU_CSREG 0x7F92
@@ -53,15 +121,19 @@ struct dibusb_pid {
struct usb_dibusb *dib;
};
+#define DIBUSB_TS_NUM_URBS 3
+#define DIBUSB_TS_URB_BUFFER_SIZE 4096
+#define DIBUSB_TS_BUFFER_SIZE (DIBUSB_TS_NUM_URBS * DIBUSB_TS_URB_BUFFER_SIZE)
+#define DIBUSB_TS_DEFAULT_SIZE (188*21)
+
struct usb_dibusb {
/* usb */
struct usb_device * udev;
struct dibusb_device * dibdev;
- int streaming;
- int feed_count;
- struct urb *buf_urb;
+ int feedcount;
+ struct urb * buf_urb[DIBUSB_TS_NUM_URBS];
u8 *buffer;
dma_addr_t dma_handle;
@@ -77,52 +149,13 @@ struct usb_dibusb {
struct semaphore i2c_sem;
/* dvb */
+ int dvb_is_ready;
struct dvb_adapter *adapter;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dvb_net dvb_net;
};
-
-struct dibusb_device {
- u16 cold_product_id;
- u16 warm_product_id;
- u8 demod_addr;
- const char *name;
-};
-
-/* static array of valid firmware names, the best one first */
-static const char * valid_firmware_filenames[] = {
- "dvb-dibusb-5.0.0.11.fw",
-};
-
-#define DIBUSB_SUPPORTED_DEVICES 4
-
-/* USB Driver stuff */
-static struct dibusb_device dibusb_devices[DIBUSB_SUPPORTED_DEVICES] = {
- { .cold_product_id = USB_VP7041_PRODUCT_PREFW_ID,
- .warm_product_id = USB_VP7041_PRODUCT_ID,
- .name = "Twinhan VisionDTV USB-Ter/HAMA USB DVB-T device",
- .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
- },
- { .cold_product_id = USB_VSTREAM_PRODUCT_PREFW_ID,
- .warm_product_id = USB_VSTREAM_PRODUCT_ID,
- .name = "KWorld V-Stream XPERT DTV - DVB-T USB",
- .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
- },
- { .cold_product_id = USB_DIBCOM_PRODUCT_PREFW_ID,
- .warm_product_id = USB_DIBCOM_PRODUCT_ID,
- .name = "DiBcom USB reference design",
- .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
- },
- {
- .cold_product_id = USB_ULTIMA_ELEC_PROD_PREFW_ID,
- .warm_product_id = USB_ULTIMA_ELEC_PROD_ID,
- .name = "Ultima Electronic/Artec T1 USB TVBOX",
- .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT,
- },
-};
-
#define COMMAND_PIPE usb_sndbulkpipe(dib->udev, 0x01)
#define RESULT_PIPE usb_rcvbulkpipe(dib->udev, 0x81)
#define DATA_PIPE usb_rcvbulkpipe(dib->udev, 0x82)