Tim Connors wrote:
> On Sat, 26 Apr 2003, David Atkinson wrote:
>
>
>>Probably a software artifact due to the fact the gpio register is
>>polled. This has been fixed in the latest version, which uses interrupts
>>instead of polling, available here:
>>
>>http://users.tpg.com.au/atko/gpf/ir/
>>
>>Note that it freezes when you try to unload the LIRC module.
>
>
> It does too. I tried applying the patch to 0.2.8 - patched successfully
> with a little fuzz. But now when I close a v4l client, the picture keeps
> distplaying on the screen. When I switch to another X session, the
picture
> is still updated on the sceen (albeit, corrupted). I got an kernel panic
> in there somewhere, and I can't register any keystrokes on the
> remote whatsoever.
That's what you get when you use a snapshot :) Seriously though, are you
sure this is a problem with my patch? I just tried the 0.9.8 snapshot
with the IR patch applied, and I could use xawtv/motv/tvtime all fine. I
just updated the patch adding support for Cinergy 400 IR remotes, this
is the patch I tried against 0.9.8. Sure, the IR won't work without
changing a line or two, but I don't think the patch should cause the
problems you mention. Did you try 0.9.8 without the patch?
> Oh yeah, and that module unload freeze is still fun :)
Try the attached patch (against lirc-0.6.6).
eg. lirc-0.6.6$ patch -p1 < patch-lirc-0.6.6-nocrash
> What's the status on this driver these days?
The remote control driver needs to be redesigned. It's on my todo list
in the next few months (when I have time).
- David.
diff -u lirc-0.6.6/drivers/lirc_dev/lirc_dev.c lirc-0.6.6-patched/drivers/lirc_dev/lirc_dev.c
--- lirc-0.6.6/drivers/lirc_dev/lirc_dev.c 2001-12-13 09:27:38.000000000 +1100
+++ lirc-0.6.6-patched/drivers/lirc_dev/lirc_dev.c 2003-05-09 15:03:24.000000000 +1000
@@ -1,7 +1,7 @@
/*
* LIRC base driver
*
- * (L) by Artur Lipowski <alipowski@xxxxxxxxxx>
+ * (L) by Artur Lipowski <alipowski@xxxxxxxxxx>
*
* 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
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * $Id: lirc_dev.c,v 1.18 2001/12/12 20:26:01 ranty Exp $
+ * $Id: lirc_dev.c,v 1.22 2002/11/09 22:13:15 lirc Exp $
*
*/
@@ -30,10 +30,10 @@
#define LIRC_HAVE_DEVFS
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 4)
-#error "********************************************************"
-#error " Sorry, this driver needs kernel version 2.2.4 or higher"
-#error "********************************************************"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
+#error "**********************************************************"
+#error " Sorry, this driver needs kernel version 2.2.18 or higher "
+#error "**********************************************************"
#endif
#include <linux/config.h>
@@ -87,6 +87,7 @@
int tpid;
struct semaphore *t_notify;
+ struct semaphore *t_notify2;
int shutdown;
long jiffies_to_wait;
@@ -118,6 +119,7 @@
ir->tpid = -1;
ir->t_notify = NULL;
+ ir->t_notify2 = NULL;
ir->shutdown = 0;
ir->jiffies_to_wait = 0;
@@ -202,7 +204,7 @@
} else {
interruptible_sleep_on(ir->p.get_queue(ir->p.data));
}
- if (signal_pending(current)) {
+ if (ir->shutdown) {
break;
}
if (!add_to_buf(ir)) {
@@ -213,8 +215,12 @@
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ/2);
}
- } while (!ir->shutdown && !signal_pending(current));
+ } while (!ir->shutdown);
+ if (ir->t_notify2 != NULL) {
+ down(ir->t_notify2);
+ }
+
ir->tpid = -1;
if (ir->t_notify != NULL) {
up(ir->t_notify);
@@ -258,18 +264,26 @@
return -EBADRQC;
}
+ printk("lirc_dev: lirc_register_plugin:"
+ "sample_rate: %d\n",p->sample_rate);
if (p->sample_rate) {
if (2 > p->sample_rate || 50 < p->sample_rate) {
printk("lirc_dev: lirc_register_plugin:"
"sample_rate must be beetween 2 and 50!\n");
return -EBADRQC;
}
- } else {
+ } else if (!p->fops) {
if (!p->get_queue) {
printk("lirc_dev: lirc_register_plugin:"
"get_queue cannot be NULL!\n");
return -EBADRQC;
}
+ } else {
+ if (!p->fops->read || !p->fops->poll || !p->fops->ioctl) {
+ printk("lirc_dev: lirc_register_plugin:"
+ "neither read, poll nor ioctl can be NULL!\n");
+ return -EBADRQC;
+ }
}
down_interruptible(&plugin_lock);
@@ -325,18 +339,21 @@
&fops, NULL);
#endif
- /* try to fire up polling thread */
- ir->t_notify = &tn;
- ir->tpid = kernel_thread(lirc_thread, (void*)ir, 0);
- if (ir->tpid < 0) {
- IRUNLOCK;
- up(&plugin_lock);
- printk("lirc_dev: lirc_register_plugin:"
- "cannot run poll thread for minor = %d\n", p->minor);
- return -ECHILD;
+ if(p->sample_rate || p->get_queue) {
+ /* try to fire up polling thread */
+ ir->t_notify = &tn;
+ ir->tpid = kernel_thread(lirc_thread, (void*)ir, 0);
+ if (ir->tpid < 0) {
+ IRUNLOCK;
+ up(&plugin_lock);
+ printk("lirc_dev: lirc_register_plugin:"
+ "cannot run poll thread for minor = %d\n",
+ p->minor);
+ return -ECHILD;
+ }
+ down(&tn);
+ ir->t_notify = NULL;
}
- down(&tn);
- ir->t_notify = NULL;
up(&plugin_lock);
MOD_INC_USE_COUNT;
@@ -354,6 +371,7 @@
{
struct irctl *ir;
DECLARE_MUTEX_LOCKED(tn);
+ DECLARE_MUTEX_LOCKED(tn2);
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
printk("lirc_dev: lirc_unregister_plugin:"
@@ -383,9 +401,23 @@
/* end up polling thread */
if (ir->tpid >= 0) {
ir->t_notify = &tn;
+ ir->t_notify2 = &tn2;
ir->shutdown = 1;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+ {
+ struct task_struct *p;
+
+ p = find_task_by_pid(ir->tpid);
+ wake_up_process(p);
+ }
+#else
+ /* 2.2.x does not export wake_up_process() */
+ wake_up_interruptible(ir->p.get_queue(ir->p.data));
+#endif
+ up(&tn2);
down(&tn);
ir->t_notify = NULL;
+ ir->t_notify2 = NULL;
}
dprintk("lirc_dev: plugin %s unregistered from minor number = %d\n",
@@ -421,6 +453,10 @@
dprintk(LOGHEAD "open called\n", ir->p.name, ir->p.minor);
+ /* if the plugin has an open function use it instead */
+ if(ir->p.fops && ir->p.fops->open)
+ return ir->p.fops->open(inode, file);
+
down_interruptible(&plugin_lock);
if (ir->p.minor == NOPLUG) {
@@ -462,6 +498,10 @@
dprintk(LOGHEAD "close called\n", ir->p.name, ir->p.minor);
+ /* if the plugin has a close function use it instead */
+ if(ir->p.fops && ir->p.fops->release)
+ return ir->p.fops->release(inode, file);
+
down_interruptible(&plugin_lock);
--ir->open;
@@ -481,6 +521,10 @@
dprintk(LOGHEAD "poll called\n", ir->p.name, ir->p.minor);
+ /* if the plugin has a poll function use it instead */
+ if(ir->p.fops && ir->p.fops->poll)
+ return ir->p.fops->poll(file, wait);
+
if (!ir->in_buf) {
poll_wait(file, &ir->wait_poll, wait);
}
@@ -505,6 +549,10 @@
dprintk(LOGHEAD "poll called (%u)\n",
ir->p.name, ir->p.minor, cmd);
+ /* if the plugin has a ioctl function use it instead */
+ if(ir->p.fops && ir->p.fops->ioctl)
+ return ir->p.fops->ioctl(inode, file, cmd, arg);
+
if (ir->p.minor == NOPLUG) {
dprintk(LOGHEAD "ioctl result = -ENODEV\n",
ir->p.name, ir->p.minor);
@@ -555,6 +603,10 @@
dprintk(LOGHEAD "read called\n", ir->p.name, ir->p.minor);
+ /* if the plugin has a specific read function use it instead */
+ if(ir->p.fops && ir->p.fops->read)
+ return ir->p.fops->read(file, buffer, length, ppos);
+
if (ir->bytes_in_key != length) {
dprintk(LOGHEAD "read result = -EIO\n",
ir->p.name, ir->p.minor);
@@ -611,9 +663,24 @@
return ret ? -EFAULT : length;
}
+static ssize_t irctl_write(struct file *file, const char *buffer,
+ size_t length, loff_t * ppos)
+{
+ struct irctl *ir = &irctls[MINOR(file->f_dentry->d_inode->i_rdev)];
+
+ dprintk(LOGHEAD "read called\n", ir->p.name, ir->p.minor);
+
+ /* if the plugin has a specific read function use it instead */
+ if(ir->p.fops && ir->p.fops->write)
+ return ir->p.fops->write(file, buffer, length, ppos);
+
+ return -EINVAL;
+}
+
static struct file_operations fops = {
read: irctl_read,
+ write: irctl_write,
poll: irctl_poll,
ioctl: irctl_ioctl,
open: irctl_open,
diff -u lirc-0.6.6/drivers/lirc_dev/lirc_dev.h lirc-0.6.6-patched/drivers/lirc_dev/lirc_dev.h
--- lirc-0.6.6/drivers/lirc_dev/lirc_dev.h 2000-12-04 05:02:55.000000000 +1100
+++ lirc-0.6.6-patched/drivers/lirc_dev/lirc_dev.h 2003-05-09 15:06:09.000000000 +1000
@@ -1,21 +1,16 @@
/*
* LIRC base driver
*
- * (L) by Artur Lipowski <alipowski@xxxxxxxxxx>
+ * (L) by Artur Lipowski <alipowski@xxxxxxxxxx>
* This code is licensed under GNU GPL
*
- * $Id: lirc_dev.h,v 1.3 2000/12/03 18:02:55 columbus Exp $
+ * $Id: lirc_dev.h,v 1.7 2002/11/19 20:22:06 ranty Exp $
*
*/
#ifndef _LINUX_LIRC_DEV_H
#define _LINUX_LIRC_DEV_H
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)
-/* comes with bttv */
-#include "../drivers/char/kcompat24.h"
-#endif
-
#define MAX_IRCTL_DEVICES 2
#define BUFLEN 16
@@ -25,11 +20,14 @@
int minor;
int code_length;
int sample_rate;
+ unsigned long features;
void* data;
int (*get_key) (void* data, unsigned char* key, int key_no);
wait_queue_head_t* (*get_queue) (void* data);
- void (*set_use_inc) (void* data);
+ int (*set_use_inc) (void* data);
void (*set_use_dec) (void* data);
+ int (*ioctl) (struct inode *,struct file *,unsigned int, unsigned long);
+ struct file_operations *fops;
};
/* name:
* this string will be used for logs
@@ -72,6 +70,9 @@
*
* set_use_dec:
* set_use_dec will be called after device is closed
+ *
+ * fops:
+ * file_operations for drivers which don't fit the current plugin model.
*/