Hi!

This patch implements some of Alessandro's ideas:

* Mousedev mixing config option is gone - it's always on 13:63
 (input/mouse), and unmixed devices are on 13:32 - 13:62 (input/mouseX).

* Each of the *dev.c modules calls the input_open_device() call
  when it is really to be open, thus letting the input device driver
  know it's used. This isn't handled in the device drivers (usbmouse,
  hid, wacom ...) yet, though. Perhaps later I can implement
  removing/submitting the interrupt URB based on this info.

It doesn't do MOD_INC_USE_COUNT, though. It also implements a stronger
rawmode emulation routine that covers event codes up to 240.

-- 
Vojtech Pavlik
SuSE Labs
diff -urN linux-2.3.99-pre4-5-old/drivers/usb/Config.in 
linux-2.3.99-pre4-5-usb/drivers/usb/Config.in
--- linux-2.3.99-pre4-5-old/drivers/usb/Config.in       Sat Apr  8 11:09:37 2000
+++ linux-2.3.99-pre4-5-usb/drivers/usb/Config.in       Sat Apr  8 17:44:10 2000
@@ -66,12 +66,8 @@
    dep_tristate '  Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB
    dep_tristate '  Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB
    if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
-      bool '    Mix all mice into one device' CONFIG_INPUT_MOUSEDEV_MIX
-      bool '    Support for digitizers' CONFIG_INPUT_MOUSEDEV_DIGITIZER
-      if [ "$CONFIG_INPUT_MOUSEDEV_DIGITIZER" != "n" ]; then
-         int '     Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
-         int '      Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768
-      fi
+      int '   Horizontal screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
+      int '   Vertical screen resolution' CONFIG_INPUT_MOUSEDEV_SCREEN_Y 768
    fi
    dep_tristate '  Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_USB
    dep_tristate '  Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB
diff -urN linux-2.3.99-pre4-5-old/drivers/usb/evdev.c 
linux-2.3.99-pre4-5-usb/drivers/usb/evdev.c
--- linux-2.3.99-pre4-5-old/drivers/usb/evdev.c Sat Apr  8 11:09:37 2000
+++ linux-2.3.99-pre4-5-usb/drivers/usb/evdev.c Sat Apr  8 17:33:31 2000
@@ -40,6 +40,7 @@
 
 struct evdev {
        int used;
+       int open;
        int minor;
        struct input_handle handle;
        wait_queue_head_t wait;
@@ -98,6 +99,9 @@
        while (*listptr && (*listptr != list))
                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);
@@ -135,6 +139,9 @@
 
        list->evdev->used++;
 
+       if (!list->evdev->open++)
+               input_open_device(&list->evdev->handle);        
+
        return 0;
 }
 
@@ -250,7 +257,7 @@
        fasync:         evdev_fasync,
 };
 
-static int evdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *evdev_connect(struct input_handler *handler, struct 
+input_dev *dev)
 {
        struct evdev *evdev;
        int minor;
@@ -258,11 +265,11 @@
        for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++);
        if (evdev_table[minor]) {
                printk(KERN_ERR "evdev: no more free evdev devices\n");
-               return -1;
+               return NULL;
        }
 
        if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
-               return -1;
+               return NULL;
        memset(evdev, 0, sizeof(struct evdev));
 
        init_waitqueue_head(&evdev->wait);
@@ -276,19 +283,19 @@
 
        evdev->used = 1;
 
-       input_open_device(&evdev->handle);
        evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
        printk("event%d: Event device for input%d\n", minor, dev->number);
 
-       return 0;
+       return &evdev->handle;
 }
 
 static void evdev_disconnect(struct input_handle *handle)
 {
        struct evdev *evdev = handle->private;
 
-       input_close_device(handle);
+       if (evdev->open)
+               input_close_device(handle);
 
        if (!--evdev->used) {
                input_unregister_minor(evdev->devfs);
diff -urN linux-2.3.99-pre4-5-old/drivers/usb/input.c 
linux-2.3.99-pre4-5-usb/drivers/usb/input.c
--- linux-2.3.99-pre4-5-old/drivers/usb/input.c Sat Apr  8 11:09:37 2000
+++ linux-2.3.99-pre4-5-usb/drivers/usb/input.c Sat Apr  8 20:35:05 2000
@@ -35,23 +35,25 @@
 
 MODULE_AUTHOR("Vojtech Pavlik <[EMAIL PROTECTED]>");
 
-#ifndef MODULE
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
 EXPORT_SYMBOL(input_unregister_handler);
+EXPORT_SYMBOL(input_register_minor);
+EXPORT_SYMBOL(input_unregister_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
 EXPORT_SYMBOL(input_event);
-#endif
 
 #define INPUT_MAJOR    13
+#define INPUT_DEVICES  256
 
 static struct input_dev *input_dev = NULL;
 static struct input_handler *input_handler = NULL;
 static struct input_handler *input_table[8] = { NULL, /* ... */ };
 static devfs_handle_t input_devfs_handle = NULL;
 static int input_number = 0;
+static long input_devices[NBITS(INPUT_DEVICES)] = { 0, /* ... */ };
 
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int 
value)
 {
@@ -145,7 +147,8 @@
  */
 
        while (handle) {
-               handle->handler->event(handle, type, code, value);
+               if (handle->open)
+                       handle->handler->event(handle, type, code, value);
                handle = handle->dnext;
        }
 }
@@ -157,9 +160,48 @@
        mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
 }
 
+int input_open_device(struct input_handle *handle)
+{
+       handle->open++;
+       if (handle->dev->open)
+               return handle->dev->open(handle->dev);
+       return 0;
+}
+
+void input_close_device(struct input_handle *handle)
+{
+       if (handle->dev->close)
+               handle->dev->close(handle->dev);
+       handle->open--;
+}
+
+static void input_link_handle(struct input_handle *handle)
+{
+       handle->dnext = handle->dev->handle;
+       handle->hnext = handle->handler->handle;
+       handle->dev->handle = handle;
+       handle->handler->handle = handle;
+}
+
+static void input_unlink_handle(struct input_handle *handle)
+{
+       struct input_handle **handleptr;
+
+       handleptr = &handle->dev->handle;
+       while (*handleptr && (*handleptr != handle))
+               handleptr = &((*handleptr)->dnext);
+       *handleptr = (*handleptr)->dnext;
+
+       handleptr = &handle->handler->handle;
+       while (*handleptr && (*handleptr != handle))
+               handleptr = &((*handleptr)->hnext);
+       *handleptr = (*handleptr)->hnext;
+}
+
 void input_register_device(struct input_dev *dev)
 {
        struct input_handler *handler = input_handler;
+       struct input_handle *handle;
 
 /*
  * Initialize repeat timer to default values.
@@ -175,17 +217,25 @@
  * Add the device.
  */
 
-       MOD_INC_USE_COUNT;
-       dev->number = input_number++;
+       if (input_number >= INPUT_DEVICES) {
+               printk(KERN_WARNING "input: ran out of input device numbers!\n");
+               dev->number = input_number;
+       } else {
+               dev->number = find_first_zero_bit(input_devices, INPUT_DEVICES);
+               set_bit(dev->number, input_devices);
+       }
+               
        dev->next = input_dev;  
        input_dev = dev;
+       input_number++;
 
 /*
  * Notify handlers.
  */
 
        while (handler) {
-               handler->connect(handler, dev);
+               if ((handle = handler->connect(handler, dev)))
+                       input_link_handle(handle);
                handler = handler->next;
        }
 }
@@ -206,6 +256,7 @@
  */
 
        while (handle) {
+               input_unlink_handle(handle);
                handle->handler->disconnect(handle);
                handle = handle->dnext;
        }
@@ -219,12 +270,15 @@
        *devptr = (*devptr)->next;
 
        input_number--;
-       MOD_DEC_USE_COUNT;
+
+       if (dev->number < INPUT_DEVICES)
+               clear_bit(dev->number, input_devices);
 }
 
 void input_register_handler(struct input_handler *handler)
 {
        struct input_dev *dev = input_dev;
+       struct input_handle *handle;
 
 /*
  * Add minors if needed.
@@ -245,7 +299,8 @@
  */
 
        while (dev) {
-               handler->connect(handler, dev);
+               if ((handle = handler->connect(handler, dev)))
+                       input_link_handle(handle);
                dev = dev->next;
        }
 }
@@ -260,6 +315,7 @@
  */
 
        while (handle) {
+               input_unlink_handle(handle);
                handler->disconnect(handle);
                handle = handle->hnext;
        }
@@ -279,44 +335,6 @@
 
        if (handler->fops != NULL)
                input_table[handler->minor >> 5] = NULL;
-}
-
-void input_open_device(struct input_handle *handle)
-{
-       handle->dnext = handle->dev->handle;
-       handle->hnext = handle->handler->handle;
-       handle->dev->handle = handle;
-       handle->handler->handle = handle;
-
-       if (handle->dev->open)
-               handle->dev->open(handle->dev);
-}
-
-void input_close_device(struct input_handle *handle)
-{
-       struct input_handle **handleptr;
-
-       if (handle->dev->close)
-               handle->dev->close(handle->dev);
-/*
- * Remove from device list of handles.
- */
-
-       handleptr = &handle->dev->handle;
-
-       while (*handleptr && (*handleptr != handle))
-               handleptr = &((*handleptr)->dnext);
-       *handleptr = (*handleptr)->dnext;
-
-/*
- * Remove from handler list of handles.
- */
-
-       handleptr = &handle->handler->handle;
-
-       while (*handleptr && (*handleptr != handle))
-               handleptr = &((*handleptr)->hnext);
-       *handleptr = (*handleptr)->hnext;
 }
 
 static int input_open_file(struct inode *inode, struct file *file)
diff -urN linux-2.3.99-pre4-5-old/drivers/usb/joydev.c 
linux-2.3.99-pre4-5-usb/drivers/usb/joydev.c
--- linux-2.3.99-pre4-5-old/drivers/usb/joydev.c        Sat Apr  8 11:09:37 2000
+++ linux-2.3.99-pre4-5-usb/drivers/usb/joydev.c        Sat Apr  8 17:33:36 2000
@@ -51,6 +51,7 @@
 
 struct joydev {
        int used;
+       int open;
        int minor;
        char name[32];
        struct input_handle handle;
@@ -165,6 +166,9 @@
        while (*listptr && (*listptr != list))
                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);
@@ -202,6 +206,9 @@
 
        list->joydev->used++;
 
+       if (!list->joydev->open++)
+               input_open_device(&list->joydev->handle);
+
        return 0;
 }
 
@@ -371,7 +378,7 @@
        fasync:         joydev_fasync,
 };
 
-static int joydev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *joydev_connect(struct input_handler *handler, struct 
+input_dev *dev)
 {
        struct joydev *joydev;
        int i, j, minor;
@@ -379,16 +386,16 @@
        if (!(test_bit(EV_KEY, dev->evbit) && test_bit(EV_ABS, dev->evbit) &&
              test_bit(ABS_X, dev->absbit) && test_bit(ABS_Y, dev->absbit) &&
             (test_bit(BTN_TRIGGER, dev->keybit) || test_bit(BTN_A, dev->keybit)
-               || test_bit(BTN_1, dev->keybit)))) return -1;
+               || test_bit(BTN_1, dev->keybit)))) return NULL; 
 
        for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
        if (joydev_table[minor]) {
                printk(KERN_ERR "joydev: no more free joydev devices\n");
-               return -1;
+               return NULL;
        }
 
        if (!(joydev = kmalloc(sizeof(struct joydev), GFP_KERNEL)))
-               return -1;
+               return NULL;
        memset(joydev, 0, sizeof(struct joydev));
 
        init_waitqueue_head(&joydev->wait);
@@ -439,19 +446,19 @@
                joydev->corr[i].coef[3] = (1 << 29) / ((dev->absmax[j] - 
dev->absmin[j]) / 2 - 2 * dev->absflat[j]);
        }
 
-       input_open_device(&joydev->handle);     
        joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
 
        printk("js%d: Joystick device for input%d\n", minor, dev->number);
 
-       return 0;
+       return &joydev->handle;
 }
 
 static void joydev_disconnect(struct input_handle *handle)
 {
        struct joydev *joydev = handle->private;
 
-       input_close_device(handle);
+       if (joydev->open)
+               input_close_device(handle);     
 
        if (!--joydev->used) {
                input_unregister_minor(joydev->devfs);
diff -urN linux-2.3.99-pre4-5-old/drivers/usb/keybdev.c 
linux-2.3.99-pre4-5-usb/drivers/usb/keybdev.c
--- linux-2.3.99-pre4-5-old/drivers/usb/keybdev.c       Mon Mar 20 03:29:40 2000
+++ linux-2.3.99-pre4-5-usb/drivers/usb/keybdev.c       Sat Apr  8 17:51:07 2000
@@ -36,17 +36,63 @@
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || 
+defined(CONFIG_MIPS)
 
-static unsigned char keybdev_x86_e0s[] = 
-       { 0x1c, 0x1d, 0x35, 0x2a, 0x38, 0x39, 0x47, 0x48,
-         0x49, 0x4b, 0x4d, 0x4f, 0x50, 0x51, 0x52, 0x53,
-         0x26, 0x25, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x00,
-         0x23, 0x24, 0x25, 0x26, 0x27 };
+static int x86_sysrq_alt = 0;
 
-#elif CONFIG_ADB_KEYBOARD
+static unsigned short x86_keycodes[256] =
+       { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+        64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+        80, 81, 82, 83, 89, 85, 86, 87, 88,115,119,120,121,375,123, 90,
+       284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339,
+       367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349,
+       360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355,
+       103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361,
+       291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114,
+       118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269,
+       271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307,
+       308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330,
+       332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 };
 
-static unsigned char keybdev_mac_codes[256] =
+static int emulate_raw(unsigned int keycode, int down)
+{
+       if (keycode > 255 || !x86_keycodes[keycode])
+               return -1; 
+
+       if (keycode == KEY_PAUSE) {
+               handle_scancode(0xe1, 1);
+               handle_scancode(0x1d, down);
+               handle_scancode(0x45, down);
+               return 0;
+       } 
+
+       if (keycode == KEY_SYSRQ && x86_sysrq_alt) {
+               handle_scancode(0x54, down);
+               return 0;
+       }
+
+       if (x86_keycodes[keycode] & 0x100)
+               handle_scancode(0xe0, 1);
+
+       handle_scancode(x86_keycodes[keycode] & 0x7f, down);
+
+       if (keycode == KEY_SYSRQ) {
+               handle_scancode(0xe0, 1);
+               handle_scancode(0x37, down);
+       }
+
+       if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
+               x86_sysrq_alt = down;
+
+       return 0;
+}
+
+#elif defined(CONFIG_ADB_KEYBOARD)
+
+static unsigned char mac_keycodes[128] =
        { 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
         12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,128,  1,
          2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
@@ -56,10 +102,19 @@
         76,125, 75,105,124,  0,115, 62,116, 59, 60,119, 61,121,114,117,
          0,  0,  0,  0,127, 81,  0,113,  0,  0,  0,  0,  0, 55, 55 };
 
+static int emulate_raw(unsigned int code, unsigned char upflag)
+{
+       if (keycode > 127 || !mac_keycodes[keycode])
+               return -1;
+
+       handle_scancode(mac_keycodes[keycode] & 0x7f, down);
+
+       return 0;
+}
+
 #endif
 
 static struct input_handler keybdev_handler;
-static int keybdev_alt = 0;
 
 void keybdev_ledfunc(unsigned int led)
 {
@@ -76,70 +131,30 @@
 
 void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, 
int down)
 {
-       if (type != EV_KEY || code > 255) return;
+       if (type != EV_KEY) return;
 
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
-
-       if (code >= 189) {
-               printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
-               return; 
-       } else if (code >= 162) {
-               handle_scancode(0xe0, 1);
-               handle_scancode(code - 161, down);
-       } else if (code >= 125) {
-               handle_scancode(0xe0, 1);
-               handle_scancode(code - 34, down);
-       } else if (code == 119) {
-               handle_scancode(0xe1, 1);
-               handle_scancode(0x1d, down);
-               handle_scancode(0x45, down);
-       } else if (code >= 96) {
-               if (code == 99 && keybdev_alt) {
-                        handle_scancode(84, down);
-               } else {
-                       handle_scancode(0xe0, 1);
-                       handle_scancode(keybdev_x86_e0s[code - 96], down);
-                       if (code == 99) {
-                               handle_scancode(0xe0, 1);
-                               handle_scancode(0x37, down);
-                       }
-               }
-       } else if (code == 84) {
-               handle_scancode(43, down);
-       } else handle_scancode(code, down);
-
-       if (code == 56 || code == 100) keybdev_alt = down;
-
-#elif CONFIG_ADB_KEYBOARD
-
-       if (code < 128 && keybdev_mac_codes[code]) 
-               handle_scancode(keybdev_mac_codes[code] & 0x7f, down);
-       else
-               printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
-
-#else
-#error "Cannot generate rawmode keyboard for your architecture yet."
-#endif
+       if (emulate_raw(code, down))
+               printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode 
+%d\n", code);
 
        tasklet_schedule(&keyboard_tasklet);
 }
 
-static int keybdev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *keybdev_connect(struct input_handler *handler, struct 
+input_dev *dev)
 {
        struct input_handle *handle;
        int i;
 
        if (!test_bit(EV_KEY, dev->evbit))
-               return -1;
+               return NULL;
 
        for (i = KEY_RESERVED; i < BTN_MISC; i++)
                if (test_bit(i, dev->keybit)) break;
 
        if (i == BTN_MISC)
-               return -1;
+               return NULL;
 
        if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
-               return -1;
+               return NULL;
        memset(handle, 0, sizeof(struct input_handle));
 
        handle->dev = dev;
@@ -149,15 +164,13 @@
 
        printk("keybdev.c: Adding keyboard: input%d\n", dev->number);
 
-       return 0;
+       return handle;
 }
 
 static void keybdev_disconnect(struct input_handle *handle)
 {
        printk("keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
-
        input_close_device(handle);
-
        kfree(handle);
 }
        
diff -urN linux-2.3.99-pre4-5-old/drivers/usb/mousedev.c 
linux-2.3.99-pre4-5-usb/drivers/usb/mousedev.c
--- linux-2.3.99-pre4-5-old/drivers/usb/mousedev.c      Sat Apr  8 11:09:37 2000
+++ linux-2.3.99-pre4-5-usb/drivers/usb/mousedev.c      Sat Apr  8 17:33:25 2000
@@ -30,6 +30,7 @@
 
 #define MOUSEDEV_MINOR_BASE    32
 #define MOUSEDEV_MINORS                32
+#define MOUSEDEV_MIX           31
 
 #include <linux/malloc.h>
 #include <linux/poll.h>
@@ -47,9 +48,11 @@
 
 struct mousedev {
        int used;
+       int open;
        int minor;
        wait_queue_head_t wait;
        struct mousedev_list *list;
+       struct input_handle handle;
        devfs_handle_t devfs;
 };
 
@@ -70,72 +73,80 @@
 static unsigned char mousedev_genius_seq[] = { 0xe8, 3, 0xe6, 0xe6, 0xe6 };
 static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 };
 
+static struct input_handler mousedev_handler;
+
 static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
+static struct mousedev mousedev_mix;
 
 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned 
int code, int value)
 {
-       struct mousedev *mousedev = handle->private;
-       struct mousedev_list *list = mousedev->list;
+       struct mousedev *mousedevs[3] = { handle->private, &mousedev_mix, NULL };
+       struct mousedev **mousedev = mousedevs;
+       struct mousedev_list *list;
        int index, size;
 
-       while (list) {
-               switch (type) {
-                       case EV_ABS:
-                               switch (code) {
-                                       case ABS_X:     
-                                               size = handle->dev->absmax[ABS_X] - 
handle->dev->absmin[ABS_X];
-                                               list->dx += (value * 
CONFIG_MOUSEDEV_SCREEN_X - list->oldx) / size;
-                                               list->oldx += list->dx * size;
-                                               break;
-                                       case ABS_Y:
-                                               size = handle->dev->absmax[ABS_Y] - 
handle->dev->absmin[ABS_Y];
-                                               list->dy -= (value * 
CONFIG_MOUSEDEV_SCREEN_Y - list->oldy) / size;
-                                               list->oldy -= list->dy * size;
-                                               break;
-                               }
-                               break;
-                       case EV_REL:
-                               switch (code) {
-                                       case REL_X:     list->dx += value; break;
-                                       case REL_Y:     list->dy -= value; break;
-                                       case REL_WHEEL: if (list->mode) list->dz -= 
value; break;
-                               }
-                               break;
+       while (*mousedev) {
+               list = (*mousedev)->list;
+               while (list) {
+                       switch (type) {
+                               case EV_ABS:
+                                       switch (code) {
+                                               case ABS_X:     
+                                                       size = 
+handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
+                                                       list->dx += (value * 
+CONFIG_MOUSEDEV_SCREEN_X - list->oldx) / size;
+                                                       list->oldx += list->dx * size;
+                                                       break;
+                                               case ABS_Y:
+                                                       size = 
+handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
+                                                       list->dy -= (value * 
+CONFIG_MOUSEDEV_SCREEN_Y - list->oldy) / size;
+                                                       list->oldy -= list->dy * size;
+                                                       break;
+                                       }
+                                       break;
+                               case EV_REL:
+                                       switch (code) {
+                                               case REL_X:     list->dx += value; 
+break;
+                                               case REL_Y:     list->dy -= value; 
+break;
+                                               case REL_WHEEL: if (list->mode) 
+list->dz -= value; break;
+                                       }
+                                       break;
+
+                               case EV_KEY:
+                                       switch (code) {
+                                               case BTN_0:
+                                               case BTN_TOUCH:
+                                               case BTN_LEFT:   index = 0; break;
+                                               case BTN_4:
+                                               case BTN_EXTRA:  if (list->mode > 1) { 
+index = 4; break; }
+                                               case BTN_STYLUS:
+                                               case BTN_1:
+                                               case BTN_RIGHT:  index = 1; break;
+                                               case BTN_3:
+                                               case BTN_SIDE:   if (list->mode > 1) { 
+index = 3; break; }
+                                               case BTN_2:
+                                               case BTN_STYLUS2:
+                                               case BTN_MIDDLE: index = 2; break;     
+ 
+                                               default: return;
+                                       }
+                                       switch (value) {
+                                               case 0: clear_bit(index, 
+&list->buttons); break;
+                                               case 1: set_bit(index, 
+&list->buttons); break;
+                                               case 2: return;
+                                       }
+                                       break;
+                       }
+                                       
+                       list->ready = 1;
 
-                       case EV_KEY:
-                               switch (code) {
-                                       case BTN_0:
-                                       case BTN_TOUCH:
-                                       case BTN_LEFT:   index = 0; break;
-                                       case BTN_4:
-                                       case BTN_EXTRA:  if (list->mode > 1) { index = 
4; break; }
-                                       case BTN_STYLUS:
-                                       case BTN_1:
-                                       case BTN_RIGHT:  index = 1; break;
-                                       case BTN_3:
-                                       case BTN_SIDE:   if (list->mode > 1) { index = 
3; break; }
-                                       case BTN_2:
-                                       case BTN_STYLUS2:
-                                       case BTN_MIDDLE: index = 2; break;      
-                                       default: return;
-                               }
-                               switch (value) {
-                                       case 0: clear_bit(index, &list->buttons); 
break;
-                                       case 1: set_bit(index, &list->buttons); break;
-                                       case 2: return;
-                               }
-                               break;
-               }
-                               
-               list->ready = 1;
+                       if (list->fasync)
+                               kill_fasync(list->fasync, SIGIO, POLL_IN);
 
-               if (list->fasync)
-                       kill_fasync(list->fasync, SIGIO, POLL_IN);
+                       list = list->next;
+               }
 
-               list = list->next;
+               wake_up_interruptible(&((*mousedev)->wait));
+               mousedev++;
        }
-
-       wake_up_interruptible(&mousedev->wait);
 }
 
 static int mousedev_fasync(int fd, struct file *file, int on)
@@ -156,6 +167,21 @@
        while (*listptr && (*listptr != list))
                listptr = &((*listptr)->next);
        *listptr = (*listptr)->next;
+
+       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_close_device(handle);
+                               handle = handle->hnext;
+                       }
+               } else {
+                       if (!mousedev_mix.open) 
+                               input_close_device(&list->mousedev->handle);
+               }
+       }
        
        if (!--list->mousedev->used) {
                input_unregister_minor(list->mousedev->devfs);
@@ -188,9 +214,24 @@
        list->mousedev = mousedev_table[i];
        list->next = mousedev_table[i]->list;
        mousedev_table[i]->list = list;
+       file->private_data = list;
+
        list->mousedev->used++;
 
-       file->private_data = list;
+       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);
+                               handle = handle->hnext;
+                       }
+               } else {
+                       if (!mousedev_mix.open) 
+                               input_open_device(&list->mousedev->handle);
+               }
+       }
 
        return 0;
 }
@@ -342,63 +383,59 @@
        fasync:         mousedev_fasync,
 };
 
-static int mousedev_connect(struct input_handler *handler, struct input_dev *dev)
+static struct input_handle *mousedev_connect(struct input_handler *handler, struct 
+input_dev *dev)
 {
        struct mousedev *mousedev;
-       struct input_handle *handle;
        int minor = 0;
 
        if (!test_bit(EV_KEY, dev->evbit) ||
           (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit)))
-               return -1;
+               return NULL;
 
        if ((!test_bit(EV_REL, dev->evbit) || !test_bit(REL_X, dev->relbit)) &&
            (!test_bit(EV_ABS, dev->evbit) || !test_bit(ABS_X, dev->absbit)))
-               return -1;
+               return NULL;
 
-#ifndef CONFIG_INPUT_MOUSEDEV_MIX
        for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
        if (mousedev_table[minor]) {
                printk(KERN_ERR "mousedev: no more free mousedev devices\n");
-               return -1;
+               return NULL;
        }
 
        if (!(mousedev = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
-               return -1;
+               return NULL;
        memset(mousedev, 0, sizeof(struct mousedev));
        init_waitqueue_head(&mousedev->wait);
 
-       mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
-#else
-       mousedev = mousedev_table[0];
-#endif
-
-       if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) {
-               if (!mousedev->used) kfree(mousedev);
-               return -1;
-       }
-       memset(handle, 0, sizeof(struct input_handle));
-
-       mousedev->used++;
+       mousedev->used = 1;
        mousedev->minor = minor;
        mousedev_table[minor] = mousedev;
 
-       handle->dev = dev;
-       handle->handler = handler;
-       handle->private = mousedev;
+       mousedev->handle.dev = dev;
+       mousedev->handle.handler = handler;
+       mousedev->handle.private = mousedev;
+
+       mousedev->devfs = input_register_minor("mouse%d", minor, MOUSEDEV_MINOR_BASE);
 
-       input_open_device(handle);
+       if (mousedev_mix.open) {
+               input_open_device(&mousedev->handle);
+               mousedev_mix.open++;
+       }
 
        printk("mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
 
-       return 0;
+       return &mousedev->handle;
 }
 
 static void mousedev_disconnect(struct input_handle *handle)
 {
        struct mousedev *mousedev = handle->private;
-       input_close_device(handle);
-       kfree(handle);
+
+       if (mousedev->open || mousedev_mix.open) {
+               input_close_device(handle);
+               mousedev_mix.open--;
+       }
+
        if (!--mousedev->used) {
                input_unregister_minor(mousedev->devfs);
                mousedev_table[mousedev->minor] = NULL;
@@ -418,23 +455,21 @@
 {
        input_register_handler(&mousedev_handler);
 
-#ifdef CONFIG_INPUT_MOUSEDEV_MIX
-       if (!(mousedev_table[0] = kmalloc(sizeof(struct mousedev), GFP_KERNEL)))
-               return -1;
-       memset(mousedev_table[0], 0, sizeof(struct mousedev));
-       init_waitqueue_head(&mousedev_table[0]->wait);
-       mousedev_table[0]->devfs = input_register_minor("mouse%d", 0, 
MOUSEDEV_MINOR_BASE);
-       mousedev_table[0]->used = 1;
-#endif
+       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.minor = MOUSEDEV_MIX;
+       mousedev_mix.devfs = input_register_minor("mouse", MOUSEDEV_MIX, 
+MOUSEDEV_MINOR_BASE);
+
+       printk("mouse: PS/2 mouse device common for all mice\n");
+
        return 0;
 }
 
 static void __exit mousedev_exit(void)
 {
-#ifdef CONFIG_INPUT_MOUSEDEV_MIX
-       input_unregister_minor(mousedev_table[0]->devfs);
-       kfree(mousedev_table[0]);
-#endif
+       input_unregister_minor(mousedev_mix.devfs);
        input_unregister_handler(&mousedev_handler);
 }
 
diff -urN linux-2.3.99-pre4-5-old/include/linux/input.h 
linux-2.3.99-pre4-5-usb/include/linux/input.h
--- linux-2.3.99-pre4-5-old/include/linux/input.h       Sat Apr  8 11:09:50 2000
+++ linux-2.3.99-pre4-5-usb/include/linux/input.h       Sat Apr  8 17:47:31 2000
@@ -68,9 +68,12 @@
 
 #define EVIOCGVERSION          _IOR('E', 0x01, __u32)                  /* get driver 
version */
 #define EVIOCGID               _IOR('E', 0x02, struct input_id)        /* get device 
ID */
+#define EVIOCGREP              _IOR('E', 0x03, int[2])                 /* get repeat 
+settings */
+#define EVIOCSREP              _IOW('E', 0x03, int[2])                 /* get repeat 
+settings */
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x03, len)         /* get 
device name */
 #define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event 
bits */
-#define EVIOCGABSLIM(num)      _IOR('E', 0x40 + num, 4 * sizeof(int))  /* get abs 
event limits */ 
+#define EVIOCGABSLIM(num)      _IOR('E', 0x40 + num, int[4])           /* get abs 
+event limits */ 
+#define EVIOCGABS(num)         _IOR('E', 0x80 + num, int)              /* get abs 
+value */
 
 /*
  * Event types
@@ -299,11 +302,12 @@
 #define BTN_THUMB2             0x122
 #define BTN_TOP                        0x123
 #define BTN_TOP2               0x124
-#define BTN_BASE               0x125
-#define BTN_BASE2              0x126
-#define BTN_BASE3              0x127
-#define BTN_BASE4              0x128
-#define BTN_BASE5              0x129
+#define BTN_PINKIE             0x125
+#define BTN_BASE               0x126
+#define BTN_BASE2              0x127
+#define BTN_BASE3              0x128
+#define BTN_BASE4              0x129
+#define BTN_BASE5              0x12a
 
 #define BTN_GAMEPAD            0x130
 #define BTN_A                  0x130
@@ -459,7 +463,7 @@
        void *private;
 
        void (*event)(struct input_handle *handle, unsigned int type, unsigned int 
code, int value);
-       int (*connect)(struct input_handler *handler, struct input_dev *dev);
+       struct input_handle* (*connect)(struct input_handler *handler, struct 
+input_dev *dev);
        void (*disconnect)(struct input_handle *handle);
 
        struct file_operations *fops;
@@ -472,6 +476,8 @@
 struct input_handle {
 
        void *private;
+
+       int open;
        
        struct input_dev *dev;
        struct input_handler *handler;
@@ -486,7 +492,7 @@
 void input_register_handler(struct input_handler *);
 void input_unregister_handler(struct input_handler *);
 
-void input_open_device(struct input_handle *);
+int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
 devfs_handle_t input_register_minor(char *name, int minor, int minor_base);

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

Reply via email to