diff options
author | Patrick Boettcher <devnull@localhost> | 2004-09-20 15:25:11 +0000 |
---|---|---|
committer | Patrick Boettcher <devnull@localhost> | 2004-09-20 15:25:11 +0000 |
commit | 0c68f2871259818657693bdf2d82ac92bd70600e (patch) | |
tree | 3b9d1f9a2dcab7384f49a99f675e92e001a63c2c /linux | |
parent | f0ef0b54a60a050a2cfaf014524495710a299f89 (diff) | |
download | mediapointer-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.c | 151 | ||||
-rw-r--r-- | linux/drivers/media/dvb/dibusb/dvb-dibusb.h | 145 |
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) |