diff options
| -rw-r--r-- | drivers/hid/hid-sony.c | 53 |
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[] = { | |||
| 225 | struct sony_sc { | 225 | struct 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 |
| 618 | static int sony_play_effect(struct input_dev *dev, void *data, | 625 | static 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 | |||
| 646 | static 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 | ||
| 648 | static int sony_init_ff(struct hid_device *hdev) | 662 | static 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 | ||
| 676 | static 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 |
| 659 | static int sony_init_ff(struct hid_device *hdev) | 684 | static int sony_init_ff(struct hid_device *hdev) |
| 660 | { | 685 | { |
| 661 | return 0; | 686 | return 0; |
| 662 | } | 687 | } |
| 688 | |||
| 689 | static void sony_destroy_ff(struct hid_device *hdev) | ||
| 690 | { | ||
| 691 | } | ||
| 663 | #endif | 692 | #endif |
| 664 | 693 | ||
| 665 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | 694 | static 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 | ||
