diff options
Diffstat (limited to 'drivers/input/tsdev.c')
-rw-r--r-- | drivers/input/tsdev.c | 88 |
1 files changed, 44 insertions, 44 deletions
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c index 2db364898e15..4cd5bbc44cca 100644 --- a/drivers/input/tsdev.c +++ b/drivers/input/tsdev.c | |||
@@ -109,9 +109,11 @@ struct tsdev { | |||
109 | int open; | 109 | int open; |
110 | int minor; | 110 | int minor; |
111 | char name[8]; | 111 | char name[8]; |
112 | struct input_handle handle; | ||
112 | wait_queue_head_t wait; | 113 | wait_queue_head_t wait; |
113 | struct list_head client_list; | 114 | struct list_head client_list; |
114 | struct input_handle handle; | 115 | struct device dev; |
116 | |||
115 | int x, y, pressure; | 117 | int x, y, pressure; |
116 | struct ts_calibration cal; | 118 | struct ts_calibration cal; |
117 | }; | 119 | }; |
@@ -163,9 +165,13 @@ static int tsdev_open(struct inode *inode, struct file *file) | |||
163 | if (!tsdev || !tsdev->exist) | 165 | if (!tsdev || !tsdev->exist) |
164 | return -ENODEV; | 166 | return -ENODEV; |
165 | 167 | ||
168 | get_device(&tsdev->dev); | ||
169 | |||
166 | client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); | 170 | client = kzalloc(sizeof(struct tsdev_client), GFP_KERNEL); |
167 | if (!client) | 171 | if (!client) { |
168 | return -ENOMEM; | 172 | error = -ENOMEM; |
173 | goto err_put_tsdev; | ||
174 | } | ||
169 | 175 | ||
170 | client->tsdev = tsdev; | 176 | client->tsdev = tsdev; |
171 | client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; | 177 | client->raw = (i >= TSDEV_MINORS / 2) ? 1 : 0; |
@@ -173,19 +179,25 @@ static int tsdev_open(struct inode *inode, struct file *file) | |||
173 | 179 | ||
174 | if (!tsdev->open++ && tsdev->exist) { | 180 | if (!tsdev->open++ && tsdev->exist) { |
175 | error = input_open_device(&tsdev->handle); | 181 | error = input_open_device(&tsdev->handle); |
176 | if (error) { | 182 | if (error) |
177 | list_del(&client->node); | 183 | goto err_free_client; |
178 | kfree(client); | ||
179 | return error; | ||
180 | } | ||
181 | } | 184 | } |
182 | 185 | ||
183 | file->private_data = client; | 186 | file->private_data = client; |
184 | return 0; | 187 | return 0; |
188 | |||
189 | err_free_client: | ||
190 | list_del(&client->node); | ||
191 | kfree(client); | ||
192 | err_put_tsdev: | ||
193 | put_device(&tsdev->dev); | ||
194 | return error; | ||
185 | } | 195 | } |
186 | 196 | ||
187 | static void tsdev_free(struct tsdev *tsdev) | 197 | static void tsdev_free(struct device *dev) |
188 | { | 198 | { |
199 | struct tsdev *tsdev = container_of(dev, struct tsdev, dev); | ||
200 | |||
189 | tsdev_table[tsdev->minor] = NULL; | 201 | tsdev_table[tsdev->minor] = NULL; |
190 | kfree(tsdev); | 202 | kfree(tsdev); |
191 | } | 203 | } |
@@ -200,12 +212,10 @@ static int tsdev_release(struct inode *inode, struct file *file) | |||
200 | list_del(&client->node); | 212 | list_del(&client->node); |
201 | kfree(client); | 213 | kfree(client); |
202 | 214 | ||
203 | if (!--tsdev->open) { | 215 | if (!--tsdev->open && tsdev->exist) |
204 | if (tsdev->exist) | 216 | input_close_device(&tsdev->handle); |
205 | input_close_device(&tsdev->handle); | 217 | |
206 | else | 218 | put_device(&tsdev->dev); |
207 | tsdev_free(tsdev); | ||
208 | } | ||
209 | 219 | ||
210 | return 0; | 220 | return 0; |
211 | } | 221 | } |
@@ -388,8 +398,6 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
388 | const struct input_device_id *id) | 398 | const struct input_device_id *id) |
389 | { | 399 | { |
390 | struct tsdev *tsdev; | 400 | struct tsdev *tsdev; |
391 | struct class_device *cdev; | ||
392 | dev_t devt; | ||
393 | int minor, delta; | 401 | int minor, delta; |
394 | int error; | 402 | int error; |
395 | 403 | ||
@@ -407,14 +415,13 @@ static int tsdev_connect(struct input_handler *handler, struct input_dev *dev, | |||
407 | INIT_LIST_HEAD(&tsdev->client_list); | 415 | INIT_LIST_HEAD(&tsdev->client_list); |
408 | init_waitqueue_head(&tsdev->wait); | 416 | init_waitqueue_head(&tsdev->wait); |
409 | 417 | ||
410 | sprintf(tsdev->name, "ts%d", minor); | ||
411 | |||
412 | tsdev->exist = 1; | 418 | tsdev->exist = 1; |
413 | tsdev->minor = minor; | 419 | tsdev->minor = minor; |
414 | tsdev->handle.dev = dev; | 420 | tsdev->handle.dev = dev; |
415 | tsdev->handle.name = tsdev->name; | 421 | tsdev->handle.name = tsdev->name; |
416 | tsdev->handle.handler = handler; | 422 | tsdev->handle.handler = handler; |
417 | tsdev->handle.private = tsdev; | 423 | tsdev->handle.private = tsdev; |
424 | snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor); | ||
418 | 425 | ||
419 | /* Precompute the rough calibration matrix */ | 426 | /* Precompute the rough calibration matrix */ |
420 | delta = dev->absmax [ABS_X] - dev->absmin [ABS_X] + 1; | 427 | 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 | tsdev->cal.yscale = (yres << 8) / delta; | 436 | tsdev->cal.yscale = (yres << 8) / delta; |
430 | tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); | 437 | tsdev->cal.ytrans = - ((dev->absmin [ABS_Y] * tsdev->cal.yscale) >> 8); |
431 | 438 | ||
432 | tsdev_table[minor] = tsdev; | 439 | snprintf(tsdev->dev.bus_id, sizeof(tsdev->dev.bus_id), |
433 | 440 | "ts%d", minor); | |
434 | devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), | 441 | tsdev->dev.class = &input_class; |
442 | tsdev->dev.parent = &dev->dev; | ||
443 | tsdev->dev.devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor); | ||
444 | tsdev->dev.release = tsdev_free; | ||
445 | device_initialize(&tsdev->dev); | ||
435 | 446 | ||
436 | cdev = class_device_create(&input_class, &dev->cdev, devt, | 447 | tsdev_table[minor] = tsdev; |
437 | dev->cdev.dev, tsdev->name); | ||
438 | if (IS_ERR(cdev)) { | ||
439 | error = PTR_ERR(cdev); | ||
440 | goto err_free_tsdev; | ||
441 | } | ||
442 | 448 | ||
443 | /* temporary symlink to keep userspace happy */ | 449 | error = device_add(&tsdev->dev); |
444 | error = sysfs_create_link(&input_class.subsys.kobj, | ||
445 | &cdev->kobj, tsdev->name); | ||
446 | if (error) | 450 | if (error) |
447 | goto err_cdev_destroy; | 451 | goto err_free_tsdev; |
448 | 452 | ||
449 | error = input_register_handle(&tsdev->handle); | 453 | error = input_register_handle(&tsdev->handle); |
450 | if (error) | 454 | if (error) |
451 | goto err_remove_link; | 455 | goto err_delete_tsdev; |
452 | 456 | ||
453 | return 0; | 457 | return 0; |
454 | 458 | ||
455 | err_remove_link: | 459 | err_delete_tsdev: |
456 | sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); | 460 | device_del(&tsdev->dev); |
457 | err_cdev_destroy: | ||
458 | class_device_destroy(&input_class, devt); | ||
459 | err_free_tsdev: | 461 | err_free_tsdev: |
460 | tsdev_table[minor] = NULL; | 462 | put_device(&tsdev->dev); |
461 | kfree(tsdev); | ||
462 | return error; | 463 | return error; |
463 | } | 464 | } |
464 | 465 | ||
@@ -468,10 +469,8 @@ static void tsdev_disconnect(struct input_handle *handle) | |||
468 | struct tsdev_client *client; | 469 | struct tsdev_client *client; |
469 | 470 | ||
470 | input_unregister_handle(handle); | 471 | input_unregister_handle(handle); |
472 | device_del(&tsdev->dev); | ||
471 | 473 | ||
472 | sysfs_remove_link(&input_class.subsys.kobj, tsdev->name); | ||
473 | class_device_destroy(&input_class, | ||
474 | MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); | ||
475 | tsdev->exist = 0; | 474 | tsdev->exist = 0; |
476 | 475 | ||
477 | if (tsdev->open) { | 476 | if (tsdev->open) { |
@@ -479,8 +478,9 @@ static void tsdev_disconnect(struct input_handle *handle) | |||
479 | list_for_each_entry(client, &tsdev->client_list, node) | 478 | list_for_each_entry(client, &tsdev->client_list, node) |
480 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); | 479 | kill_fasync(&client->fasync, SIGIO, POLL_HUP); |
481 | wake_up_interruptible(&tsdev->wait); | 480 | wake_up_interruptible(&tsdev->wait); |
482 | } else | 481 | } |
483 | tsdev_free(tsdev); | 482 | |
483 | put_device(&tsdev->dev); | ||
484 | } | 484 | } |
485 | 485 | ||
486 | static const struct input_device_id tsdev_ids[] = { | 486 | static const struct input_device_id tsdev_ids[] = { |