Driver-Core: extend devnode callbacks to provide permissions
[safe/jmp/linux-2.6] / drivers / input / input.c
index 913392f..556539d 100644 (file)
@@ -29,6 +29,24 @@ MODULE_LICENSE("GPL");
 
 #define INPUT_DEVICES  256
 
+/*
+ * EV_ABS events which should not be cached are listed here.
+ */
+static unsigned int input_abs_bypass_init_data[] __initdata = {
+       ABS_MT_TOUCH_MAJOR,
+       ABS_MT_TOUCH_MINOR,
+       ABS_MT_WIDTH_MAJOR,
+       ABS_MT_WIDTH_MINOR,
+       ABS_MT_ORIENTATION,
+       ABS_MT_POSITION_X,
+       ABS_MT_POSITION_Y,
+       ABS_MT_TOOL_TYPE,
+       ABS_MT_BLOB_ID,
+       ABS_MT_TRACKING_ID,
+       0
+};
+static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
+
 static LIST_HEAD(input_dev_list);
 static LIST_HEAD(input_handler_list);
 
@@ -161,6 +179,10 @@ static void input_handle_event(struct input_dev *dev,
                                disposition = INPUT_PASS_TO_HANDLERS;
                        }
                        break;
+               case SYN_MT_REPORT:
+                       dev->sync = 0;
+                       disposition = INPUT_PASS_TO_HANDLERS;
+                       break;
                }
                break;
 
@@ -192,6 +214,11 @@ static void input_handle_event(struct input_dev *dev,
        case EV_ABS:
                if (is_event_supported(code, dev->absbit, ABS_MAX)) {
 
+                       if (test_bit(code, input_abs_bypass)) {
+                               disposition = INPUT_PASS_TO_HANDLERS;
+                               break;
+                       }
+
                        value = input_defuzz_abs_event(value,
                                        dev->abs[code], dev->absfuzz[code]);
 
@@ -910,8 +937,6 @@ static int __init input_proc_init(void)
        if (!proc_bus_input_dir)
                return -ENOMEM;
 
-       proc_bus_input_dir->owner = THIS_MODULE;
-
        entry = proc_create("devices", 0, proc_bus_input_dir,
                            &input_devices_fileops);
        if (!entry)
@@ -1119,7 +1144,7 @@ static struct attribute_group input_dev_caps_attr_group = {
        .attrs  = input_dev_caps_attrs,
 };
 
-static struct attribute_group *input_dev_attr_groups[] = {
+static const struct attribute_group *input_dev_attr_groups[] = {
        &input_dev_attr_group,
        &input_dev_id_attr_group,
        &input_dev_caps_attr_group,
@@ -1240,8 +1265,14 @@ static struct device_type input_dev_type = {
        .uevent         = input_dev_uevent,
 };
 
+static char *input_devnode(struct device *dev, mode_t *mode)
+{
+       return kasprintf(GFP_KERNEL, "input/%s", dev_name(dev));
+}
+
 struct class input_class = {
        .name           = "input",
+       .devnode        = input_devnode,
 };
 EXPORT_SYMBOL_GPL(input_class);
 
@@ -1551,7 +1582,6 @@ int input_register_handle(struct input_handle *handle)
                return error;
        list_add_tail_rcu(&handle->d_node, &dev->h_list);
        mutex_unlock(&dev->mutex);
-       synchronize_rcu();
 
        /*
         * Since we are supposed to be called from ->connect()
@@ -1637,10 +1667,20 @@ static const struct file_operations input_fops = {
        .open = input_open_file,
 };
 
+static void __init input_init_abs_bypass(void)
+{
+       const unsigned int *p;
+
+       for (p = input_abs_bypass_init_data; *p; p++)
+               input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
+}
+
 static int __init input_init(void)
 {
        int err;
 
+       input_init_abs_bypass();
+
        err = class_register(&input_class);
        if (err) {
                printk(KERN_ERR "input: unable to register input_dev class\n");