From: Michael Hunold - [DVB] dibusb: added remote control event handling, thanks to David Matthews. - [DVB] dibusb: added support for special Artec devices (with AN2235 usb controller) - [DVB] dibusb: enable several new devices (even the broken Artec T1) - [DVB] dibusb: #if 0'ing unused code - [DVB] dibusb: follow frontend changes Signed-off-by: Michael Hunold Signed-off-by: Andrew Morton --- 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.c | 578 +++++++++++++++++--------- 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.h | 348 ++++++++++----- 2 files changed, 603 insertions(+), 323 deletions(-) diff -puN drivers/media/dvb/dibusb/dvb-dibusb.c~dvb-dibusb-driver-update drivers/media/dvb/dibusb/dvb-dibusb.c --- 25/drivers/media/dvb/dibusb/dvb-dibusb.c~dvb-dibusb-driver-update Thu Nov 18 15:18:06 2004 +++ 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.c Thu Nov 18 15:18:06 2004 @@ -11,6 +11,8 @@ * 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. @@ -18,9 +20,7 @@ * Acknowledgements * * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver - * sources, on which this driver (and the dib3000mb frontend) are based. - * - * + * sources, on which this driver (and the dib3000mb/mc/p frontends) are based. * * see Documentation/dvb/README.dibusb for more information */ @@ -32,19 +32,21 @@ #include #include #include +#include #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 */ +/* debug */ #ifdef CONFIG_DVB_DIBCOM_DEBUG -#define dprintk_new(level,args...) \ +#define dprintk(level,args...) \ do { if ((debug & level)) { printk(args); } } while (0) #define debug_dump(b,l) if (debug) {\ @@ -55,20 +57,22 @@ 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 (|-able))."); +MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))."); #else -#define dprintk_new(args...) +#define dprintk(args...) #define debug_dump(b,l) #endif -#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) -#define deb_err(args...) dprintk_new(0x10,args) +#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) + /* Version information */ -#define DRIVER_VERSION "0.0" +#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" @@ -83,25 +87,28 @@ static int dibusb_readwrite_usb(struct u if ((ret = down_interruptible(&dib->usb_sem))) return ret; - if (dib->streaming && wbuf[0] == DIBUSB_REQ_I2C_WRITE) - deb_err("BUG: writing to i2c, while TS-streaming destroys the stream. What" - " did you do ? Please enable debugging and send the syslog to the author. (%x reg: %x %x)", - wbuf[0],wbuf[2],wbuf[3]); + 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)", wbuf[0],wbuf[2],wbuf[3]); debug_dump(wbuf,wlen); - ret = usb_bulk_msg(dib->udev,COMMAND_PIPE, - wbuf,wlen,&actlen,DIBUSB_I2C_TIMEOUT); + 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 */ + /* an answer is expected, and no error before */ if (!ret && rbuf && rlen) { - ret = usb_bulk_msg(dib->udev,RESULT_PIPE,rbuf,rlen, - &actlen,DIBUSB_I2C_TIMEOUT); + 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); @@ -115,11 +122,6 @@ static int dibusb_readwrite_usb(struct u return ret; } -static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len) -{ - return dibusb_readwrite_usb(dib,buf,len,NULL,0); -} - static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { @@ -146,97 +148,21 @@ static int dibusb_i2c_msg(struct usb_dib /* * DVB stuff */ - -static struct dibusb_pid * dibusb_get_free_pid(struct usb_dibusb *dib) -{ - int i; - unsigned long flags; - struct dibusb_pid *dpid = NULL; - - spin_lock_irqsave(&dib->pid_list_lock,flags); - for (i=0; i < DIBUSB_MAX_PIDS; i++) - if (!dib->pid_list[i].active) { - dpid = dib->pid_list + i; - dpid->active = 1; - break; - } - spin_unlock_irqrestore(&dib->pid_list_lock,flags); - return dpid; -} - -static int dibusb_start_xfer(struct usb_dibusb *dib) -{ - u8 b[4] = { - (DIB3000MB_REG_FIFO >> 8) & 0xff, - (DIB3000MB_REG_FIFO) & 0xff, - (DIB3000MB_FIFO_ACTIVATE >> 8) & 0xff, - (DIB3000MB_FIFO_ACTIVATE) & 0xff - }; - dib->streaming = 1; - deb_ts("start streaming\n"); - return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0); -} - -static int dibusb_stop_xfer(struct usb_dibusb *dib) -{ - u8 b[4] = { - (DIB3000MB_REG_FIFO >> 8) & 0xff, - (DIB3000MB_REG_FIFO) & 0xff, - (DIB3000MB_FIFO_INHIBIT >> 8) & 0xff, - (DIB3000MB_FIFO_INHIBIT) & 0xff - }; - dib->streaming = 0; - deb_ts("stop streaming\n"); - return dibusb_i2c_msg(dib,DIBUSB_DEMOD_I2C_ADDR_DEFAULT,b,4,NULL,0); -} - -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, - (dpid->reg) & 0xff, - (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); - - 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; - deb_xfer("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status); + deb_ts("urb complete feedcount: %d, status: %d\n",dib->feedcount,urb->status); if (dib->feedcount > 0 && urb->status == 0) { - deb_xfer("URB return len: %d\n",urb->actual_length); + 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); + 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 == DIBUSB_TS_DEFAULT_SIZE && dib->dvb_is_ready) + 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 " @@ -247,78 +173,181 @@ static void dibusb_urb_complete(struct u usb_submit_urb(urb,GFP_KERNEL); } - -static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed) +static int dibusb_ctrl_feed(struct usb_dibusb *dib, int pid, int onoff) { -// struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct usb_dibusb *dib = dvbdmxfeed->demux->priv; - struct dibusb_pid *dpid; + 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; + } + } - deb_ts("pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); + dib->feedcount += onoff ? 1 : -1; - if ((dpid = dibusb_get_free_pid(dib)) == NULL) { + 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; } - dvbdmxfeed->priv = dpid; - dpid->pid = dvbdmxfeed->pid; - - dibusb_set_pid(dpid); - - return 0; + } 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("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; } - -static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -{ - struct dibusb_pid *dpid = (struct dibusb_pid *) dvbdmxfeed->priv; - - deb_ts("stopfeed pid: 0x%04x, feedtype: %d\n",dvbdmxfeed->pid, dvbdmxfeed->type); - - if (dpid == NULL) - err("channel in dmxfeed->priv was NULL"); - else { - dpid->active = 0; - dpid->pid = 0; - dibusb_set_pid(dpid); } - return 0; } -/* - * firmware transfers - */ +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); +} -/* - * 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) +static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { - u8 b[1] = { DIBUSB_REQ_INTR_READ }; - return dibusb_write_usb(dib,b,1); + 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. */ + /* 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 }, +}; /* - * TODO: a tasklet should run with a delay of 1/10 second - * and feed an appropriate event device ? - * NEC protocol is used for remote controlls + * 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_EMPTY: 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; } @@ -326,6 +355,46 @@ static int dibusb_read_remote_control(st 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 5 functions as they are not in use _now_, + * but probably will be sometime. + */ + +static int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len) +{ + return dibusb_readwrite_usb(dib,buf,len,NULL,0); +} + +/* + * 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 the firmware */ @@ -355,6 +424,8 @@ static int dibusb_hw_wakeup(struct usb_d return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1); } +#endif + /* * I2C */ @@ -387,19 +458,44 @@ static u32 dibusb_i2c_func(struct i2c_ad return I2C_FUNC_I2C; } -static int dibusb_i2c_client_register (struct i2c_client *i2c) -{ - struct usb_dibusb *dib = i2c_get_adapdata(i2c->adapter); - if (i2c->driver->command) - return i2c->driver->command(i2c,FE_REGISTER,dib->adapter); - return 0; -} +static int thomson_cable_eu_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params); -static int dibusb_i2c_client_unregister (struct i2c_client *i2c) +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 = i2c_get_adapdata(i2c->adapter); - if (i2c->driver->command) - return i2c->driver->command(i2c,FE_UNREGISTER,dib->adapter); + 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; } @@ -410,6 +506,24 @@ static struct i2c_algorithm dibusb_algo .functionality = dibusb_i2c_func, }; +static void frontend_init(struct usb_dibusb* dib) +{ + dib->fe = dib3000mb_attach(&thomson_cable_eu_config, &dib->i2c_adap,&dib->xfer_ops); + + 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; @@ -423,6 +537,7 @@ static int dibusb_dvb_init(struct usb_di 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 @@ -433,8 +548,6 @@ static int dibusb_dvb_init(struct usb_di dib->i2c_adap.algo = &dibusb_algo; dib->i2c_adap.algo_data = NULL; dib->i2c_adap.id = I2C_ALGO_BIT; - dib->i2c_adap.client_register = dibusb_i2c_client_register, - dib->i2c_adap.client_unregister = dibusb_i2c_client_unregister, i2c_set_adapdata(&dib->i2c_adap, dib); @@ -446,8 +559,8 @@ static int dibusb_dvb_init(struct usb_di dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; dib->demux.priv = (void *)dib; - dib->demux.filternum = DIBUSB_MAX_PIDS; - dib->demux.feednum = DIBUSB_MAX_PIDS; + /* 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; @@ -466,6 +579,11 @@ static int dibusb_dvb_init(struct usb_di 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); @@ -482,12 +600,17 @@ success: 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); @@ -497,21 +620,36 @@ static int dibusb_dvb_exit(struct usb_di static int dibusb_exit(struct usb_dibusb *dib) { int i; - for (i = 0; i < DIBUSB_TS_NUM_URBS; i++) - if (dib->buf_urb[i] != NULL) { + 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); - usb_kill_urb(dib->buf_urb[i]); // TODO kernel version ifdef for unlink_urb + + /* 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); - usb_free_urb(dib->buf_urb[i]); + /* free the URBs */ + usb_free_urb(dib->urb_list[i]); + } } - pci_free_consistent(NULL,DIBUSB_TS_BUFFER_SIZE,dib->buffer,dib->dma_handle); + /* 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; + int ret,i,bufsize; sema_init(&dib->usb_sem, 1); sema_init(&dib->i2c_sem, 1); @@ -519,46 +657,70 @@ static int dibusb_init(struct usb_dibusb * when reloading the driver w/o replugging the device * a timeout occures, this helps */ - usb_clear_halt(dib->udev,COMMAND_PIPE); - usb_clear_halt(dib->udev,RESULT_PIPE); - usb_clear_halt(dib->udev,DATA_PIPE); - - /* dibusb_reset_cpu(dib); */ + 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 *)); - if ((dib->buffer = pci_alloc_consistent(NULL,DIBUSB_TS_BUFFER_SIZE, &dib->dma_handle)) == NULL) { + 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) { + dibusb_exit(dib); 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))) { + 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->buf_urb[i], dib->udev, DATA_PIPE, - &dib->buffer[i*DIBUSB_TS_URB_BUFFER_SIZE], DIBUSB_TS_URB_BUFFER_SIZE, + 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->buf_urb[i]->transfer_flags = 0; - if ((ret = usb_submit_urb(dib->buf_urb[i],GFP_KERNEL))) { + 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; } } - for (i=0; i < DIBUSB_MAX_PIDS; i++) { - dib->pid_list[i].reg = i+DIB3000MB_REG_FIRST_PID; - dib->pid_list[i].pid = 0; - dib->pid_list[i].active = 0; - dib->pid_list[i].dib = dib; - } - - dib->feedcount = 0; - dib->streaming = 0; 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; irc_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); + if ((ret = dibusb_dvb_init(dib))) { dibusb_exit(dib); return ret; @@ -579,17 +741,20 @@ static int dibusb_loadfirmware(struct us struct dibusb_device *dibdev) { const struct firmware *fw = NULL; + const char **fws; u16 addr; u8 *b,*p; int ret = 0,i; - for (i = 0; i < sizeof(valid_firmware_filenames)/sizeof(const char*); i++) { - if ((ret = request_firmware(&fw, valid_firmware_filenames[i], &udev->dev)) == 0) { - info("using firmware file (%s).",valid_firmware_filenames[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", - valid_firmware_filenames[i],ret); + fws[i],ret); } if (fw == NULL) { @@ -609,7 +774,7 @@ static int dibusb_loadfirmware(struct us /* stop the CPU */ reset = 1; - if ((ret = dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1)) != 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]; @@ -631,7 +796,7 @@ static int dibusb_loadfirmware(struct us ret = 0; /* restart the CPU */ reset = 0; - if (ret || dibusb_writemem(udev,DIBUSB_CPU_CSREG,&reset,1) != 1) { + if (ret || dibusb_writemem(udev,dibdev->parm->usb_cpu_csreg,&reset,1) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } @@ -679,6 +844,21 @@ static int dibusb_probe(struct usb_inter if (cold) ret = dibusb_loadfirmware(udev,dibdev); else { + 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 filter."); + break; + case USB_SPEED_HIGH: + info("running at HIGH speed, will deliver the complete TS."); + break; + case USB_SPEED_UNKNOWN: /* fall through */ + default: + err("cannot handle USB speed because it is unkown."); + break; + } dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL); if (dib == NULL) { err("no memory"); diff -puN drivers/media/dvb/dibusb/dvb-dibusb.h~dvb-dibusb-driver-update drivers/media/dvb/dibusb/dvb-dibusb.h --- 25/drivers/media/dvb/dibusb/dvb-dibusb.h~dvb-dibusb-driver-update Thu Nov 18 15:18:06 2004 +++ 25-akpm/drivers/media/dvb/dibusb/dvb-dibusb.h Thu Nov 18 15:18:06 2004 @@ -7,136 +7,252 @@ * 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 . */ #ifndef __DVB_DIBUSB_H__ #define __DVB_DIBUSB_H__ -#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT 0x10 +#include "dib3000.h" -/* Vendor IDs */ -#define USB_VID_TWINHAN_ID 0x1822 -#define USB_VID_IMC_NETWORKS_ID 0x13d3 -#define USB_VID_EMPIA_ID 0xeb1a -#define USB_VID_DIBCOM_ID 0x10b8 -#define USB_VID_ULTIMA_ELECTRONIC_ID 0x05d8 -#define USB_VID_COMPRO_ID 0x185b -#define USB_VID_HYPER_PALTEK 0x1025 +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" +}; -/* Product IDs before loading the firmware */ -#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 -#define USB_PID_UNK_HYPER_PALTEK_COLD_ID 0x005e - -/* product ID afterwards */ -#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 -#define USB_PID_UNK_HYPER_PALTEK_WARM_ID 0x005f - -/* static array of valid firmware names, the best one first */ -static const char * valid_firmware_filenames[] = { - "dvb-dibusb-5.0.0.11.fw", +static const char * dibusb_fw_filenames2_0[] = { + "dvb-dibusb-6.0.0.5.fw" +}; + +struct dibusb_device_parameter { + dibusb_type type; + u8 demod_addr; + const char **fw_filenames; + const char *usb_controller; + u16 usb_cpu_csreg; + + int num_urbs; + int urb_buf_size; + int default_size; + int firmware_bug; + + 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 = 0x10, + .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, + } }; struct dibusb_device { + const char *name; u16 cold_product_id; u16 warm_product_id; - u8 demod_addr; - const char *name; + struct dibusb_device_parameter *parm; }; -#define DIBUSB_SUPPORTED_DEVICES 6 +/* Vendor IDs */ +#define USB_VID_ANCHOR 0x0547 +#define USB_VID_AVERMEDIA 0x14aa +#define USB_VID_COMPRO 0x185b +#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_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_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_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 12 /* 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 = "TwinhanDTV USB-Ter/Magic Box / 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 DVB-T reference design (MOD300)", - .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, - }, - { .cold_product_id = USB_PID_UNK_HYPER_PALTEK_COLD_ID, - .warm_product_id = USB_PID_UNK_HYPER_PALTEK_WARM_ID, - .name = "Unkown USB DVB-T device ???? please report the name to linux-dvb or to the author", - .demod_addr = DIBUSB_DEMOD_I2C_ADDR_DEFAULT, + { .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 = "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 = "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 = "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_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_EMPIA_ID, USB_PID_KWORLD_VSTREAM_COLD_ID) }, - { USB_DEVICE(USB_VID_EMPIA_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) }, - { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD_ID) }, - { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM_ID) }, + { 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) }, + +/* + * activate the following define when you have the device and want to compile + * build from build-2.6 in dvb-kernel + */ +// #define CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235 +#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_AN2235 + { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) }, +#endif { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, dibusb_table); -/* CS register start/stop the usb controller cpu */ -#define DIBUSB_CPU_CSREG 0x7F92 - -// 0x10 is the I2C address of the first demodulator on the board -#define DIBUSB_DEMOD_I2C_ADDR_DEFAULT 0x10 #define DIBUSB_I2C_TIMEOUT HZ*5 -#define DIBUSB_MAX_PIDS 16 - -#define DIB3000MB_REG_FIRST_PID ( 153) - -struct usb_dibusb; - -struct dibusb_pid { - u16 reg; - u16 pid; - int active; - 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; @@ -144,14 +260,12 @@ struct usb_dibusb { struct dibusb_device * dibdev; int feedcount; - int streaming; - struct urb * buf_urb[DIBUSB_TS_NUM_URBS]; + struct dib3000_xfer_ops xfer_ops; + + struct urb **urb_list; u8 *buffer; dma_addr_t dma_handle; - spinlock_t pid_list_lock; - struct dibusb_pid pid_list[DIBUSB_MAX_PIDS]; - /* I2C */ struct i2c_adapter i2c_adap; struct i2c_client i2c_client; @@ -166,16 +280,14 @@ struct usb_dibusb { struct dmxdev dmxdev; struct dvb_demux demux; struct dvb_net dvb_net; + struct dvb_frontend* fe; + + /* remote control */ + struct input_dev rc_input_dev; + struct work_struct rc_query_work; + int rc_input_event; }; -#define COMMAND_PIPE usb_sndbulkpipe(dib->udev, 0x01) -#define RESULT_PIPE usb_rcvbulkpipe(dib->udev, 0x81) -#define DATA_PIPE usb_rcvbulkpipe(dib->udev, 0x82) -/* - * last endpoint 0x83 only used for chaining the buffers - * of the endpoints in the cypress - */ -#define CHAIN_PIPE_DO_NOT_USE usb_rcvbulkpipe(dib->udev, 0x83) /* types of first byte of each buffer */ @@ -209,16 +321,4 @@ struct usb_dibusb { #define DIBUSB_IOCTL_POWER_SLEEP 0x00 #define DIBUSB_IOCTL_POWER_WAKEUP 0x01 - -/* - * values from the demodulator which are needed in - * the usb driver as well - */ - -#define DIB3000MB_REG_FIFO ( 145) -#define DIB3000MB_FIFO_INHIBIT ( 1) -#define DIB3000MB_FIFO_ACTIVATE ( 0) - -#define DIB3000MB_ACTIVATE_FILTERING (0x2000) - #endif _