aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-sony.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid/hid-sony.c')
-rw-r--r--drivers/hid/hid-sony.c53
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index da551d113762..098af2f84b8c 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -225,6 +225,13 @@ static const unsigned int buzz_keymap[] = {
225struct sony_sc { 225struct sony_sc {
226 unsigned long quirks; 226 unsigned long quirks;
227 227
228#ifdef CONFIG_SONY_FF
229 struct work_struct rumble_worker;
230 struct hid_device *hdev;
231 __u8 left;
232 __u8 right;
233#endif
234
228 void *extra; 235 void *extra;
229}; 236};
230 237
@@ -615,9 +622,9 @@ static void buzz_remove(struct hid_device *hdev)
615} 622}
616 623
617#ifdef CONFIG_SONY_FF 624#ifdef CONFIG_SONY_FF
618static int sony_play_effect(struct input_dev *dev, void *data, 625static void sony_rumble_worker(struct work_struct *work)
619 struct ff_effect *effect)
620{ 626{
627 struct sony_sc *sc = container_of(work, struct sony_sc, rumble_worker);
621 unsigned char buf[] = { 628 unsigned char buf[] = {
622 0x01, 629 0x01,
623 0x00, 0xff, 0x00, 0xff, 0x00, 630 0x00, 0xff, 0x00, 0xff, 0x00,
@@ -628,21 +635,28 @@ static int sony_play_effect(struct input_dev *dev, void *data,
628 0xff, 0x27, 0x10, 0x00, 0x32, 635 0xff, 0x27, 0x10, 0x00, 0x32,
629 0x00, 0x00, 0x00, 0x00, 0x00 636 0x00, 0x00, 0x00, 0x00, 0x00
630 }; 637 };
631 __u8 left; 638
632 __u8 right; 639 buf[3] = sc->right;
640 buf[5] = sc->left;
641
642 sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
643 HID_OUTPUT_REPORT);
644}
645
646static int sony_play_effect(struct input_dev *dev, void *data,
647 struct ff_effect *effect)
648{
633 struct hid_device *hid = input_get_drvdata(dev); 649 struct hid_device *hid = input_get_drvdata(dev);
650 struct sony_sc *sc = hid_get_drvdata(hid);
634 651
635 if (effect->type != FF_RUMBLE) 652 if (effect->type != FF_RUMBLE)
636 return 0; 653 return 0;
637 654
638 left = effect->u.rumble.strong_magnitude / 256; 655 sc->left = effect->u.rumble.strong_magnitude / 256;
639 right = effect->u.rumble.weak_magnitude ? 1 : 0; 656 sc->right = effect->u.rumble.weak_magnitude ? 1 : 0;
640
641 buf[3] = right;
642 buf[5] = left;
643 657
644 return hid->hid_output_raw_report(hid, buf, sizeof(buf), 658 schedule_work(&sc->rumble_worker);
645 HID_OUTPUT_REPORT); 659 return 0;
646} 660}
647 661
648static int sony_init_ff(struct hid_device *hdev) 662static int sony_init_ff(struct hid_device *hdev)
@@ -650,16 +664,31 @@ static int sony_init_ff(struct hid_device *hdev)
650 struct hid_input *hidinput = list_entry(hdev->inputs.next, 664 struct hid_input *hidinput = list_entry(hdev->inputs.next,
651 struct hid_input, list); 665 struct hid_input, list);
652 struct input_dev *input_dev = hidinput->input; 666 struct input_dev *input_dev = hidinput->input;
667 struct sony_sc *sc = hid_get_drvdata(hdev);
668
669 sc->hdev = hdev;
670 INIT_WORK(&sc->rumble_worker, sony_rumble_worker);
653 671
654 input_set_capability(input_dev, EV_FF, FF_RUMBLE); 672 input_set_capability(input_dev, EV_FF, FF_RUMBLE);
655 return input_ff_create_memless(input_dev, NULL, sony_play_effect); 673 return input_ff_create_memless(input_dev, NULL, sony_play_effect);
656} 674}
657 675
676static void sony_destroy_ff(struct hid_device *hdev)
677{
678 struct sony_sc *sc = hid_get_drvdata(hdev);
679
680 cancel_work_sync(&sc->rumble_worker);
681}
682
658#else 683#else
659static int sony_init_ff(struct hid_device *hdev) 684static int sony_init_ff(struct hid_device *hdev)
660{ 685{
661 return 0; 686 return 0;
662} 687}
688
689static void sony_destroy_ff(struct hid_device *hdev)
690{
691}
663#endif 692#endif
664 693
665static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 694static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -728,6 +757,8 @@ static void sony_remove(struct hid_device *hdev)
728 if (sc->quirks & BUZZ_CONTROLLER) 757 if (sc->quirks & BUZZ_CONTROLLER)
729 buzz_remove(hdev); 758 buzz_remove(hdev);
730 759
760 sony_destroy_ff(hdev);
761
731 hid_hw_stop(hdev); 762 hid_hw_stop(hdev);
732} 763}
733 764