headers: remove sched.h from poll.h
[safe/jmp/linux-2.6] / drivers / input / evdev.c
index d404aa8..dee6706 100644 (file)
 #define EVDEV_BUFFER_SIZE      64
 
 #include <linux/poll.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/major.h>
 #include <linux/device.h>
-#include <linux/compat.h>
+#include "input-compat.h"
 
 struct evdev {
        int exist;
        int open;
        int minor;
-       char name[16];
        struct input_handle handle;
        wait_queue_head_t wait;
        struct evdev_client *grab;
@@ -63,10 +63,7 @@ static void evdev_pass_event(struct evdev_client *client,
 }
 
 /*
- * Pass incoming event to all connected clients. Note that we are
- * caleld under a spinlock with interrupts off so we don't need
- * to use rcu_read_lock() here. Writers will be using syncronize_sched()
- * instead of synchrnoize_rcu().
+ * Pass incoming event to all connected clients.
  */
 static void evdev_event(struct input_handle *handle,
                        unsigned int type, unsigned int code, int value)
@@ -80,6 +77,8 @@ static void evdev_event(struct input_handle *handle,
        event.code = code;
        event.value = value;
 
+       rcu_read_lock();
+
        client = rcu_dereference(evdev->grab);
        if (client)
                evdev_pass_event(client, &event);
@@ -87,17 +86,16 @@ static void evdev_event(struct input_handle *handle,
                list_for_each_entry_rcu(client, &evdev->client_list, node)
                        evdev_pass_event(client, &event);
 
+       rcu_read_unlock();
+
        wake_up_interruptible(&evdev->wait);
 }
 
 static int evdev_fasync(int fd, struct file *file, int on)
 {
        struct evdev_client *client = file->private_data;
-       int retval;
 
-       retval = fasync_helper(fd, file, on, &client->fasync);
-
-       return retval < 0 ? retval : 0;
+       return fasync_helper(fd, file, on, &client->fasync);
 }
 
 static int evdev_flush(struct file *file, fl_owner_t id)
@@ -123,6 +121,7 @@ static void evdev_free(struct device *dev)
 {
        struct evdev *evdev = container_of(dev, struct evdev, dev);
 
+       input_put_device(evdev->handle.dev);
        kfree(evdev);
 }
 
@@ -142,12 +141,7 @@ static int evdev_grab(struct evdev *evdev, struct evdev_client *client)
                return error;
 
        rcu_assign_pointer(evdev->grab, client);
-       /*
-        * We don't use synchronize_rcu() here because read-side
-        * critical section is protected by a spinlock instead
-        * of rcu_read_lock().
-        */
-       synchronize_sched();
+       synchronize_rcu();
 
        return 0;
 }
@@ -158,7 +152,7 @@ static int evdev_ungrab(struct evdev *evdev, struct evdev_client *client)
                return  -EINVAL;
 
        rcu_assign_pointer(evdev->grab, NULL);
-       synchronize_sched();
+       synchronize_rcu();
        input_release_device(&evdev->handle);
 
        return 0;
@@ -170,7 +164,7 @@ static void evdev_attach_client(struct evdev *evdev,
        spin_lock(&evdev->client_lock);
        list_add_tail_rcu(&client->node, &evdev->client_list);
        spin_unlock(&evdev->client_lock);
-       synchronize_sched();
+       synchronize_rcu();
 }
 
 static void evdev_detach_client(struct evdev *evdev,
@@ -179,7 +173,7 @@ static void evdev_detach_client(struct evdev *evdev,
        spin_lock(&evdev->client_lock);
        list_del_rcu(&client->node);
        spin_unlock(&evdev->client_lock);
-       synchronize_sched();
+       synchronize_rcu();
 }
 
 static int evdev_open_device(struct evdev *evdev)
@@ -238,7 +232,6 @@ static int evdev_release(struct inode *inode, struct file *file)
                evdev_ungrab(evdev, client);
        mutex_unlock(&evdev->mutex);
 
-       evdev_fasync(-1, file, 0);
        evdev_detach_client(evdev, client);
        kfree(client);
 
@@ -294,110 +287,6 @@ static int evdev_open(struct inode *inode, struct file *file)
        return error;
 }
 
-#ifdef CONFIG_COMPAT
-
-struct input_event_compat {
-       struct compat_timeval time;
-       __u16 type;
-       __u16 code;
-       __s32 value;
-};
-
-/* Note to the author of this code: did it ever occur to
-   you why the ifdefs are needed? Think about it again. -AK */
-#ifdef CONFIG_X86_64
-#  define COMPAT_TEST is_compat_task()
-#elif defined(CONFIG_IA64)
-#  define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
-#elif defined(CONFIG_S390)
-#  define COMPAT_TEST test_thread_flag(TIF_31BIT)
-#elif defined(CONFIG_MIPS)
-#  define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR)
-#else
-#  define COMPAT_TEST test_thread_flag(TIF_32BIT)
-#endif
-
-static inline size_t evdev_event_size(void)
-{
-       return COMPAT_TEST ?
-               sizeof(struct input_event_compat) : sizeof(struct input_event);
-}
-
-static int evdev_event_from_user(const char __user *buffer,
-                                struct input_event *event)
-{
-       if (COMPAT_TEST) {
-               struct input_event_compat compat_event;
-
-               if (copy_from_user(&compat_event, buffer,
-                                  sizeof(struct input_event_compat)))
-                       return -EFAULT;
-
-               event->time.tv_sec = compat_event.time.tv_sec;
-               event->time.tv_usec = compat_event.time.tv_usec;
-               event->type = compat_event.type;
-               event->code = compat_event.code;
-               event->value = compat_event.value;
-
-       } else {
-               if (copy_from_user(event, buffer, sizeof(struct input_event)))
-                       return -EFAULT;
-       }
-
-       return 0;
-}
-
-static int evdev_event_to_user(char __user *buffer,
-                               const struct input_event *event)
-{
-       if (COMPAT_TEST) {
-               struct input_event_compat compat_event;
-
-               compat_event.time.tv_sec = event->time.tv_sec;
-               compat_event.time.tv_usec = event->time.tv_usec;
-               compat_event.type = event->type;
-               compat_event.code = event->code;
-               compat_event.value = event->value;
-
-               if (copy_to_user(buffer, &compat_event,
-                                sizeof(struct input_event_compat)))
-                       return -EFAULT;
-
-       } else {
-               if (copy_to_user(buffer, event, sizeof(struct input_event)))
-                       return -EFAULT;
-       }
-
-       return 0;
-}
-
-#else
-
-static inline size_t evdev_event_size(void)
-{
-       return sizeof(struct input_event);
-}
-
-static int evdev_event_from_user(const char __user *buffer,
-                                struct input_event *event)
-{
-       if (copy_from_user(event, buffer, sizeof(struct input_event)))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int evdev_event_to_user(char __user *buffer,
-                               const struct input_event *event)
-{
-       if (copy_to_user(buffer, event, sizeof(struct input_event)))
-               return -EFAULT;
-
-       return 0;
-}
-
-#endif /* CONFIG_COMPAT */
-
 static ssize_t evdev_write(struct file *file, const char __user *buffer,
                           size_t count, loff_t *ppos)
 {
@@ -417,14 +306,14 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
 
        while (retval < count) {
 
-               if (evdev_event_from_user(buffer + retval, &event)) {
+               if (input_event_from_user(buffer + retval, &event)) {
                        retval = -EFAULT;
                        goto out;
                }
 
                input_inject_event(&evdev->handle,
                                   event.type, event.code, event.value);
-               retval += evdev_event_size();
+               retval += input_event_size();
        }
 
  out:
@@ -458,7 +347,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
        struct input_event event;
        int retval;
 
-       if (count < evdev_event_size())
+       if (count < input_event_size())
                return -EINVAL;
 
        if (client->head == client->tail && evdev->exist &&
@@ -473,13 +362,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
        if (!evdev->exist)
                return -ENODEV;
 
-       while (retval + evdev_event_size() <= count &&
+       while (retval + input_event_size() <= count &&
               evdev_fetch_next_event(client, &event)) {
 
-               if (evdev_event_to_user(buffer + retval, &event))
+               if (input_event_to_user(buffer + retval, &event))
                        return -EFAULT;
 
-               retval += evdev_event_size();
+               retval += input_event_size();
        }
 
        return retval;
@@ -499,7 +388,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait)
 #ifdef CONFIG_COMPAT
 
 #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
-#define NBITS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
+#define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
 
 #ifdef __BIG_ENDIAN
 static int bits_to_user(unsigned long *bits, unsigned int maxbit,
@@ -508,7 +397,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
        int len, i;
 
        if (compat) {
-               len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
+               len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
                if (len > maxlen)
                        len = maxlen;
 
@@ -519,7 +408,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
                                         sizeof(compat_long_t)))
                                return -EFAULT;
        } else {
-               len = NBITS(maxbit) * sizeof(long);
+               len = BITS_TO_LONGS(maxbit) * sizeof(long);
                if (len > maxlen)
                        len = maxlen;
 
@@ -534,8 +423,8 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
                        unsigned int maxlen, void __user *p, int compat)
 {
        int len = compat ?
-                       NBITS_COMPAT(maxbit) * sizeof(compat_long_t) :
-                       NBITS(maxbit) * sizeof(long);
+                       BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) :
+                       BITS_TO_LONGS(maxbit) * sizeof(long);
 
        if (len > maxlen)
                len = maxlen;
@@ -549,7 +438,7 @@ static int bits_to_user(unsigned long *bits, unsigned int maxbit,
 static int bits_to_user(unsigned long *bits, unsigned int maxbit,
                        unsigned int maxlen, void __user *p, int compat)
 {
-       int len = NBITS(maxbit) * sizeof(long);
+       int len = BITS_TO_LONGS(maxbit) * sizeof(long);
 
        if (len > maxlen)
                len = maxlen;
@@ -573,6 +462,47 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
        return copy_to_user(p, str, len) ? -EFAULT : len;
 }
 
+#define OLD_KEY_MAX    0x1ff
+static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode)
+{
+       static unsigned long keymax_warn_time;
+       unsigned long *bits;
+       int len;
+
+       switch (_IOC_NR(cmd) & EV_MAX) {
+
+       case      0: bits = dev->evbit;  len = EV_MAX;  break;
+       case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
+       case EV_REL: bits = dev->relbit; len = REL_MAX; break;
+       case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
+       case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
+       case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
+       case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
+       case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
+       case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
+       default: return -EINVAL;
+       }
+
+       /*
+        * Work around bugs in userspace programs that like to do
+        * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len'
+        * should be in bytes, not in bits.
+        */
+       if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
+               len = OLD_KEY_MAX;
+               if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000))
+                       printk(KERN_WARNING
+                               "evdev.c(EVIOCGBIT): Suspicious buffer size %u, "
+                               "limiting output to %zu bytes. See "
+                               "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n",
+                               OLD_KEY_MAX,
+                               BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long));
+       }
+
+       return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
+}
+#undef OLD_KEY_MAX
+
 static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                           void __user *p, int compat_mode)
 {
@@ -621,7 +551,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                if (get_user(t, ip))
                        return -EFAULT;
 
-               error = dev->getkeycode(dev, t, &v);
+               error = input_get_keycode(dev, t, &v);
                if (error)
                        return error;
 
@@ -634,18 +564,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                if (get_user(t, ip) || get_user(v, ip + 1))
                        return -EFAULT;
 
-               return dev->setkeycode(dev, t, v);
-
-       case EVIOCSFF:
-               if (copy_from_user(&effect, p, sizeof(effect)))
-                       return -EFAULT;
-
-               error = input_ff_upload(dev, &effect, file);
-
-               if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
-                       return -EFAULT;
-
-               return error;
+               return input_set_keycode(dev, t, v);
 
        case EVIOCRMFF:
                return input_ff_erase(dev, (int)(unsigned long) p, file);
@@ -670,26 +589,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                if (_IOC_DIR(cmd) == _IOC_READ) {
 
-                       if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
-
-                               unsigned long *bits;
-                               int len;
-
-                               switch (_IOC_NR(cmd) & EV_MAX) {
-
-                               case      0: bits = dev->evbit;  len = EV_MAX;  break;
-                               case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
-                               case EV_REL: bits = dev->relbit; len = REL_MAX; break;
-                               case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
-                               case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
-                               case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
-                               case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
-                               case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
-                               case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
-                               default: return -EINVAL;
-                       }
-                               return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
-                       }
+                       if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
+                               return handle_eviocgbit(dev, cmd, p, compat_mode);
 
                        if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
                                return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd),
@@ -725,8 +626,11 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                                abs.maximum = dev->absmax[t];
                                abs.fuzz = dev->absfuzz[t];
                                abs.flat = dev->absflat[t];
+                               abs.resolution = dev->absres[t];
 
-                               if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
+                               if (copy_to_user(p, &abs, min_t(size_t,
+                                                               _IOC_SIZE(cmd),
+                                                               sizeof(struct input_absinfo))))
                                        return -EFAULT;
 
                                return 0;
@@ -736,12 +640,26 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                if (_IOC_DIR(cmd) == _IOC_WRITE) {
 
+                       if (_IOC_NR(cmd) == _IOC_NR(EVIOCSFF)) {
+
+                               if (input_ff_effect_from_user(p, _IOC_SIZE(cmd), &effect))
+                                       return -EFAULT;
+
+                               error = input_ff_upload(dev, &effect, file);
+
+                               if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+                                       return -EFAULT;
+
+                               return error;
+                       }
+
                        if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) {
 
                                t = _IOC_NR(cmd) & ABS_MAX;
 
-                               if (copy_from_user(&abs, p,
-                                               sizeof(struct input_absinfo)))
+                               if (copy_from_user(&abs, p, min_t(size_t,
+                                                                 _IOC_SIZE(cmd),
+                                                                 sizeof(struct input_absinfo))))
                                        return -EFAULT;
 
                                /*
@@ -756,6 +674,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                                dev->absmax[t] = abs.maximum;
                                dev->absfuzz[t] = abs.fuzz;
                                dev->absflat[t] = abs.flat;
+                               dev->absres[t] = _IOC_SIZE(cmd) < sizeof(struct input_absinfo) ?
+                                                       0 : abs.resolution;
 
                                spin_unlock_irq(&dev->event_lock);
 
@@ -893,16 +813,15 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
        mutex_init(&evdev->mutex);
        init_waitqueue_head(&evdev->wait);
 
-       snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
+       dev_set_name(&evdev->dev, "event%d", minor);
        evdev->exist = 1;
        evdev->minor = minor;
 
-       evdev->handle.dev = dev;
-       evdev->handle.name = evdev->name;
+       evdev->handle.dev = input_get_device(dev);
+       evdev->handle.name = dev_name(&evdev->dev);
        evdev->handle.handler = handler;
        evdev->handle.private = evdev;
 
-       strlcpy(evdev->dev.bus_id, evdev->name, sizeof(evdev->dev.bus_id));
        evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
        evdev->dev.class = &input_class;
        evdev->dev.parent = &dev->dev;