diff options
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 99 |
1 files changed, 33 insertions, 66 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 118d0300f1fb..6ae2ac47c9c8 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -23,11 +23,11 @@ | |||
| 23 | #include <linux/input/mt.h> | 23 | #include <linux/input/mt.h> |
| 24 | #include <linux/major.h> | 24 | #include <linux/major.h> |
| 25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
| 26 | #include <linux/cdev.h> | ||
| 26 | #include "input-compat.h" | 27 | #include "input-compat.h" |
| 27 | 28 | ||
| 28 | struct evdev { | 29 | struct evdev { |
| 29 | int open; | 30 | int open; |
| 30 | int minor; | ||
| 31 | struct input_handle handle; | 31 | struct input_handle handle; |
| 32 | wait_queue_head_t wait; | 32 | wait_queue_head_t wait; |
| 33 | struct evdev_client __rcu *grab; | 33 | struct evdev_client __rcu *grab; |
| @@ -35,6 +35,7 @@ struct evdev { | |||
| 35 | spinlock_t client_lock; /* protects client_list */ | 35 | spinlock_t client_lock; /* protects client_list */ |
| 36 | struct mutex mutex; | 36 | struct mutex mutex; |
| 37 | struct device dev; | 37 | struct device dev; |
| 38 | struct cdev cdev; | ||
| 38 | bool exist; | 39 | bool exist; |
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| @@ -51,9 +52,6 @@ struct evdev_client { | |||
| 51 | struct input_event buffer[]; | 52 | struct input_event buffer[]; |
| 52 | }; | 53 | }; |
| 53 | 54 | ||
| 54 | static struct evdev *evdev_table[EVDEV_MINORS]; | ||
| 55 | static DEFINE_MUTEX(evdev_table_mutex); | ||
| 56 | |||
| 57 | static void __pass_event(struct evdev_client *client, | 55 | static void __pass_event(struct evdev_client *client, |
| 58 | const struct input_event *event) | 56 | const struct input_event *event) |
| 59 | { | 57 | { |
| @@ -310,35 +308,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev) | |||
| 310 | 308 | ||
| 311 | static int evdev_open(struct inode *inode, struct file *file) | 309 | static int evdev_open(struct inode *inode, struct file *file) |
| 312 | { | 310 | { |
| 313 | struct evdev *evdev; | 311 | struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); |
| 312 | unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); | ||
| 314 | struct evdev_client *client; | 313 | struct evdev_client *client; |
| 315 | int i = iminor(inode) - EVDEV_MINOR_BASE; | ||
| 316 | unsigned int bufsize; | ||
| 317 | int error; | 314 | int error; |
| 318 | 315 | ||
| 319 | if (i >= EVDEV_MINORS) | ||
| 320 | return -ENODEV; | ||
| 321 | |||
| 322 | error = mutex_lock_interruptible(&evdev_table_mutex); | ||
| 323 | if (error) | ||
| 324 | return error; | ||
| 325 | evdev = evdev_table[i]; | ||
| 326 | if (evdev) | ||
| 327 | get_device(&evdev->dev); | ||
| 328 | mutex_unlock(&evdev_table_mutex); | ||
| 329 | |||
| 330 | if (!evdev) | ||
| 331 | return -ENODEV; | ||
| 332 | |||
| 333 | bufsize = evdev_compute_buffer_size(evdev->handle.dev); | ||
| 334 | |||
| 335 | client = kzalloc(sizeof(struct evdev_client) + | 316 | client = kzalloc(sizeof(struct evdev_client) + |
| 336 | bufsize * sizeof(struct input_event), | 317 | bufsize * sizeof(struct input_event), |
| 337 | GFP_KERNEL); | 318 | GFP_KERNEL); |
| 338 | if (!client) { | 319 | if (!client) |
| 339 | error = -ENOMEM; | 320 | return -ENOMEM; |
| 340 | goto err_put_evdev; | ||
| 341 | } | ||
| 342 | 321 | ||
| 343 | client->bufsize = bufsize; | 322 | client->bufsize = bufsize; |
| 344 | spin_lock_init(&client->buffer_lock); | 323 | spin_lock_init(&client->buffer_lock); |
| @@ -352,13 +331,12 @@ static int evdev_open(struct inode *inode, struct file *file) | |||
| 352 | file->private_data = client; | 331 | file->private_data = client; |
| 353 | nonseekable_open(inode, file); | 332 | nonseekable_open(inode, file); |
| 354 | 333 | ||
| 334 | get_device(&evdev->dev); | ||
| 355 | return 0; | 335 | return 0; |
| 356 | 336 | ||
| 357 | err_free_client: | 337 | err_free_client: |
| 358 | evdev_detach_client(evdev, client); | 338 | evdev_detach_client(evdev, client); |
| 359 | kfree(client); | 339 | kfree(client); |
| 360 | err_put_evdev: | ||
| 361 | put_device(&evdev->dev); | ||
| 362 | return error; | 340 | return error; |
| 363 | } | 341 | } |
| 364 | 342 | ||
| @@ -942,26 +920,6 @@ static const struct file_operations evdev_fops = { | |||
| 942 | .llseek = no_llseek, | 920 | .llseek = no_llseek, |
| 943 | }; | 921 | }; |
| 944 | 922 | ||
| 945 | static int evdev_install_chrdev(struct evdev *evdev) | ||
| 946 | { | ||
| 947 | /* | ||
| 948 | * No need to do any locking here as calls to connect and | ||
| 949 | * disconnect are serialized by the input core | ||
| 950 | */ | ||
| 951 | evdev_table[evdev->minor] = evdev; | ||
| 952 | return 0; | ||
| 953 | } | ||
| 954 | |||
| 955 | static void evdev_remove_chrdev(struct evdev *evdev) | ||
| 956 | { | ||
| 957 | /* | ||
| 958 | * Lock evdev table to prevent race with evdev_open() | ||
| 959 | */ | ||
| 960 | mutex_lock(&evdev_table_mutex); | ||
| 961 | evdev_table[evdev->minor] = NULL; | ||
| 962 | mutex_unlock(&evdev_table_mutex); | ||
| 963 | } | ||
| 964 | |||
| 965 | /* | 923 | /* |
| 966 | * Mark device non-existent. This disables writes, ioctls and | 924 | * Mark device non-existent. This disables writes, ioctls and |
| 967 | * prevents new users from opening the device. Already posted | 925 | * prevents new users from opening the device. Already posted |
| @@ -980,7 +938,8 @@ static void evdev_cleanup(struct evdev *evdev) | |||
| 980 | 938 | ||
| 981 | evdev_mark_dead(evdev); | 939 | evdev_mark_dead(evdev); |
| 982 | evdev_hangup(evdev); | 940 | evdev_hangup(evdev); |
| 983 | evdev_remove_chrdev(evdev); | 941 | |
| 942 | cdev_del(&evdev->cdev); | ||
| 984 | 943 | ||
| 985 | /* evdev is marked dead so no one else accesses evdev->open */ | 944 | /* evdev is marked dead so no one else accesses evdev->open */ |
| 986 | if (evdev->open) { | 945 | if (evdev->open) { |
| @@ -991,43 +950,47 @@ static void evdev_cleanup(struct evdev *evdev) | |||
| 991 | 950 | ||
| 992 | /* | 951 | /* |
| 993 | * Create new evdev device. Note that input core serializes calls | 952 | * Create new evdev device. Note that input core serializes calls |
| 994 | * to connect and disconnect so we don't need to lock evdev_table here. | 953 | * to connect and disconnect. |
| 995 | */ | 954 | */ |
| 996 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | 955 | static int evdev_connect(struct input_handler *handler, struct input_dev *dev, |
| 997 | const struct input_device_id *id) | 956 | const struct input_device_id *id) |
| 998 | { | 957 | { |
| 999 | struct evdev *evdev; | 958 | struct evdev *evdev; |
| 1000 | int minor; | 959 | int minor; |
| 960 | int dev_no; | ||
| 1001 | int error; | 961 | int error; |
| 1002 | 962 | ||
| 1003 | for (minor = 0; minor < EVDEV_MINORS; minor++) | 963 | minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true); |
| 1004 | if (!evdev_table[minor]) | 964 | if (minor < 0) { |
| 1005 | break; | 965 | error = minor; |
| 1006 | 966 | pr_err("failed to reserve new minor: %d\n", error); | |
| 1007 | if (minor == EVDEV_MINORS) { | 967 | return error; |
| 1008 | pr_err("no more free evdev devices\n"); | ||
| 1009 | return -ENFILE; | ||
| 1010 | } | 968 | } |
| 1011 | 969 | ||
| 1012 | evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); | 970 | evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); |
| 1013 | if (!evdev) | 971 | if (!evdev) { |
| 1014 | return -ENOMEM; | 972 | error = -ENOMEM; |
| 973 | goto err_free_minor; | ||
| 974 | } | ||
| 1015 | 975 | ||
| 1016 | INIT_LIST_HEAD(&evdev->client_list); | 976 | INIT_LIST_HEAD(&evdev->client_list); |
| 1017 | spin_lock_init(&evdev->client_lock); | 977 | spin_lock_init(&evdev->client_lock); |
| 1018 | mutex_init(&evdev->mutex); | 978 | mutex_init(&evdev->mutex); |
| 1019 | init_waitqueue_head(&evdev->wait); | 979 | init_waitqueue_head(&evdev->wait); |
| 1020 | |||
| 1021 | dev_set_name(&evdev->dev, "event%d", minor); | ||
| 1022 | evdev->exist = true; | 980 | evdev->exist = true; |
| 1023 | evdev->minor = minor; | 981 | |
| 982 | dev_no = minor; | ||
| 983 | /* Normalize device number if it falls into legacy range */ | ||
| 984 | if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) | ||
| 985 | dev_no -= EVDEV_MINOR_BASE; | ||
| 986 | dev_set_name(&evdev->dev, "event%d", dev_no); | ||
| 1024 | 987 | ||
| 1025 | evdev->handle.dev = input_get_device(dev); | 988 | evdev->handle.dev = input_get_device(dev); |
| 1026 | evdev->handle.name = dev_name(&evdev->dev); | 989 | evdev->handle.name = dev_name(&evdev->dev); |
| 1027 | evdev->handle.handler = handler; | 990 | evdev->handle.handler = handler; |
| 1028 | evdev->handle.private = evdev; | 991 | evdev->handle.private = evdev; |
| 1029 | 992 | ||
| 1030 | evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); | 993 | evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); |
| 1031 | evdev->dev.class = &input_class; | 994 | evdev->dev.class = &input_class; |
| 1032 | evdev->dev.parent = &dev->dev; | 995 | evdev->dev.parent = &dev->dev; |
| 1033 | evdev->dev.release = evdev_free; | 996 | evdev->dev.release = evdev_free; |
| @@ -1037,7 +1000,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 1037 | if (error) | 1000 | if (error) |
| 1038 | goto err_free_evdev; | 1001 | goto err_free_evdev; |
| 1039 | 1002 | ||
| 1040 | error = evdev_install_chrdev(evdev); | 1003 | cdev_init(&evdev->cdev, &evdev_fops); |
| 1004 | error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); | ||
| 1041 | if (error) | 1005 | if (error) |
| 1042 | goto err_unregister_handle; | 1006 | goto err_unregister_handle; |
| 1043 | 1007 | ||
| @@ -1053,6 +1017,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
| 1053 | input_unregister_handle(&evdev->handle); | 1017 | input_unregister_handle(&evdev->handle); |
| 1054 | err_free_evdev: | 1018 | err_free_evdev: |
| 1055 | put_device(&evdev->dev); | 1019 | put_device(&evdev->dev); |
| 1020 | err_free_minor: | ||
| 1021 | input_free_minor(minor); | ||
| 1056 | return error; | 1022 | return error; |
| 1057 | } | 1023 | } |
| 1058 | 1024 | ||
| @@ -1062,6 +1028,7 @@ static void evdev_disconnect(struct input_handle *handle) | |||
| 1062 | 1028 | ||
| 1063 | device_del(&evdev->dev); | 1029 | device_del(&evdev->dev); |
| 1064 | evdev_cleanup(evdev); | 1030 | evdev_cleanup(evdev); |
| 1031 | input_free_minor(MINOR(evdev->dev.devt)); | ||
| 1065 | input_unregister_handle(handle); | 1032 | input_unregister_handle(handle); |
| 1066 | put_device(&evdev->dev); | 1033 | put_device(&evdev->dev); |
| 1067 | } | 1034 | } |
| @@ -1078,7 +1045,7 @@ static struct input_handler evdev_handler = { | |||
| 1078 | .events = evdev_events, | 1045 | .events = evdev_events, |
| 1079 | .connect = evdev_connect, | 1046 | .connect = evdev_connect, |
| 1080 | .disconnect = evdev_disconnect, | 1047 | .disconnect = evdev_disconnect, |
| 1081 | .fops = &evdev_fops, | 1048 | .legacy_minors = true, |
| 1082 | .minor = EVDEV_MINOR_BASE, | 1049 | .minor = EVDEV_MINOR_BASE, |
| 1083 | .name = "evdev", | 1050 | .name = "evdev", |
| 1084 | .id_table = evdev_ids, | 1051 | .id_table = evdev_ids, |
