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 <[EMAIL PROTECTED]>
+ * (L) by Artur Lipowski <[EMAIL PROTECTED]>
  *
  *  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 <[EMAIL PROTECTED]>
+ * (L) by Artur Lipowski <[EMAIL PROTECTED]>
  *        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.
  */
 
 

Reply via email to