aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tsdev.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2007-04-12 01:29:46 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-04-12 01:29:46 -0400
commit5b2a08262a8c952fef008154933953f083ca5766 (patch)
tree47fb54c30509a4c444613a1737a212ddda3bb05d /drivers/input/tsdev.c
parent6e782584e0713ea89da151333e7fe754c8f40324 (diff)
Input: rework handle creation code
- consolidate code for binding handlers to a device - return error codes from handlers connect() methods back to input core and log failures Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/tsdev.c')
-rw-r--r--drivers/input/tsdev.c58
1 files changed, 41 insertions, 17 deletions
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index 0300dca8591d..a23aedc64ab1 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -155,7 +155,7 @@ static int tsdev_open(struct inode *inode, struct file *file)
155 "for removal.\nSee Documentation/feature-removal-schedule.txt " 155 "for removal.\nSee Documentation/feature-removal-schedule.txt "
156 "for details.\n"); 156 "for details.\n");
157 157
158 if (i >= TSDEV_MINORS || !tsdev_table[i & TSDEV_MINOR_MASK]) 158 if (i >= TSDEV_MINORS)
159 return -ENODEV; 159 return -ENODEV;
160 160
161 if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL))) 161 if (!(list = kzalloc(sizeof(struct tsdev_list), GFP_KERNEL)))
@@ -246,14 +246,14 @@ static int tsdev_ioctl(struct inode *inode, struct file *file,
246 246
247 switch (cmd) { 247 switch (cmd) {
248 case TS_GET_CAL: 248 case TS_GET_CAL:
249 if (copy_to_user ((void __user *)arg, &tsdev->cal, 249 if (copy_to_user((void __user *)arg, &tsdev->cal,
250 sizeof (struct ts_calibration))) 250 sizeof (struct ts_calibration)))
251 retval = -EFAULT; 251 retval = -EFAULT;
252 break; 252 break;
253 253
254 case TS_SET_CAL: 254 case TS_SET_CAL:
255 if (copy_from_user (&tsdev->cal, (void __user *)arg, 255 if (copy_from_user(&tsdev->cal, (void __user *)arg,
256 sizeof (struct ts_calibration))) 256 sizeof (struct ts_calibration)))
257 retval = -EFAULT; 257 retval = -EFAULT;
258 break; 258 break;
259 259
@@ -370,23 +370,25 @@ static void tsdev_event(struct input_handle *handle, unsigned int type,
370 wake_up_interruptible(&tsdev->wait); 370 wake_up_interruptible(&tsdev->wait);
371} 371}
372 372
373static struct input_handle *tsdev_connect(struct input_handler *handler, 373static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
374 struct input_dev *dev, 374 const struct input_device_id *id)
375 const struct input_device_id *id)
376{ 375{
377 struct tsdev *tsdev; 376 struct tsdev *tsdev;
378 struct class_device *cdev; 377 struct class_device *cdev;
378 dev_t devt;
379 int minor, delta; 379 int minor, delta;
380 int error;
380 381
381 for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++); 382 for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++);
382 if (minor >= TSDEV_MINORS / 2) { 383 if (minor >= TSDEV_MINORS / 2) {
383 printk(KERN_ERR 384 printk(KERN_ERR
384 "tsdev: You have way too many touchscreens\n"); 385 "tsdev: You have way too many touchscreens\n");
385 return NULL; 386 return -ENFILE;
386 } 387 }
387 388
388 if (!(tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL))) 389 tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
389 return NULL; 390 if (!tsdev)
391 return -ENOMEM;
390 392
391 INIT_LIST_HEAD(&tsdev->list); 393 INIT_LIST_HEAD(&tsdev->list);
392 init_waitqueue_head(&tsdev->wait); 394 init_waitqueue_head(&tsdev->wait);
@@ -415,15 +417,35 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
415 417
416 tsdev_table[minor] = tsdev; 418 tsdev_table[minor] = tsdev;
417 419
418 cdev = class_device_create(&input_class, &dev->cdev, 420 devt = MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
419 MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), 421
420 dev->cdev.dev, tsdev->name); 422 cdev = class_device_create(&input_class, &dev->cdev, devt,
423 dev->cdev.dev, tsdev->name);
424 if (IS_ERR(cdev)) {
425 error = PTR_ERR(cdev);
426 goto err_free_tsdev;
427 }
421 428
422 /* temporary symlink to keep userspace happy */ 429 /* temporary symlink to keep userspace happy */
423 sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, 430 error = sysfs_create_link(&input_class.subsys.kset.kobj,
424 tsdev->name); 431 &cdev->kobj, tsdev->name);
432 if (error)
433 goto err_cdev_destroy;
425 434
426 return &tsdev->handle; 435 error = input_register_handle(&tsdev->handle);
436 if (error)
437 goto err_remove_link;
438
439 return 0;
440
441 err_remove_link:
442 sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
443 err_cdev_destroy:
444 class_device_destroy(&input_class, devt);
445 err_free_tsdev:
446 tsdev_table[minor] = NULL;
447 kfree(tsdev);
448 return error;
427} 449}
428 450
429static void tsdev_disconnect(struct input_handle *handle) 451static void tsdev_disconnect(struct input_handle *handle)
@@ -431,6 +453,8 @@ static void tsdev_disconnect(struct input_handle *handle)
431 struct tsdev *tsdev = handle->private; 453 struct tsdev *tsdev = handle->private;
432 struct tsdev_list *list; 454 struct tsdev_list *list;
433 455
456 input_unregister_handle(handle);
457
434 sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name); 458 sysfs_remove_link(&input_class.subsys.kset.kobj, tsdev->name);
435 class_device_destroy(&input_class, 459 class_device_destroy(&input_class,
436 MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor)); 460 MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));