Commit 9657d75c authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: convert from class devices to standard devices

Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent d63219a1
...@@ -30,6 +30,7 @@ struct evdev { ...@@ -30,6 +30,7 @@ struct evdev {
wait_queue_head_t wait; wait_queue_head_t wait;
struct evdev_client *grab; struct evdev_client *grab;
struct list_head client_list; struct list_head client_list;
struct device dev;
}; };
struct evdev_client { struct evdev_client {
...@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id) ...@@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
return input_flush_device(&evdev->handle, file); return input_flush_device(&evdev->handle, file);
} }
static void evdev_free(struct evdev *evdev) static void evdev_free(struct device *dev)
{ {
struct evdev *evdev = container_of(dev, struct evdev, dev);
evdev_table[evdev->minor] = NULL; evdev_table[evdev->minor] = NULL;
kfree(evdev); kfree(evdev);
} }
...@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file) ...@@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file)
list_del(&client->node); list_del(&client->node);
kfree(client); kfree(client);
if (!--evdev->open) { if (!--evdev->open && evdev->exist)
if (evdev->exist) input_close_device(&evdev->handle);
input_close_device(&evdev->handle);
else put_device(&evdev->dev);
evdev_free(evdev);
}
return 0; return 0;
} }
...@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file) ...@@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file)
if (!evdev || !evdev->exist) if (!evdev || !evdev->exist)
return -ENODEV; return -ENODEV;
get_device(&evdev->dev);
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL); client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
if (!client) if (!client) {
return -ENOMEM; error = -ENOMEM;
goto err_put_evdev;
}
client->evdev = evdev; client->evdev = evdev;
list_add_tail(&client->node, &evdev->client_list); list_add_tail(&client->node, &evdev->client_list);
if (!evdev->open++ && evdev->exist) { if (!evdev->open++ && evdev->exist) {
error = input_open_device(&evdev->handle); error = input_open_device(&evdev->handle);
if (error) { if (error)
list_del(&client->node); goto err_free_client;
kfree(client);
return error;
}
} }
file->private_data = client; file->private_data = client;
return 0; return 0;
err_free_client:
list_del(&client->node);
kfree(client);
err_put_evdev:
put_device(&evdev->dev);
return error;
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id) const struct input_device_id *id)
{ {
struct evdev *evdev; struct evdev *evdev;
struct class_device *cdev;
dev_t devt;
int minor; int minor;
int error; int error;
...@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev->handle.name = evdev->name; evdev->handle.name = evdev->name;
evdev->handle.handler = handler; evdev->handle.handler = handler;
evdev->handle.private = evdev; evdev->handle.private = evdev;
sprintf(evdev->name, "event%d", minor); snprintf(evdev->name, sizeof(evdev->name), "event%d", minor);
evdev_table[minor] = evdev;
devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), snprintf(evdev->dev.bus_id, sizeof(evdev->dev.bus_id),
"event%d", minor);
evdev->dev.class = &input_class;
evdev->dev.parent = &dev->dev;
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
evdev->dev.release = evdev_free;
device_initialize(&evdev->dev);
cdev = class_device_create(&input_class, &dev->cdev, devt, evdev_table[minor] = evdev;
dev->cdev.dev, evdev->name);
if (IS_ERR(cdev)) {
error = PTR_ERR(cdev);
goto err_free_evdev;
}
/* temporary symlink to keep userspace happy */ error = device_add(&evdev->dev);
error = sysfs_create_link(&input_class.subsys.kobj,
&cdev->kobj, evdev->name);
if (error) if (error)
goto err_cdev_destroy; goto err_free_evdev;
error = input_register_handle(&evdev->handle); error = input_register_handle(&evdev->handle);
if (error) if (error)
goto err_remove_link; goto err_delete_evdev;
return 0; return 0;
err_remove_link: err_delete_evdev:
sysfs_remove_link(&input_class.subsys.kobj, evdev->name); device_del(&evdev->dev);
err_cdev_destroy:
class_device_destroy(&input_class, devt);
err_free_evdev: err_free_evdev:
kfree(evdev); put_device(&evdev->dev);
evdev_table[minor] = NULL;
return error; return error;
} }
...@@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle) ...@@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev_client *client; struct evdev_client *client;
input_unregister_handle(handle); input_unregister_handle(handle);
device_del(&evdev->dev);
sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
evdev->exist = 0; evdev->exist = 0;
if (evdev->open) { if (evdev->open) {
...@@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle) ...@@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &evdev->client_list, node) list_for_each_entry(client, &evdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&evdev->wait); wake_up_interruptible(&evdev->wait);
} else }
evdev_free(evdev);
put_device(&evdev->dev);
} }
static const struct input_device_id evdev_ids[] = { static const struct input_device_id evdev_ids[] = {
......
...@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han ...@@ -442,7 +442,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
printk(KERN_ERR printk(KERN_ERR
"input: failed to attach handler %s to device %s, " "input: failed to attach handler %s to device %s, "
"error: %d\n", "error: %d\n",
handler->name, kobject_name(&dev->cdev.kobj), error); handler->name, kobject_name(&dev->dev.kobj), error);
return error; return error;
} }
...@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, ...@@ -527,7 +527,7 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
static int input_devices_seq_show(struct seq_file *seq, void *v) static int input_devices_seq_show(struct seq_file *seq, void *v)
{ {
struct input_dev *dev = container_of(v, struct input_dev, node); struct input_dev *dev = container_of(v, struct input_dev, node);
const char *path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); const char *path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
struct input_handle *handle; struct input_handle *handle;
seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
...@@ -682,15 +682,17 @@ static inline int input_proc_init(void) { return 0; } ...@@ -682,15 +682,17 @@ static inline int input_proc_init(void) { return 0; }
static inline void input_proc_exit(void) { } static inline void input_proc_exit(void) { }
#endif #endif
#define INPUT_DEV_STRING_ATTR_SHOW(name) \ #define INPUT_DEV_STRING_ATTR_SHOW(name) \
static ssize_t input_dev_show_##name(struct class_device *dev, char *buf) \ static ssize_t input_dev_show_##name(struct device *dev, \
{ \ struct device_attribute *attr, \
struct input_dev *input_dev = to_input_dev(dev); \ char *buf) \
\ { \
return scnprintf(buf, PAGE_SIZE, "%s\n", \ struct input_dev *input_dev = to_input_dev(dev); \
input_dev->name ? input_dev->name : ""); \ \
} \ return scnprintf(buf, PAGE_SIZE, "%s\n", \
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL); input_dev->name ? input_dev->name : ""); \
} \
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
INPUT_DEV_STRING_ATTR_SHOW(name); INPUT_DEV_STRING_ATTR_SHOW(name);
INPUT_DEV_STRING_ATTR_SHOW(phys); INPUT_DEV_STRING_ATTR_SHOW(phys);
...@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id, ...@@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
return len; return len;
} }
static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) static ssize_t input_dev_show_modalias(struct device *dev,
struct device_attribute *attr,
char *buf)
{ {
struct input_dev *id = to_input_dev(dev); struct input_dev *id = to_input_dev(dev);
ssize_t len; ssize_t len;
...@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) ...@@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
return min_t(int, len, PAGE_SIZE); return min_t(int, len, PAGE_SIZE);
} }
static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); static DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
static struct attribute *input_dev_attrs[] = { static struct attribute *input_dev_attrs[] = {
&class_device_attr_name.attr, &dev_attr_name.attr,
&class_device_attr_phys.attr, &dev_attr_phys.attr,
&class_device_attr_uniq.attr, &dev_attr_uniq.attr,
&class_device_attr_modalias.attr, &dev_attr_modalias.attr,
NULL NULL
}; };
...@@ -767,13 +771,15 @@ static struct attribute_group input_dev_attr_group = { ...@@ -767,13 +771,15 @@ static struct attribute_group input_dev_attr_group = {
.attrs = input_dev_attrs, .attrs = input_dev_attrs,
}; };
#define INPUT_DEV_ID_ATTR(name) \ #define INPUT_DEV_ID_ATTR(name) \
static ssize_t input_dev_show_id_##name(struct class_device *dev, char *buf) \ static ssize_t input_dev_show_id_##name(struct device *dev, \
{ \ struct device_attribute *attr, \
struct input_dev *input_dev = to_input_dev(dev); \ char *buf) \
return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \ { \
} \ struct input_dev *input_dev = to_input_dev(dev); \
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL); return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
} \
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
INPUT_DEV_ID_ATTR(bustype); INPUT_DEV_ID_ATTR(bustype);
INPUT_DEV_ID_ATTR(vendor); INPUT_DEV_ID_ATTR(vendor);
...@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product); ...@@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product);
INPUT_DEV_ID_ATTR(version); INPUT_DEV_ID_ATTR(version);
static struct attribute *input_dev_id_attrs[] = { static struct attribute *input_dev_id_attrs[] = {
&class_device_attr_bustype.attr, &dev_attr_bustype.attr,
&class_device_attr_vendor.attr, &dev_attr_vendor.attr,
&class_device_attr_product.attr, &dev_attr_product.attr,
&class_device_attr_version.attr, &dev_attr_version.attr,
NULL NULL
}; };
...@@ -813,15 +819,17 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, ...@@ -813,15 +819,17 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
return len; return len;
} }
#define INPUT_DEV_CAP_ATTR(ev, bm) \ #define INPUT_DEV_CAP_ATTR(ev, bm) \
static ssize_t input_dev_show_cap_##bm(struct class_device *dev, char *buf) \ static ssize_t input_dev_show_cap_##bm(struct device *dev, \
{ \ struct device_attribute *attr, \
struct input_dev *input_dev = to_input_dev(dev); \ char *buf) \
int len = input_print_bitmap(buf, PAGE_SIZE, \ { \
input_dev->bm##bit, ev##_MAX, 1); \ struct input_dev *input_dev = to_input_dev(dev); \
return min_t(int, len, PAGE_SIZE); \ int len = input_print_bitmap(buf, PAGE_SIZE, \
} \ input_dev->bm##bit, ev##_MAX, 1); \
static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL); return min_t(int, len, PAGE_SIZE); \
} \
static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
INPUT_DEV_CAP_ATTR(EV, ev); INPUT_DEV_CAP_ATTR(EV, ev);
INPUT_DEV_CAP_ATTR(KEY, key); INPUT_DEV_CAP_ATTR(KEY, key);
...@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff); ...@@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff);
INPUT_DEV_CAP_ATTR(SW, sw); INPUT_DEV_CAP_ATTR(SW, sw);
static struct attribute *input_dev_caps_attrs[] = { static struct attribute *input_dev_caps_attrs[] = {
&class_device_attr_ev.attr, &dev_attr_ev.attr,
&class_device_attr_key.attr, &dev_attr_key.attr,
&class_device_attr_rel.attr, &dev_attr_rel.attr,
&class_device_attr_abs.attr, &dev_attr_abs.attr,
&class_device_attr_msc.attr, &dev_attr_msc.attr,
&class_device_attr_led.attr, &dev_attr_led.attr,
&class_device_attr_snd.attr, &dev_attr_snd.attr,
&class_device_attr_ff.attr, &dev_attr_ff.attr,
&class_device_attr_sw.attr, &dev_attr_sw.attr,
NULL NULL
}; };
...@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = { ...@@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = {
NULL NULL
}; };
static void input_dev_release(struct class_device *class_dev) static void input_dev_release(struct device *device)
{ {
struct input_dev *dev = to_input_dev(class_dev); struct input_dev *dev = to_input_dev(device);
input_ff_destroy(dev); input_ff_destroy(dev);
kfree(dev); kfree(dev);
...@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind ...@@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind
return err; \ return err; \
} while (0) } while (0)
static int input_dev_uevent(struct class_device *cdev, char **envp, static int input_dev_uevent(struct device *device, char **envp,
int num_envp, char *buffer, int buffer_size) int num_envp, char *buffer, int buffer_size)
{ {
struct input_dev *dev = to_input_dev(cdev); struct input_dev *dev = to_input_dev(device);
int i = 0; int i = 0;
int len = 0; int len = 0;
...@@ -988,10 +996,14 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, ...@@ -988,10 +996,14 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
return 0; return 0;
} }
static struct device_type input_dev_type = {
.groups = input_dev_attr_groups,
.release = input_dev_release,
.uevent = input_dev_uevent,
};
struct class input_class = { struct class input_class = {
.name = "input", .name = "input",
.release = input_dev_release,
.uevent = input_dev_uevent,
}; };
EXPORT_SYMBOL_GPL(input_class); EXPORT_SYMBOL_GPL(input_class);
...@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void) ...@@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void)
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) { if (dev) {
dev->cdev.class = &input_class; dev->dev.type = &input_dev_type;
dev->cdev.groups = input_dev_attr_groups; dev->dev.class = &input_class;
class_device_initialize(&dev->cdev); device_initialize(&dev->dev);
mutex_init(&dev->mutex); mutex_init(&dev->mutex);
INIT_LIST_HEAD(&dev->h_list); INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node); INIT_LIST_HEAD(&dev->node);
...@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev) ...@@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev)
list_add_tail(&dev->node, &input_dev_list); list_add_tail(&dev->node, &input_dev_list);
snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id), snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
if (!dev->cdev.dev) if (dev->cdev.dev)
dev->cdev.dev = dev->dev.parent; dev->dev.parent = dev->cdev.dev;
error = class_device_add(&dev->cdev); error = device_add(&dev->dev);
if (error) if (error)
return error; return error;
path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n", printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A"); dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
kfree(path); kfree(path);
...@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev) ...@@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev)
list_del_init(&dev->node); list_del_init(&dev->node);
class_device_unregister(&dev->cdev); device_unregister(&dev->dev);
input_wakeup_procfs_readers(); input_wakeup_procfs_readers();
} }
......
...@@ -43,6 +43,8 @@ struct joydev { ...@@ -43,6 +43,8 @@ struct joydev {
struct input_handle handle; struct input_handle handle;
wait_queue_head_t wait; wait_queue_head_t wait;
struct list_head client_list; struct list_head client_list;
struct device dev;
struct js_corr corr[ABS_MAX + 1]; struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue; struct JS_DATA_SAVE_TYPE glue;
int nabs; int nabs;
...@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on) ...@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
return retval < 0 ? retval : 0; return retval < 0 ? retval : 0;
} }
static void joydev_free(struct joydev *joydev) static void joydev_free(struct device *dev)
{ {
struct joydev *joydev = container_of(dev, struct joydev, dev);
joydev_table[joydev->minor] = NULL; joydev_table[joydev->minor] = NULL;
kfree(joydev); kfree(joydev);
} }
...@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file) ...@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
list_del(&client->node); list_del(&client->node);
kfree(client); kfree(client);
if (!--joydev->open) { if (!--joydev->open && joydev->exist)
if (joydev->exist) input_close_device(&joydev->handle);
input_close_device(&joydev->handle);
else put_device(&joydev->dev);
joydev_free(joydev);
}
return 0; return 0;
} }
...@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file) ...@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
if (!joydev || !joydev->exist) if (!joydev || !joydev->exist)
return -ENODEV; return -ENODEV;
get_device(&joydev->dev);
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
if (!client) if (!client) {
return -ENOMEM; error = -ENOMEM;
goto err_put_joydev;
}
client->joydev = joydev; client->joydev = joydev;
list_add_tail(&client->node, &joydev->client_list); list_add_tail(&client->node, &joydev->client_list);
if (!joydev->open++ && joydev->exist) { if (!joydev->open++ && joydev->exist) {
error = input_open_device(&joydev->handle); error = input_open_device(&joydev->handle);
if (error) { if (error)
list_del(&client->node); goto err_free_client;
kfree(client);
return error;
}
} }
file->private_data = client; file->private_data = client;
return 0; return 0;
err_free_client:
list_del(&client->node);
kfree(client);
err_put_joydev:
put_device(&joydev->dev);
return error;
} }
static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
...@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id) const struct input_device_id *id)
{ {
struct joydev *joydev; struct joydev *joydev;
struct class_device *cdev;
dev_t devt;
int i, j, t, minor; int i, j, t, minor;
int error; int error;
...@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->handle.name = joydev->name; joydev->handle.name = joydev->name;
joydev->handle.handler = handler; joydev->handle.handler = handler;
joydev->handle.private = joydev; joydev->handle.private = joydev;
sprintf(joydev->name, "js%d", minor); snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
for (i = 0; i < ABS_MAX + 1; i++) for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) { if (test_bit(i, dev->absbit)) {
...@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
} }
joydev_table[minor] = joydev; snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
"js%d", minor);
devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), joydev->dev.class = &input_class;
joydev->dev.parent = &dev->dev;
joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
joydev->dev.release = joydev_free;
device_initialize(&joydev->dev);
cdev = class_device_create(&input_class, &dev->cdev, devt, joydev_table[minor] = joydev;
dev->cdev.dev, joydev->name);
if (IS_ERR(cdev)) {
error = PTR_ERR(cdev);
goto err_free_joydev;
}
/* temporary symlink to keep userspace happy */ error = device_add(&joydev->dev);
error = sysfs_create_link(&input_class.subsys.kobj,
&cdev->kobj, joydev->name);
if (error) if (error)
goto err_cdev_destroy; goto err_free_joydev;
error = input_register_handle(&joydev->handle); error = input_register_handle(&joydev->handle);
if (error) if (error)
goto err_remove_link; goto err_delete_joydev;
return 0; return 0;
err_remove_link: err_delete_joydev:
sysfs_remove_link(&input_class.subsys.kobj, joydev->name); device_del(&joydev->dev);
err_cdev_destroy:
class_device_destroy(&input_class, devt);
err_free_joydev: err_free_joydev:
joydev_table[minor] = NULL; put_device(&joydev->dev);
kfree(joydev);
return error; return error;
} }
...@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle) ...@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev_client *client; struct joydev_client *client;
input_unregister_handle(handle); input_unregister_handle(handle);
device_del(&joydev->dev);
sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
joydev->exist = 0; joydev->exist = 0;
if (joydev->open) { if (joydev->open) {
...@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle) ...@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &joydev->client_list, node) list_for_each_entry(client, &joydev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&joydev->wait); wake_up_interruptible(&joydev->wait);
} else }
joydev_free(joydev);
put_device(&joydev->dev);
} }
static const struct input_device_id joydev_blacklist[] = { static const struct input_device_id joydev_blacklist[] = {
......
This diff is collapsed.
...@@ -109,9 +109,11 @@ struct tsdev { ...@@ -109,9 +109,11 @@ struct tsdev {
int open; int open;
int minor; int minor;
char name[8]; char name[8];
struct input_handle handle;
wait_queue_head_t wait; wait_queue_head_t wait;
struct list_head client_list; struct list_head client_list;
struct input_handle handle; struct device dev;
int x, y, pressure; int x, y, pressure;
struct ts_calibration cal; struct ts_calibration cal;
}; };
...@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file) ...@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev || !tsdev->exist) if (!tsdev || !tsdev->exist)
return -ENODEV; return -ENODEV;
get_device(&tsdev->dev);
client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
if (!client) if (!client) {
return -ENOMEM; error = -ENOMEM;
goto err_put_tsdev;
}
client->tsdev = tsdev; client->tsdev = tsdev;
client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
...@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file) ...@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file)
if (!tsdev->open++ && tsdev->exist) { if (!tsdev->open++ && tsdev->exist) {
error = input_open_device(&tsdev->handle); error = input_open_device(&tsdev->handle);
if (error) { if (error)
list_del(&client->node); goto err_free_client;
kfree(client);
return error;
}
} }
file->private_data = client; file->private_data = client;
return 0; return 0;
err_free_client:
list_del(&client->node);
kfree(client);
err_put_tsdev:
put_device(&tsdev->dev);
return error;
} }
static void tsdev_free(struct tsdev *tsdev) static void tsdev_free(struct device *dev)
{ {
struct tsdev *tsdev = container_of(dev, struct tsdev, dev);
tsdev_table[tsdev->minor] = NULL; tsdev_table[tsdev->minor] = NULL;
kfree(tsdev); kfree(tsdev);
} }
...@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file) ...@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file)
list_del(&client->node); list_del(&client->node);
kfree(client); kfree(client);
if (!--tsdev->open) { if (!--tsdev->open && tsdev->exist)
if (tsdev->exist) input_close_device(&tsdev->handle);
input_close_device(&tsdev->handle);
else put_device(&tsdev->dev);
tsdev_free(tsdev);
}
return 0; return 0;
} }
...@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id) const struct input_device_id *id)
{ {
struct tsdev *tsdev; struct tsdev *tsdev;
struct class_device *cdev;
dev_t devt;
int minor, delta; int minor, delta;
int error; int error;
...@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
INIT_LIST_HEAD(&tsdev->client_list); INIT_LIST_HEAD(&tsdev->client_list);
init_waitqueue_head(&tsdev->wait); init_waitqueue_head(&tsdev->wait);
sprintf(tsdev->name, "ts%d", minor);
tsdev->exist = 1; tsdev->exist = 1;
tsdev->minor = minor; tsdev->minor = minor;
tsdev->handle.dev = dev; tsdev->handle.dev = dev;
tsdev->handle.name = tsdev->name; tsdev->handle.name = tsdev->name;
tsdev->handle.handler = handler; tsdev->handle.handler = handler;
tsdev->handle.private = tsdev; tsdev->handle.private = tsdev;
snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
/* Precompute the rough calibration matrix */ /* Precompute the rough calibration matrix */
delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1;
...@@ -429,36 +436,30 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -429,36 +436,30 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
tsdev->cal.yscale = (yres << 8) / delta; tsdev->cal.yscale = (yres << 8) / delta;
tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
tsdev_table[minor] = tsdev; snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
"ts%d", minor);
devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), tsdev->dev.class = &input_class;
tsdev->dev.parent = &dev->dev;
tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor);
tsdev->dev.release = tsdev_free;
device_initialize(&tsdev->dev);
cdev = class_device_create(&input_class, &dev->cdev, devt, tsdev_table[minor] = tsdev;
dev->cdev.dev, tsdev->name);
if (IS_ERR(cdev)) {
error = PTR_ERR(cdev);
goto err_free_tsdev;
}
/* temporary symlink to keep userspace happy */ error = device_add(&tsdev->dev);
error = sysfs_create_link(&input_class.subsys.kobj,
&cdev->kobj, tsdev->name);
if (error) if (error)
goto err_cdev_destroy; goto err_free_tsdev;
error = input_register_handle(&tsdev->handle); error = input_register_handle(&tsdev->handle);
if (error) if (error)
goto err_remove_link; goto err_delete_tsdev;
return 0; return 0;
err_remove_link: err_delete_tsdev:
sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); device_del(&tsdev->dev);
err_cdev_destroy:
class_device_destroy(&input_class, devt);
err_free_tsdev: err_free_tsdev:
tsdev_table[minor] = NULL; put_device(&tsdev->dev);
kfree(tsdev);
return error; return error;
} }
...@@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle) ...@@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev_client *client; struct tsdev_client *client;
input_unregister_handle(handle); input_unregister_handle(handle);
device_del(&tsdev->dev);
sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
class_device_destroy(&input_class,
MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
tsdev->exist = 0; tsdev->exist = 0;
if (tsdev->open) { if (tsdev->open) {
...@@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle) ...@@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle)
list_for_each_entry(client, &tsdev->client_list, node) list_for_each_entry(client, &tsdev->client_list, node)
kill_fasync(&client->fasync, SIGIO, POLL_HUP); kill_fasync(&client->fasync, SIGIO, POLL_HUP);
wake_up_interruptible(&tsdev->wait); wake_up_interruptible(&tsdev->wait);
} else }
tsdev_free(tsdev);
put_device(&tsdev->dev);
} }
static const struct input_device_id tsdev_ids[] = { static const struct input_device_id tsdev_ids[] = {
......
...@@ -981,15 +981,15 @@ struct input_dev { ...@@ -981,15 +981,15 @@ struct input_dev {
struct mutex mutex; /* serializes open and close operations */ struct mutex mutex; /* serializes open and close operations */
unsigned int users; unsigned int users;
struct class_device cdev; struct device dev;
union { /* temporarily so while we switching to struct device */ union { /* temporarily so while we switching to struct device */
struct device *parent; struct device *dev;
} dev; } cdev;
struct list_head h_list; struct list_head h_list;
struct list_head node; struct list_head node;
}; };
#define to_input_dev(d) container_of(d, struct input_dev, cdev) #define to_input_dev(d) container_of(d, struct input_dev, dev)
/* /*
* Verify that we are in sync with input_device_id mod_devicetable.h #defines * Verify that we are in sync with input_device_id mod_devicetable.h #defines
...@@ -1096,22 +1096,22 @@ struct input_handle { ...@@ -1096,22 +1096,22 @@ struct input_handle {
struct list_head h_node; struct list_head h_node;
}; };
#define to_dev(n) container_of(n,struct input_dev,node) #define to_dev(n) container_of(n, struct input_dev, node)
#define to_handler(n) container_of(n,struct input_handler,node) #define to_handler(n) container_of(n, struct input_handler, node)
#define to_handle(n) container_of(n,struct input_handle,d_node) #define to_handle(n) container_of(n, struct input_handle, d_node)
#define to_handle_h(n) container_of(n,struct input_handle,h_node) #define to_handle_h(n) container_of(n, struct input_handle, h_node)
struct input_dev *input_allocate_device(void); struct input_dev *input_allocate_device(void);
void input_free_device(struct input_dev *dev); void input_free_device(struct input_dev *dev);
static inline struct input_dev *input_get_device(struct input_dev *dev) static inline struct input_dev *input_get_device(struct input_dev *dev)
{ {
return to_input_dev(class_device_get(&dev->cdev)); return to_input_dev(get_device(&dev->dev));
} }
static inline void input_put_device(struct input_dev *dev) static inline void input_put_device(struct input_dev *dev)
{ {
class_device_put(&dev->cdev); put_device(&dev->dev);
} }
static inline void *input_get_drvdata(struct input_dev *dev) static inline void *input_get_drvdata(struct input_dev *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment