diff options
author | Dmitry Torokhov <dtor@insightbb.com> | 2007-04-12 01:29:46 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-04-12 01:29:46 -0400 |
commit | 5b2a08262a8c952fef008154933953f083ca5766 (patch) | |
tree | 47fb54c30509a4c444613a1737a212ddda3bb05d /drivers/input/tsdev.c | |
parent | 6e782584e0713ea89da151333e7fe754c8f40324 (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.c | 58 |
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 | ||
373 | static struct input_handle *tsdev_connect(struct input_handler *handler, | 373 | static 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 | ||
429 | static void tsdev_disconnect(struct input_handle *handle) | 451 | static 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)); |