vserver 2.0 rc7
[linux-2.6.git] / drivers / input / joydev.c
index 4fe982d..627d343 100644 (file)
@@ -47,15 +47,15 @@ struct joydev {
        struct input_handle handle;
        wait_queue_head_t wait;
        struct list_head list;
-       struct js_corr corr[ABS_MAX];
+       struct js_corr corr[ABS_MAX + 1];
        struct JS_DATA_SAVE_TYPE glue;
        int nabs;
        int nkey;
-       __u16 keymap[KEY_MAX - BTN_MISC];
-       __u16 keypam[KEY_MAX - BTN_MISC];
-       __u8 absmap[ABS_MAX];
-       __u8 abspam[ABS_MAX];
-       __s16 abs[ABS_MAX];
+       __u16 keymap[KEY_MAX - BTN_MISC + 1];
+       __u16 keypam[KEY_MAX - BTN_MISC + 1];
+       __u8 absmap[ABS_MAX + 1];
+       __u8 abspam[ABS_MAX + 1];
+       __s16 abs[ABS_MAX + 1];
 };
 
 struct joydev_list {
@@ -281,9 +281,8 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait)
 {
        struct joydev_list *list = file->private_data;
        poll_wait(file, &list->joydev->wait, wait);
-       if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
-               return POLLIN | POLLRDNORM;
-       return 0;
+       return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? 
+               (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -338,7 +337,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        return copy_to_user(argp, joydev->corr,
                                                sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
                case JSIOCSAXMAP:
-                       if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * ABS_MAX))
+                       if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
                                return -EFAULT;
                        for (i = 0; i < joydev->nabs; i++) {
                                if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
@@ -347,9 +346,9 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        return 0;
                case JSIOCGAXMAP:
                        return copy_to_user(argp, joydev->abspam,
-                                               sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
+                                               sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
                case JSIOCSBTNMAP:
-                       if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+                       if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
                                return -EFAULT;
                        for (i = 0; i < joydev->nkey; i++) {
                                if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
@@ -358,7 +357,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        return 0;
                case JSIOCGBTNMAP:
                        return copy_to_user(argp, joydev->keypam,
-                                               sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0;
+                                               sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
                default:
                        if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
                                int len;
@@ -409,14 +408,14 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
        joydev->handle.private = joydev;
        sprintf(joydev->name, "js%d", minor);
 
-       for (i = 0; i < ABS_MAX; i++)
+       for (i = 0; i < ABS_MAX + 1; i++)
                if (test_bit(i, dev->absbit)) {
                        joydev->absmap[i] = joydev->nabs;
                        joydev->abspam[joydev->nabs] = i;
                        joydev->nabs++;
                }
 
-       for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++)
+       for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++)
                if (test_bit(i + BTN_MISC, dev->keybit)) {
                        joydev->keymap[i] = joydev->nkey;
                        joydev->keypam[joydev->nkey] = i + BTN_MISC;
@@ -463,14 +462,18 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
 static void joydev_disconnect(struct input_handle *handle)
 {
        struct joydev *joydev = handle->private;
+       struct joydev_list *list;
 
        class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
        devfs_remove("input/js%d", joydev->minor);
        joydev->exist = 0;
 
-       if (joydev->open)
+       if (joydev->open) {
                input_close_device(handle);
-       else
+               wake_up_interruptible(&joydev->wait);
+               list_for_each_entry(list, &joydev->list, node)
+                       kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+       } else
                joydev_free(joydev);
 }