Input: convert from class devices to standard devices
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
Родитель
d63219a101
Коммит
9657d75c5f
|
@ -30,6 +30,7 @@ struct evdev {
|
|||
wait_queue_head_t wait;
|
||||
struct evdev_client *grab;
|
||||
struct list_head client_list;
|
||||
struct device dev;
|
||||
};
|
||||
|
||||
struct evdev_client {
|
||||
|
@ -94,8 +95,10 @@ static int evdev_flush(struct file *file, fl_owner_t id)
|
|||
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;
|
||||
kfree(evdev);
|
||||
}
|
||||
|
@ -114,12 +117,10 @@ static int evdev_release(struct inode *inode, struct file *file)
|
|||
list_del(&client->node);
|
||||
kfree(client);
|
||||
|
||||
if (!--evdev->open) {
|
||||
if (evdev->exist)
|
||||
if (!--evdev->open && evdev->exist)
|
||||
input_close_device(&evdev->handle);
|
||||
else
|
||||
evdev_free(evdev);
|
||||
}
|
||||
|
||||
put_device(&evdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -139,24 +140,32 @@ static int evdev_open(struct inode *inode, struct file *file)
|
|||
if (!evdev || !evdev->exist)
|
||||
return -ENODEV;
|
||||
|
||||
get_device(&evdev->dev);
|
||||
|
||||
client = kzalloc(sizeof(struct evdev_client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
if (!client) {
|
||||
error = -ENOMEM;
|
||||
goto err_put_evdev;
|
||||
}
|
||||
|
||||
client->evdev = evdev;
|
||||
list_add_tail(&client->node, &evdev->client_list);
|
||||
|
||||
if (!evdev->open++ && evdev->exist) {
|
||||
error = input_open_device(&evdev->handle);
|
||||
if (error) {
|
||||
list_del(&client->node);
|
||||
kfree(client);
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
goto err_free_client;
|
||||
}
|
||||
|
||||
file->private_data = client;
|
||||
return 0;
|
||||
|
||||
err_free_client:
|
||||
list_del(&client->node);
|
||||
kfree(client);
|
||||
err_put_evdev:
|
||||
put_device(&evdev->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@ -625,8 +634,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
const struct input_device_id *id)
|
||||
{
|
||||
struct evdev *evdev;
|
||||
struct class_device *cdev;
|
||||
dev_t devt;
|
||||
int minor;
|
||||
int error;
|
||||
|
||||
|
@ -649,38 +656,32 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
evdev->handle.name = evdev->name;
|
||||
evdev->handle.handler = handler;
|
||||
evdev->handle.private = evdev;
|
||||
sprintf(evdev->name, "event%d", minor);
|
||||
snprintf(evdev->name, sizeof(evdev->name), "event%d", 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);
|
||||
|
||||
evdev_table[minor] = evdev;
|
||||
|
||||
devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
|
||||
|
||||
cdev = class_device_create(&input_class, &dev->cdev, devt,
|
||||
dev->cdev.dev, evdev->name);
|
||||
if (IS_ERR(cdev)) {
|
||||
error = PTR_ERR(cdev);
|
||||
goto err_free_evdev;
|
||||
}
|
||||
|
||||
/* temporary symlink to keep userspace happy */
|
||||
error = sysfs_create_link(&input_class.subsys.kobj,
|
||||
&cdev->kobj, evdev->name);
|
||||
error = device_add(&evdev->dev);
|
||||
if (error)
|
||||
goto err_cdev_destroy;
|
||||
goto err_free_evdev;
|
||||
|
||||
error = input_register_handle(&evdev->handle);
|
||||
if (error)
|
||||
goto err_remove_link;
|
||||
goto err_delete_evdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_link:
|
||||
sysfs_remove_link(&input_class.subsys.kobj, evdev->name);
|
||||
err_cdev_destroy:
|
||||
class_device_destroy(&input_class, devt);
|
||||
err_delete_evdev:
|
||||
device_del(&evdev->dev);
|
||||
err_free_evdev:
|
||||
kfree(evdev);
|
||||
evdev_table[minor] = NULL;
|
||||
put_device(&evdev->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -690,10 +691,8 @@ static void evdev_disconnect(struct input_handle *handle)
|
|||
struct evdev_client *client;
|
||||
|
||||
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;
|
||||
|
||||
if (evdev->open) {
|
||||
|
@ -702,8 +701,9 @@ static void evdev_disconnect(struct input_handle *handle)
|
|||
list_for_each_entry(client, &evdev->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
wake_up_interruptible(&evdev->wait);
|
||||
} else
|
||||
evdev_free(evdev);
|
||||
}
|
||||
|
||||
put_device(&evdev->dev);
|
||||
}
|
||||
|
||||
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
|
|||
printk(KERN_ERR
|
||||
"input: failed to attach handler %s to device %s, "
|
||||
"error: %d\n",
|
||||
handler->name, kobject_name(&dev->cdev.kobj), error);
|
||||
handler->name, kobject_name(&dev->dev.kobj), error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
|
||||
seq_printf(seq, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n",
|
||||
|
@ -683,14 +683,16 @@ static inline void input_proc_exit(void) { }
|
|||
#endif
|
||||
|
||||
#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, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct input_dev *input_dev = to_input_dev(dev); \
|
||||
\
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n", \
|
||||
input_dev->name ? input_dev->name : ""); \
|
||||
} \
|
||||
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL);
|
||||
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_##name, NULL)
|
||||
|
||||
INPUT_DEV_STRING_ATTR_SHOW(name);
|
||||
INPUT_DEV_STRING_ATTR_SHOW(phys);
|
||||
|
@ -744,7 +746,9 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
|||
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);
|
||||
ssize_t len;
|
||||
|
@ -753,13 +757,13 @@ static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
|
|||
|
||||
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[] = {
|
||||
&class_device_attr_name.attr,
|
||||
&class_device_attr_phys.attr,
|
||||
&class_device_attr_uniq.attr,
|
||||
&class_device_attr_modalias.attr,
|
||||
&dev_attr_name.attr,
|
||||
&dev_attr_phys.attr,
|
||||
&dev_attr_uniq.attr,
|
||||
&dev_attr_modalias.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -768,12 +772,14 @@ static struct attribute_group input_dev_attr_group = {
|
|||
};
|
||||
|
||||
#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, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct input_dev *input_dev = to_input_dev(dev); \
|
||||
return scnprintf(buf, PAGE_SIZE, "%04x\n", input_dev->id.name); \
|
||||
} \
|
||||
static CLASS_DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL);
|
||||
static DEVICE_ATTR(name, S_IRUGO, input_dev_show_id_##name, NULL)
|
||||
|
||||
INPUT_DEV_ID_ATTR(bustype);
|
||||
INPUT_DEV_ID_ATTR(vendor);
|
||||
|
@ -781,10 +787,10 @@ INPUT_DEV_ID_ATTR(product);
|
|||
INPUT_DEV_ID_ATTR(version);
|
||||
|
||||
static struct attribute *input_dev_id_attrs[] = {
|
||||
&class_device_attr_bustype.attr,
|
||||
&class_device_attr_vendor.attr,
|
||||
&class_device_attr_product.attr,
|
||||
&class_device_attr_version.attr,
|
||||
&dev_attr_bustype.attr,
|
||||
&dev_attr_vendor.attr,
|
||||
&dev_attr_product.attr,
|
||||
&dev_attr_version.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -814,14 +820,16 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
|
|||
}
|
||||
|
||||
#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, \
|
||||
char *buf) \
|
||||
{ \
|
||||
struct input_dev *input_dev = to_input_dev(dev); \
|
||||
int len = input_print_bitmap(buf, PAGE_SIZE, \
|
||||
input_dev->bm##bit, ev##_MAX, 1); \
|
||||
return min_t(int, len, PAGE_SIZE); \
|
||||
} \
|
||||
static CLASS_DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL);
|
||||
static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
|
||||
|
||||
INPUT_DEV_CAP_ATTR(EV, ev);
|
||||
INPUT_DEV_CAP_ATTR(KEY, key);
|
||||
|
@ -834,15 +842,15 @@ INPUT_DEV_CAP_ATTR(FF, ff);
|
|||
INPUT_DEV_CAP_ATTR(SW, sw);
|
||||
|
||||
static struct attribute *input_dev_caps_attrs[] = {
|
||||
&class_device_attr_ev.attr,
|
||||
&class_device_attr_key.attr,
|
||||
&class_device_attr_rel.attr,
|
||||
&class_device_attr_abs.attr,
|
||||
&class_device_attr_msc.attr,
|
||||
&class_device_attr_led.attr,
|
||||
&class_device_attr_snd.attr,
|
||||
&class_device_attr_ff.attr,
|
||||
&class_device_attr_sw.attr,
|
||||
&dev_attr_ev.attr,
|
||||
&dev_attr_key.attr,
|
||||
&dev_attr_rel.attr,
|
||||
&dev_attr_abs.attr,
|
||||
&dev_attr_msc.attr,
|
||||
&dev_attr_led.attr,
|
||||
&dev_attr_snd.attr,
|
||||
&dev_attr_ff.attr,
|
||||
&dev_attr_sw.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -858,9 +866,9 @@ static struct attribute_group *input_dev_attr_groups[] = {
|
|||
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);
|
||||
kfree(dev);
|
||||
|
@ -947,10 +955,10 @@ static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_ind
|
|||
return err; \
|
||||
} 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)
|
||||
{
|
||||
struct input_dev *dev = to_input_dev(cdev);
|
||||
struct input_dev *dev = to_input_dev(device);
|
||||
int i = 0;
|
||||
int len = 0;
|
||||
|
||||
|
@ -988,11 +996,15 @@ static int input_dev_uevent(struct class_device *cdev, char **envp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct class input_class = {
|
||||
.name = "input",
|
||||
static struct device_type input_dev_type = {
|
||||
.groups = input_dev_attr_groups,
|
||||
.release = input_dev_release,
|
||||
.uevent = input_dev_uevent,
|
||||
};
|
||||
|
||||
struct class input_class = {
|
||||
.name = "input",
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(input_class);
|
||||
|
||||
/**
|
||||
|
@ -1010,9 +1022,9 @@ struct input_dev *input_allocate_device(void)
|
|||
|
||||
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
|
||||
if (dev) {
|
||||
dev->cdev.class = &input_class;
|
||||
dev->cdev.groups = input_dev_attr_groups;
|
||||
class_device_initialize(&dev->cdev);
|
||||
dev->dev.type = &input_dev_type;
|
||||
dev->dev.class = &input_class;
|
||||
device_initialize(&dev->dev);
|
||||
mutex_init(&dev->mutex);
|
||||
INIT_LIST_HEAD(&dev->h_list);
|
||||
INIT_LIST_HEAD(&dev->node);
|
||||
|
@ -1131,17 +1143,17 @@ int input_register_device(struct input_dev *dev)
|
|||
|
||||
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);
|
||||
|
||||
if (!dev->cdev.dev)
|
||||
dev->cdev.dev = dev->dev.parent;
|
||||
if (dev->cdev.dev)
|
||||
dev->dev.parent = dev->cdev.dev;
|
||||
|
||||
error = class_device_add(&dev->cdev);
|
||||
error = device_add(&dev->dev);
|
||||
if (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",
|
||||
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
|
||||
kfree(path);
|
||||
|
@ -1173,7 +1185,7 @@ void input_unregister_device(struct input_dev *dev)
|
|||
|
||||
list_del_init(&dev->node);
|
||||
|
||||
class_device_unregister(&dev->cdev);
|
||||
device_unregister(&dev->dev);
|
||||
|
||||
input_wakeup_procfs_readers();
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ struct joydev {
|
|||
struct input_handle handle;
|
||||
wait_queue_head_t wait;
|
||||
struct list_head client_list;
|
||||
struct device dev;
|
||||
|
||||
struct js_corr corr[ABS_MAX + 1];
|
||||
struct JS_DATA_SAVE_TYPE glue;
|
||||
int nabs;
|
||||
|
@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
|
|||
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;
|
||||
kfree(joydev);
|
||||
}
|
||||
|
@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
|
|||
list_del(&client->node);
|
||||
kfree(client);
|
||||
|
||||
if (!--joydev->open) {
|
||||
if (joydev->exist)
|
||||
if (!--joydev->open && joydev->exist)
|
||||
input_close_device(&joydev->handle);
|
||||
else
|
||||
joydev_free(joydev);
|
||||
}
|
||||
|
||||
put_device(&joydev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
|
|||
if (!joydev || !joydev->exist)
|
||||
return -ENODEV;
|
||||
|
||||
get_device(&joydev->dev);
|
||||
|
||||
client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
if (!client) {
|
||||
error = -ENOMEM;
|
||||
goto err_put_joydev;
|
||||
}
|
||||
|
||||
client->joydev = joydev;
|
||||
list_add_tail(&client->node, &joydev->client_list);
|
||||
|
||||
if (!joydev->open++ && joydev->exist) {
|
||||
error = input_open_device(&joydev->handle);
|
||||
if (error) {
|
||||
list_del(&client->node);
|
||||
kfree(client);
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
goto err_free_client;
|
||||
}
|
||||
|
||||
file->private_data = client;
|
||||
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)
|
||||
|
@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
const struct input_device_id *id)
|
||||
{
|
||||
struct joydev *joydev;
|
||||
struct class_device *cdev;
|
||||
dev_t devt;
|
||||
int i, j, t, minor;
|
||||
int error;
|
||||
|
||||
|
@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
joydev->handle.name = joydev->name;
|
||||
joydev->handle.handler = handler;
|
||||
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++)
|
||||
if (test_bit(i, dev->absbit)) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
|
||||
"js%d", 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);
|
||||
|
||||
joydev_table[minor] = joydev;
|
||||
|
||||
devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
|
||||
|
||||
cdev = class_device_create(&input_class, &dev->cdev, devt,
|
||||
dev->cdev.dev, joydev->name);
|
||||
if (IS_ERR(cdev)) {
|
||||
error = PTR_ERR(cdev);
|
||||
goto err_free_joydev;
|
||||
}
|
||||
|
||||
/* temporary symlink to keep userspace happy */
|
||||
error = sysfs_create_link(&input_class.subsys.kobj,
|
||||
&cdev->kobj, joydev->name);
|
||||
error = device_add(&joydev->dev);
|
||||
if (error)
|
||||
goto err_cdev_destroy;
|
||||
goto err_free_joydev;
|
||||
|
||||
error = input_register_handle(&joydev->handle);
|
||||
if (error)
|
||||
goto err_remove_link;
|
||||
goto err_delete_joydev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_link:
|
||||
sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
|
||||
err_cdev_destroy:
|
||||
class_device_destroy(&input_class, devt);
|
||||
err_delete_joydev:
|
||||
device_del(&joydev->dev);
|
||||
err_free_joydev:
|
||||
joydev_table[minor] = NULL;
|
||||
kfree(joydev);
|
||||
put_device(&joydev->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
|
|||
struct joydev_client *client;
|
||||
|
||||
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;
|
||||
|
||||
if (joydev->open) {
|
||||
|
@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle)
|
|||
list_for_each_entry(client, &joydev->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
wake_up_interruptible(&joydev->wait);
|
||||
} else
|
||||
joydev_free(joydev);
|
||||
}
|
||||
|
||||
put_device(&joydev->dev);
|
||||
}
|
||||
|
||||
static const struct input_device_id joydev_blacklist[] = {
|
||||
|
|
|
@ -64,6 +64,7 @@ struct mousedev {
|
|||
wait_queue_head_t wait;
|
||||
struct list_head client_list;
|
||||
struct input_handle handle;
|
||||
struct device dev;
|
||||
|
||||
struct list_head mixdev_node;
|
||||
int mixdev_open;
|
||||
|
@ -112,7 +113,7 @@ static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 };
|
|||
static struct input_handler mousedev_handler;
|
||||
|
||||
static struct mousedev *mousedev_table[MOUSEDEV_MINORS];
|
||||
static struct mousedev mousedev_mix;
|
||||
static struct mousedev *mousedev_mix;
|
||||
static LIST_HEAD(mousedev_mix_list);
|
||||
|
||||
#define fx(i) (mousedev->old_x[(mousedev->pkt_count - (i)) & 03])
|
||||
|
@ -218,10 +219,10 @@ static void mousedev_key_event(struct mousedev *mousedev, unsigned int code, int
|
|||
|
||||
if (value) {
|
||||
set_bit(index, &mousedev->packet.buttons);
|
||||
set_bit(index, &mousedev_mix.packet.buttons);
|
||||
set_bit(index, &mousedev_mix->packet.buttons);
|
||||
} else {
|
||||
clear_bit(index, &mousedev->packet.buttons);
|
||||
clear_bit(index, &mousedev_mix.packet.buttons);
|
||||
clear_bit(index, &mousedev_mix->packet.buttons);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,11 +288,11 @@ static void mousedev_touchpad_touch(struct mousedev *mousedev, int value)
|
|||
* motion packet so we won't mess current position.
|
||||
*/
|
||||
set_bit(0, &mousedev->packet.buttons);
|
||||
set_bit(0, &mousedev_mix.packet.buttons);
|
||||
mousedev_notify_readers(mousedev, &mousedev_mix.packet);
|
||||
mousedev_notify_readers(&mousedev_mix, &mousedev_mix.packet);
|
||||
set_bit(0, &mousedev_mix->packet.buttons);
|
||||
mousedev_notify_readers(mousedev, &mousedev_mix->packet);
|
||||
mousedev_notify_readers(mousedev_mix, &mousedev_mix->packet);
|
||||
clear_bit(0, &mousedev->packet.buttons);
|
||||
clear_bit(0, &mousedev_mix.packet.buttons);
|
||||
clear_bit(0, &mousedev_mix->packet.buttons);
|
||||
}
|
||||
mousedev->touch = mousedev->pkt_count = 0;
|
||||
mousedev->frac_dx = 0;
|
||||
|
@ -343,7 +344,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
|
|||
}
|
||||
|
||||
mousedev_notify_readers(mousedev, &mousedev->packet);
|
||||
mousedev_notify_readers(&mousedev_mix, &mousedev->packet);
|
||||
mousedev_notify_readers(mousedev_mix, &mousedev->packet);
|
||||
|
||||
mousedev->packet.dx = mousedev->packet.dy = mousedev->packet.dz = 0;
|
||||
mousedev->packet.abs_event = 0;
|
||||
|
@ -362,8 +363,10 @@ static int mousedev_fasync(int fd, struct file *file, int on)
|
|||
return retval < 0 ? retval : 0;
|
||||
}
|
||||
|
||||
static void mousedev_free(struct mousedev *mousedev)
|
||||
static void mousedev_free(struct device *dev)
|
||||
{
|
||||
struct mousedev *mousedev = container_of(dev, struct mousedev, dev);
|
||||
|
||||
mousedev_table[mousedev->minor] = NULL;
|
||||
kfree(mousedev);
|
||||
}
|
||||
|
@ -372,15 +375,16 @@ static int mixdev_add_device(struct mousedev *mousedev)
|
|||
{
|
||||
int error;
|
||||
|
||||
if (mousedev_mix.open) {
|
||||
if (mousedev_mix->open) {
|
||||
error = input_open_device(&mousedev->handle);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mousedev->open++;
|
||||
mousedev->mixdev_open++;
|
||||
mousedev->mixdev_open = 1;
|
||||
}
|
||||
|
||||
get_device(&mousedev->dev);
|
||||
list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);
|
||||
|
||||
return 0;
|
||||
|
@ -395,36 +399,40 @@ static void mixdev_remove_device(struct mousedev *mousedev)
|
|||
}
|
||||
|
||||
list_del_init(&mousedev->mixdev_node);
|
||||
put_device(&mousedev->dev);
|
||||
}
|
||||
|
||||
static void mixdev_open_devices(void)
|
||||
{
|
||||
struct mousedev *mousedev;
|
||||
|
||||
if (mousedev_mix->open++)
|
||||
return;
|
||||
|
||||
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
|
||||
if (mousedev->exist && !mousedev->open) {
|
||||
if (!mousedev->mixdev_open) {
|
||||
if (!mousedev->open && mousedev->exist)
|
||||
if (input_open_device(&mousedev->handle))
|
||||
continue;
|
||||
|
||||
mousedev->open++;
|
||||
mousedev->mixdev_open++;
|
||||
mousedev->mixdev_open = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mixdev_close_devices(void)
|
||||
{
|
||||
struct mousedev *mousedev, *next;
|
||||
struct mousedev *mousedev;
|
||||
|
||||
list_for_each_entry_safe(mousedev, next, &mousedev_mix_list, mixdev_node) {
|
||||
if (--mousedev_mix->open)
|
||||
return;
|
||||
|
||||
list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) {
|
||||
if (mousedev->mixdev_open) {
|
||||
mousedev->mixdev_open = 0;
|
||||
if (!--mousedev->open) {
|
||||
if (mousedev->exist)
|
||||
if (!--mousedev->open && mousedev->exist)
|
||||
input_close_device(&mousedev->handle);
|
||||
else
|
||||
mousedev_free(mousedev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -439,14 +447,12 @@ static int mousedev_release(struct inode *inode, struct file *file)
|
|||
list_del(&client->node);
|
||||
kfree(client);
|
||||
|
||||
if (!--mousedev->open) {
|
||||
if (mousedev->minor == MOUSEDEV_MIX)
|
||||
mixdev_close_devices();
|
||||
else if (mousedev->exist)
|
||||
else if (!--mousedev->open && mousedev->exist)
|
||||
input_close_device(&mousedev->handle);
|
||||
else
|
||||
mousedev_free(mousedev);
|
||||
}
|
||||
|
||||
put_device(&mousedev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -473,9 +479,13 @@ static int mousedev_open(struct inode *inode, struct file *file)
|
|||
if (!mousedev)
|
||||
return -ENODEV;
|
||||
|
||||
get_device(&mousedev->dev);
|
||||
|
||||
client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
if (!client) {
|
||||
error = -ENOMEM;
|
||||
goto err_put_mousedev;
|
||||
}
|
||||
|
||||
spin_lock_init(&client->packet_lock);
|
||||
client->pos_x = xres / 2;
|
||||
|
@ -483,21 +493,23 @@ static int mousedev_open(struct inode *inode, struct file *file)
|
|||
client->mousedev = mousedev;
|
||||
list_add_tail(&client->node, &mousedev->client_list);
|
||||
|
||||
if (!mousedev->open++) {
|
||||
if (mousedev->minor == MOUSEDEV_MIX)
|
||||
mixdev_open_devices();
|
||||
else if (mousedev->exist) {
|
||||
else if (!mousedev->open++ && mousedev->exist) {
|
||||
error = input_open_device(&mousedev->handle);
|
||||
if (error) {
|
||||
list_del(&client->node);
|
||||
kfree(client);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
goto err_free_client;
|
||||
}
|
||||
|
||||
file->private_data = client;
|
||||
return 0;
|
||||
|
||||
err_free_client:
|
||||
list_del(&client->node);
|
||||
kfree(client);
|
||||
err_put_mousedev:
|
||||
put_device(&mousedev->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
static inline int mousedev_limit_delta(int delta, int limit)
|
||||
|
@ -680,12 +692,80 @@ static const struct file_operations mousedev_fops = {
|
|||
.fasync = mousedev_fasync,
|
||||
};
|
||||
|
||||
static struct mousedev *mousedev_create(struct input_dev *dev,
|
||||
struct input_handler *handler,
|
||||
int minor)
|
||||
{
|
||||
struct mousedev *mousedev;
|
||||
int error;
|
||||
|
||||
mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
|
||||
if (!mousedev) {
|
||||
error = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&mousedev->client_list);
|
||||
INIT_LIST_HEAD(&mousedev->mixdev_node);
|
||||
init_waitqueue_head(&mousedev->wait);
|
||||
|
||||
if (minor == MOUSEDEV_MIX)
|
||||
strlcpy(mousedev->name, "mice", sizeof(mousedev->name));
|
||||
else
|
||||
snprintf(mousedev->name, sizeof(mousedev->name),
|
||||
"mouse%d", minor);
|
||||
|
||||
mousedev->minor = minor;
|
||||
mousedev->exist = 1;
|
||||
mousedev->handle.dev = dev;
|
||||
mousedev->handle.name = mousedev->name;
|
||||
mousedev->handle.handler = handler;
|
||||
mousedev->handle.private = mousedev;
|
||||
|
||||
strlcpy(mousedev->dev.bus_id, mousedev->name,
|
||||
sizeof(mousedev->dev.bus_id));
|
||||
mousedev->dev.class = &input_class;
|
||||
if (dev)
|
||||
mousedev->dev.parent = &dev->dev;
|
||||
mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor);
|
||||
mousedev->dev.release = mousedev_free;
|
||||
device_initialize(&mousedev->dev);
|
||||
|
||||
mousedev_table[minor] = mousedev;
|
||||
|
||||
error = device_add(&mousedev->dev);
|
||||
if (error)
|
||||
goto err_free_mousedev;
|
||||
|
||||
return mousedev;
|
||||
|
||||
err_free_mousedev:
|
||||
put_device(&mousedev->dev);
|
||||
err_out:
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
static void mousedev_destroy(struct mousedev *mousedev)
|
||||
{
|
||||
struct mousedev_client *client;
|
||||
|
||||
device_del(&mousedev->dev);
|
||||
mousedev->exist = 0;
|
||||
|
||||
if (mousedev->open) {
|
||||
input_close_device(&mousedev->handle);
|
||||
list_for_each_entry(client, &mousedev->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
wake_up_interruptible(&mousedev->wait);
|
||||
}
|
||||
|
||||
put_device(&mousedev->dev);
|
||||
}
|
||||
|
||||
static int mousedev_connect(struct input_handler *handler, struct input_dev *dev,
|
||||
const struct input_device_id *id)
|
||||
{
|
||||
struct mousedev *mousedev;
|
||||
struct class_device *cdev;
|
||||
dev_t devt;
|
||||
int minor;
|
||||
int error;
|
||||
|
||||
|
@ -695,42 +775,13 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
|
|||
return -ENFILE;
|
||||
}
|
||||
|
||||
mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL);
|
||||
if (!mousedev)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&mousedev->client_list);
|
||||
INIT_LIST_HEAD(&mousedev->mixdev_node);
|
||||
init_waitqueue_head(&mousedev->wait);
|
||||
|
||||
mousedev->minor = minor;
|
||||
mousedev->exist = 1;
|
||||
mousedev->handle.dev = dev;
|
||||
mousedev->handle.name = mousedev->name;
|
||||
mousedev->handle.handler = handler;
|
||||
mousedev->handle.private = mousedev;
|
||||
sprintf(mousedev->name, "mouse%d", minor);
|
||||
|
||||
mousedev_table[minor] = mousedev;
|
||||
|
||||
devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
|
||||
|
||||
cdev = class_device_create(&input_class, &dev->cdev, devt,
|
||||
dev->cdev.dev, mousedev->name);
|
||||
if (IS_ERR(cdev)) {
|
||||
error = PTR_ERR(cdev);
|
||||
goto err_free_mousedev;
|
||||
}
|
||||
|
||||
/* temporary symlink to keep userspace happy */
|
||||
error = sysfs_create_link(&input_class.subsys.kobj,
|
||||
&cdev->kobj, mousedev->name);
|
||||
if (error)
|
||||
goto err_cdev_destroy;
|
||||
mousedev = mousedev_create(dev, handler, minor);
|
||||
if (IS_ERR(mousedev))
|
||||
return PTR_ERR(mousedev);
|
||||
|
||||
error = input_register_handle(&mousedev->handle);
|
||||
if (error)
|
||||
goto err_remove_link;
|
||||
goto err_delete_mousedev;
|
||||
|
||||
error = mixdev_add_device(mousedev);
|
||||
if (error)
|
||||
|
@ -740,37 +791,18 @@ static int mousedev_connect(struct input_handler *handler, struct input_dev *dev
|
|||
|
||||
err_unregister_handle:
|
||||
input_unregister_handle(&mousedev->handle);
|
||||
err_remove_link:
|
||||
sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
|
||||
err_cdev_destroy:
|
||||
class_device_destroy(&input_class, devt);
|
||||
err_free_mousedev:
|
||||
mousedev_table[minor] = NULL;
|
||||
kfree(mousedev);
|
||||
err_delete_mousedev:
|
||||
device_unregister(&mousedev->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void mousedev_disconnect(struct input_handle *handle)
|
||||
{
|
||||
struct mousedev *mousedev = handle->private;
|
||||
struct mousedev_client *client;
|
||||
|
||||
input_unregister_handle(handle);
|
||||
|
||||
sysfs_remove_link(&input_class.subsys.kobj, mousedev->name);
|
||||
class_device_destroy(&input_class,
|
||||
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
|
||||
mousedev->exist = 0;
|
||||
|
||||
mixdev_remove_device(mousedev);
|
||||
|
||||
if (mousedev->open) {
|
||||
input_close_device(handle);
|
||||
list_for_each_entry(client, &mousedev->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
wake_up_interruptible(&mousedev->wait);
|
||||
} else
|
||||
mousedev_free(mousedev);
|
||||
input_unregister_handle(handle);
|
||||
mousedev_destroy(mousedev);
|
||||
}
|
||||
|
||||
static const struct input_device_id mousedev_ids[] = {
|
||||
|
@ -822,25 +854,16 @@ static int psaux_registered;
|
|||
|
||||
static int __init mousedev_init(void)
|
||||
{
|
||||
struct class_device *cdev;
|
||||
int error;
|
||||
|
||||
mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX);
|
||||
if (IS_ERR(mousedev_mix))
|
||||
return PTR_ERR(mousedev_mix);
|
||||
|
||||
error = input_register_handler(&mousedev_handler);
|
||||
if (error)
|
||||
if (error) {
|
||||
mousedev_destroy(mousedev_mix);
|
||||
return error;
|
||||
|
||||
memset(&mousedev_mix, 0, sizeof(struct mousedev));
|
||||
INIT_LIST_HEAD(&mousedev_mix.client_list);
|
||||
init_waitqueue_head(&mousedev_mix.wait);
|
||||
mousedev_table[MOUSEDEV_MIX] = &mousedev_mix;
|
||||
mousedev_mix.exist = 1;
|
||||
mousedev_mix.minor = MOUSEDEV_MIX;
|
||||
|
||||
cdev = class_device_create(&input_class, NULL,
|
||||
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
|
||||
if (IS_ERR(cdev)) {
|
||||
input_unregister_handler(&mousedev_handler);
|
||||
return PTR_ERR(cdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
|
||||
|
@ -863,9 +886,8 @@ static void __exit mousedev_exit(void)
|
|||
if (psaux_registered)
|
||||
misc_deregister(&psaux_mouse);
|
||||
#endif
|
||||
class_device_destroy(&input_class,
|
||||
MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
|
||||
input_unregister_handler(&mousedev_handler);
|
||||
mousedev_destroy(mousedev_mix);
|
||||
}
|
||||
|
||||
module_init(mousedev_init);
|
||||
|
|
|
@ -109,9 +109,11 @@ struct tsdev {
|
|||
int open;
|
||||
int minor;
|
||||
char name[8];
|
||||
struct input_handle handle;
|
||||
wait_queue_head_t wait;
|
||||
struct list_head client_list;
|
||||
struct input_handle handle;
|
||||
struct device dev;
|
||||
|
||||
int x, y, pressure;
|
||||
struct ts_calibration cal;
|
||||
};
|
||||
|
@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file)
|
|||
if (!tsdev || !tsdev->exist)
|
||||
return -ENODEV;
|
||||
|
||||
get_device(&tsdev->dev);
|
||||
|
||||
client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL);
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
if (!client) {
|
||||
error = -ENOMEM;
|
||||
goto err_put_tsdev;
|
||||
}
|
||||
|
||||
client->tsdev = tsdev;
|
||||
client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0;
|
||||
|
@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file)
|
|||
|
||||
if (!tsdev->open++ && tsdev->exist) {
|
||||
error = input_open_device(&tsdev->handle);
|
||||
if (error) {
|
||||
list_del(&client->node);
|
||||
kfree(client);
|
||||
return error;
|
||||
}
|
||||
if (error)
|
||||
goto err_free_client;
|
||||
}
|
||||
|
||||
file->private_data = client;
|
||||
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;
|
||||
kfree(tsdev);
|
||||
}
|
||||
|
@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file)
|
|||
list_del(&client->node);
|
||||
kfree(client);
|
||||
|
||||
if (!--tsdev->open) {
|
||||
if (tsdev->exist)
|
||||
if (!--tsdev->open && tsdev->exist)
|
||||
input_close_device(&tsdev->handle);
|
||||
else
|
||||
tsdev_free(tsdev);
|
||||
}
|
||||
|
||||
put_device(&tsdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
const struct input_device_id *id)
|
||||
{
|
||||
struct tsdev *tsdev;
|
||||
struct class_device *cdev;
|
||||
dev_t devt;
|
||||
int minor, delta;
|
||||
int error;
|
||||
|
||||
|
@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
INIT_LIST_HEAD(&tsdev->client_list);
|
||||
init_waitqueue_head(&tsdev->wait);
|
||||
|
||||
sprintf(tsdev->name, "ts%d", minor);
|
||||
|
||||
tsdev->exist = 1;
|
||||
tsdev->minor = minor;
|
||||
tsdev->handle.dev = dev;
|
||||
tsdev->handle.name = tsdev->name;
|
||||
tsdev->handle.handler = handler;
|
||||
tsdev->handle.private = tsdev;
|
||||
snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
|
||||
|
||||
/* Precompute the rough calibration matrix */
|
||||
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,
|
|||
tsdev->cal.yscale = (yres << 8) / delta;
|
||||
tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8);
|
||||
|
||||
snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id),
|
||||
"ts%d", 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);
|
||||
|
||||
tsdev_table[minor] = tsdev;
|
||||
|
||||
devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
|
||||
|
||||
cdev = class_device_create(&input_class, &dev->cdev, devt,
|
||||
dev->cdev.dev, tsdev->name);
|
||||
if (IS_ERR(cdev)) {
|
||||
error = PTR_ERR(cdev);
|
||||
goto err_free_tsdev;
|
||||
}
|
||||
|
||||
/* temporary symlink to keep userspace happy */
|
||||
error = sysfs_create_link(&input_class.subsys.kobj,
|
||||
&cdev->kobj, tsdev->name);
|
||||
error = device_add(&tsdev->dev);
|
||||
if (error)
|
||||
goto err_cdev_destroy;
|
||||
goto err_free_tsdev;
|
||||
|
||||
error = input_register_handle(&tsdev->handle);
|
||||
if (error)
|
||||
goto err_remove_link;
|
||||
goto err_delete_tsdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_link:
|
||||
sysfs_remove_link(&input_class.subsys.kobj, tsdev->name);
|
||||
err_cdev_destroy:
|
||||
class_device_destroy(&input_class, devt);
|
||||
err_delete_tsdev:
|
||||
device_del(&tsdev->dev);
|
||||
err_free_tsdev:
|
||||
tsdev_table[minor] = NULL;
|
||||
kfree(tsdev);
|
||||
put_device(&tsdev->dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle)
|
|||
struct tsdev_client *client;
|
||||
|
||||
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;
|
||||
|
||||
if (tsdev->open) {
|
||||
|
@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle)
|
|||
list_for_each_entry(client, &tsdev->client_list, node)
|
||||
kill_fasync(&client->fasync, SIGIO, POLL_HUP);
|
||||
wake_up_interruptible(&tsdev->wait);
|
||||
} else
|
||||
tsdev_free(tsdev);
|
||||
}
|
||||
|
||||
put_device(&tsdev->dev);
|
||||
}
|
||||
|
||||
static const struct input_device_id tsdev_ids[] = {
|
||||
|
|
|
@ -981,15 +981,15 @@ struct input_dev {
|
|||
struct mutex mutex; /* serializes open and close operations */
|
||||
unsigned int users;
|
||||
|
||||
struct class_device cdev;
|
||||
struct device dev;
|
||||
union { /* temporarily so while we switching to struct device */
|
||||
struct device *parent;
|
||||
} dev;
|
||||
struct device *dev;
|
||||
} cdev;
|
||||
|
||||
struct list_head h_list;
|
||||
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
|
||||
|
@ -1106,12 +1106,12 @@ void input_free_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)
|
||||
{
|
||||
class_device_put(&dev->cdev);
|
||||
put_device(&dev->dev);
|
||||
}
|
||||
|
||||
static inline void *input_get_drvdata(struct input_dev *dev)
|
||||
|
|
Загрузка…
Ссылка в новой задаче