aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joydev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r--drivers/input/joydev.c84
1 files changed, 43 insertions, 41 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 10e3b7bc925f..a9a0180bfd46 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -43,6 +43,8 @@ struct joydev {
43 struct input_handle handle; 43 struct input_handle handle;
44 wait_queue_head_t wait; 44 wait_queue_head_t wait;
45 struct list_head client_list; 45 struct list_head client_list;
46 struct device dev;
47
46 struct js_corr corr[ABS_MAX + 1]; 48 struct js_corr corr[ABS_MAX + 1];
47 struct JS_DATA_SAVE_TYPE glue; 49 struct JS_DATA_SAVE_TYPE glue;
48 int nabs; 50 int nabs;
@@ -138,8 +140,10 @@ static int joydev_fasync(int fd, struct file *file, int on)
138 return retval < 0 ? retval : 0; 140 return retval < 0 ? retval : 0;
139} 141}
140 142
141static void joydev_free(struct joydev *joydev) 143static void joydev_free(struct device *dev)
142{ 144{
145 struct joydev *joydev = container_of(dev, struct joydev, dev);
146
143 joydev_table[joydev->minor] = NULL; 147 joydev_table[joydev->minor] = NULL;
144 kfree(joydev); 148 kfree(joydev);
145} 149}
@@ -154,12 +158,10 @@ static int joydev_release(struct inode *inode, struct file *file)
154 list_del(&client->node); 158 list_del(&client->node);
155 kfree(client); 159 kfree(client);
156 160
157 if (!--joydev->open) { 161 if (!--joydev->open && joydev->exist)
158 if (joydev->exist) 162 input_close_device(&joydev->handle);
159 input_close_device(&joydev->handle); 163
160 else 164 put_device(&joydev->dev);
161 joydev_free(joydev);
162 }
163 165
164 return 0; 166 return 0;
165} 167}
@@ -178,24 +180,32 @@ static int joydev_open(struct inode *inode, struct file *file)
178 if (!joydev || !joydev->exist) 180 if (!joydev || !joydev->exist)
179 return -ENODEV; 181 return -ENODEV;
180 182
183 get_device(&joydev->dev);
184
181 client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); 185 client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL);
182 if (!client) 186 if (!client) {
183 return -ENOMEM; 187 error = -ENOMEM;
188 goto err_put_joydev;
189 }
184 190
185 client->joydev = joydev; 191 client->joydev = joydev;
186 list_add_tail(&client->node, &joydev->client_list); 192 list_add_tail(&client->node, &joydev->client_list);
187 193
188 if (!joydev->open++ && joydev->exist) { 194 if (!joydev->open++ && joydev->exist) {
189 error = input_open_device(&joydev->handle); 195 error = input_open_device(&joydev->handle);
190 if (error) { 196 if (error)
191 list_del(&client->node); 197 goto err_free_client;
192 kfree(client);
193 return error;
194 }
195 } 198 }
196 199
197 file->private_data = client; 200 file->private_data = client;
198 return 0; 201 return 0;
202
203 err_free_client:
204 list_del(&client->node);
205 kfree(client);
206 err_put_joydev:
207 put_device(&joydev->dev);
208 return error;
199} 209}
200 210
201static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) 211static ssize_t joydev_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
@@ -481,8 +491,6 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
481 const struct input_device_id *id) 491 const struct input_device_id *id)
482{ 492{
483 struct joydev *joydev; 493 struct joydev *joydev;
484 struct class_device *cdev;
485 dev_t devt;
486 int i, j, t, minor; 494 int i, j, t, minor;
487 int error; 495 int error;
488 496
@@ -505,7 +513,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
505 joydev->handle.name = joydev->name; 513 joydev->handle.name = joydev->name;
506 joydev->handle.handler = handler; 514 joydev->handle.handler = handler;
507 joydev->handle.private = joydev; 515 joydev->handle.private = joydev;
508 sprintf(joydev->name, "js%d", minor); 516 snprintf(joydev->name, sizeof(joydev->name), "js%d", minor);
509 517
510 for (i = 0; i < ABS_MAX + 1; i++) 518 for (i = 0; i < ABS_MAX + 1; i++)
511 if (test_bit(i, dev->absbit)) { 519 if (test_bit(i, dev->absbit)) {
@@ -547,36 +555,30 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
547 joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i); 555 joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
548 } 556 }
549 557
550 joydev_table[minor] = joydev; 558 snprintf(joydev->dev.bus_id, sizeof(joydev->dev.bus_id),
551 559 "js%d", minor);
552 devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), 560 joydev->dev.class = &input_class;
561 joydev->dev.parent = &dev->dev;
562 joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor);
563 joydev->dev.release = joydev_free;
564 device_initialize(&joydev->dev);
553 565
554 cdev = class_device_create(&input_class, &dev->cdev, devt, 566 joydev_table[minor] = joydev;
555 dev->cdev.dev, joydev->name);
556 if (IS_ERR(cdev)) {
557 error = PTR_ERR(cdev);
558 goto err_free_joydev;
559 }
560 567
561 /* temporary symlink to keep userspace happy */ 568 error = device_add(&joydev->dev);
562 error = sysfs_create_link(&input_class.subsys.kobj,
563 &cdev->kobj, joydev->name);
564 if (error) 569 if (error)
565 goto err_cdev_destroy; 570 goto err_free_joydev;
566 571
567 error = input_register_handle(&joydev->handle); 572 error = input_register_handle(&joydev->handle);
568 if (error) 573 if (error)
569 goto err_remove_link; 574 goto err_delete_joydev;
570 575
571 return 0; 576 return 0;
572 577
573 err_remove_link: 578 err_delete_joydev:
574 sysfs_remove_link(&input_class.subsys.kobj, joydev->name); 579 device_del(&joydev->dev);
575 err_cdev_destroy:
576 class_device_destroy(&input_class, devt);
577 err_free_joydev: 580 err_free_joydev:
578 joydev_table[minor] = NULL; 581 put_device(&joydev->dev);
579 kfree(joydev);
580 return error; 582 return error;
581} 583}
582 584
@@ -587,9 +589,8 @@ static void joydev_disconnect(struct input_handle *handle)
587 struct joydev_client *client; 589 struct joydev_client *client;
588 590
589 input_unregister_handle(handle); 591 input_unregister_handle(handle);
592 device_del(&joydev->dev);
590 593
591 sysfs_remove_link(&input_class.subsys.kobj, joydev->name);
592 class_device_destroy(&input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
593 joydev->exist = 0; 594 joydev->exist = 0;
594 595
595 if (joydev->open) { 596 if (joydev->open) {
@@ -597,8 +598,9 @@ static void joydev_disconnect(struct input_handle *handle)
597 list_for_each_entry(client, &joydev->client_list, node) 598 list_for_each_entry(client, &joydev->client_list, node)
598 kill_fasync(&client->fasync, SIGIO, POLL_HUP); 599 kill_fasync(&client->fasync, SIGIO, POLL_HUP);
599 wake_up_interruptible(&joydev->wait); 600 wake_up_interruptible(&joydev->wait);
600 } else 601 }
601 joydev_free(joydev); 602
603 put_device(&joydev->dev);
602} 604}
603 605
604static const struct input_device_id joydev_blacklist[] = { 606static const struct input_device_id joydev_blacklist[] = {