Hi!

Brian Gerst found a bug in the usecounting of the *dev.c modules. Fairly
stupid and would cause an oops on a close of a disconnected device. This
patch fixes it. It also adds some more event filtering to joydev.c, so
that it never generates two consecutive events with the same value. 

-- 
Vojtech Pavlik
SuSE Labs
diff -urN linux-2.4.0-test2-pre9/drivers/usb/evdev.c linux/drivers/usb/evdev.c
--- linux-2.4.0-test2-pre9/drivers/usb/evdev.c  Thu Jun 22 09:12:30 2000
+++ linux/drivers/usb/evdev.c   Fri Jun 23 09:20:17 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: evdev.c,v 1.8 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: evdev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -39,7 +39,7 @@
 #include <linux/input.h>
 
 struct evdev {
-       int used;
+       int exist;
        int open;
        int minor;
        struct input_handle handle;
@@ -99,13 +99,14 @@
                listptr = &((*listptr)->next);
        *listptr = (*listptr)->next;
 
-       if (!--list->evdev->open)
-               input_close_device(&list->evdev->handle);       
-       
-       if (!--list->evdev->used) {
-               input_unregister_minor(list->evdev->devfs);
-               evdev_table[list->evdev->minor] = NULL;
-               kfree(list->evdev);
+       if (!--list->evdev->open) {
+               if (list->evdev->exist) {
+                       input_close_device(&list->evdev->handle);       
+               } else {
+                       input_unregister_minor(list->evdev->devfs);
+                       evdev_table[list->evdev->minor] = NULL;
+                       kfree(list->evdev);
+               }
        }
 
        kfree(list);
@@ -121,9 +122,8 @@
        if (i > EVDEV_MINORS || !evdev_table[i])
                return -ENODEV;
 
-       if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) {
+       if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
                return -ENOMEM;
-       }
        memset(list, 0, sizeof(struct evdev_list));
 
        list->evdev = evdev_table[i];
@@ -132,10 +132,9 @@
 
        file->private_data = list;
 
-       list->evdev->used++;
-
        if (!list->evdev->open++)
-               input_open_device(&list->evdev->handle);        
+               if (list->evdev->exist)
+                       input_open_device(&list->evdev->handle);        
 
        return 0;
 }
@@ -303,7 +302,7 @@
        evdev->handle.handler = handler;
        evdev->handle.private = evdev;
 
-       evdev->used = 1;
+       evdev->exist = 1;
 
        evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
@@ -316,10 +315,11 @@
 {
        struct evdev *evdev = handle->private;
 
-       if (evdev->open)
-               input_close_device(handle);
+       evdev->exist = 0;
 
-       if (!--evdev->used) {
+       if (evdev->open) {
+               input_close_device(handle);
+       } else {
                input_unregister_minor(evdev->devfs);
                evdev_table[evdev->minor] = NULL;
                kfree(evdev);
diff -urN linux-2.4.0-test2-pre9/drivers/usb/joydev.c linux/drivers/usb/joydev.c
--- linux-2.4.0-test2-pre9/drivers/usb/joydev.c Thu Jun 22 09:12:30 2000
+++ linux/drivers/usb/joydev.c  Fri Jun 23 09:20:25 2000
@@ -1,7 +1,7 @@
 /*
- * $Id: joydev.c,v 1.7 2000/05/29 09:01:52 vojtech Exp $
+ * $Id: joydev.c,v 1.11 2000/06/23 09:23:00 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2000 Vojtech Pavlik                                       
  *  Copyright (c) 1999 Colin Van Dyke 
  *
  *  Joystick device driver for the input driver suite.
@@ -50,7 +50,7 @@
 #define JOYDEV_BUFFER_SIZE     64
 
 struct joydev {
-       int used;
+       int exist;
        int open;
        int minor;
        struct input_handle handle;
@@ -66,6 +66,7 @@
        __u16 keypam[KEY_MAX - BTN_MISC];
        __u8 absmap[ABS_MAX];
        __u8 abspam[ABS_MAX];
+       __s16 abs[ABS_MAX];
 };
 
 struct joydev_list {
@@ -121,7 +122,9 @@
                case EV_ABS:
                        event.type = JS_EVENT_AXIS;
                        event.number = joydev->absmap[code];
-                       event.value = joydev_correct(value, 
&joydev->corr[event.number]);
+                       event.value = joydev_correct(value, joydev->corr + 
+event.number);
+                       if (event.value == joydev->abs[event.number]) return;
+                       joydev->abs[event.number] = event.value;
                        break;
 
                default:
@@ -165,13 +168,14 @@
                listptr = &((*listptr)->next);
        *listptr = (*listptr)->next;
 
-       if (!--list->joydev->open)
-               input_close_device(&list->joydev->handle);
-       
-       if (!--list->joydev->used) {
-               input_unregister_minor(list->joydev->devfs);
-               joydev_table[list->joydev->minor] = NULL;
-               kfree(list->joydev);
+       if (!--list->joydev->open) {
+               if (list->joydev->exist) {
+                       input_close_device(&list->joydev->handle);
+               } else {
+                       input_unregister_minor(list->joydev->devfs);
+                       joydev_table[list->joydev->minor] = NULL;
+                       kfree(list->joydev);
+               }
        }
 
        kfree(list);
@@ -187,9 +191,8 @@
        if (i > JOYDEV_MINORS || !joydev_table[i])
                return -ENODEV;
 
-       if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) {
+       if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL)))
                return -ENOMEM;
-       }
        memset(list, 0, sizeof(struct joydev_list));
 
        list->joydev = joydev_table[i];
@@ -198,10 +201,9 @@
 
        file->private_data = list;
 
-       list->joydev->used++;
-
        if (!list->joydev->open++)
-               input_open_device(&list->joydev->handle);
+               if (list->joydev->exist)
+                       input_open_device(&list->joydev->handle);
 
        return 0;
 }
@@ -228,8 +230,8 @@
 
                data.buttons =  ((joydev->nkey > 0 && test_bit(joydev->keypam[0], 
input->key)) ? 1 : 0) |
                                ((joydev->nkey > 1 && test_bit(joydev->keypam[1], 
input->key)) ? 2 : 0);
-               data.x = ((joydev_correct(input->abs[ABS_X], &joydev->corr[0]) / 256) 
+ 128) >> joydev->glue.JS_CORR.x;
-               data.y = ((joydev_correct(input->abs[ABS_Y], &joydev->corr[1]) / 256) 
+ 128) >> joydev->glue.JS_CORR.y;
+               data.x = (joydev->abs[0] / 256 + 128) >> joydev->glue.JS_CORR.x;
+               data.y = (joydev->abs[1] / 256 + 128) >> joydev->glue.JS_CORR.y;
 
                if (copy_to_user(buf, &data, sizeof(struct JS_DATA_TYPE)))
                        return -EFAULT;
@@ -274,13 +276,12 @@
 
                if (list->startup < joydev->nkey) {
                        event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
-                       event.value = !!test_bit(joydev->keypam[list->startup], 
input->key);
                        event.number = list->startup;
+                       event.value = !!test_bit(joydev->keypam[event.number], 
+input->key);
                } else {
                        event.type = JS_EVENT_AXIS | JS_EVENT_INIT;
-                       event.value = 
joydev_correct(input->abs[joydev->abspam[list->startup - joydev->nkey]],
-                                                       &joydev->corr[list->startup - 
joydev->nkey]);
                        event.number = list->startup - joydev->nkey;
+                       event.value = joydev->abs[event.number];
                }
 
                if (copy_to_user(buf + retval, &event, sizeof(struct js_event)))
@@ -407,7 +408,7 @@
        joydev->handle.handler = handler;
        joydev->handle.private = joydev;
 
-       joydev->used = 1;
+       joydev->exist = 1;
 
        for (i = 0; i < ABS_MAX; i++)
                if (test_bit(i, dev->absbit)) {
@@ -442,6 +443,8 @@
                joydev->corr[i].coef[1] = (dev->absmax[j] + dev->absmin[j]) / 2 + 
dev->absflat[j];
                joydev->corr[i].coef[2] = (1 << 29) / ((dev->absmax[j] - 
dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
                joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - 
dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
+
+               joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
        }
 
        joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
@@ -455,10 +458,11 @@
 {
        struct joydev *joydev = handle->private;
 
-       if (joydev->open)
-               input_close_device(handle);     
+       joydev->exist = 0;
 
-       if (!--joydev->used) {
+       if (joydev->open) {
+               input_close_device(handle);     
+       } else {
                input_unregister_minor(joydev->devfs);
                joydev_table[joydev->minor] = NULL;
                kfree(joydev);
diff -urN linux-2.4.0-test2-pre9/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c
--- linux-2.4.0-test2-pre9/drivers/usb/mousedev.c       Thu Jun 22 09:12:30 2000
+++ linux/drivers/usb/mousedev.c        Fri Jun 23 09:20:21 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: mousedev.c,v 1.8 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: mousedev.c,v 1.10 2000/06/23 09:23:00 vojtech Exp $
  *
  *  Copyright (c) 1999-2000 Vojtech Pavlik
  *
@@ -47,7 +47,7 @@
 #endif
 
 struct mousedev {
-       int used;
+       int exist;
        int open;
        int minor;
        wait_queue_head_t wait;
@@ -172,22 +172,30 @@
                        struct input_handle *handle = mousedev_handler.handle;
                        while (handle) {
                                struct mousedev *mousedev = handle->private;
-                               if (!mousedev->open)
-                                       input_close_device(handle);
+                               if (!mousedev->open) {
+                                       if (mousedev->exist) {
+                                               input_close_device(&mousedev->handle);
+                                       } else {
+                                               
+input_unregister_minor(mousedev->devfs);
+                                               mousedev_table[mousedev->minor] = NULL;
+                                               kfree(mousedev);
+                                       }
+                               }
                                handle = handle->hnext;
                        }
                } else {
-                       if (!mousedev_mix.open) 
-                               input_close_device(&list->mousedev->handle);
+                       if (!mousedev_mix.open) {
+                               if (list->mousedev->exist) {
+                                       input_close_device(&list->mousedev->handle);
+                               } else {
+                                       input_unregister_minor(list->mousedev->devfs);
+                                       mousedev_table[list->mousedev->minor] = NULL;
+                                       kfree(list->mousedev);
+                               }
+                       }
                }
        }
        
-       if (!--list->mousedev->used) {
-               input_unregister_minor(list->mousedev->devfs);
-               mousedev_table[list->mousedev->minor] = NULL;
-               kfree(list->mousedev);
-       }
-
        kfree(list);
 
        return 0;
@@ -210,20 +218,20 @@
        mousedev_table[i]->list = list;
        file->private_data = list;
 
-       list->mousedev->used++;
-
        if (!list->mousedev->open++) {
                if (list->mousedev->minor == MOUSEDEV_MIX) {
                        struct input_handle *handle = mousedev_handler.handle;
                        while (handle) {
                                struct mousedev *mousedev = handle->private;
                                if (!mousedev->open)
-                                       input_open_device(handle);
+                                       if (mousedev->exist)    
+                                               input_open_device(handle);
                                handle = handle->hnext;
                        }
                } else {
-                       if (!mousedev_mix.open) 
-                               input_open_device(&list->mousedev->handle);
+                       if (!mousedev_mix.open)
+                               if (list->mousedev->exist)      
+                                       input_open_device(&list->mousedev->handle);
                }
        }
 
@@ -402,7 +410,7 @@
        memset(mousedev, 0, sizeof(struct mousedev));
        init_waitqueue_head(&mousedev->wait);
 
-       mousedev->used = 1;
+       mousedev->exist = 1;
        mousedev->minor = minor;
        mousedev_table[minor] = mousedev;
 
@@ -424,10 +432,13 @@
 {
        struct mousedev *mousedev = handle->private;
 
-       if (mousedev->open || mousedev_mix.open)
-               input_close_device(handle);
+       mousedev->exist = 0;
 
-       if (!--mousedev->used) {
+       if (mousedev->open) {
+               input_close_device(handle);
+       } else {
+               if (mousedev_mix.open)
+                       input_close_device(handle);
                input_unregister_minor(mousedev->devfs);
                mousedev_table[mousedev->minor] = NULL;
                kfree(mousedev);
@@ -449,7 +460,7 @@
        memset(&mousedev_mix, 0, sizeof(struct mousedev));
        init_waitqueue_head(&mousedev_mix.wait);
        mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
-       mousedev_mix.used = 1;
+       mousedev_mix.exist = 1;
        mousedev_mix.minor = MOUSEDEV_MIX;
        mousedev_mix.devfs = input_register_minor("mice", MOUSEDEV_MIX, 
MOUSEDEV_MINOR_BASE);
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to