diff options
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r-- | drivers/input/joydev.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 9f3529ad3fda..cf24a5bde539 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -465,21 +465,24 @@ static const struct file_operations joydev_fops = { | |||
465 | .fasync = joydev_fasync, | 465 | .fasync = joydev_fasync, |
466 | }; | 466 | }; |
467 | 467 | ||
468 | static struct input_handle *joydev_connect(struct input_handler *handler, struct input_dev *dev, | 468 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, |
469 | const struct input_device_id *id) | 469 | const struct input_device_id *id) |
470 | { | 470 | { |
471 | struct joydev *joydev; | 471 | struct joydev *joydev; |
472 | struct class_device *cdev; | 472 | struct class_device *cdev; |
473 | dev_t devt; | ||
473 | int i, j, t, minor; | 474 | int i, j, t, minor; |
475 | int error; | ||
474 | 476 | ||
475 | for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); | 477 | for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); |
476 | if (minor == JOYDEV_MINORS) { | 478 | if (minor == JOYDEV_MINORS) { |
477 | printk(KERN_ERR "joydev: no more free joydev devices\n"); | 479 | printk(KERN_ERR "joydev: no more free joydev devices\n"); |
478 | return NULL; | 480 | return -ENFILE; |
479 | } | 481 | } |
480 | 482 | ||
481 | if (!(joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL))) | 483 | joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); |
482 | return NULL; | 484 | if (!joydev) |
485 | return -ENOMEM; | ||
483 | 486 | ||
484 | INIT_LIST_HEAD(&joydev->list); | 487 | INIT_LIST_HEAD(&joydev->list); |
485 | init_waitqueue_head(&joydev->wait); | 488 | init_waitqueue_head(&joydev->wait); |
@@ -534,22 +537,45 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct | |||
534 | 537 | ||
535 | joydev_table[minor] = joydev; | 538 | joydev_table[minor] = joydev; |
536 | 539 | ||
537 | cdev = class_device_create(&input_class, &dev->cdev, | 540 | devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), |
538 | MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), | 541 | |
539 | dev->cdev.dev, joydev->name); | 542 | cdev = class_device_create(&input_class, &dev->cdev, devt, |
543 | dev->cdev.dev, joydev->name); | ||
544 | if (IS_ERR(cdev)) { | ||
545 | error = PTR_ERR(cdev); | ||
546 | goto err_free_joydev; | ||
547 | } | ||
540 | 548 | ||
541 | /* temporary symlink to keep userspace happy */ | 549 | /* temporary symlink to keep userspace happy */ |
542 | sysfs_create_link(&input_class.subsys.kset.kobj, &cdev->kobj, | 550 | error = sysfs_create_link(&input_class.subsys.kset.kobj, |
543 | joydev->name); | 551 | &cdev->kobj, joydev->name); |
552 | if (error) | ||
553 | goto err_cdev_destroy; | ||
554 | |||
555 | error = input_register_handle(&joydev->handle); | ||
556 | if (error) | ||
557 | goto err_remove_link; | ||
558 | |||
559 | return 0; | ||
544 | 560 | ||
545 | return &joydev->handle; | 561 | err_remove_link: |
562 | sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name); | ||
563 | err_cdev_destroy: | ||
564 | class_device_destroy(&input_class, devt); | ||
565 | err_free_joydev: | ||
566 | joydev_table[minor] = NULL; | ||
567 | kfree(joydev); | ||
568 | return error; | ||
546 | } | 569 | } |
547 | 570 | ||
571 | |||
548 | static void joydev_disconnect(struct input_handle *handle) | 572 | static void joydev_disconnect(struct input_handle *handle) |
549 | { | 573 | { |
550 | struct joydev *joydev = handle->private; | 574 | struct joydev *joydev = handle->private; |
551 | struct joydev_list *list; | 575 | struct joydev_list *list; |
552 | 576 | ||
577 | input_unregister_handle(handle); | ||
578 | |||
553 | sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name); | 579 | sysfs_remove_link(&input_class.subsys.kset.kobj, joydev->name); |
554 | class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); | 580 | class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor)); |
555 | joydev->exist = 0; | 581 | joydev->exist = 0; |