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]