]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Input drivers, step #3
authorVojtech Pavlik <vojtech@suse.cz>
Thu, 7 Feb 2002 01:46:57 +0000 (17:46 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Thu, 7 Feb 2002 01:46:57 +0000 (17:46 -0800)
This patch updates the input core to the current version, fixing a bunch
of bugs, adding hotplug support and a listing of available input devices
in /proc. The later is very useful for troubleshooting.

Vojtech Pavlik
SuSE Labs

drivers/input/evdev.c
drivers/input/input.c
drivers/input/joydev.c
drivers/input/joystick/iforce.c
drivers/input/keybdev.c
drivers/input/mousedev.c
include/linux/gameport.h
include/linux/input.h
include/linux/serio.h

index 4fa77c99ccf7e9de3ae245eef3c12b986b3938a5..413002ffa57428a784d9a4d05727fdbd442e0e37 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * $Id: evdev.c,v 1.27 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: evdev.c,v 1.42 2002/01/02 11:59:56 vojtech Exp $
  *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
  *  Event char devices, giving access to raw input device events.
- *
- *  Sponsored by SuSE
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #define EVDEV_MINOR_BASE       64
@@ -42,7 +40,9 @@
 struct evdev {
        int exist;
        int open;
+       int open_for_write;
        int minor;
+       char name[16];
        struct input_handle handle;
        wait_queue_head_t wait;
        devfs_handle_t devfs;
@@ -89,6 +89,11 @@ static int evdev_fasync(int fd, struct file *file, int on)
        return retval < 0 ? retval : 0;
 }
 
+static int evdev_flush(struct file * file)
+{
+       return input_flush_device(&((struct evdev_list*)file->private_data)->evdev->handle, file);
+}
+
 static int evdev_release(struct inode * inode, struct file * file)
 {
        struct evdev_list *list = file->private_data;
@@ -120,10 +125,16 @@ static int evdev_open(struct inode * inode, struct file * file)
 {
        struct evdev_list *list;
        int i = minor(inode->i_rdev) - EVDEV_MINOR_BASE;
+       int accept_err;
 
        if (i >= EVDEV_MINORS || !evdev_table[i])
                return -ENODEV;
 
+       /* Ask the driver if he wishes to accept the open() */
+       if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) {
+               return accept_err;
+       }
+
        if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
                return -ENOMEM;
        memset(list, 0, sizeof(struct evdev_list));
@@ -167,7 +178,7 @@ static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_
        if (list->head == list->tail) {
 
                add_wait_queue(&list->evdev->wait, &wait);
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
 
                while (list->head == list->tail) {
 
@@ -187,7 +198,7 @@ static ssize_t evdev_read(struct file * file, char * buffer, size_t count, loff_
                        schedule();
                }
 
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
                remove_wait_queue(&list->evdev->wait, &wait);
        }
 
@@ -219,7 +230,7 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        struct evdev_list *list = file->private_data;
        struct evdev *evdev = list->evdev;
        struct input_dev *dev = evdev->handle.dev;
-       int retval;
+       int retval, t, u;
 
        switch (cmd) {
 
@@ -232,6 +243,40 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        if ((retval = put_user(dev->idproduct, ((short *) arg) + 2))) return retval;
                        if ((retval = put_user(dev->idversion, ((short *) arg) + 3))) return retval;
                        return 0;
+               
+               case EVIOCGREP:
+                       if ((retval = put_user(dev->rep[0], ((int *) arg) + 0))) return retval;
+                       if ((retval = put_user(dev->rep[1], ((int *) arg) + 1))) return retval;
+                       return 0;
+
+               case EVIOCSREP:
+                       if ((retval = get_user(dev->rep[0], ((int *) arg) + 0))) return retval;
+                       if ((retval = get_user(dev->rep[1], ((int *) arg) + 1))) return retval;
+                       return 0;
+
+               case EVIOCGKEYCODE:
+                       if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
+                       if (t < 0 || t > dev->keycodemax) return -EINVAL;
+                       switch (dev->keycodesize) {
+                               case 1: u = *(u8*)(dev->keycode + t); break;
+                               case 2: u = *(u16*)(dev->keycode + t * 2); break;
+                               case 4: u = *(u32*)(dev->keycode + t * 4); break;
+                               default: return -EINVAL;
+                       }
+                       if ((retval = put_user(u, ((int *) arg) + 1))) return retval;
+                       return 0;
+
+               case EVIOCSKEYCODE:
+                       if ((retval = get_user(t, ((int *) arg) + 0))) return retval;
+                       if (t < 0 || t > dev->keycodemax) return -EINVAL;
+                       if ((retval = get_user(u, ((int *) arg) + 1))) return retval;
+                       switch (dev->keycodesize) {
+                               case 1: *(u8*)(dev->keycode + t) = u; break;
+                               case 2: *(u16*)(dev->keycode + t * 2) = u; break;
+                               case 4: *(u32*)(dev->keycode + t * 4) = u; break;
+                               default: return -EINVAL;
+                       }
+                       return 0;
 
                case EVIOCSFF:
                        if (dev->upload_effect) {
@@ -280,22 +325,55 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                                        default: return -EINVAL;
                                }
                                len = NBITS(len) * sizeof(long);
-                               if (len > _IOC_SIZE(cmd)) {
-                                       printk(KERN_WARNING "evdev.c: Truncating bitfield length from %d to %d\n",
-                                               len, _IOC_SIZE(cmd));
-                                       len = _IOC_SIZE(cmd);
-                               }
+                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
                                return copy_to_user((char *) arg, bits, len) ? -EFAULT : len;
                        }
 
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) {
+                               int len;
+                               len = NBITS(KEY_MAX) * sizeof(long);
+                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                               return copy_to_user((char *) arg, dev->key, len) ? -EFAULT : len;
+                       }
+
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) {
+                               int len;
+                               len = NBITS(LED_MAX) * sizeof(long);
+                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                               return copy_to_user((char *) arg, dev->led, len) ? -EFAULT : len;
+                       }
+
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) {
+                               int len;
+                               len = NBITS(SND_MAX) * sizeof(long);
+                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                               return copy_to_user((char *) arg, dev->snd, len) ? -EFAULT : len;
+                       }
+
                        if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) {
                                int len;
-                               if (!dev->name) return 0;
+                               if (!dev->name) return -ENOENT;
                                len = strlen(dev->name) + 1;
                                if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
                                return copy_to_user((char *) arg, dev->name, len) ? -EFAULT : len;
                        }
 
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) {
+                               int len;
+                               if (!dev->phys) return -ENOENT;
+                               len = strlen(dev->phys) + 1;
+                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                               return copy_to_user((char *) arg, dev->phys, len) ? -EFAULT : len;
+                       }
+
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) {
+                               int len;
+                               if (!dev->uniq) return -ENOENT;
+                               len = strlen(dev->uniq) + 1;
+                               if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
+                               return copy_to_user((char *) arg, dev->uniq, len) ? -EFAULT : len;
+                       }
+
                        if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
 
                                int t = _IOC_NR(cmd) & ABS_MAX;
@@ -321,9 +399,10 @@ static struct file_operations evdev_fops = {
        release:        evdev_release,
        ioctl:          evdev_ioctl,
        fasync:         evdev_fasync,
+       flush:          evdev_flush
 };
 
-static struct input_handle *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 input_device_id *id)
 {
        struct evdev *evdev;
        int minor;
@@ -342,16 +421,17 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
 
        evdev->minor = minor;
        evdev_table[minor] = evdev;
+       
+       sprintf(evdev->name, "event%d", minor);
 
        evdev->handle.dev = dev;
+       evdev->handle.name = evdev->name;
        evdev->handle.handler = handler;
        evdev->handle.private = evdev;
 
-       evdev->exist = 1;
-
        evdev->devfs = input_register_minor("event%d", minor, EVDEV_MINOR_BASE);
 
-//     printk(KERN_INFO "event%d: Event device for input%d\n", minor, dev->number);
+       evdev->exist = 1;
 
        return &evdev->handle;
 }
@@ -372,12 +452,21 @@ static void evdev_disconnect(struct input_handle *handle)
        }
 }
 
+static struct input_device_id evdev_ids[] = {
+       { driver_info: 1 },     /* Matches all devices */
+       { },                    /* Terminating zero entry */
+};
+
+MODULE_DEVICE_TABLE(input, evdev_ids);
+
 static struct input_handler evdev_handler = {
        event:          evdev_event,
        connect:        evdev_connect,
        disconnect:     evdev_disconnect,
        fops:           &evdev_fops,
        minor:          EVDEV_MINOR_BASE,
+       name:           "evdev",
+       id_table:       evdev_ids,
 };
 
 static int __init evdev_init(void)
@@ -394,7 +483,6 @@ static void __exit evdev_exit(void)
 module_init(evdev_init);
 module_exit(evdev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Event character device driver");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input driver event char devices");
 MODULE_LICENSE("GPL");
-
index eb7fe0f1729c102afb304ae64c8eff51e6e83297..32349d2c21b4dad2c07aca1f71928099966ddfd7 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * $Id: input.c,v 1.20 2001/05/17 15:50:27 vojtech Exp $
+ * $Id: input.c,v 1.48 2001/12/26 21:08:33 jsimmons Exp $
  *
  *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  The input layer module itself
- *
- *  Sponsored by SuSE
+ *  The input core
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/random.h>
-
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input layer module");
+#include <linux/pm.h>
+#include <linux/proc_fs.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
-
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
@@ -48,6 +50,8 @@ EXPORT_SYMBOL(input_register_minor);
 EXPORT_SYMBOL(input_unregister_minor);
 EXPORT_SYMBOL(input_open_device);
 EXPORT_SYMBOL(input_close_device);
+EXPORT_SYMBOL(input_accept_process);
+EXPORT_SYMBOL(input_flush_device);
 EXPORT_SYMBOL(input_event);
 
 #define INPUT_MAJOR    13
@@ -60,10 +64,22 @@ static devfs_handle_t input_devfs_handle;
 static int input_number;
 static long input_devices[NBITS(INPUT_DEVICES)];
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_bus_input_dir;
+DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static int input_devices_state;
+#endif
+
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
        struct input_handle *handle = dev->handle;
 
+/*
+ * Wake up the device if it is sleeping.
+ */
+       if (dev->pm_dev)
+               pm_access(dev->pm_dev);
+
 /*
  * Filter non-events, and bad input values out.
  */
@@ -71,6 +87,8 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
        if (type > EV_MAX || !test_bit(type, dev->evbit))
                return;
 
+       add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
+
        switch (type) {
 
                case EV_KEY:
@@ -130,6 +148,8 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
 
                        if (code > MSC_MAX || !test_bit(code, dev->mscbit))
                                return;
+
+                       if (dev->event) dev->event(dev, type, code, value);     
        
                        break;
 
@@ -185,16 +205,36 @@ static void input_repeat_key(unsigned long data)
        mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
 }
 
+int input_accept_process(struct input_handle *handle, struct file *file)
+{
+       if (handle->dev->accept)
+               return handle->dev->accept(handle->dev, file);
+
+       return 0;
+}
+
 int input_open_device(struct input_handle *handle)
 {
+       if (handle->dev->pm_dev)
+               pm_access(handle->dev->pm_dev);
        handle->open++;
        if (handle->dev->open)
                return handle->dev->open(handle->dev);
        return 0;
 }
 
+int input_flush_device(struct input_handle* handle, struct file* file)
+{
+       if (handle->dev->flush)
+               return handle->dev->flush(handle->dev, file);
+
+       return 0;
+}
+
 void input_close_device(struct input_handle *handle)
 {
+       if (handle->dev->pm_dev)
+               pm_dev_idle(handle->dev->pm_dev);
        if (handle->dev->close)
                handle->dev->close(handle->dev);
        handle->open--;
@@ -208,25 +248,197 @@ static void input_link_handle(struct input_handle *handle)
        handle->handler->handle = handle;
 }
 
+/**
+ *     input_find_and_remove - Find and remove node
+ *
+ *     @type:          data type
+ *     @initval:       initial value
+ *     @targ:          node to find
+ *     @next:          next node in the list
+ *
+ *     Searches the linked list for the target node @targ. If the node
+ *     is found, it is removed from the list.
+ *
+ *     If the node is not found, the end of the list will be hit,
+ *     indicating that it wasn't in the list to begin with.
+ *
+ *     Returns nothing.
+ */
+#define input_find_and_remove(type, initval, targ, next)               \
+       do {                                                            \
+               type **ptr;                                             \
+               for (ptr = &initval; *ptr; ptr = &((*ptr)->next))       \
+                       if (*ptr == targ) break;                        \
+               if (*ptr) *ptr = (*ptr)->next;                          \
+       } while (0)
+
 static void input_unlink_handle(struct input_handle *handle)
 {
-       struct input_handle **handleptr;
+       input_find_and_remove(struct input_handle, handle->dev->handle, handle, dnext);
+        input_find_and_remove(struct input_handle, handle->handler->handle, handle, hnext);
+}
+
+#define MATCH_BIT(bit, max) \
+               for (i = 0; i < NBITS(max); i++) \
+                       if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
+                               break; \
+               if (i != NBITS(max)) \
+                       continue;
+
+static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+{
+       int i;
 
-       handleptr = &handle->dev->handle;
-       while (*handleptr && (*handleptr != handle))
-               handleptr = &((*handleptr)->dnext);
-       *handleptr = (*handleptr)->dnext;
+       for (; id->flags || id->driver_info; id++) {
 
-       handleptr = &handle->handler->handle;
-       while (*handleptr && (*handleptr != handle))
-               handleptr = &((*handleptr)->hnext);
-       *handleptr = (*handleptr)->hnext;
+               if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+                       if (id->idbus != dev->idbus)
+                               continue;
+
+               if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)
+                       if (id->idvendor != dev->idvendor)
+                               continue;
+       
+               if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)
+                       if (id->idproduct != dev->idproduct)
+                               continue;
+               
+               if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
+                       if (id->idversion != dev->idversion)
+                               continue;
+
+               MATCH_BIT(evbit,  EV_MAX);
+               MATCH_BIT(keybit, KEY_MAX);
+               MATCH_BIT(relbit, REL_MAX);
+               MATCH_BIT(absbit, ABS_MAX);
+               MATCH_BIT(mscbit, MSC_MAX);
+               MATCH_BIT(ledbit, LED_MAX);
+               MATCH_BIT(sndbit, SND_MAX);
+               MATCH_BIT(ffbit,  FF_MAX);
+
+               return id;
+       }
+
+       return NULL;
 }
 
+/*
+ * Input hotplugging interface - loading event handlers based on
+ * device bitfields.
+ */
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * Input hotplugging invokes what /proc/sys/kernel/hotplug says
+ * (normally /sbin/hotplug) when input devices get added or removed.
+ *
+ * This invokes a user mode policy agent, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ */
+
+#define SPRINTF_BIT_A(bit, name, max) \
+       do { \
+               envp[i++] = scratch; \
+               scratch += sprintf(scratch, name); \
+               for (j = NBITS(max) - 1; j >= 0; j--) \
+                       if (dev->bit[j]) break; \
+               for (; j >= 0; j--) \
+                       scratch += sprintf(scratch, "%lx ", dev->bit[j]); \
+               scratch++; \
+       } while (0)
+
+#define SPRINTF_BIT_A2(bit, name, max, ev) \
+       do { \
+               if (test_bit(ev, dev->evbit)) \
+                       SPRINTF_BIT_A(bit, name, max); \
+       } while (0)
+
+static void input_call_hotplug(char *verb, struct input_dev *dev)
+{
+       char *argv[3], **envp, *buf, *scratch;
+       int i = 0, j, value;
+
+       if (!hotplug_path[0]) {
+               printk(KERN_ERR "input.c: calling hotplug a hotplug agent defined\n");
+               return;
+       }
+       if (in_interrupt()) {
+               printk(KERN_ERR "input.c: calling hotplug from interrupt\n");
+               return; 
+       }
+       if (!current->fs->root) {
+               printk(KERN_WARNING "input.c: calling hotplug without valid filesystem\n");
+               return; 
+       }
+       if (!(envp = (char **) kmalloc(20 * sizeof(char *), GFP_KERNEL))) {
+               printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+               return;
+       }
+       if (!(buf = kmalloc(1024, GFP_KERNEL))) {
+               kfree (envp);
+               printk(KERN_ERR "input.c: not enough memory allocating hotplug environment\n");
+               return;
+       }
+
+       argv[0] = hotplug_path;
+       argv[1] = "input";
+       argv[2] = 0;
+
+       envp[i++] = "HOME=/";
+       envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+
+       scratch = buf;
+
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
+
+       envp[i++] = scratch;
+       scratch += sprintf(scratch, "PRODUCT=%x/%x/%x/%x",
+               dev->idbus, dev->idvendor, dev->idproduct, dev->idversion) + 1; 
+       
+       if (dev->name) {
+               envp[i++] = scratch;
+               scratch += sprintf(scratch, "NAME=%s", dev->name) + 1; 
+       }
+
+       if (dev->phys) {
+               envp[i++] = scratch;
+               scratch += sprintf(scratch, "PHYS=%s", dev->phys) + 1; 
+       }       
+
+       SPRINTF_BIT_A(evbit, "EV=", EV_MAX);
+       SPRINTF_BIT_A2(keybit, "KEY=", KEY_MAX, EV_KEY);
+       SPRINTF_BIT_A2(relbit, "REL=", REL_MAX, EV_REL);
+       SPRINTF_BIT_A2(absbit, "ABS=", ABS_MAX, EV_ABS);
+       SPRINTF_BIT_A2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+       SPRINTF_BIT_A2(ledbit, "LED=", LED_MAX, EV_LED);
+       SPRINTF_BIT_A2(sndbit, "SND=", SND_MAX, EV_SND);
+       SPRINTF_BIT_A2(ffbit,  "FF=",  FF_MAX, EV_FF);
+
+       envp[i++] = 0;
+
+       printk(KERN_DEBUG "input.c: calling %s %s [%s %s %s %s %s]\n",
+               argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);
+
+       value = call_usermodehelper(argv [0], argv, envp);
+
+       kfree(buf);
+       kfree(envp);
+
+       if (value != 0)
+               printk(KERN_WARNING "input.c: hotplug returned %d\n", value);
+}
+
+#endif
+
 void input_register_device(struct input_dev *dev)
 {
        struct input_handler *handler = input_handler;
        struct input_handle *handle;
+       struct input_device_id *id;
 
 /*
  * Initialize repeat timer to default values.
@@ -259,18 +471,45 @@ void input_register_device(struct input_dev *dev)
  */
 
        while (handler) {
-               if ((handle = handler->connect(handler, dev)))
-                       input_link_handle(handle);
+               if ((id = input_match_device(handler->id_table, dev)))
+                       if ((handle = handler->connect(handler, dev)))
+                               input_link_handle(handle);
                handler = handler->next;
        }
+
+/*
+ * Notify the hotplug agent.
+ */
+
+#ifdef CONFIG_HOTPLUG
+       input_call_hotplug("add", dev);
+#endif
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+       input_devices_state++;
+       wake_up(&input_devices_poll_wait);
+#endif
+
 }
 
 void input_unregister_device(struct input_dev *dev)
 {
        struct input_handle *handle = dev->handle;
-       struct input_dev **devptr = &input_dev;
        struct input_handle *dnext;
 
+       if (!dev) return;
+
+/*
+ * Turn off power management for the device.
+ */
+       if (dev->pm_dev)
+               pm_unregister(dev->pm_dev);
+
+
 /*
  * Kill any pending repeat timers.
  */
@@ -289,23 +528,36 @@ void input_unregister_device(struct input_dev *dev)
        }
 
 /*
- * Remove the device.
+ * Notify the hotplug agent.
  */
 
-       while (*devptr && (*devptr != dev))
-               devptr = &((*devptr)->next);
-       *devptr = (*devptr)->next;
+#ifdef CONFIG_HOTPLUG
+       input_call_hotplug("remove", dev);
+#endif
+
+/*
+ * Remove the device.
+ */
+       input_find_and_remove(struct input_dev, input_dev, dev, next);
 
        input_number--;
+/*
+ * Notify /proc.
+ */
 
-       if (dev->number < INPUT_DEVICES)
-               clear_bit(dev->number, input_devices);
+#ifdef CONFIG_PROC_FS
+       input_devices_state++;
+       wake_up(&input_devices_poll_wait);
+#endif
 }
 
 void input_register_handler(struct input_handler *handler)
 {
        struct input_dev *dev = input_dev;
        struct input_handle *handle;
+       struct input_device_id *id;
+
+       if (!handler) return;
 
 /*
  * Add minors if needed.
@@ -326,15 +578,24 @@ void input_register_handler(struct input_handler *handler)
  */
 
        while (dev) {
-               if ((handle = handler->connect(handler, dev)))
-                       input_link_handle(handle);
+               if ((id = input_match_device(handler->id_table, dev)))
+                       if ((handle = handler->connect(handler, dev, id)))
+                               input_link_handle(handle);
                dev = dev->next;
        }
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+       input_devices_state++;
+       wake_up(&input_devices_poll_wait);
+#endif
 }
 
 void input_unregister_handler(struct input_handler *handler)
 {
-       struct input_handler **handlerptr = &input_handler;
        struct input_handle *handle = handler->handle;
        struct input_handle *hnext;
 
@@ -352,18 +613,23 @@ void input_unregister_handler(struct input_handler *handler)
 /*
  * Remove it.
  */
-
-       while (*handlerptr && (*handlerptr != handler))
-               handlerptr = &((*handlerptr)->next);
-
-       *handlerptr = (*handlerptr)->next;
+       input_find_and_remove(struct input_handler, input_handler, handler,
+                               next);
 
 /*
  * Remove minors.
  */
-
        if (handler->fops != NULL)
                input_table[handler->minor >> 5] = NULL;
+
+/*
+ * Notify /proc.
+ */
+
+#ifdef CONFIG_PROC_FS
+       input_devices_state++;
+       wake_up(&input_devices_poll_wait);
+#endif
 }
 
 static int input_open_file(struct inode *inode, struct file *file)
@@ -415,18 +681,164 @@ void input_unregister_minor(devfs_handle_t handle)
        devfs_unregister(handle);
 }
 
+/*
+ * ProcFS interface for the input drivers.
+ */
+
+#ifdef CONFIG_PROC_FS
+
+#define SPRINTF_BIT_B(bit, name, max) \
+       do { \
+               len += sprintf(buf + len, "B: %s", name); \
+               for (i = NBITS(max) - 1; i >= 0; i--) \
+                       if (dev->bit[i]) break; \
+               for (; i >= 0; i--) \
+                       len += sprintf(buf + len, "%lx ", dev->bit[i]); \
+               len += sprintf(buf + len, "\n"); \
+       } while (0)
+
+#define SPRINTF_BIT_B2(bit, name, max, ev) \
+       do { \
+               if (test_bit(ev, dev->evbit)) \
+                       SPRINTF_BIT_B(bit, name, max); \
+       } while (0)
+
+
+static unsigned int input_devices_poll(struct file *file, poll_table *wait)
+{
+       int state = input_devices_state;
+       poll_wait(file, &input_devices_poll_wait, wait);
+       if (state != input_devices_state)
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+static int input_devices_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+       struct input_dev *dev = input_dev;
+       struct input_handle *handle;
+
+       off_t at = 0;
+       int i, len, cnt = 0;
+
+       while (dev) {
+
+               len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
+                       dev->idbus, dev->idvendor, dev->idproduct, dev->idversion);
+
+               len += sprintf(buf + len, "N: Name=\"%s\"\n", dev->name ? dev->name : "");
+               len += sprintf(buf + len, "P: Phys=%s\n", dev->phys ? dev->phys : "");
+               len += sprintf(buf + len, "D: Drivers=");
+
+               handle = dev->handle;
+
+               while (handle) {
+                       len += sprintf(buf + len, "%s ", handle->name);
+                       handle = handle->dnext;
+               }
+
+               len += sprintf(buf + len, "\n");
+
+               SPRINTF_BIT_B(evbit, "EV=", EV_MAX);
+               SPRINTF_BIT_B2(keybit, "KEY=", KEY_MAX, EV_KEY);
+               SPRINTF_BIT_B2(relbit, "REL=", REL_MAX, EV_REL);
+               SPRINTF_BIT_B2(absbit, "ABS=", ABS_MAX, EV_ABS);
+               SPRINTF_BIT_B2(mscbit, "MSC=", MSC_MAX, EV_MSC);
+               SPRINTF_BIT_B2(ledbit, "LED=", LED_MAX, EV_LED);
+               SPRINTF_BIT_B2(sndbit, "SND=", SND_MAX, EV_SND);
+               SPRINTF_BIT_B2(ffbit,  "FF=",  FF_MAX, EV_FF);
+
+               len += sprintf(buf + len, "\n");
+
+               at += len;
+
+               if (at >= pos) {
+                       if (!*start) {
+                               *start = buf + (pos - (at - len));
+                               cnt = at - pos;
+                       } else  cnt += len;
+                       buf += len;
+                       if (cnt >= count)
+                               break;
+               }
+
+               dev = dev->next;
+       }
+
+       if (!dev) *eof = 1;
+
+       return (count > cnt) ? cnt : count;
+}
+
+static int input_handlers_read(char *buf, char **start, off_t pos, int count, int *eof, void *data)
+{
+       struct input_handler *handler = input_handler;
+
+       off_t at = 0;
+       int len = 0, cnt = 0;
+       int i = 0;
+
+       while (handler) {
+
+               if (handler->fops)
+                       len = sprintf(buf, "N: Number=%d Name=%s Minor=%d\n",
+                               i++, handler->name, handler->minor);
+               else
+                       len = sprintf(buf, "N: Number=%d Name=%s\n",
+                               i++, handler->name);
+
+               at += len;
+
+               if (at >= pos) {
+                       if (!*start) {
+                               *start = buf + (pos - (at - len));
+                               cnt = at - pos;
+                       } else  cnt += len;
+                       buf += len;
+                       if (cnt >= count)
+                               break;
+               }
+
+               handler = handler->next;
+       }
+
+       if (!handler) *eof = 1;
+
+       return (count > cnt) ? cnt : count;
+}
+
+#endif
+
 static int __init input_init(void)
 {
+       struct proc_dir_entry *entry;
+
+#ifdef CONFIG_PROC_FS
+       proc_bus_input_dir = proc_mkdir("input", proc_bus);
+       proc_bus_input_dir->owner = THIS_MODULE;
+       entry = create_proc_read_entry("devices", 0, proc_bus_input_dir, input_devices_read, NULL);
+       entry->owner = THIS_MODULE;
+       entry->proc_fops->poll = input_devices_poll;
+       entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
+       entry->owner = THIS_MODULE;
+#endif
        if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
                printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
                return -EBUSY;
        }
+
        input_devfs_handle = devfs_mk_dir(NULL, "input", NULL);
+
        return 0;
 }
 
 static void __exit input_exit(void)
 {
+#ifdef CONFIG_PROC_FS
+       remove_proc_entry("devices", proc_bus_input_dir);
+       remove_proc_entry("handlers", proc_bus_input_dir);
+       remove_proc_entry("input", proc_bus);
+#endif
        devfs_unregister(input_devfs_handle);
         if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
                 printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
index f17165bddc0ab831a19a7d1e17b083ec4d6b9d8d..e5b845e2946864f160c5d7895a180eb66169e4a1 100644 (file)
@@ -1,12 +1,10 @@
 /*
- * $Id: joydev.c,v 1.19 2001/01/10 19:49:40 vojtech Exp $
+ * $Id: joydev.c,v 1.38 2001/12/27 10:37:41 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik 
+ *  Copyright (c) 1999-2001 Vojtech Pavlik 
  *  Copyright (c) 1999 Colin Van Dyke 
  *
  *  Joystick device driver for the input driver suite.
- *
- *  Sponsored by SuSE and Intel
  */
 
 /*
@@ -25,8 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <asm/io.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Joystick device interfaces");
+MODULE_SUPPORTED_DEVICE("input/js");
+MODULE_LICENSE("GPL");
+
 #define JOYDEV_MINOR_BASE      0
 #define JOYDEV_MINORS          32
 #define JOYDEV_BUFFER_SIZE     64
 
+#define MSECS(t)       (1000 * ((t) / HZ) + 1000 * ((t) % HZ) / HZ)
+
 struct joydev {
        int exist;
        int open;
        int minor;
+       char name[16];
        struct input_handle handle;
        wait_queue_head_t wait;
        devfs_handle_t devfs;
@@ -81,11 +87,6 @@ struct joydev_list {
 
 static struct joydev *joydev_table[JOYDEV_MINORS];
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Joystick device driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("input/js");
-
 static int joydev_correct(int value, struct js_corr *corr)
 {
        switch (corr->type) {
@@ -133,7 +134,7 @@ static void joydev_event(struct input_handle *handle, unsigned int type, unsigne
                        return;
        }  
 
-       event.time = jiffies * (1000 / HZ);
+       event.time = MSECS(jiffies);
 
        while (list) {
 
@@ -163,7 +164,7 @@ static int joydev_release(struct inode * inode, struct file * file)
 {
        struct joydev_list *list = file->private_data;
        struct joydev_list **listptr;
-       
+
        listptr = &list->joydev->list;
        joydev_fasync(-1, file, 0);
 
@@ -249,7 +250,7 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
        if (list->head == list->tail && list->startup == joydev->nabs + joydev->nkey) {
 
                add_wait_queue(&list->joydev->wait, &wait);
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
 
                while (list->head == list->tail) {
 
@@ -265,7 +266,7 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
                        schedule();
                }
 
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
                remove_wait_queue(&list->joydev->wait, &wait);
        }
 
@@ -276,7 +277,7 @@ static ssize_t joydev_read(struct file *file, char *buf, size_t count, loff_t *p
 
                struct js_event event;
 
-               event.time = jiffies * (1000/HZ);
+               event.time = MSECS(jiffies);
 
                if (list->startup < joydev->nkey) {
                        event.type = JS_EVENT_BUTTON | JS_EVENT_INIT;
@@ -360,9 +361,9 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        return copy_to_user((struct js_corr *) arg, joydev->corr,
                                                sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
                case JSIOCSAXMAP:
-                       if (copy_from_user((__u8 *) arg, joydev->abspam, sizeof(__u8) * ABS_MAX))
+                       if (copy_from_user(joydev->abspam, (__u8 *) arg, sizeof(__u8) * ABS_MAX))
                                return -EFAULT;
-                       for (i = 0; i < ABS_MAX; i++) {
+                       for (i = 0; i < joydev->nabs; i++) {
                                if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
                                joydev->absmap[joydev->abspam[i]] = i;
                        }
@@ -371,11 +372,11 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        return copy_to_user((__u8 *) arg, joydev->abspam,
                                                sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
                case JSIOCSBTNMAP:
-                       if (copy_from_user((__u16 *) arg, joydev->absmap, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+                       if (copy_from_user(joydev->keypam, (__u16 *) arg, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
                                return -EFAULT;
-                       for (i = 0; i < KEY_MAX - BTN_MISC; i++); {
+                       for (i = 0; i < joydev->nkey; i++); {
                                if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
-                               joydev->keymap[joydev->abspam[i - BTN_MISC]] = i;
+                               joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
                        }
                        return 0;
                case JSIOCGBTNMAP:
@@ -405,15 +406,13 @@ static struct file_operations joydev_fops = {
        fasync:         joydev_fasync,
 };
 
-static struct input_handle *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 input_device_id *id)
 {
        struct joydev *joydev;
-       int i, j, minor;
+       int i, j, t, minor;
 
-       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 NULL; 
+        if (test_bit(BTN_TOUCH, dev->keybit))
+               return NULL;
 
        for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++);
        if (minor == JOYDEV_MINORS) {
@@ -430,12 +429,13 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
        joydev->minor = minor;
        joydev_table[minor] = joydev;
 
+       sprintf(joydev->name, "js%d", minor);
+
        joydev->handle.dev = dev;
+       joydev->handle.name = joydev->name;
        joydev->handle.handler = handler;
        joydev->handle.private = joydev;
 
-       joydev->exist = 1;
-
        for (i = 0; i < ABS_MAX; i++)
                if (test_bit(i, dev->absbit)) {
                        joydev->absmap[i] = joydev->nabs;
@@ -467,15 +467,17 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
                joydev->corr[i].prec = dev->absfuzz[j];
                joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
                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]);
+               if (!(t = ((dev->absmax[j] - dev->absmin[j]) / 2 - 2 * dev->absflat[j])))
+                       continue;
+               joydev->corr[i].coef[2] = (1 << 29) / t;
+               joydev->corr[i].coef[3] = (1 << 29) / t;
 
                joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
        }
 
        joydev->devfs = input_register_minor("js%d", minor, JOYDEV_MINOR_BASE);
 
-//     printk(KERN_INFO "js%d: Joystick device for input%d\n", minor, dev->number);
+       joydev->exist = 1;
 
        return &joydev->handle;
 }
@@ -495,12 +497,35 @@ static void joydev_disconnect(struct input_handle *handle)
        }
 }
 
+static struct input_device_id joydev_ids[] = {
+       {
+               flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+               evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+               absbit: { BIT(ABS_X) },
+       },
+       {
+               flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+               evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+               absbit: { BIT(ABS_WHEEL) },
+       },
+       {
+               flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+               evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+               absbit: { BIT(ABS_THROTTLE) },
+       },
+       { },    /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, joydev_ids);
+
 static struct input_handler joydev_handler = {
        event:          joydev_event,
        connect:        joydev_connect,
        disconnect:     joydev_disconnect,
        fops:           &joydev_fops,
        minor:          JOYDEV_MINOR_BASE,
+       name:           "joydev",
+       id_table:       joydev_ids,
 };
 
 static int __init joydev_init(void)
index f77ec220ba30357928f657ef089bae1c3bd0e32d..3dd126a4254955085eaad8ea15c73421a4454baa 100644 (file)
@@ -641,7 +641,7 @@ static int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effec
                effect->replay.delay,
                effect->trigger.button,
                effect->trigger.interval,
-               effect->u.periodic.direction);
+               effect->direction);
 
        return err;
 }
@@ -680,7 +680,7 @@ static int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effec
                effect->replay.delay,
                effect->trigger.button,
                effect->trigger.interval,
-               effect->u.constant.direction);
+               effect->direction);
 
        return err;
 }
@@ -722,7 +722,7 @@ static int iforce_upload_interactive(struct iforce* iforce, struct ff_effect* ef
                case 0: /* Only one axis, choose orientation */
                        mod1 = mod_chunk->start;
                        mod2 = 0xffff;
-                       direction = effect->u.interactive.direction;
+                       direction = effect->direction;
                        axes = 0x20;
                        break;
 
index a437ac103e704dbbdaa87ebe66ca351e7e292fc3..6731dd2542c2cefebc83f857ec39d6493b0a132a 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * $Id: keybdev.c,v 1.3 2000/05/28 17:31:36 vojtech Exp $
+ * $Id: keybdev.c,v 1.16 2002/01/09 04:21:41 lethal Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  Input driver to keyboard driver binding.
- *
- *  Sponsored by SuSE
+ *  Input core to console keyboard binding.
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Input core to console keyboard binding");
+MODULE_LICENSE("GPL");
+
+char keybdev_name[] = "keyboard";
+
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
     defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH) || \
     defined(CONFIG_PPC) || defined(__mc68000__) || defined(__hppa__) || \
-    defined(__arm__)
+    defined(__arm__) || defined(__x86_64__)
 
 static int x86_sysrq_alt = 0;
 #ifdef CONFIG_SPARC64
@@ -48,8 +52,6 @@ static int sparc_l1_a_state = 0;
 extern void batten_down_hatches(void);
 #endif
 
-static int jp_kbd_109 = 1;     /* Yes, .jp is the default. See 51142. */
-
 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,
@@ -62,7 +64,7 @@ static unsigned short x86_keycodes[256] =
        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,
+       118,117,125,374,379,115,112,125,121,123,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 };
@@ -167,26 +169,38 @@ void keybdev_ledfunc(unsigned int led)
        }
 }
 
+/* Tell the user who may be running in X and not see the console that we have 
+   panic'ed. This is to distingush panics from "real" lockups. 
+   Could in theory send the panic message as morse, but that is left as an
+   exercise for the reader.  */ 
+
+void panic_blink(void)
+{ 
+       static unsigned long last_jiffie;
+       static char led;
+       /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is different. */
+       if (jiffies - last_jiffie > HZ/2) {
+               led ^= 0x01 | 0x04;
+               keybdev_ledfunc(led);
+               last_jiffie = jiffies;
+       }
+}  
+
 void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
 {
        if (type != EV_KEY) return;
-
-       if (emulate_raw(code, down))
-               printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", code);
-
+       emulate_raw(code, down);
        tasklet_schedule(&keyboard_tasklet);
 }
 
-static struct input_handle *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_device_id *id)
 {
        struct input_handle *handle;
        int i;
 
-       if (!test_bit(EV_KEY, dev->evbit))
-               return NULL;
-
-       for (i = KEY_RESERVED; i < BTN_MISC; i++)
-               if (test_bit(i, dev->keybit)) break;
+       for (i = KEY_ESC; i < BTN_MISC; i++)
+               if (test_bit(i, dev->keybit))
+                       break;
 
        if (i == BTN_MISC)
                return NULL;
@@ -196,41 +210,42 @@ static struct input_handle *keybdev_connect(struct input_handler *handler, struc
        memset(handle, 0, sizeof(struct input_handle));
 
        handle->dev = dev;
+       handle->name = keybdev_name;
        handle->handler = handler;
 
        input_open_device(handle);
 
-//     printk(KERN_INFO "keybdev.c: Adding keyboard: input%d\n", dev->number);
-
        return handle;
 }
 
 static void keybdev_disconnect(struct input_handle *handle)
 {
-//     printk(KERN_INFO "keybdev.c: Removing keyboard: input%d\n", handle->dev->number);
        input_close_device(handle);
        kfree(handle);
 }
+
+static struct input_device_id keybdev_ids[] = {
+       {
+               flags: INPUT_DEVICE_ID_MATCH_EVBIT,
+               evbit: { BIT(EV_KEY) },
+       },      
+       { },    /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, keybdev_ids);
        
 static struct input_handler keybdev_handler = {
        event:          keybdev_event,
        connect:        keybdev_connect,
        disconnect:     keybdev_disconnect,
+       name:           "keybdev",
+       id_table:       keybdev_ids,
 };
 
 static int __init keybdev_init(void)
 {
        input_register_handler(&keybdev_handler);
        kbd_ledfunc = keybdev_ledfunc;
-
-       if (jp_kbd_109) {
-               x86_keycodes[0xb5] = 0x73;      /* backslash, underscore */
-               x86_keycodes[0xb6] = 0x70;
-               x86_keycodes[0xb7] = 0x7d;      /* Yen, pipe */
-               x86_keycodes[0xb8] = 0x79;
-               x86_keycodes[0xb9] = 0x7b;
-       }
-
        return 0;
 }
 
@@ -243,7 +258,3 @@ static void __exit keybdev_exit(void)
 module_init(keybdev_init);
 module_exit(keybdev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input driver to keyboard driver binding");
-MODULE_PARM(jp_kbd_109, "i");
-MODULE_LICENSE("GPL");
index c37b6a0ddd7657aced5efa5a9f2cffaf56e36acc..01fb98c7f30fac0b2aa982b61bc54770456977e4 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * $Id: mousedev.c,v 1.24 2000/11/15 10:57:45 vojtech Exp $
+ * $Id: mousedev.c,v 1.38 2001/12/26 21:08:33 jsimmons Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  *
- *  Input driver to ImExPS/2 device driver module.
- *
- *  Sponsored by SuSE
+ *  Input driver to ExplorerPS/2 device driver module.
  */
 
 /*
@@ -24,8 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  * 
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #define MOUSEDEV_MINOR_BASE    32
 #include <linux/smp_lock.h>
 #include <linux/random.h>
 
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
+MODULE_LICENSE("GPL");
+
 #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X
 #define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024
 #endif
@@ -52,6 +54,7 @@ struct mousedev {
        int exist;
        int open;
        int minor;
+       char name[16];
        wait_queue_head_t wait;
        struct mousedev_list *list;
        struct input_handle handle;
@@ -89,8 +92,6 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
        struct mousedev_list *list;
        int index, size;
 
-       add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value);
-
        while (*mousedev) {
                list = (*mousedev)->list;
                while (list) {
@@ -101,13 +102,23 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
                                        switch (code) {
                                                case ABS_X:     
                                                        size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
-                                                       list->dx += (value * xres - list->oldx) / size;
-                                                       list->oldx += list->dx * size;
+                                                       if (size != 0) {
+                                                               list->dx += (value * xres - list->oldx) / size;
+                                                               list->oldx += list->dx * size;
+                                                       } else {
+                                                               list->dx += value - list->oldx;
+                                                               list->oldx += list->dx;
+                                                       }
                                                        break;
                                                case ABS_Y:
                                                        size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
-                                                       list->dy -= (value * yres - list->oldy) / size;
-                                                       list->oldy -= list->dy * size;
+                                                       if (size != 0) {
+                                                               list->dy -= (value * yres - list->oldy) / size;
+                                                               list->oldy -= list->dy * size;
+                                                       } else {
+                                                               list->dy -= value - list->oldy;
+                                                               list->oldy -= list->dy;
+                                                       }
                                                        break;
                                        }
                                        break;
@@ -169,7 +180,7 @@ static int mousedev_release(struct inode * inode, struct file * file)
 {
        struct mousedev_list *list = file->private_data;
        struct mousedev_list **listptr;
-       
+
        listptr = &list->mousedev->list;
        mousedev_fasync(-1, file, 0);
 
@@ -344,7 +355,7 @@ static ssize_t mousedev_read(struct file * file, char * buffer, size_t count, lo
        if (!list->ready && !list->buffer) {
 
                add_wait_queue(&list->mousedev->wait, &wait);
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
 
                while (!list->ready) {
 
@@ -360,7 +371,7 @@ static ssize_t mousedev_read(struct file * file, char * buffer, size_t count, lo
                        schedule();
                }
 
-               current->state = TASK_RUNNING;
+               set_current_state(TASK_RUNNING);
                remove_wait_queue(&list->mousedev->wait, &wait);
        }
 
@@ -401,19 +412,11 @@ struct file_operations mousedev_fops = {
        fasync:         mousedev_fasync,
 };
 
-static struct input_handle *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 input_device_id *id)
 {
        struct mousedev *mousedev;
        int minor = 0;
 
-       if (!test_bit(EV_KEY, dev->evbit) ||
-          (!test_bit(BTN_LEFT, dev->keybit) && !test_bit(BTN_TOUCH, dev->keybit)))
-               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 NULL;
-
        for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++);
        if (minor == MOUSEDEV_MINORS) {
                printk(KERN_ERR "mousedev: no more free mousedev devices\n");
@@ -425,11 +428,12 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
        memset(mousedev, 0, sizeof(struct mousedev));
        init_waitqueue_head(&mousedev->wait);
 
-       mousedev->exist = 1;
        mousedev->minor = minor;
        mousedev_table[minor] = mousedev;
+       sprintf(mousedev->name, "mouse%d", minor);
 
        mousedev->handle.dev = dev;
+       mousedev->handle.name = mousedev->name;
        mousedev->handle.handler = handler;
        mousedev->handle.private = mousedev;
 
@@ -438,7 +442,7 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
        if (mousedev_mix.open)
                input_open_device(&mousedev->handle);
 
-//     printk(KERN_INFO "mouse%d: PS/2 mouse device for input%d\n", minor, dev->number);
+       mousedev->exist = 1;
 
        return &mousedev->handle;
 }
@@ -459,6 +463,26 @@ static void mousedev_disconnect(struct input_handle *handle)
                kfree(mousedev);
        }
 }
+
+static struct input_device_id mousedev_ids[] = {
+       {
+               flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
+               evbit: { BIT(EV_KEY) | BIT(EV_REL) },
+               keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
+               relbit: { BIT(REL_X) | BIT(REL_Y) },
+       },      /* A mouse like device, at least one button, two relative axes */
+
+       {
+               flags: INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
+               evbit: { BIT(EV_KEY) | BIT(EV_ABS) },
+               keybit: { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+               absbit: { BIT(ABS_X) | BIT(ABS_Y) },
+       },      /* A tablet like device, at least touch detection, two absolute axes */
+
+       { },    /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(input, mousedev_ids);
        
 static struct input_handler mousedev_handler = {
        event:          mousedev_event,
@@ -466,6 +490,8 @@ static struct input_handler mousedev_handler = {
        disconnect:     mousedev_disconnect,
        fops:           &mousedev_fops,
        minor:          MOUSEDEV_MINOR_BASE,
+       name:           "mousedev",
+       id_table:       mousedev_ids,
 };
 
 static int __init mousedev_init(void)
@@ -493,10 +519,6 @@ static void __exit mousedev_exit(void)
 module_init(mousedev_init);
 module_exit(mousedev_exit);
 
-MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
-MODULE_DESCRIPTION("Input driver to PS/2 or ImPS/2 device driver");
-MODULE_LICENSE("GPL");
-
 MODULE_PARM(xres, "i");
 MODULE_PARM_DESC(xres, "Horizontal screen resolution");
 MODULE_PARM(yres, "i");
index 5e741a18c004aecf326f6a1e24889453501cd17d..4077fd8e16ec25f1429010a1b036ae5f9e2a8635 100644 (file)
@@ -2,11 +2,9 @@
 #define _GAMEPORT_H
 
 /*
- * $Id: gameport.h,v 1.11 2001/04/26 10:24:46 vojtech Exp $
+ * $Id: gameport.h,v 1.20 2002/01/03 08:55:05 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
 /*
  *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
-#include <linux/sched.h>
-#include <linux/delay.h>
 #include <asm/io.h>
+#include <linux/input.h>
 
 struct gameport;
 
 struct gameport {
 
-       void *private;
-
+       void *private;  /* Private pointer for joystick drivers */
+       void *driver;   /* Private pointer for gameport drivers */
+       char *name;
+       char *phys;
        int number;
 
+       unsigned short idbus;
+       unsigned short idvendor;
+       unsigned short idproduct;
+       unsigned short idversion;
+
        int io;
        int speed;
        int fuzz;
@@ -59,6 +63,7 @@ struct gameport {
 struct gameport_dev {
 
        void *private;
+       char *name;
 
        void (*connect)(struct gameport *, struct gameport_dev *dev);
        void (*disconnect)(struct gameport *);
@@ -74,8 +79,8 @@ void gameport_rescan(struct gameport *gameport);
 void gameport_register_port(struct gameport *gameport);
 void gameport_unregister_port(struct gameport *gameport);
 #else
-static void __inline__ gameport_register_port(struct gameport *gameport) { return; }
-static void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
+void __inline__ gameport_register_port(struct gameport *gameport) { return; }
+void __inline__ gameport_unregister_port(struct gameport *gameport) { return; }
 #endif
 
 void gameport_register_device(struct gameport_dev *dev);
@@ -94,6 +99,7 @@ void gameport_unregister_device(struct gameport_dev *dev);
 #define GAMEPORT_ID_VENDOR_MICROSOFT   0x0007
 #define GAMEPORT_ID_VENDOR_THRUSTMASTER        0x0008
 #define GAMEPORT_ID_VENDOR_GRAVIS      0x0009
+#define GAMEPORT_ID_VENDOR_GUILLEMOT   0x000a
 
 static __inline__ void gameport_trigger(struct gameport *gameport)
 {
@@ -134,7 +140,7 @@ static __inline__ int gameport_time(struct gameport *gameport, int time)
 
 static __inline__ void wait_ms(unsigned int ms)
 {
-       current->state = TASK_UNINTERRUPTIBLE;
+       set_current_state(TASK_UNINTERRUPTIBLE);
        schedule_timeout(1 + ms * HZ / 1000);
 }
 
index 3f961ae82a178991673e392f73ef18b94319ca2f..7ebdaaa7ae3f5bf4dad544f5f525bab8fb6463d6 100644 (file)
@@ -2,11 +2,9 @@
 #define _INPUT_H
 
 /*
- * $Id: input.h,v 1.34 2001/05/28 09:06:44 vojtech Exp $
+ * $Id: input.h,v 1.57 2002/01/02 11:59:56 vojtech Exp $
  *
- *  Copyright (c) 1999-2000 Vojtech Pavlik
- *
- *  Sponsored by SuSE
+ *  Copyright (c) 1999-2001 Vojtech Pavlik
  */
 
 /*
@@ -17,7 +15,7 @@
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
@@ -25,8 +23,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 #ifdef __KERNEL__
@@ -64,17 +62,20 @@ struct input_event {
 #define EVIOCSREP              _IOW('E', 0x03, int[2])                 /* get repeat settings */
 #define EVIOCGKEYCODE          _IOR('E', 0x04, int[2])                 /* get keycode */
 #define EVIOCSKEYCODE          _IOW('E', 0x04, int[2])                 /* set keycode */
-#define EVIOCGKEY              _IOR('E', 0x05, int[2])                 /* get key value */
+
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
-#define EVIOCGBUS              _IOR('E', 0x07, short[4])               /* get bus address */
+#define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
+#define EVIOCGUNIQ(len)                _IOC(_IOC_READ, 'E', 0x08, len)         /* get unique identifier */
+
+#define EVIOCGKEY(len)         _IOC(_IOC_READ, 'E', 0x18, len)         /* get global keystate */
+#define EVIOCGLED(len)         _IOC(_IOC_READ, 'E', 0x19, len)         /* get all LEDs */
+#define EVIOCGSND(len)         _IOC(_IOC_READ, 'E', 0x1a, len)         /* get all sounds status */
 
 #define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event bits */
 #define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, int[5])           /* get abs value/limits */
 
 #define EVIOCSFF               _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))   /* send a force effect to a force feedback device */
 #define EVIOCRMFF              _IOW('E', 0x81, int)                    /* Erase a force effect */
-#define EVIOCSGAIN             _IOW('E', 0x82, unsigned short)         /* Set overall gain */
-#define EVIOCSAUTOCENTER       _IOW('E', 0x83, unsigned short)         /* Enable or disable auto-centering */
 #define EVIOCGEFFECTS          _IOR('E', 0x84, int)                    /* Report number of effects playable at the same time */
 
 /*
@@ -90,6 +91,8 @@ struct input_event {
 #define EV_SND                 0x12
 #define EV_REP                 0x14
 #define EV_FF                  0x15
+#define EV_PWR                 0x16
+#define EV_FF_STATUS           0x17
 #define EV_MAX                 0x1f
 
 /*
@@ -304,8 +307,23 @@ struct input_event {
 #define KEY_PROG4              203
 #define KEY_SUSPEND            205
 #define KEY_CLOSE              206
-
-#define KEY_UNKNOWN            220
+#define KEY_PLAY               207
+#define KEY_FASTFORWARD                208
+#define KEY_BASSBOOST          209
+#define KEY_PRINT              210
+#define KEY_HP                 211
+#define KEY_CAMERA             212
+#define KEY_SOUND              213
+#define KEY_QUESTION           214
+#define KEY_EMAIL              215
+#define KEY_CHAT               216
+#define KEY_SEARCH             217
+#define KEY_CONNECT            218
+#define KEY_FINANCE            219
+#define KEY_SPORT              220
+#define KEY_SHOP               221
+
+#define KEY_UNKNOWN            240
 
 #define BTN_MISC               0x100
 #define BTN_0                  0x100
@@ -415,14 +433,16 @@ struct input_event {
 #define ABS_DISTANCE           0x19
 #define ABS_TILT_X             0x1a
 #define ABS_TILT_Y             0x1b
-#define ABS_MISC               0x1c
-#define ABS_MAX                        0x1f
+#define ABS_VOLUME             0x20
+#define ABS_MISC               0x28
+#define ABS_MAX                        0x3f
 
 /*
  * Misc events
  */
 
 #define MSC_SERIAL             0x00
+#define MSC_PULSELED           0x01
 #define MSC_MAX                        0x07
 
 /*
@@ -468,6 +488,7 @@ struct input_event {
 #define BUS_PCI                        0x01
 #define BUS_ISAPNP             0x02
 #define BUS_USB                        0x03
+#define BUS_HIL                        0x04
 
 #define BUS_ISA                        0x10
 #define BUS_I8042              0x11
@@ -479,33 +500,43 @@ struct input_event {
 #define BUS_ADB                        0x17
 #define BUS_I2C                        0x18
 
+/*
+ * Values describing the status of an effect
+ */
+#define FF_STATUS_STOPPED      0x00
+#define FF_STATUS_PLAYING      0x01
+#define FF_STATUS_MAX          0x01
+
 /*
  * Structures used in ioctls to upload effects to a device
  * The first structures are not passed directly by using ioctls.
  * They are sub-structures of the actually sent structure (called ff_effect)
+ *
+ * Ranges:
+ *  0 <= __u16 <= 65535
+ *  -32767 <= __s16 <= +32767     ! Not -32768 for lower bound !
  */
 
 struct ff_replay {
-       __u16 length;           /* Duration of an effect */
+       __u16 length;           /* Duration of an effect in ms. All other times are also expressed in ms */
        __u16 delay;            /* Time to wait before to start playing an effect */
 };
 
 struct ff_trigger {
        __u16 button;           /* Number of button triggering an effect */
-       __u16 interval;         /* Time to wait before an effect can be re-triggered */
+       __u16 interval;         /* Time to wait before an effect can be re-triggered (ms) */
 };
 
 struct ff_shape {
-       __u16 attack_length;    /* Duration of attack */
-       __s16 attack_level;     /* Level at beginning of attack */
-       __u16 fade_length;      /* Duration of fade */
-       __s16 fade_level;       /* Level at end of fade */
+       __u16 attack_length;    /* Duration of attack (ms) */
+       __u16 attack_level;     /* Level at beginning of attack */
+       __u16 fade_length;      /* Duration of fade (ms) */
+       __u16 fade_level;       /* Level at end of fade */
 };
 
 /* FF_CONSTANT */
 struct ff_constant_effect {
-       __s16 level;            /* Strength of effect */
-       __u16 direction;        /* Direction of effect (see periodic effects) */
+       __s16 level;            /* Strength of effect. Negative values are OK */
        struct ff_shape shape;
 };
 
@@ -514,12 +545,13 @@ struct ff_interactive_effect {
 /* Axis along which effect must be created. If null, the field named direction
  * is used
  * It is a bit array (ie to enable axes X and Y, use BIT(ABS_X) | BIT(ABS_Y)
+ * It overrides the value of ff_effect::direction, which is used only if
+ * axis == 0
  */
        __u16 axis;
-       __u16 direction;
 
-       __s16 right_saturation; /* Max level when joystick is on the right */
-       __s16 left_saturation;  /* Max level when joystick in on the left */
+       __u16 right_saturation; /* Max level when joystick is on the right */
+       __u16 left_saturation;  /* Max level when joystick in on the left */
 
        __s16 right_coeff;      /* Indicates how fast the force grows when the
                                   joystick moves to the right */
@@ -533,12 +565,10 @@ struct ff_interactive_effect {
 /* FF_PERIODIC */
 struct ff_periodic_effect {
        __u16 waveform;         /* Kind of wave (sine, square...) */
-       __u16 period;
+       __u16 period;           /* in ms */
        __s16 magnitude;        /* Peak value */
        __s16 offset;           /* Mean value of wave (roughly) */
        __u16 phase;            /* 'Horizontal' shift */
-       __u16 direction;        /* Direction. 0 deg -> 0x0000
-                                            90 deg -> 0x4000 */
 
        struct ff_shape shape;
 };
@@ -549,10 +579,17 @@ struct ff_periodic_effect {
 struct ff_effect {
        __u16 type;
 /* Following field denotes the unique id assigned to an effect.
- * It is set by the driver.
+ * If user sets if to -1, a new effect is created, and its id is returned in the same field
+ * Else, the user sets it to the effect id it wants to update.
  */
        __s16 id;
 
+       __u16 direction;        /* Direction. 0 deg -> 0x0000 (down)
+                                            90 deg -> 0x4000 (left)
+                                           180 deg -> 0x8000 (up)
+                                           270 deg -> 0xC000 (right)
+                               */
+
        struct ff_trigger trigger;
        struct ff_replay replay;
 
@@ -564,7 +601,7 @@ struct ff_effect {
 };
 
 /*
- * Buttons that can trigger effects.  Use for example FF_BTN(BTN_TRIGGER) to
+ * Buttons that can trigger effects. Use for example FF_BTN(BTN_TRIGGER) to
  * access the bitmap.
  */
 
@@ -625,8 +662,11 @@ struct input_dev {
 
        void *private;
 
-       int number;
        char *name;
+       char *phys;
+       char *uniq;
+       int number;
+
        unsigned short idbus;
        unsigned short idvendor;
        unsigned short idproduct;
@@ -649,6 +689,9 @@ struct input_dev {
        unsigned int repeat_key;
        struct timer_list timer;
 
+       struct pm_dev *pm_dev;
+       int state;
+
        int abs[ABS_MAX + 1];
        int rep[REP_MAX + 1];
 
@@ -661,8 +704,12 @@ struct input_dev {
        int absfuzz[ABS_MAX + 1];
        int absflat[ABS_MAX + 1];
 
+       int only_one_writer;
+
        int (*open)(struct input_dev *dev);
        void (*close)(struct input_dev *dev);
+       int (*accept)(struct input_dev *dev, struct file *file);
+       int (*flush)(struct input_dev *dev, struct file *file);
        int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
        int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect);
        int (*erase_effect)(struct input_dev *dev, int effect_id);
@@ -671,16 +718,63 @@ struct input_dev {
        struct input_dev *next;
 };
 
+/*
+ * Structure for hotplug & device<->driver matching.
+ */
+
+#define INPUT_DEVICE_ID_MATCH_BUS      1
+#define INPUT_DEVICE_ID_MATCH_VENDOR   2
+#define INPUT_DEVICE_ID_MATCH_PRODUCT  4
+#define INPUT_DEVICE_ID_MATCH_VERSION  8
+
+#define INPUT_DEVICE_ID_MATCH_EVBIT    0x010
+#define INPUT_DEVICE_ID_MATCH_KEYBIT   0x020
+#define INPUT_DEVICE_ID_MATCH_RELBIT   0x040
+#define INPUT_DEVICE_ID_MATCH_ABSBIT   0x080
+#define INPUT_DEVICE_ID_MATCH_MSCIT    0x100
+#define INPUT_DEVICE_ID_MATCH_LEDBIT   0x200
+#define INPUT_DEVICE_ID_MATCH_SNDBIT   0x400
+#define INPUT_DEVICE_ID_MATCH_FFBIT    0x800
+
+#define INPUT_DEVICE_ID_MATCH_DEVICE\
+       (INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
+#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
+       (INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
+
+struct input_device_id {
+
+       unsigned long flags;
+
+       unsigned short idbus;
+       unsigned short idvendor;
+       unsigned short idproduct;
+       unsigned short idversion;
+
+       unsigned long evbit[NBITS(EV_MAX)];
+       unsigned long keybit[NBITS(KEY_MAX)];
+       unsigned long relbit[NBITS(REL_MAX)];
+       unsigned long absbit[NBITS(ABS_MAX)];
+       unsigned long mscbit[NBITS(MSC_MAX)];
+       unsigned long ledbit[NBITS(LED_MAX)];
+       unsigned long sndbit[NBITS(SND_MAX)];
+       unsigned long ffbit[NBITS(FF_MAX)];
+
+       unsigned long driver_info;
+};
+
 struct input_handler {
 
        void *private;
 
        void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
-       struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev);
+       struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id);
        void (*disconnect)(struct input_handle *handle);
 
        struct file_operations *fops;
        int minor;
+       char *name;
+
+       struct input_device_id *id_table;
 
        struct input_handle *handle;
        struct input_handler *next;
@@ -691,6 +785,7 @@ struct input_handle {
        void *private;
 
        int open;
+       char *name;
 
        struct input_dev *dev;
        struct input_handler *handler;
@@ -708,6 +803,9 @@ void input_unregister_handler(struct input_handler *);
 int input_open_device(struct input_handle *);
 void input_close_device(struct input_handle *);
 
+int input_accept_process(struct input_handle *handle, struct file *file);
+int input_flush_device(struct input_handle* handle, struct file* file);
+
 devfs_handle_t input_register_minor(char *name, int minor, int minor_base);
 void input_unregister_minor(devfs_handle_t handle);
 
@@ -716,6 +814,8 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in
 #define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c))
 #define input_report_rel(a,b,c) input_event(a, EV_REL, b, c)
 #define input_report_abs(a,b,c) input_event(a, EV_ABS, b, c)
+#define input_report_ff(a,b,c) input_event(a, EV_FF, b, c)
+#define input_report_ff_status(a,b,c)  input_event(a, EV_FF_STATUS, b, c)
 
 #endif
 #endif
index 3619a866ec57f4233919f80084540c7b7ebc6749..fae360265d9fb0007f23e0ac5b45372afe82f2fb 100644 (file)
@@ -2,31 +2,29 @@
 #define _SERIO_H
 
 /*
- * $Id: serio.h,v 1.11 2001/05/29 02:58:50 jsimmons Exp $
+ * $Id: serio.h,v 1.21 2001/12/19 05:15:21 skids Exp $
  *
- * Copyright (C) 1999 Vojtech Pavlik
- *
- * Sponsored by SuSE
+ * Copyright (C) 1999-2001 Vojtech Pavlik
  */
 
 /*
  * 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
- * the Free Software Foundation; either version 2 of the License, or 
+ * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * 
+ *
  * Should you need to contact me, the author, you can do so either by
  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
 /*
@@ -42,23 +40,31 @@ struct serio {
 
        void *private;
        void *driver;
+       char *name;
+       char *phys;
+       int number;
+
+       unsigned short idbus;
+       unsigned short idvendor;
+       unsigned short idproduct;
+       unsigned short idversion;
 
        unsigned long type;
-       int number;
 
        int (*write)(struct serio *, unsigned char);
        int (*open)(struct serio *);
        void (*close)(struct serio *);
 
        struct serio_dev *dev;
-
        struct serio *next;
 };
 
 struct serio_dev {
 
        void *private;
+       char *name;
 
+       void (*write_wakeup)(struct serio *);
        void (*interrupt)(struct serio *, unsigned char, unsigned int);
        void (*connect)(struct serio *, struct serio_dev *dev);
        void (*disconnect)(struct serio *);
@@ -80,6 +86,13 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
        return serio->write(serio, data);
 }
 
+static __inline__ void serio_dev_write_wakeup(struct serio *serio)
+{
+       if (serio->dev && serio->dev->write_wakeup) {
+               serio->dev->write_wakeup(serio);
+       }
+}
+
 #define SERIO_TIMEOUT  1
 #define SERIO_PARITY   2
 
@@ -87,6 +100,7 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
 #define SERIO_XT       0x00000000UL
 #define SERIO_8042     0x01000000UL
 #define SERIO_RS232    0x02000000UL
+#define SERIO_HIL_MLC  0x03000000UL
 
 #define SERIO_PROTO    0xFFUL
 #define SERIO_MSC      0x01
@@ -108,6 +122,9 @@ static __inline__ int serio_write(struct serio *serio, unsigned char data)
 #define SERIO_STOWAWAY 0x20
 #define SERIO_H3600    0x21
 #define SERIO_PS2SER   0x22
+#define SERIO_TWIDKBD  0x23
+#define SERIO_TWIDJOY  0x24
+#define SERIO_HIL      0x25
 
 #define SERIO_ID       0xff00UL
 #define SERIO_EXTRA    0xff0000UL