[PATCH] Input: prepare to sysfs integration
authorDmitry Torokhov <dtor_core@ameritech.net>
Thu, 15 Sep 2005 07:01:39 +0000 (02:01 -0500)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 28 Oct 2005 16:52:52 +0000 (09:52 -0700)
Input: prepare to sysfs integration

Add struct class_device to input_dev; add input_allocate_dev()
to dynamically allocate input devices; dynamically allocated
devices are automatically registered with sysfs.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/input/input.c
include/linux/input.h

index 072bbf528151ca18f6c02b107745120ac7d19ff4..0e2e890c0988ce470eaf2c73db913084c1d0ae52 100644 (file)
@@ -27,6 +27,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
+EXPORT_SYMBOL(input_allocate_device);
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
@@ -605,6 +606,56 @@ static inline int input_proc_init(void) { return 0; }
 static inline void input_proc_exit(void) { }
 #endif
 
+static void input_dev_release(struct class_device *class_dev)
+{
+       struct input_dev *dev = to_input_dev(class_dev);
+
+       kfree(dev);
+       module_put(THIS_MODULE);
+}
+
+static struct class input_dev_class = {
+       .name                   = "input_dev",
+       .release                = input_dev_release,
+};
+
+struct input_dev *input_allocate_device(void)
+{
+       struct input_dev *dev;
+
+       dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
+       if (dev) {
+               dev->dynalloc = 1;
+               dev->cdev.class = &input_dev_class;
+               class_device_initialize(&dev->cdev);
+               INIT_LIST_HEAD(&dev->h_list);
+               INIT_LIST_HEAD(&dev->node);
+       }
+
+       return dev;
+}
+
+static void input_register_classdevice(struct input_dev *dev)
+{
+       static atomic_t input_no = ATOMIC_INIT(0);
+       const char *path;
+
+       __module_get(THIS_MODULE);
+
+       dev->dev = dev->cdev.dev;
+
+       snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
+                "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+
+       path = kobject_get_path(&dev->cdev.class->subsys.kset.kobj, GFP_KERNEL);
+       printk(KERN_INFO "input: %s/%s as %s\n",
+               dev->name ? dev->name : "Unspecified device",
+               path ? path : "", dev->cdev.class_id);
+       kfree(path);
+
+       class_device_add(&dev->cdev);
+}
+
 void input_register_device(struct input_dev *dev)
 {
        struct input_handle *handle;
@@ -637,6 +688,10 @@ void input_register_device(struct input_dev *dev)
                                if ((handle = handler->connect(handler, dev, id)))
                                        input_link_handle(handle);
 
+
+       if (dev->dynalloc)
+               input_register_classdevice(dev);
+
 #ifdef CONFIG_HOTPLUG
        input_call_hotplug("add", dev);
 #endif
@@ -665,6 +720,9 @@ void input_unregister_device(struct input_dev *dev)
 
        list_del_init(&dev->node);
 
+       if (dev->dynalloc)
+               class_device_unregister(&dev->cdev);
+
        input_wakeup_procfs_readers();
 }
 
@@ -753,26 +811,34 @@ static int __init input_init(void)
 {
        int err;
 
+       err = class_register(&input_dev_class);
+       if (err) {
+               printk(KERN_ERR "input: unable to register input_dev class\n");
+               return err;
+       }
+
        input_class = class_create(THIS_MODULE, "input");
        if (IS_ERR(input_class)) {
                printk(KERN_ERR "input: unable to register input class\n");
-               return PTR_ERR(input_class);
+               err = PTR_ERR(input_class);
+               goto fail1;
        }
 
        err = input_proc_init();
        if (err)
-               goto fail1;
+               goto fail2;
 
        err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
        if (err) {
                printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
-               goto fail2;
+               goto fail3;
        }
 
        return 0;
 
- fail2:        input_proc_exit();
- fail1:        class_destroy(input_class);
+ fail3:        input_proc_exit();
+ fail2:        class_destroy(input_class);
+ fail1:        class_unregister(&input_dev_class);
        return err;
 }
 
@@ -781,6 +847,7 @@ static void __exit input_exit(void)
        input_proc_exit();
        unregister_chrdev(INPUT_MAJOR, "input");
        class_destroy(input_class);
+       class_unregister(&input_dev_class);
 }
 
 subsys_initcall(input_init);
index e8c296ff6257adeccdd9d60245f463d1ea0255a3..3defa29a17d3ca7fe7a9a1cd79b03409249fb29e 100644 (file)
@@ -12,6 +12,7 @@
 #ifdef __KERNEL__
 #include <linux/time.h>
 #include <linux/list.h>
+#include <linux/device.h>
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
@@ -889,11 +890,15 @@ struct input_dev {
        struct semaphore sem;   /* serializes open and close operations */
        unsigned int users;
 
-       struct device *dev;
+       struct class_device cdev;
+       struct device *dev;     /* will be removed soon */
+
+       int dynalloc;   /* temporarily */
 
        struct list_head        h_list;
        struct list_head        node;
 };
+#define to_input_dev(d) container_of(d, struct input_dev, cdev)
 
 /*
  * Structure for hotplug & device<->driver matching.
@@ -984,6 +989,23 @@ static inline void init_input_dev(struct input_dev *dev)
        INIT_LIST_HEAD(&dev->node);
 }
 
+struct input_dev *input_allocate_device(void);
+
+static inline void input_free_device(struct input_dev *dev)
+{
+       kfree(dev);
+}
+
+static inline struct input_dev *input_get_device(struct input_dev *dev)
+{
+       return to_input_dev(class_device_get(&dev->cdev));
+}
+
+static inline void input_put_device(struct input_dev *dev)
+{
+       class_device_put(&dev->cdev);
+}
+
 void input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);