summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb
diff options
context:
space:
mode:
authorHolger Waechtler <devnull@localhost>2002-11-15 14:36:18 +0000
committerHolger Waechtler <devnull@localhost>2002-11-15 14:36:18 +0000
commit95d59f27fe9a34fe457ba3313f845a4cb9a80cd6 (patch)
tree32c9e4b84aa42227a41fa1f428d323714e28675e /linux/drivers/media/dvb
parentfa11322bf2bcab6d953b79dc6fa61ce9cb8ff4df (diff)
downloadmediapointer-dvb-s2-95d59f27fe9a34fe457ba3313f845a4cb9a80cd6.tar.gz
mediapointer-dvb-s2-95d59f27fe9a34fe457ba3313f845a4cb9a80cd6.tar.bz2
frontend notification fixes by Florian Schirmer
Diffstat (limited to 'linux/drivers/media/dvb')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.c131
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_frontend.h2
2 files changed, 86 insertions, 47 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
index 1d0bdd5bc..614fa281b 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -52,18 +52,10 @@ struct dvb_fe_events {
};
-struct dvb_fe_notifier_callbacks {
- struct list_head list_head;
- void (*callback) (fe_status_t s, void *data);
- void *data;
-};
-
-
struct dvb_frontend_data {
struct dvb_frontend_info *info;
struct dvb_frontend frontend;
struct dvb_device *dvbdev;
- struct list_head notifier_callbacks;
struct dvb_frontend_parameters parameters;
struct dvb_fe_events events;
struct semaphore sem;
@@ -92,8 +84,17 @@ struct dvb_frontend_ioctl_data {
};
+struct dvb_frontend_notifier_data {
+ struct list_head list_head;
+ struct dvb_adapter *adapter;
+ void (*callback) (fe_status_t s, void *data);
+ void *data;
+};
+
+
static LIST_HEAD(frontend_list);
static LIST_HEAD(frontend_ioctl_list);
+static LIST_HEAD(frontend_notifier_list);
static DECLARE_MUTEX(frontend_mutex);
@@ -192,9 +193,6 @@ static
void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe,
fe_status_t s)
{
- struct list_head *e;
- struct dvb_fe_notifier_callbacks *c;
-
dprintk ("%s\n", __FUNCTION__);
if ((fe->status & FE_HAS_LOCK) && !(s & FE_HAS_LOCK))
@@ -211,10 +209,8 @@ void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe,
/**
* now tell the Demux about the TS status changes...
*/
- list_for_each (e, &fe->notifier_callbacks) {
- c = list_entry (e, struct dvb_fe_notifier_callbacks, list_head);
- c->callback (fe->status, c->data);
- }
+ if (fe->frontend.notifier_callback)
+ fe->frontend.notifier_callback(fe->status, fe->frontend.notifier_data);
}
@@ -472,7 +468,7 @@ int dvb_frontend_thread (void *data)
fe->lost_sync_count = 0;
} else {
fe->lost_sync_count++;
- if (fe->lost_sync_count < 10) /* XXX FIXME CHECKME! */
+ if (fe->lost_sync_count < 4) /* XXX FIXME CHECKME! */
continue;
dvb_frontend_recover (fe);
delay = HZ/5;
@@ -686,7 +682,7 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
int (*after_ioctl) (struct dvb_frontend *frontend,
unsigned int cmd, void *arg))
{
- struct list_head *entry;
+ struct list_head *entry, *n;
dprintk ("%s\n", __FUNCTION__);
@@ -708,6 +704,22 @@ dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
}
}
+ list_for_each_safe (entry, n, &frontend_ioctl_list) {
+ struct dvb_frontend_ioctl_data *ioctl;
+
+ ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head);
+
+ if (ioctl->adapter == adapter &&
+ ioctl->before_ioctl == before_ioctl &&
+ ioctl->after_ioctl == after_ioctl)
+ {
+ list_del (&ioctl->list_head);
+ kfree (ioctl);
+
+ break;
+ }
+ }
+
up (&frontend_mutex);
}
@@ -717,41 +729,45 @@ dvb_add_frontend_notifier (struct dvb_adapter *adapter,
void (*callback) (fe_status_t s, void *data),
void *data)
{
- struct list_head *entry;
+ struct dvb_frontend_notifier_data *notifier;
+ struct list_head *entry;
+ int frontend_count = 0;
dprintk ("%s\n", __FUNCTION__);
if (down_interruptible (&frontend_mutex))
return -ERESTARTSYS;
- list_for_each (entry, &frontend_list) {
- struct dvb_frontend_data *fe;
+ notifier = kmalloc (sizeof(struct dvb_frontend_notifier_data), GFP_KERNEL);
- fe = list_entry (entry, struct dvb_frontend_data, list_head);
+ if (!notifier) {
+ up (&frontend_mutex);
+ return -ENOMEM;
+ }
- if (fe->frontend.i2c->adapter == adapter) {
- struct dvb_fe_notifier_callbacks *e;
+ notifier->adapter = adapter;
+ notifier->callback = callback;
+ notifier->data = data;
- e = kmalloc (sizeof(struct dvb_fe_notifier_callbacks),
- GFP_KERNEL);
+ list_add_tail (&notifier->list_head, &frontend_notifier_list);
- if (!e) {
- up (&frontend_mutex);
- return -ENOMEM;
- }
+ list_for_each (entry, &frontend_list) {
+ struct dvb_frontend_data *fe;
- e->callback = callback;
- e->data = data;
- list_add_tail (&e->list_head, &fe->notifier_callbacks);
+ fe = list_entry (entry, struct dvb_frontend_data, list_head);
- up (&frontend_mutex);
- return 0;
+ if (fe->frontend.i2c->adapter == adapter &&
+ fe->frontend.notifier_callback == NULL)
+ {
+ fe->frontend.notifier_callback = callback;
+ fe->frontend.notifier_data = data;
+ frontend_count++;
}
}
up (&frontend_mutex);
- return -ENODEV;
+ return frontend_count;
}
@@ -759,7 +775,7 @@ void
dvb_remove_frontend_notifier (struct dvb_adapter *adapter,
void (*callback) (fe_status_t s, void *data))
{
- struct list_head *entry;
+ struct list_head *entry, *n;
dprintk ("%s\n", __FUNCTION__);
@@ -771,18 +787,26 @@ dvb_remove_frontend_notifier (struct dvb_adapter *adapter,
fe = list_entry (entry, struct dvb_frontend_data, list_head);
- if (fe->frontend.i2c->adapter == adapter) {
- struct list_head *e0, *n0;
+ if (fe->frontend.i2c->adapter == adapter &&
+ fe->frontend.notifier_callback == callback)
+ {
+ fe->frontend.notifier_callback = NULL;
- list_for_each_safe (e0, n0, &fe->notifier_callbacks) {
- struct dvb_fe_notifier_callbacks *e;
+ }
+ }
- e = list_entry (e0,
- struct dvb_fe_notifier_callbacks,
- list_head);
- list_del (&e->list_head);
- kfree (e);
- }
+ list_for_each_safe (entry, n, &frontend_notifier_list) {
+ struct dvb_frontend_notifier_data *notifier;
+
+ notifier = list_entry (entry, struct dvb_frontend_notifier_data, list_head);
+
+ if (notifier->adapter == adapter &&
+ notifier->callback == callback)
+ {
+ list_del (&notifier->list_head);
+ kfree (notifier);
+
+ break;
}
}
@@ -835,7 +859,6 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
init_MUTEX (&fe->events.sem);
fe->events.eventw = fe->events.eventr = 0;
fe->events.overflow = 0;
- INIT_LIST_HEAD (&fe->notifier_callbacks);
fe->frontend.ioctl = ioctl;
fe->frontend.i2c = i2c;
@@ -857,6 +880,20 @@ dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
}
}
+ list_for_each (entry, &frontend_notifier_list) {
+ struct dvb_frontend_notifier_data *notifier;
+
+ notifier = list_entry (entry,
+ struct dvb_frontend_notifier_data,
+ list_head);
+
+ if (notifier->adapter == i2c->adapter) {
+ fe->frontend.notifier_callback = notifier->callback;
+ fe->frontend.notifier_data = notifier->data;
+ break;
+ }
+ }
+
list_add_tail (&fe->list_head, &frontend_list);
printk ("DVB: registering frontend %i:%i (%s)...\n",
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
index 5c1950022..03a37b946 100644
--- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -52,8 +52,10 @@ struct dvb_frontend {
int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
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;
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... */
};