fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / input / evdev.c
index 745979f..6439f37 100644 (file)
@@ -78,14 +78,19 @@ static int evdev_fasync(int fd, struct file *file, int on)
 {
        int retval;
        struct evdev_list *list = file->private_data;
+
        retval = fasync_helper(fd, file, on, &list->fasync);
+
        return retval < 0 ? retval : 0;
 }
 
-static int evdev_flush(struct file * file)
+static int evdev_flush(struct file *file, fl_owner_t id)
 {
        struct evdev_list *list = file->private_data;
-       if (!list->evdev->exist) return -ENODEV;
+
+       if (!list->evdev->exist)
+               return -ENODEV;
+
        return input_flush_device(&list->evdev->handle, file);
 }
 
@@ -122,17 +127,12 @@ static int evdev_open(struct inode * inode, struct file * file)
 {
        struct evdev_list *list;
        int i = iminor(inode) - EVDEV_MINOR_BASE;
-       int accept_err;
 
        if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist)
                return -ENODEV;
 
-       if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file)))
-               return accept_err;
-
-       if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL)))
+       if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL)))
                return -ENOMEM;
-       memset(list, 0, sizeof(struct evdev_list));
 
        list->evdev = evdev_table[i];
        list_add_tail(&list->node, &evdev_table[i]->list);
@@ -256,7 +256,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_
 
                if (evdev_event_from_user(buffer + retval, &event))
                        return -EFAULT;
-               input_event(list->evdev->handle.dev, event.type, event.code, event.value);
+               input_inject_event(&list->evdev->handle, event.type, event.code, event.value);
                retval += evdev_event_size();
        }
 
@@ -301,6 +301,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count
 static unsigned int evdev_poll(struct file *file, poll_table *wait)
 {
        struct evdev_list *list = file->private_data;
+
        poll_wait(file, &list->evdev->wait, wait);
        return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
                (list->evdev->exist ? 0 : (POLLHUP | POLLERR));
@@ -390,8 +391,10 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
        struct evdev *evdev = list->evdev;
        struct input_dev *dev = evdev->handle.dev;
        struct input_absinfo abs;
+       struct ff_effect effect;
        int __user *ip = (int __user *)p;
        int i, t, u, v;
+       int error;
 
        if (!evdev->exist)
                return -ENODEV;
@@ -404,6 +407,27 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
                case EVIOCGID:
                        if (copy_to_user(p, &dev->id, sizeof(struct input_id)))
                                return -EFAULT;
+                       return 0;
+
+               case EVIOCGREP:
+                       if (!test_bit(EV_REP, dev->evbit))
+                               return -ENOSYS;
+                       if (put_user(dev->rep[REP_DELAY], ip))
+                               return -EFAULT;
+                       if (put_user(dev->rep[REP_PERIOD], ip + 1))
+                               return -EFAULT;
+                       return 0;
+
+               case EVIOCSREP:
+                       if (!test_bit(EV_REP, dev->evbit))
+                               return -ENOSYS;
+                       if (get_user(u, ip))
+                               return -EFAULT;
+                       if (get_user(v, ip + 1))
+                               return -EFAULT;
+
+                       input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u);
+                       input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v);
 
                        return 0;
 
@@ -438,27 +462,22 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
                        return 0;
 
                case EVIOCSFF:
-                       if (dev->upload_effect) {
-                               struct ff_effect effect;
-                               int err;
-
-                               if (copy_from_user(&effect, p, sizeof(effect)))
-                                       return -EFAULT;
-                               err = dev->upload_effect(dev, &effect);
-                               if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
-                                       return -EFAULT;
-                               return err;
-                       } else
-                               return -ENOSYS;
+                       if (copy_from_user(&effect, p, sizeof(effect)))
+                               return -EFAULT;
 
-               case EVIOCRMFF:
-                       if (!dev->erase_effect)
-                               return -ENOSYS;
+                       error = input_ff_upload(dev, &effect, file);
+
+                       if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+                               return -EFAULT;
 
-                       return dev->erase_effect(dev, (int)(unsigned long) p);
+                       return error;
+
+               case EVIOCRMFF:
+                       return input_ff_erase(dev, (int)(unsigned long) p, file);
 
                case EVIOCGEFFECTS:
-                       if (put_user(dev->ff_effects_max, ip))
+                       i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0;
+                       if (put_user(i, ip))
                                return -EFAULT;
                        return 0;
 
@@ -582,7 +601,7 @@ static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned lon
 }
 #endif
 
-static struct file_operations evdev_fops = {
+static const struct file_operations evdev_fops = {
        .owner =        THIS_MODULE,
        .read =         evdev_read,
        .write =        evdev_write,
@@ -597,7 +616,8 @@ static struct file_operations evdev_fops = {
        .flush =        evdev_flush
 };
 
-static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id)
+static struct input_handle *evdev_connect(struct input_handler *handler, struct input_dev *dev,
+                                         const struct input_device_id *id)
 {
        struct evdev *evdev;
        struct class_device *cdev;
@@ -609,9 +629,8 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
                return NULL;
        }
 
-       if (!(evdev = kmalloc(sizeof(struct evdev), GFP_KERNEL)))
+       if (!(evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL)))
                return NULL;
-       memset(evdev, 0, sizeof(struct evdev));
 
        INIT_LIST_HEAD(&evdev->list);
        init_waitqueue_head(&evdev->wait);
@@ -648,6 +667,7 @@ static void evdev_disconnect(struct input_handle *handle)
        evdev->exist = 0;
 
        if (evdev->open) {
+               input_flush_device(handle, NULL);
                input_close_device(handle);
                wake_up_interruptible(&evdev->wait);
                list_for_each_entry(list, &evdev->list, node)
@@ -656,7 +676,7 @@ static void evdev_disconnect(struct input_handle *handle)
                evdev_free(evdev);
 }
 
-static struct input_device_id evdev_ids[] = {
+static const struct input_device_id evdev_ids[] = {
        { .driver_info = 1 },   /* Matches all devices */
        { },                    /* Terminating zero entry */
 };
@@ -675,8 +695,7 @@ static struct input_handler evdev_handler = {
 
 static int __init evdev_init(void)
 {
-       input_register_handler(&evdev_handler);
-       return 0;
+       return input_register_handler(&evdev_handler);
 }
 
 static void __exit evdev_exit(void)