aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tsdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/tsdev.c')
-rw-r--r--drivers/input/tsdev.c88
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
187static void tsdev_free(struct tsdev *tsdev) 197static 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
486static const struct input_device_id tsdev_ids[] = { 486static const struct input_device_id tsdev_ids[] = {