From: Michael Hunold <hunold@linuxtv.org>
To: Linus Torvalds <torvalds@osdl.org>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Andrew Morton <akpm@osdl.org>
Subject: Re: [PATCH][2.6][4/14] dvb core update
Date: Fri, 17 Sep 2004 16:27:45 +0200 [thread overview]
Message-ID: <414AF461.4050707@linuxtv.org> (raw)
In-Reply-To: <414AF41A.6060009@linuxtv.org>
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: 04-DVB-dvb-core-update.diff --]
[-- Type: text/plain, Size: 76188 bytes --]
- [DVB] remove non-linux compatibility stuff from dvb_functions. rest in peace.
- [DVB] remove home-brewn dvb-i2c stuff. rest in peace.
- [DVB] convert MODULE_PARM() to module_param()
- [DVB] convert dvb_delay() to mdelay()
- [DVB] convert C++ comments to C comments
- [DVB] dvb_ca_en50221: fix for matrix CAMs from Sjoerd Simons, use c99 initializers, Fix for aston CAM read timeout problems, Moved CAM CTRL IF reset to a better place, better debugging with multiple cards (Sjoerd Simons)
- [DVB] dvb-frontend: patch by Wolfgang Fritz: suppress spurious events during tuning, Do not allow write (and related) ioctls when frontend is opened RDONLY, Properly lock the frontend module on open/close, patch by Christopher Pascoe: remove bogus up(fe->sem) on fe thread exit, patch by Christopher Pascoe: remove bogus up(fe->sem) on fe thread exit
- [DVB] dvb-demux: using spin_lock instead of spin_lock_irq caused a race condition between irq/tasklet and user space task
- [DVB] dvb-core: add sysfs/udev support using "class_simple", prevent Oops when PES filter is set with invalid pes_type, protect feed_list with spin_locks
Signed-off-by: Michael Hunold <hunold@linuxtv.org>
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dmxdev.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dmxdev.c
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dmxdev.c 2004-08-23 09:34:58.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dmxdev.c 2004-08-18 19:52:17.000000000 +0200
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/ioctl.h>
@@ -33,10 +34,11 @@
#include <asm/system.h>
#include "dmxdev.h"
-#include "dvb_functions.h"
-MODULE_PARM(debug,"i");
-static int debug = 0;
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
#define dprintk if (debug) printk
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_ca_en50221.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2004-08-23 09:34:58.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2004-08-18 19:52:17.000000000 +0200
@@ -32,16 +32,20 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
-#include <asm/semaphore.h>
+#include <asm/rwsem.h>
#include <asm/atomic.h>
#include "dvb_ca_en50221.h"
-#include "dvb_functions.h"
#include "dvb_ringbuffer.h"
-static int dvb_ca_en50221_debug = 0;
+static int dvb_ca_en50221_debug;
+
+module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644);
+MODULE_PARM_DESC(dvb_ca_en50221_debug, "enable verbose debug messages");
+
#define dprintk if (dvb_ca_en50221_debug) printk
#define INIT_TIMEOUT_SECS 5
@@ -108,7 +112,7 @@
int link_buf_size;
/* semaphore for syncing access to slot structure */
- struct semaphore sem;
+ struct rw_semaphore sem;
/* buffer for incoming packets */
struct dvb_ringbuffer rx_buffer;
@@ -199,7 +203,6 @@
static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private* ca, int slot)
{
int slot_status;
- int status;
int cam_present_now;
int cam_changed;
@@ -209,9 +212,7 @@
}
/* poll mode */
- if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status;
slot_status = ca->pub->poll_slot_status(ca->pub, slot);
- up(&ca->slot_info[slot].sem);
cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1: 0;
cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1: 0;
@@ -277,7 +278,7 @@
}
/* wait for a bit */
- dvb_delay(1);
+ msleep(1);
}
dprintk("%s failed timeout:%lu\n", __FUNCTION__, jiffies - start);
@@ -360,6 +361,13 @@
/* grab the next tuple length and type */
if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) return _tupleType;
+ if (_tupleType == 0xff) {
+ dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType);
+ *address += 2;
+ *tupleType = _tupleType;
+ *tupleLength = 0;
+ return 0;
+ }
if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address+2)) < 0) return _tupleLength;
_address += 4;
@@ -550,25 +558,22 @@
dprintk ("%s\n", __FUNCTION__);
- /* acquire the slot */
- if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status;
-
/* check if we have space for a link buf in the rx_buffer */
if (ebuf == NULL) {
- if (dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer) <
- (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
+ int buf_free;
+
+ down_read(&ca->slot_info[slot].sem);
+ buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);
+ up_read(&ca->slot_info[slot].sem);
+
+ if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
status = -EAGAIN;
goto exit;
}
}
- /* reset the interface if there's been a tx error */
+ /* check if there is data available */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
- if (status & STATUSREG_TXERR) {
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- status = -EIO;
- goto exit;
- }
if (!(status & STATUSREG_DA)) {
/* no data */
status = 0;
@@ -612,20 +617,25 @@
buf[i] = status;
}
- /* check for read error (RE should now go to 0) */
+ /* check for read error (RE should now be 0) */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
if (status & STATUSREG_RE) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
status = -EIO;
goto exit;
}
/* OK, add it to the receive buffer, or copy into external buffer if supplied */
if (ebuf == NULL) {
+ down_read(&ca->slot_info[slot].sem);
dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
+ up_read(&ca->slot_info[slot].sem);
} else {
memcpy(ebuf, buf, bytes_read);
}
+ dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_read);
+
/* wake up readers when a last_fragment is received */
if ((buf[1] & 0x80) == 0x00) {
wake_up_interruptible(&ca->wait_queue);
@@ -634,7 +643,6 @@
status = bytes_read;
exit:
- up(&ca->slot_info[slot].sem);
return status;
}
@@ -662,19 +670,9 @@
// sanity check
if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL;
- /* acquire the slot */
- if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status;
-
- /* reset the interface if there's been a tx error */
+ /* check if interface is actually waiting for us to read from it, or if a read is in progress */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite;
- if (status & STATUSREG_TXERR) {
- ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
- status = -EIO;
- goto exitnowrite;
- }
-
- /* check if interface is actually waiting for us to read from it */
- if (status & STATUSREG_DA) {
+ if (status & (STATUSREG_DA|STATUSREG_RE)) {
status = -EAGAIN;
goto exitnowrite;
}
@@ -702,16 +700,18 @@
/* check for write error (WE should now be 0) */
if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
if (status & STATUSREG_WE) {
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
status = -EIO;
goto exit;
}
status = bytes_write;
+ dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_write);
+
exit:
ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
exitnowrite:
- up(&ca->slot_info[slot].sem);
return status;
}
@@ -729,16 +729,14 @@
*/
static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private* ca, int slot)
{
- int status;
-
dprintk ("%s\n", __FUNCTION__);
- if ((status = down_interruptible(&ca->slot_info[slot].sem)) != 0) return status;
+ down_write(&ca->slot_info[slot].sem);
ca->pub->slot_shutdown(ca->pub, slot);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
if (ca->slot_info[slot].rx_buffer.data) vfree(ca->slot_info[slot].rx_buffer.data);
ca->slot_info[slot].rx_buffer.data = NULL;
- up(&ca->slot_info[slot].sem);
+ up_write(&ca->slot_info[slot].sem);
/* need to wake up all processes to check if they're now
trying to write to a defunct CAM */
@@ -821,10 +819,7 @@
break;
case DVB_CA_SLOTSTATE_RUNNING:
- flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS);
- if (flags & STATUSREG_DA) {
- dvb_ca_en50221_thread_wakeup(ca);
- }
+ if (ca->open) dvb_ca_en50221_read_data(ca, slot, NULL, 0);
break;
}
}
@@ -934,7 +929,11 @@
/* setup kernel thread */
snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id);
- dvb_kernel_thread_setup(name);
+
+ lock_kernel ();
+ daemonize (name);
+ sigfillset (¤t->blocked);
+ unlock_kernel ();
/* choose the correct initial delay */
dvb_ca_en50221_thread_update_delay(ca);
@@ -993,6 +992,12 @@
break;
case DVB_CA_SLOTSTATE_VALIDATE:
+ if (ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS) != 0) {
+ printk("dvb_ca: Unable to reset CAM IF\n");
+ ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+ dvb_ca_en50221_thread_update_delay(ca);
+ break;
+ }
if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
printk("dvb_ca: Invalid PC card inserted :(\n");
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
@@ -1054,6 +1058,10 @@
case DVB_CA_SLOTSTATE_RUNNING:
if (!ca->open) break;
+ // no need to poll if the CAM supports IRQs
+ if (ca->slot_info[slot].da_irq_supported) break;
+
+ // poll mode
pktcount = 0;
while(dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) {
if (!ca->open) break;
@@ -1233,7 +1241,7 @@
}
if (status != -EAGAIN) goto exit;
- dvb_delay(1);
+ msleep(1);
}
if (!written) {
status = -EIO;
@@ -1266,7 +1274,7 @@
while((slot_count < ca->slot_count) && (!found)) {
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) goto nextslot;
- if ((*result = down_interruptible(&ca->slot_info[slot].sem)) != 0) return 1;
+ down_read(&ca->slot_info[slot].sem);
idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
while(idx != -1) {
@@ -1281,7 +1289,7 @@
idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
}
- if (!found) up(&ca->slot_info[slot].sem);
+ if (!found) up_read(&ca->slot_info[slot].sem);
nextslot:
slot = (slot + 1) % ca->slot_count;
@@ -1378,7 +1386,7 @@
status = pktlen;
exit:
- up(&ca->slot_info[slot].sem);
+ up_read(&ca->slot_info[slot].sem);
return status;
}
@@ -1406,7 +1414,9 @@
for(i=0; i< ca->slot_count; i++) {
if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
+ down_write(&ca->slot_info[i].sem);
dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
+ up_write(&ca->slot_info[i].sem);
}
}
@@ -1464,7 +1474,7 @@
dprintk ("%s\n", __FUNCTION__);
if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
- up(&ca->slot_info[slot].sem);
+ up_read(&ca->slot_info[slot].sem);
mask |= POLLIN;
}
@@ -1475,7 +1485,7 @@
poll_wait(file, &ca->wait_queue, wait);
if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
- up(&ca->slot_info[slot].sem);
+ up_read(&ca->slot_info[slot].sem);
mask |= POLLIN;
}
@@ -1484,21 +1494,21 @@
static struct file_operations dvb_ca_fops = {
- owner: THIS_MODULE,
- read: dvb_ca_en50221_io_read,
- write: dvb_ca_en50221_io_write,
- ioctl: dvb_ca_en50221_io_ioctl,
- open: dvb_ca_en50221_io_open,
- release: dvb_ca_en50221_io_release,
- poll: dvb_ca_en50221_io_poll,
+ .owner = THIS_MODULE,
+ .read = dvb_ca_en50221_io_read,
+ .write = dvb_ca_en50221_io_write,
+ .ioctl = dvb_ca_en50221_io_ioctl,
+ .open = dvb_ca_en50221_io_open,
+ .release= dvb_ca_en50221_io_release,
+ .poll = dvb_ca_en50221_io_poll,
};
static struct dvb_device dvbdev_ca = {
- priv: NULL,
- users: 1,
- readers: 1,
- writers: 1,
- fops: &dvb_ca_fops,
+ .priv = NULL,
+ .users = 1,
+ .readers= 1,
+ .writers= 1,
+ .fops = &dvb_ca_fops,
};
@@ -1559,7 +1569,7 @@
ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
atomic_set(&ca->slot_info[i].camchange_count, 0);
ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
- init_MUTEX(&ca->slot_info[i].sem);
+ init_rwsem(&ca->slot_info[i].sem);
}
if (signal_pending(current)) {
@@ -1623,6 +1635,3 @@
pubca->private = NULL;
}
-MODULE_PARM(dvb_ca_en50221_debug,"i");
-
-MODULE_PARM_DESC(dvb_ca_en50221_debug, "enable verbose debug messages");
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_ca_en50221.h linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_ca_en50221.h 2004-07-19 19:40:04.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ca_en50221.h 2004-05-14 18:54:27.000000000 +0200
@@ -42,6 +42,9 @@
/* Structure describing a CA interface */
struct dvb_ca_en50221 {
+ /* NOTE: the read_*, write_* and poll_slot_status functions must use locks as
+ * they may be called from several threads at once */
+
/* functions for accessing attribute memory on the CAM */
int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_demux.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_demux.c
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_demux.c 2004-08-23 09:34:58.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_demux.c 2004-08-18 19:52:17.000000000 +0200
@@ -31,7 +31,6 @@
#include <asm/uaccess.h>
#include "dvb_demux.h"
-#include "dvb_functions.h"
#define NOBUFS
/*
@@ -570,24 +570,30 @@
static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
{
+ spin_lock(&feed->demux->lock);
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
- return;
+ goto out;
}
list_add(&feed->list_head, &feed->demux->feed_list);
+out:
+ spin_unlock(&feed->demux->lock);
}
static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
{
+ spin_lock(&feed->demux->lock);
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
- return;
+ goto out;
}
list_del(&feed->list_head);
+out:
+ spin_unlock(&feed->demux->lock);
}
static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
@@ -789,7 +795,7 @@
feed->pid = 0xffff;
- if (feed->ts_type & TS_DECODER)
+ if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
demux->pesfilter[feed->pes_type] = NULL;
up(&demux->mutex);
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvbdev.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvbdev.c
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvbdev.c 2004-08-23 09:34:58.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvbdev.c 2004-08-18 19:58:18.000000000 +0200
@@ -25,22 +25,26 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/device.h>
#include "dvbdev.h"
-#include "dvb_functions.h"
-static int dvbdev_debug = 0;
+static int dvbdev_debug;
+
+module_param(dvbdev_debug, int, 0644);
+MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
+
#define dprintk if (dvbdev_debug) printk
static LIST_HEAD(dvb_adapter_list);
static DECLARE_MUTEX(dvbdev_register_lock);
-
-static char *dnames[] = {
+static const char * const dnames[] = {
"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
"net", "osd"
};
@@ -49,6 +52,9 @@
#define DVB_MAX_IDS 4
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
+struct class_simple *dvb_class;
+EXPORT_SYMBOL(dvb_class);
+
static struct dvb_device* dvbdev_find_device (int minor)
{
struct list_head *entry;
@@ -219,6 +224,9 @@
S_IFCHR | S_IRUSR | S_IWUSR,
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
+ class_simple_device_add(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
nums2minor(adap->num, type, id));
@@ -235,6 +243,9 @@
devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
dnames[dvbdev->type], dvbdev->id);
+ class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
+ dvbdev->type, dvbdev->id)));
+
list_del(&dvbdev->list_head);
kfree(dvbdev);
}
@@ -300,24 +310,95 @@
int dvb_unregister_adapter(struct dvb_adapter *adap)
{
+ devfs_remove("dvb/adapter%d", adap->num);
+
if (down_interruptible (&dvbdev_register_lock))
return -ERESTARTSYS;
- devfs_remove("dvb/adapter%d", adap->num);
list_del (&adap->list_head);
up (&dvbdev_register_lock);
kfree (adap);
return 0;
}
+/* if the miracle happens and "generic_usercopy()" is included into
+ the kernel, then this can vanish. please don't make the mistake and
+ define this as video_usercopy(). this will introduce a dependecy
+ to the v4l "videodev.o" module, which is unnecessary for some
+ cards (ie. the budget dvb-cards don't need the v4l module...) */
+int dvb_usercopy(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ int (*func)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg))
+{
+ char sbuf[128];
+ void *mbuf = NULL;
+ void *parg = NULL;
+ int err = -EINVAL;
+
+ /* Copy arguments into temp kernel buffer */
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE:
+ /*
+ * For this command, the pointer is actually an integer
+ * argument.
+ */
+ parg = (void *) arg;
+ break;
+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */
+ case _IOC_WRITE:
+ case (_IOC_WRITE | _IOC_READ):
+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+ parg = sbuf;
+ } else {
+ /* too big to allocate from stack */
+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+ if (NULL == mbuf)
+ return -ENOMEM;
+ parg = mbuf;
+ }
+
+ err = -EFAULT;
+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+ goto out;
+ break;
+ }
+
+ /* call driver */
+ if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD)
+ err = -EINVAL;
+
+ if (err < 0)
+ goto out;
+
+ /* Copy results into user buffer */
+ switch (_IOC_DIR(cmd))
+ {
+ case _IOC_READ:
+ case (_IOC_WRITE | _IOC_READ):
+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+ err = -EFAULT;
+ break;
+ }
+
+out:
+ if (mbuf)
+ kfree(mbuf);
+
+ return err;
+}
static int __init init_dvbdev(void)
{
int retval;
+
+ if ((retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops)))
+ printk("dvb-core: unable to get major %d\n", DVB_MAJOR);
+
devfs_mk_dir("dvb");
- retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops);
- if (retval)
- printk("video_dev: unable to get major %d\n", DVB_MAJOR);
+ dvb_class = class_simple_create(THIS_MODULE, "dvb");
+ if (IS_ERR(dvb_class))
+ return PTR_ERR(dvb_class);
return retval;
}
@@ -327,6 +408,7 @@
{
unregister_chrdev(DVB_MAJOR, "DVB");
devfs_remove("dvb");
+ class_simple_destroy(dvb_class);
}
module_init(init_dvbdev);
@@ -336,6 +418,3 @@
MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
MODULE_LICENSE("GPL");
-MODULE_PARM(dvbdev_debug,"i");
-MODULE_PARM_DESC(dvbdev_debug, "enable verbose debug messages");
-
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvbdev.h linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvbdev.h
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvbdev.h 2004-08-23 09:34:58.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvbdev.h 2004-08-18 19:58:18.000000000 +0200
@@ -28,6 +28,7 @@
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/devfs_fs_kernel.h>
+#include <linux/smp_lock.h>
#define DVB_MAJOR 212
@@ -92,5 +90,15 @@
extern int dvb_generic_release (struct inode *inode, struct file *file);
extern int dvb_generic_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
+
+/* we don't mess with video_usercopy() any more,
+we simply define out own dvb_usercopy(), which will hopefully become
+generic_usercopy() someday... */
+
+extern int dvb_usercopy(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ int (*func)(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg));
+
#endif /* #ifndef _DVBDEV_H_ */
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_frontend.c
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_frontend.c 2004-07-19 19:40:04.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_frontend.c 2004-08-18 19:52:17.000000000 +0200
@@ -1,5 +1,6 @@
/*
- * dvb-core.c: DVB core driver
+ * dvb_frontend.c: DVB frontend tuning interface/thread
+ *
*
* Copyright (C) 1999-2001 Ralph Metzler
* Marcus Metzler
@@ -31,13 +32,33 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/list.h>
#include <asm/processor.h>
#include <asm/semaphore.h>
#include "dvb_frontend.h"
#include "dvbdev.h"
-#include "dvb_functions.h"
+
+static int dvb_frontend_debug;
+static int dvb_shutdown_timeout = 5;
+static int dvb_override_frequency_bending;
+static int dvb_force_auto_inversion;
+static int dvb_override_tune_delay;
+static int do_frequency_bending;
+
+module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
+MODULE_PARM_DESC(dvb_frontend_debug, "Turn on/off frontend core debugging (default:off).");
+module_param(dvb_shutdown_timeout, int, 0444);
+MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
+module_param(dvb_override_frequency_bending, int, 0444);
+MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending");
+module_param(dvb_force_auto_inversion, int, 0444);
+MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
+module_param(dvb_override_tune_delay, int, 0444);
+MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
+
+#define dprintk if (dvb_frontend_debug) printk
#define FESTATE_IDLE 1
#define FESTATE_RETUNE 2
@@ -66,17 +87,6 @@
* FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
*/
-
-static int dvb_frontend_debug = 0;
-static int dvb_shutdown_timeout = 5;
-static int dvb_override_frequency_bending = 0;
-static int dvb_force_auto_inversion = 0;
-static int dvb_override_tune_delay = 0;
-
-static int do_frequency_bending = 0;
-
-#define dprintk if (dvb_frontend_debug) printk
-
#define MAX_EVENT 8
struct dvb_fe_events {
@@ -95,6 +105,7 @@
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters;
struct dvb_fe_events events;
+ struct module *module;
struct semaphore sem;
struct list_head list_head;
wait_queue_head_t wait_queue;
@@ -174,7 +185,7 @@
{
struct list_head *entry;
int stepsize = this_fe->info->frequency_stepsize;
- int this_fe_adap_num = this_fe->frontend.i2c->adapter->num;
+ int this_fe_adap_num = this_fe->frontend.dvb_adapter->num;
int frequency;
if (!stepsize || recursive > 10) {
@@ -198,7 +209,7 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.i2c->adapter->num != this_fe_adap_num)
+ if (fe->frontend.dvb_adapter->num != this_fe_adap_num)
continue;
f = fe->parameters.frequency;
@@ -233,13 +244,10 @@
dprintk ("%s\n", __FUNCTION__);
if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK))
- dvb_delay (fe->info->notifier_delay);
+ msleep (fe->info->notifier_delay);
fe->status = s;
- if (!(s & FE_HAS_LOCK) && (fe->info->caps & FE_CAN_MUTE_TS))
- return;
-
/**
* now tell the Demux about the TS status changes...
*/
@@ -333,8 +341,8 @@
{
struct dvb_frontend *frontend = &fe->frontend;
- dprintk ("DVB: initialising frontend %i:%i (%s)...\n",
- frontend->i2c->adapter->num, frontend->i2c->id,
+ dprintk ("DVB: initialising frontend %i (%s)...\n",
+ frontend->dvb_adapter->num,
fe->info->name);
dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL);
@@ -371,25 +379,26 @@
int original_inversion = fe->parameters.inversion;
u32 original_frequency = fe->parameters.frequency;
- // are we using autoinversion?
- autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO));
+ /* are we using autoinversion? */
+ autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) &&
+ (fe->parameters.inversion == INVERSION_AUTO));
- // setup parameters correctly
+ /* setup parameters correctly */
while(!ready) {
- // calculate the lnb_drift
+ /* calculate the lnb_drift */
fe->lnb_drift = fe->auto_step * fe->step_size;
- // wrap the auto_step if we've exceeded the maximum drift
+ /* wrap the auto_step if we've exceeded the maximum drift */
if (fe->lnb_drift > fe->max_drift) {
fe->auto_step = 0;
fe->auto_sub_step = 0;
fe->lnb_drift = 0;
}
- // perform inversion and +/- zigzag
+ /* perform inversion and +/- zigzag */
switch(fe->auto_sub_step) {
case 0:
- // try with the current inversion and current drift setting
+ /* try with the current inversion and current drift setting */
ready = 1;
break;
@@ -418,35 +427,36 @@
default:
fe->auto_step++;
- fe->auto_sub_step = -1; // it'll be incremented to 0 in a moment
+ fe->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
break;
}
if (!ready) fe->auto_sub_step++;
}
- // if this attempt would hit where we started, indicate a complete iteration has occurred
- if ((fe->auto_step == fe->started_auto_step) && (fe->auto_sub_step == 0) && check_wrapped) {
+ /* if this attempt would hit where we started, indicate a complete
+ * iteration has occurred */
+ if ((fe->auto_step == fe->started_auto_step) &&
+ (fe->auto_sub_step == 0) && check_wrapped) {
return 1;
}
- // perform frequency bending if necessary
+ /* perform frequency bending if necessary */
if ((dvb_override_frequency_bending != 1) && do_frequency_bending)
dvb_bend_frequency(fe, 0);
- // instrumentation
- dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i auto_sub_step:%i started_auto_step:%i\n",
- __FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion, fe->auto_step, fe->auto_sub_step,
- fe->started_auto_step);
+ dprintk("%s: drift:%i bending:%i inversion:%i auto_step:%i "
+ "auto_sub_step:%i started_auto_step:%i\n",
+ __FUNCTION__, fe->lnb_drift, fe->bending, fe->inversion,
+ fe->auto_step, fe->auto_sub_step, fe->started_auto_step);
- // set the frontend itself
+ /* set the frontend itself */
fe->parameters.frequency += fe->lnb_drift + fe->bending;
if (autoinversion) fe->parameters.inversion = fe->inversion;
dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters);
fe->parameters.frequency = original_frequency;
fe->parameters.inversion = original_inversion;
- // normal return
fe->auto_sub_step++;
return 0;
}
@@ -490,10 +500,13 @@
dprintk ("%s\n", __FUNCTION__);
- snprintf (name, sizeof(name), "kdvb-fe-%i:%i",
- fe->frontend.i2c->adapter->num, fe->frontend.i2c->id);
+ snprintf (name, sizeof(name), "kdvb-fe-%i",
+ fe->frontend.dvb_adapter->num);
- dvb_kernel_thread_setup (name);
+ lock_kernel ();
+ daemonize (name);
+ sigfillset (¤t->blocked);
+ unlock_kernel ();
dvb_call_frontend_notifiers (fe, 0);
dvb_frontend_init (fe);
@@ -511,65 +524,70 @@
if (down_interruptible (&fe->sem))
break;
- // if we've got no parameters, just keep idling
+ /* if we've got no parameters, just keep idling */
if (fe->state & FESTATE_IDLE) {
delay = 3*HZ;
quality = 0;
continue;
}
- // get the frontend status
+ /* get the frontend status */
+ if (fe->state & FESTATE_RETUNE) {
+ s = 0;
+ } else {
dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s);
- if (s != fe->status)
+ if (s != fe->status) {
dvb_frontend_add_event (fe, s);
-
- // if we're not tuned, and we have a lock, move to the TUNED state
+ }
+ }
+ /* if we're not tuned, and we have a lock, move to the TUNED state */
if ((fe->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
fe->state = FESTATE_TUNED;
- // if we're tuned, then we have determined the correct inversion
- if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) && (fe->parameters.inversion == INVERSION_AUTO)) {
+ /* if we're tuned, then we have determined the correct inversion */
+ if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) &&
+ (fe->parameters.inversion == INVERSION_AUTO)) {
fe->parameters.inversion = fe->inversion;
}
continue;
}
- // if we are tuned already, check we're still locked
+ /* if we are tuned already, check we're still locked */
if (fe->state & FESTATE_TUNED) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
- // we're tuned, and the lock is still good...
- if (s & FE_HAS_LOCK) {
+ /* we're tuned, and the lock is still good... */
+ if (s & FE_HAS_LOCK)
continue;
- } else {
- // if we _WERE_ tuned, but now don't have a lock, need to zigzag
+ else {
+ /* if we _WERE_ tuned, but now don't have a lock,
+ * need to zigzag */
fe->state = FESTATE_ZIGZAG_FAST;
fe->started_auto_step = fe->auto_step;
check_wrapped = 0;
- // fallthrough
}
}
- // don't actually do anything if we're in the LOSTLOCK state, the frontend is set to
- // FE_CAN_RECOVER, and the max_drift is 0
+ /* don't actually do anything if we're in the LOSTLOCK state,
+ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
if ((fe->state & FESTATE_LOSTLOCK) &&
(fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
continue;
}
- // don't do anything if we're in the DISEQC state, since this might be someone
- // with a motorized dish controlled by DISEQC. If its actually a re-tune, there will
- // be a SET_FRONTEND soon enough.
+ /* don't do anything if we're in the DISEQC state, since this
+ * might be someone with a motorized dish controlled by DISEQC.
+ * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
if (fe->state & FESTATE_DISEQC) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
continue;
}
- // if we're in the RETUNE state, set everything up for a brand new scan,
- // keeping the current inversion setting, as the next tune is _very_ likely
- // to require the same
+ /* if we're in the RETUNE state, set everything up for a brand
+ * new scan, keeping the current inversion setting, as the next
+ * tune is _very_ likely to require the same */
if (fe->state & FESTATE_RETUNE) {
fe->lnb_drift = 0;
fe->auto_step = 0;
@@ -578,35 +596,36 @@
check_wrapped = 0;
}
- // fast zigzag.
+ /* fast zigzag. */
if ((fe->state & FESTATE_SEARCHING_FAST) || (fe->state & FESTATE_RETUNE)) {
delay = fe->min_delay;
- // peform a tune
+ /* peform a tune */
if (dvb_frontend_autotune(fe, check_wrapped)) {
- // OK, if we've run out of trials at the fast speed. Drop back to
- // slow for the _next_ attempt
+ /* OK, if we've run out of trials at the fast speed.
+ * Drop back to slow for the _next_ attempt */
fe->state = FESTATE_SEARCHING_SLOW;
fe->started_auto_step = fe->auto_step;
continue;
}
check_wrapped = 1;
- // if we've just retuned, enter the ZIGZAG_FAST state. This ensures
- // we cannot return from an FE_SET_FRONTEND ioctl before the first frontend
- // tune occurs
+ /* if we've just retuned, enter the ZIGZAG_FAST state.
+ * This ensures we cannot return from an
+ * FE_SET_FRONTEND ioctl before the first frontend tune
+ * occurs */
if (fe->state & FESTATE_RETUNE) {
fe->state = FESTATE_TUNING_FAST;
wake_up_interruptible(&fe->wait_queue);
}
}
- // slow zigzag
+ /* slow zigzag */
if (fe->state & FESTATE_SEARCHING_SLOW) {
update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
- // Note: don't bother checking for wrapping; we stay in this state
- // until we get a lock
+ /* Note: don't bother checking for wrapping; we stay in this
+ * state until we get a lock */
dvb_frontend_autotune(fe, 0);
}
};
@@ -614,8 +633,6 @@
if (dvb_shutdown_timeout)
dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL);
- up (&fe->sem);
-
fe->thread_pid = 0;
mb();
@@ -711,6 +729,11 @@
if (!fe || !fe->frontend.ioctl || fe->exit)
return -ENODEV;
+ if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
+ (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT ||
+ cmd == FE_DISEQC_RECV_SLAVE_REPLY))
+ return -EPERM;
+
if (down_interruptible (&fe->sem))
return -ERESTARTSYS;
@@ -718,6 +741,7 @@
case FE_DISEQC_SEND_MASTER_CMD:
case FE_DISEQC_SEND_BURST:
case FE_SET_TONE:
+ case FE_SET_VOLTAGE:
if (fe->status)
dvb_call_frontend_notifiers (fe, 0);
dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
@@ -734,43 +758,48 @@
memcpy(&fetunesettings.parameters, parg,
sizeof (struct dvb_frontend_parameters));
- // force auto frequency inversion if requested
+ /* force auto frequency inversion if requested */
if (dvb_force_auto_inversion) {
fe->parameters.inversion = INVERSION_AUTO;
fetunesettings.parameters.inversion = INVERSION_AUTO;
}
- // get frontend-specific tuning settings
- if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS, &fetunesettings) == 0) {
+ /* get frontend-specific tuning settings */
+ if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS,
+ &fetunesettings) == 0) {
fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
fe->max_drift = fetunesettings.max_drift;
fe->step_size = fetunesettings.step_size;
} else {
- // default values
+ /* default values */
switch(fe->info->type) {
case FE_QPSK:
- fe->min_delay = HZ/20; // default mindelay of 50ms
+ fe->min_delay = HZ/20;
fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000;
fe->max_drift = fe->parameters.u.qpsk.symbol_rate / 2000;
break;
case FE_QAM:
- fe->min_delay = HZ/20; // default mindelay of 50ms
- fe->step_size = 0;
- fe->max_drift = 0; // don't want any zigzagging under DVB-C frontends
+ fe->min_delay = HZ/20;
+ fe->step_size = 0; /* no zigzag */
+ fe->max_drift = 0;
break;
case FE_OFDM:
- fe->min_delay = HZ/20; // default mindelay of 50ms
+ fe->min_delay = HZ/20;
fe->step_size = fe->info->frequency_stepsize * 2;
fe->max_drift = (fe->info->frequency_stepsize * 2) + 1;
break;
+ case FE_ATSC:
+ printk("dvb-core: FE_ATSC not handled yet.\n");
+ break;
}
}
if (dvb_override_tune_delay > 0) {
fe->min_delay = (dvb_override_tune_delay * HZ) / 1000;
}
+ dvb_frontend_wakeup(fe);
dvb_frontend_add_event (fe, 0);
break;
@@ -789,20 +819,13 @@
if (err < 0)
return err;
- // Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't do it, it is done for it.
+ /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
+ * do it, it is done for it. */
if ((cmd == FE_GET_INFO) && (err == 0)) {
struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg;
tmp->caps |= FE_CAN_INVERSION_AUTO;
}
- // if the frontend has just been set, wait until the first tune has finished.
- // This ensures the app doesn't start reading data too quickly, perhaps from the
- // previous lock, which is REALLY CONFUSING TO DEBUG!
- if ((cmd == FE_SET_FRONTEND) && (err == 0)) {
- dvb_frontend_wakeup(fe);
- err = wait_event_interruptible(fe->wait_queue, fe->state & ~FESTATE_RETUNE);
- }
-
return err;
}
@@ -843,6 +866,11 @@
fe->events.eventr = fe->events.eventw = 0;
}
+ if (!ret && fe->module) {
+ if (!try_module_get(fe->module))
+ return -EINVAL;
+ }
+
return ret;
}
@@ -851,13 +879,19 @@
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend_data *fe = dvbdev->priv;
+ int ret = 0;
dprintk ("%s\n", __FUNCTION__);
if ((file->f_flags & O_ACCMODE) != O_RDONLY)
fe->release_jiffies = jiffies;
- return dvb_generic_release (inode, file);
+ ret = dvb_generic_release (inode, file);
+
+ if (!ret && fe->module)
+ module_put(fe->module);
+
+ return ret;
}
@@ -897,7 +931,7 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.i2c->adapter == adapter &&
+ if (fe->frontend.dvb_adapter == adapter &&
fe->frontend.before_ioctl == NULL &&
fe->frontend.after_ioctl == NULL)
{
@@ -931,7 +965,7 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.i2c->adapter == adapter &&
+ if (fe->frontend.dvb_adapter == adapter &&
fe->frontend.before_ioctl == before_ioctl &&
fe->frontend.after_ioctl == after_ioctl)
{
@@ -992,7 +1026,7 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.i2c->adapter == adapter &&
+ if (fe->frontend.dvb_adapter == adapter &&
fe->frontend.notifier_callback == NULL)
{
fe->frontend.notifier_callback = callback;
@@ -1021,7 +1055,7 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.i2c->adapter == adapter &&
+ if (fe->frontend.dvb_adapter == adapter &&
fe->frontend.notifier_callback == callback)
{
fe->frontend.notifier_callback = NULL;
@@ -1061,9 +1093,10 @@
int
dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
unsigned int cmd, void *arg),
- struct dvb_i2c_bus *i2c,
+ struct dvb_adapter *dvb_adapter,
void *data,
- struct dvb_frontend_info *info)
+ struct dvb_frontend_info *info,
+ struct module *module)
{
struct list_head *entry;
struct dvb_frontend_data *fe;
@@ -1093,9 +1126,10 @@
init_MUTEX (&fe->events.sem);
fe->events.eventw = fe->events.eventr = 0;
fe->events.overflow = 0;
+ fe->module = module;
fe->frontend.ioctl = ioctl;
- fe->frontend.i2c = i2c;
+ fe->frontend.dvb_adapter = dvb_adapter;
fe->frontend.data = data;
fe->info = info;
fe->inversion = INVERSION_OFF;
@@ -1107,7 +1141,7 @@
struct dvb_frontend_ioctl_data,
list_head);
- if (ioctl->adapter == i2c->adapter) {
+ if (ioctl->adapter == dvb_adapter) {
fe->frontend.before_ioctl = ioctl->before_ioctl;
fe->frontend.after_ioctl = ioctl->after_ioctl;
fe->frontend.before_after_data = ioctl->before_after_data;
@@ -1122,7 +1156,7 @@
struct dvb_frontend_notifier_data,
list_head);
- if (notifier->adapter == i2c->adapter) {
+ if (notifier->adapter == dvb_adapter) {
fe->frontend.notifier_callback = notifier->callback;
fe->frontend.notifier_data = notifier->data;
break;
@@ -1131,11 +1165,11 @@
list_add_tail (&fe->list_head, &frontend_list);
- printk ("DVB: registering frontend %i:%i (%s)...\n",
- fe->frontend.i2c->adapter->num, fe->frontend.i2c->id,
+ printk ("DVB: registering frontend %i (%s)...\n",
+ fe->frontend.dvb_adapter->num,
fe->info->name);
- dvb_register_device (i2c->adapter, &fe->dvbdev, &dvbdev_template,
+ dvb_register_device (dvb_adapter, &fe->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND);
if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2))
@@ -1146,10 +1179,9 @@
return 0;
}
-
-int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
+int dvb_unregister_frontend_new (int (*ioctl) (struct dvb_frontend *frontend,
unsigned int cmd, void *arg),
- struct dvb_i2c_bus *i2c)
+ struct dvb_adapter *dvb_adapter)
{
struct list_head *entry, *n;
@@ -1162,7 +1194,7 @@
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.ioctl == ioctl && fe->frontend.i2c == i2c) {
+ if (fe->frontend.ioctl == ioctl && fe->frontend.dvb_adapter == dvb_adapter) {
dvb_unregister_device (fe->dvbdev);
list_del (entry);
up (&frontend_mutex);
@@ -1176,14 +1208,3 @@
return -EINVAL;
}
-MODULE_PARM(dvb_frontend_debug,"i");
-MODULE_PARM(dvb_shutdown_timeout,"i");
-MODULE_PARM(dvb_override_frequency_bending,"i");
-MODULE_PARM(dvb_force_auto_inversion,"i");
-MODULE_PARM(dvb_override_tune_delay,"i");
-
-MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages");
-MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
-MODULE_PARM_DESC(dvb_override_frequency_bending, "0: normal (default), 1: never use frequency bending, 2: always use frequency bending");
-MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
-MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_frontend.h linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_frontend.h
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_frontend.h 2004-07-19 19:40:04.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_frontend.h 2004-08-18 19:52:17.000000000 +0200
@@ -31,14 +34,29 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/delay.h>
#include <linux/dvb/frontend.h>
-#include "dvb_i2c.h"
#include "dvbdev.h"
-
-
+/* FIXME: Move to i2c-id.h */
+#define I2C_DRIVERID_DVBFE_ALPS_TDLB7 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_ALPS_TDMB7 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_AT76C651 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_CX24110 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_DST I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_DUMMY I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_L64781 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_MT312 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_MT352 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_NXT6000 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_SP887X I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_STV0299 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_TDA1004X I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_TDA8083 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_VES1820 I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_VES1X93 I2C_DRIVERID_EXP2
/**
* when before_ioctl is registered and returns value 0, ioctl and after_ioctl
@@ -50,7 +68,7 @@
int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
void (*notifier_callback) (fe_status_t s, void *data);
- struct dvb_i2c_bus *i2c;
+ struct dvb_adapter *dvb_adapter;
void *before_after_data; /* can be used by hardware module... */
void *notifier_data; /* can be used by hardware module... */
void *data; /* can be used by hardware module... */
@@ -75,19 +93,21 @@
#define FE_SLEEP _IO('v', 80)
#define FE_INIT _IO('v', 81)
#define FE_GET_TUNE_SETTINGS _IOWR('v', 83, struct dvb_frontend_tune_settings)
-
+#define FE_REGISTER _IO ('v', 84)
+#define FE_UNREGISTER _IO ('v', 85)
extern int
dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
unsigned int cmd, void *arg),
- struct dvb_i2c_bus *i2c,
+ struct dvb_adapter *dvb_adapter,
void *data,
- struct dvb_frontend_info *info);
+ struct dvb_frontend_info *info,
+ struct module *module);
extern int
-dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
+dvb_unregister_frontend_new (int (*ioctl) (struct dvb_frontend *frontend,
unsigned int cmd, void *arg),
- struct dvb_i2c_bus *i2c);
+ struct dvb_adapter *dvb_adapter);
/**
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_ksyms.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ksyms.c
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/dvb_ksyms.c 2004-07-19 19:40:04.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ksyms.c 2004-08-18 19:52:17.000000000 +0200
@@ -24,17 +24,12 @@
EXPORT_SYMBOL(dvbdmx_disconnect_frontend);
EXPORT_SYMBOL(dvb_register_frontend);
-EXPORT_SYMBOL(dvb_unregister_frontend);
+EXPORT_SYMBOL(dvb_unregister_frontend_new);
EXPORT_SYMBOL(dvb_add_frontend_ioctls);
EXPORT_SYMBOL(dvb_remove_frontend_ioctls);
EXPORT_SYMBOL(dvb_add_frontend_notifier);
EXPORT_SYMBOL(dvb_remove_frontend_notifier);
-EXPORT_SYMBOL(dvb_register_i2c_bus);
-EXPORT_SYMBOL(dvb_unregister_i2c_bus);
-EXPORT_SYMBOL(dvb_register_i2c_device);
-EXPORT_SYMBOL(dvb_unregister_i2c_device);
-
EXPORT_SYMBOL(dvb_net_init);
EXPORT_SYMBOL(dvb_net_release);
diff -uraNwB xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/Makefile linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/Makefile
--- xx-linux-2.6.8.1/drivers/media/dvb/dvb-core/Makefile 2004-07-19 19:40:04.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/Makefile 2004-08-18 19:44:05.000000000 +0200
@@ -3,7 +3,7 @@
#
dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
- dvb_ca_en50221.o dvb_functions.o dvb_frontend.o \
- dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o
+ dvb_ca_en50221.o dvb_frontend.o \
+ dvb_net.o dvb_ksyms.o dvb_ringbuffer.o
obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff -uraN a/drivers/media/dvb/dvb-core/dvb_functions.c b/drivers/media/dvb/dvb-core/dvb_functions.c
--- a/drivers/media/dvb/dvb-core/dvb_functions.c 2004-08-24 16:34:45.000000000 +0200
+++ b/drivers/media/dvb/dvb-core/dvb_functions.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,89 +0,0 @@
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-
-void dvb_kernel_thread_setup (const char *thread_name)
-{
- lock_kernel ();
-
- daemonize (thread_name);
-
- sigfillset (¤t->blocked);
-
- unlock_kernel ();
-}
-
-/* if the miracle happens and "generic_usercopy()" is included into
- the kernel, then this can vanish. please don't make the mistake and
- define this as video_usercopy(). this will introduce a dependecy
- to the v4l "videodev.o" module, which is unnecessary for some
- cards (ie. the budget dvb-cards don't need the v4l module...) */
-int dvb_usercopy(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- int (*func)(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg))
-{
- char sbuf[128];
- void *mbuf = NULL;
- void *parg = NULL;
- int err = -EINVAL;
-
- /* Copy arguments into temp kernel buffer */
- switch (_IOC_DIR(cmd)) {
- case _IOC_NONE:
- /*
- * For this command, the pointer is actually an integer
- * argument.
- */
- parg = (void *) arg;
- break;
- case _IOC_READ: /* some v4l ioctls are marked wrong ... */
- case _IOC_WRITE:
- case (_IOC_WRITE | _IOC_READ):
- if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
- parg = sbuf;
- } else {
- /* too big to allocate from stack */
- mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
- if (NULL == mbuf)
- return -ENOMEM;
- parg = mbuf;
- }
-
- err = -EFAULT;
- if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
- goto out;
- break;
- }
-
- /* call driver */
- if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD)
- err = -EINVAL;
-
- if (err < 0)
- goto out;
-
- /* Copy results into user buffer */
- switch (_IOC_DIR(cmd))
- {
- case _IOC_READ:
- case (_IOC_WRITE | _IOC_READ):
- if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
- err = -EFAULT;
- break;
- }
-
-out:
- if (mbuf)
- kfree(mbuf);
-
- return err;
-}
-
-EXPORT_SYMBOL(dvb_usercopy);
-EXPORT_SYMBOL(dvb_kernel_thread_setup);
diff -uraN a/drivers/media/dvb/dvb-core/dvb_functions.h b/drivers/media/dvb/dvb-core/dvb_functions.h
--- a/drivers/media/dvb/dvb-core/dvb_functions.h 2004-08-24 16:34:45.000000000 +0200
+++ b/drivers/media/dvb/dvb-core/dvb_functions.h 1970-01-01 01:00:00.000000000 +0100
@@ -1,50 +0,0 @@
-/*
- * dvb_functions.h: isolate some Linux specific stuff from the dvb-core
- * that can't be expressed as a one-liner
- * in order to make porting to other environments easier
- *
- * Copyright (C) 2003 Convergence GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- */
-
-#ifndef __DVB_FUNCTIONS_H__
-#define __DVB_FUNCTIONS_H__
-
-/**
- * a sleeping delay function, waits i ms
- *
- */
-static inline
-void dvb_delay(int i)
-{
- current->state=TASK_INTERRUPTIBLE;
- schedule_timeout((HZ*i)/1000);
-}
-
-/* we don't mess with video_usercopy() any more,
-we simply define out own dvb_usercopy(), which will hopefull become
-generic_usercopy() someday... */
-
-extern int dvb_usercopy(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg,
- int (*func)(struct inode *inode, struct file *file,
- unsigned int cmd, void *arg));
-
-extern void dvb_kernel_thread_setup (const char *thread_name);
-
-#endif
-
diff -uraN a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c
--- a/drivers/media/dvb/dvb-core/dvb_i2c.c 2004-08-24 16:34:51.000000000 +0200
+++ b/drivers/media/dvb/dvb-core/dvb_i2c.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,290 +0,0 @@
-/*
- * dvb_i2c.h: simplified i2c interface for DVB adapters to get rid of i2c-core.c
- *
- * Copyright (C) 2002 Holger Waechtler for convergence integrated media GmbH
- *
- * 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; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <asm/semaphore.h>
-
-#include "dvb_i2c.h"
-#include "dvb_functions.h"
-
-
-struct dvb_i2c_device {
- struct list_head list_head;
- struct module *owner;
- int (*attach) (struct dvb_i2c_bus *i2c, void **data);
- void (*detach) (struct dvb_i2c_bus *i2c, void *data);
- void *data;
-};
-
-LIST_HEAD(dvb_i2c_buslist);
-LIST_HEAD(dvb_i2c_devicelist);
-
-DECLARE_MUTEX(dvb_i2c_mutex);
-
-static int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
-{
- struct dvb_i2c_device *client;
-
- if (!(client = kmalloc (sizeof (struct dvb_i2c_device), GFP_KERNEL)))
- return -ENOMEM;
-
- client->detach = dev->detach;
- client->owner = dev->owner;
- client->data = dev->data;
-
- INIT_LIST_HEAD(&client->list_head);
-
- list_add_tail (&client->list_head, &i2c->client_list);
-
- return 0;
-}
-
-
-static void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
-{
- if (dev->owner) {
- if (!try_module_get(dev->owner))
- return;
- }
-
- if (dev->attach (i2c, &dev->data) == 0) {
- register_i2c_client (i2c, dev);
- } else {
- if (dev->owner)
- module_put (dev->owner);
- }
-}
-
-
-static void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
-{
- dev->detach (i2c, dev->data);
-
- if (dev->owner)
- module_put (dev->owner);
-}
-
-
-static void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev,
- struct dvb_i2c_bus *i2c)
-{
- struct list_head *entry, *n;
-
- list_for_each_safe (entry, n, &i2c->client_list) {
- struct dvb_i2c_device *client;
-
- client = list_entry (entry, struct dvb_i2c_device, list_head);
-
- if (client->detach == dev->detach) {
- list_del (entry);
- detach_device (i2c, dev);
- }
- }
-}
-
-
-static void unregister_i2c_client_from_all_busses (struct dvb_i2c_device *dev)
-{
- struct list_head *entry, *n;
-
- list_for_each_safe (entry, n, &dvb_i2c_buslist) {
- struct dvb_i2c_bus *i2c;
-
- i2c = list_entry (entry, struct dvb_i2c_bus, list_head);
-
- unregister_i2c_client_from_bus (dev, i2c);
- }
-}
-
-
-static void unregister_all_clients_from_bus (struct dvb_i2c_bus *i2c)
-{
- struct list_head *entry, *n;
-
- list_for_each_safe (entry, n, &(i2c->client_list)) {
- struct dvb_i2c_device *dev;
-
- dev = list_entry (entry, struct dvb_i2c_device, list_head);
-
- unregister_i2c_client_from_bus (dev, i2c);
- }
-}
-
-
-static void probe_device_on_all_busses (struct dvb_i2c_device *dev)
-{
- struct list_head *entry;
-
- list_for_each (entry, &dvb_i2c_buslist) {
- struct dvb_i2c_bus *i2c;
-
- i2c = list_entry (entry, struct dvb_i2c_bus, list_head);
-
- try_attach_device (i2c, dev);
- }
-}
-
-
-static void probe_devices_on_bus (struct dvb_i2c_bus *i2c)
-{
- struct list_head *entry;
-
- list_for_each (entry, &dvb_i2c_devicelist) {
- struct dvb_i2c_device *dev;
-
- dev = list_entry (entry, struct dvb_i2c_device, list_head);
-
- try_attach_device (i2c, dev);
- }
-}
-
-
-static struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
- const struct i2c_msg msgs[],
- int num),
- struct dvb_adapter *adapter,
- int id)
-{
- struct list_head *entry;
-
- list_for_each (entry, &dvb_i2c_buslist) {
- struct dvb_i2c_bus *i2c;
-
- i2c = list_entry (entry, struct dvb_i2c_bus, list_head);
-
- if (i2c->xfer == xfer && i2c->adapter == adapter && i2c->id == id)
- return i2c;
- }
-
- return NULL;
-}
-
-
-struct dvb_i2c_bus*
-dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
- const struct i2c_msg *msgs, int num),
- void *data, struct dvb_adapter *adapter, int id)
-{
- struct dvb_i2c_bus *i2c;
-
- if (down_interruptible (&dvb_i2c_mutex))
- return NULL;
-
- if (!(i2c = kmalloc (sizeof (struct dvb_i2c_bus), GFP_KERNEL))) {
- up (&dvb_i2c_mutex);
- return NULL;
- }
-
- INIT_LIST_HEAD(&i2c->list_head);
- INIT_LIST_HEAD(&i2c->client_list);
-
- i2c->xfer = xfer;
- i2c->data = data;
- i2c->adapter = adapter;
- i2c->id = id;
-
- probe_devices_on_bus (i2c);
-
- list_add_tail (&i2c->list_head, &dvb_i2c_buslist);
-
- up (&dvb_i2c_mutex);
-
- return i2c;
-}
-
-
-void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
- const struct i2c_msg msgs[], int num),
- struct dvb_adapter *adapter, int id)
-{
- struct dvb_i2c_bus *i2c;
-
- down (&dvb_i2c_mutex);
-
- if ((i2c = dvb_find_i2c_bus (xfer, adapter, id))) {
- unregister_all_clients_from_bus (i2c);
- list_del (&i2c->list_head);
- kfree (i2c);
- }
-
- up (&dvb_i2c_mutex);
-}
-
-
-int dvb_register_i2c_device (struct module *owner,
- int (*attach) (struct dvb_i2c_bus *i2c, void **data),
- void (*detach) (struct dvb_i2c_bus *i2c, void *data))
-{
- struct dvb_i2c_device *entry;
-
- if (down_interruptible (&dvb_i2c_mutex))
- return -ERESTARTSYS;
-
- if (!(entry = kmalloc (sizeof (struct dvb_i2c_device), GFP_KERNEL))) {
- up(&dvb_i2c_mutex);
- return -ENOMEM;
- }
-
- entry->owner = owner;
- entry->attach = attach;
- entry->detach = detach;
-
- INIT_LIST_HEAD(&entry->list_head);
-
- probe_device_on_all_busses (entry);
-
- list_add_tail (&entry->list_head, &dvb_i2c_devicelist);
-
- up (&dvb_i2c_mutex);
-
- return 0;
-}
-
-
-int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c, void **data))
-{
- struct list_head *entry, *n;
-
- down (&dvb_i2c_mutex);
-
- list_for_each_safe (entry, n, &dvb_i2c_devicelist) {
- struct dvb_i2c_device *dev;
-
- dev = list_entry (entry, struct dvb_i2c_device, list_head);
-
- if (dev->attach == attach) {
- list_del (entry);
- unregister_i2c_client_from_all_busses (dev);
- kfree (entry);
- up (&dvb_i2c_mutex);
- return 0;
- }
- }
-
- up (&dvb_i2c_mutex);
-
- return -EINVAL;
-}
-
-
diff -uraN a/drivers/media/dvb/dvb-core/dvb_i2c.h b/drivers/media/dvb/dvb-core/dvb_i2c.h
--- a/drivers/media/dvb/dvb-core/dvb_i2c.h 2004-08-24 16:34:51.000000000 +0200
+++ b/drivers/media/dvb/dvb-core/dvb_i2c.h 1970-01-01 01:00:00.000000000 +0100
@@ -1,63 +0,0 @@
-/*
- * dvb_i2c.h: i2c interface to get rid of i2c-core.c
- *
- * Copyright (C) 2002 Holger Waechtler for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DVB_I2C_H_
-#define _DVB_I2C_H_
-
-#include <linux/list.h>
-#include <linux/i2c.h>
-
-#include "dvbdev.h"
-
-
-struct dvb_i2c_bus {
- struct list_head list_head;
- int (*xfer) (struct dvb_i2c_bus *i2c,
- const struct i2c_msg msgs[],
- int num);
- void *data;
- struct dvb_adapter *adapter;
- int id;
- struct list_head client_list;
-};
-
-
-extern struct dvb_i2c_bus*
-dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
- const struct i2c_msg *msgs, int num),
- void *data,
- struct dvb_adapter *adapter,
- int id);
-
-extern
-void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c,
- const struct i2c_msg msgs[], int num),
- struct dvb_adapter *adapter,
- int id);
-
-
-extern int dvb_register_i2c_device (struct module *owner,
- int (*attach) (struct dvb_i2c_bus *i2c, void **data),
- void (*detach) (struct dvb_i2c_bus *i2c, void *data));
-
-extern int dvb_unregister_i2c_device (int (*attach) (struct dvb_i2c_bus *i2c, void **data));
-
-#endif
-
diff -uraNwB xx-linux-2.6.8.1/include/linux/dvb/frontend.h linux-2.6.8.1-patched/include/linux/dvb/frontend.h
--- xx-linux-2.6.8.1/include/linux/dvb/frontend.h 2004-07-19 19:39:37.000000000 +0200
+++ linux-2.6.8.1-patched/include/linux/dvb/frontend.h 2004-08-05 20:28:20.000000000 +0200
@@ -32,7 +32,8 @@
typedef enum fe_type {
FE_QPSK,
FE_QAM,
- FE_OFDM
+ FE_OFDM,
+ FE_ATSC
} fe_type_t;
@@ -59,6 +60,8 @@
FE_CAN_BANDWIDTH_AUTO = 0x40000,
FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
FE_CAN_HIERARCHY_AUTO = 0x100000,
+ FE_CAN_8VSB = 0x200000,
+ FE_CAN_16VSB = 0x400000,
FE_NEEDS_BENDING = 0x20000000, // frontend requires frequency bending
FE_CAN_RECOVER = 0x40000000, // frontend can recover from a cable unplug automatically
FE_CAN_MUTE_TS = 0x80000000 // frontend can stop spurious TS data output
diff -uraNwB linux-2.6.8.1-dvb1/drivers/media/dvb/dvb-core/dvb_ca_en50221.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
--- linux-2.6.8.1-dvb1/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2004-09-17 12:26:16.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_ca_en50221.c 2004-09-01 12:19:01.000000000 +0200
@@ -35,8 +35,7 @@
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
-#include <asm/rwsem.h>
-#include <asm/atomic.h>
+#include <linux/rwsem.h>
#include "dvb_ca_en50221.h"
#include "dvb_ringbuffer.h"
@@ -44,7 +43,7 @@
static int dvb_ca_en50221_debug;
module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644);
-MODULE_PARM_DESC(dvb_ca_en50221_debug, "enable verbose debug messages");
+MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
#define dprintk if (dvb_ca_en50221_debug) printk
@@ -307,10 +306,6 @@
/* we'll be determining these during this function */
ca->slot_info[slot].da_irq_supported = 0;
- /* reset the link interface. Note CAM IRQs are disabled */
- if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS)) != 0) return ret;
- if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ/10)) != 0) return ret;
-
/* set the host link buffer size temporarily. it will be overwritten with the
* real negotiated size later. */
ca->slot_info[slot].link_buf_size = 2;
@@ -460,8 +455,8 @@
/* is it a version we support? */
if (strncmp(dvb_str + 8, "1.00", 4)) {
- printk("dvb_ca: Unsupported DVB CAM module version %c%c%c%c\n",
- dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);
+ printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
+ ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);
return -EINVAL;
}
@@ -589,20 +584,20 @@
/* check it will fit */
if (ebuf == NULL) {
if (bytes_read > ca->slot_info[slot].link_buf_size) {
- printk("dvb_ca: CAM tried to send a buffer larger than the link buffer size!\n");
+ printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size!\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
status = -EIO;
goto exit;
}
if (bytes_read < 2) {
- printk("dvb_ca: CAM sent a buffer that was less than 2 bytes!\n");
+ printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
status = -EIO;
goto exit;
}
} else {
if (bytes_read > ecount) {
- printk("dvb_ca: CAM tried to send a buffer larger than the ecount size!\n");
+ printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", ca->dvbdev->adapter->num);
status = -EIO;
goto exit;
}
@@ -984,7 +978,7 @@
case DVB_CA_SLOTSTATE_WAITREADY:
if (time_after(jiffies, ca->slot_info[slot].timeout)) {
- printk("dvb_ca: PC card did not respond :(\n");
+ printk("dvb_ca adaptor %d: PC card did not respond :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
@@ -993,20 +987,20 @@
break;
case DVB_CA_SLOTSTATE_VALIDATE:
- if (ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS) != 0) {
- printk("dvb_ca: Unable to reset CAM IF\n");
+ if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
+ printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
}
- if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
- printk("dvb_ca: Invalid PC card inserted :(\n");
+ if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
+ printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
}
- if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
- printk("dvb_ca: Unable to initialise CAM :(\n");
+ if (ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS) != 0) {
+ printk("dvb_ca adapter %d: Unable to reset CAM IF\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
@@ -1021,7 +1014,7 @@
case DVB_CA_SLOTSTATE_WAITFR:
if (time_after(jiffies, ca->slot_info[slot].timeout)) {
- printk("dvb_ca: DVB CAM did not respond :(\n");
+ printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
@@ -1036,7 +1029,7 @@
case DVB_CA_SLOTSTATE_LINKINIT:
if (dvb_ca_en50221_link_init(ca, slot) != 0) {
- printk("dvb_ca: DVB CAM link initialisation failed :(\n");
+ printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
@@ -1044,7 +1037,7 @@
rxbuf = vmalloc(RX_BUFFER_SIZE);
if (rxbuf == NULL) {
- printk("dvb_ca: Unable to allocate CAM rx buffer :(\n");
+ printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break;
@@ -1054,7 +1047,7 @@
ca->pub->slot_ts_enable(ca->pub, slot);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
dvb_ca_en50221_thread_update_delay(ca);
- printk("dvb_ca: DVB CAM detected and initialised successfully\n");
+ printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num);
break;
case DVB_CA_SLOTSTATE_RUNNING:
@@ -1351,7 +1344,7 @@
pktlen = 2;
do {
if (idx == -1) {
- printk("dvb_ca: BUG: read packet ended before last_fragment encountered\n");
+ printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num);
status = -EIO;
goto exit;
}
@@ -1617,7 +1612,7 @@
/* shutdown the thread if there was one */
if (ca->thread_pid) {
if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
- printk("dvb_ca_release: thread PID %d already died\n", ca->thread_pid);
+ printk("dvb_ca_release adapter %d: thread PID %d already died\n", ca->dvbdev->adapter->num, ca->thread_pid);
} else {
ca->exit = 1;
mb();
diff -uraNwB linux-2.6.8.1-dvb1/drivers/media/dvb/dvb-core/dvb_demux.c linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_demux.c
--- linux-2.6.8.1-dvb1/drivers/media/dvb/dvb-core/dvb_demux.c 2004-09-17 12:26:16.000000000 +0200
+++ linux-2.6.8.1-patched/drivers/media/dvb/dvb-core/dvb_demux.c 2004-09-15 10:26:44.000000000 +0200
@@ -569,7 +570,7 @@
static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
{
- spin_lock(&feed->demux->lock);
+ spin_lock_irq(&feed->demux->lock);
if (dvb_demux_feed_find(feed)) {
printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
@@ -578,12 +579,12 @@
list_add(&feed->list_head, &feed->demux->feed_list);
out:
- spin_unlock(&feed->demux->lock);
+ spin_unlock_irq(&feed->demux->lock);
}
static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
{
- spin_lock(&feed->demux->lock);
+ spin_lock_irq(&feed->demux->lock);
if (!(dvb_demux_feed_find(feed))) {
printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
__FUNCTION__, feed->type, feed->state, feed->pid);
@@ -592,7 +593,7 @@
list_del(&feed->list_head);
out:
- spin_unlock(&feed->demux->lock);
+ spin_unlock_irq(&feed->demux->lock);
}
static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type,
diff -uraN a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
--- a/drivers/media/dvb/dvb-core/dvb_net.c 2004-09-17 14:31:22.000000000 +0200
+++ b/drivers/media/dvb/dvb-core/dvb_net.c 2004-09-17 14:31:34.000000000 +0200
@@ -40,8 +40,6 @@
#include "dvb_demux.h"
#include "dvb_net.h"
-#include "dvb_functions.h"
-
static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
{
next prev parent reply other threads:[~2004-09-17 14:42 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-09-17 14:20 [PATCH][2.6][0/14] DVB subsystem update Michael Hunold
2004-09-17 14:22 ` [PATCH][2.6][1/14] update saa7146 driver Michael Hunold
2004-09-17 14:24 ` [PATCH][2.6][2/14] documentation update Michael Hunold
2004-09-17 14:26 ` [PATCH][2.6][3/14] dvb-bt8xx and skystar2 driver update Michael Hunold
2004-09-17 14:27 ` Michael Hunold [this message]
2004-09-17 14:29 ` [PATCH][2.6][5/14] convert frontend drivers to kernel i2c 1/3 Michael Hunold
2004-09-17 14:30 ` [PATCH][2.6][6/14] convert frontend drivers to kernel i2c 2/3 Michael Hunold
2004-09-17 14:32 ` [PATCH][2.6][7/14] convert frontend drivers to kernel i2c 3/3 Michael Hunold
2004-09-17 14:33 ` [PATCH][2.6][8/14] some more frontend drivers to converted to kernel i2c Michael Hunold
2004-09-17 14:34 ` [PATCH][2.6][9/14] add new frontend drivers 1/2 Michael Hunold
2004-09-17 14:36 ` [PATCH][2.6][10/14] add new frontend drivers 2/2 Michael Hunold
2004-09-17 14:37 ` [PATCH][2.6][11/14] new DVB driver Michael Hunold
2004-09-17 14:39 ` [PATCH][2.6][12/14] misc. driver updates Michael Hunold
2004-09-17 14:40 ` [PATCH][2.6][13/14] dvb frontend updates Michael Hunold
2004-09-17 14:42 ` [PATCH][2.6][14/14] follow saa7146 changes in other drivers Michael Hunold
2004-09-20 11:11 ` [PATCH][2.6][12.1/14] DVB: add kernel message classifiers Philipp Matthias Hahn
2004-09-20 16:46 ` Michael Hunold
2004-09-17 14:58 ` [PATCH][2.6][4/14] dvb core update Jesper Juhl
2004-09-17 15:35 ` Linus Torvalds
2004-09-17 15:58 ` Alan Cox
2004-09-17 15:28 ` Richard B. Johnson
2004-09-17 23:41 ` [PATCH][2.6][0/14] DVB subsystem update Andrew Morton
2004-09-20 11:42 ` Michael Hunold
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=414AF461.4050707@linuxtv.org \
--to=hunold@linuxtv.org \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.