diff options
author | Sven Eckelmann <sven@narfation.org> | 2013-11-09 13:25:57 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2013-11-11 05:25:46 -0500 |
commit | a08c22c0df0ad23d0df10ae1a9df26643589b3cc (patch) | |
tree | 476d2fe040e9337b70f73587c56f27890059ae08 /drivers/hid | |
parent | ae2aa3a512fa5f50f67feba9e66bc2efb394bd63 (diff) |
HID: sony: Add force feedback support for Dualshock3 USB
Sony Dualshock 3 controllers have two motors which can be used to provide
simple force feedback rumble effects. The right motor is can be used to create
a weak rumble effect but does not allow to set the force. The left motor is
used to create a strong rumble effect with adjustable intensity.
The state of both motors can be changed using HID_OUTPUT_REPORT packets and
have no timing information. FF memless is used to keep track of the timing and
the sony driver just generates the necessary URBs.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 8 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 52 |
2 files changed, 60 insertions, 0 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 53747245d904..48525de02a39 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -613,6 +613,14 @@ config HID_SONY | |||
613 | * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) | 613 | * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) |
614 | * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) | 614 | * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) |
615 | 615 | ||
616 | config SONY_FF | ||
617 | bool "Sony PS2/3 accessories force feedback support" | ||
618 | depends on HID_SONY | ||
619 | select INPUT_FF_MEMLESS | ||
620 | ---help--- | ||
621 | Say Y here if you have a Sony PS2/3 accessory and want to enable force | ||
622 | feedback support for it. | ||
623 | |||
616 | config HID_SPEEDLINK | 624 | config HID_SPEEDLINK |
617 | tristate "Speedlink VAD Cezanne mouse support" | 625 | tristate "Speedlink VAD Cezanne mouse support" |
618 | depends on HID | 626 | depends on HID |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index bc37a1800166..da551d113762 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
@@ -614,6 +614,54 @@ static void buzz_remove(struct hid_device *hdev) | |||
614 | drv_data->extra = NULL; | 614 | drv_data->extra = NULL; |
615 | } | 615 | } |
616 | 616 | ||
617 | #ifdef CONFIG_SONY_FF | ||
618 | static int sony_play_effect(struct input_dev *dev, void *data, | ||
619 | struct ff_effect *effect) | ||
620 | { | ||
621 | unsigned char buf[] = { | ||
622 | 0x01, | ||
623 | 0x00, 0xff, 0x00, 0xff, 0x00, | ||
624 | 0x00, 0x00, 0x00, 0x00, 0x03, | ||
625 | 0xff, 0x27, 0x10, 0x00, 0x32, | ||
626 | 0xff, 0x27, 0x10, 0x00, 0x32, | ||
627 | 0xff, 0x27, 0x10, 0x00, 0x32, | ||
628 | 0xff, 0x27, 0x10, 0x00, 0x32, | ||
629 | 0x00, 0x00, 0x00, 0x00, 0x00 | ||
630 | }; | ||
631 | __u8 left; | ||
632 | __u8 right; | ||
633 | struct hid_device *hid = input_get_drvdata(dev); | ||
634 | |||
635 | if (effect->type != FF_RUMBLE) | ||
636 | return 0; | ||
637 | |||
638 | left = effect->u.rumble.strong_magnitude / 256; | ||
639 | right = effect->u.rumble.weak_magnitude ? 1 : 0; | ||
640 | |||
641 | buf[3] = right; | ||
642 | buf[5] = left; | ||
643 | |||
644 | return hid->hid_output_raw_report(hid, buf, sizeof(buf), | ||
645 | HID_OUTPUT_REPORT); | ||
646 | } | ||
647 | |||
648 | static int sony_init_ff(struct hid_device *hdev) | ||
649 | { | ||
650 | struct hid_input *hidinput = list_entry(hdev->inputs.next, | ||
651 | struct hid_input, list); | ||
652 | struct input_dev *input_dev = hidinput->input; | ||
653 | |||
654 | input_set_capability(input_dev, EV_FF, FF_RUMBLE); | ||
655 | return input_ff_create_memless(input_dev, NULL, sony_play_effect); | ||
656 | } | ||
657 | |||
658 | #else | ||
659 | static int sony_init_ff(struct hid_device *hdev) | ||
660 | { | ||
661 | return 0; | ||
662 | } | ||
663 | #endif | ||
664 | |||
617 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | 665 | static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) |
618 | { | 666 | { |
619 | int ret; | 667 | int ret; |
@@ -663,6 +711,10 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
663 | if (ret < 0) | 711 | if (ret < 0) |
664 | goto err_stop; | 712 | goto err_stop; |
665 | 713 | ||
714 | ret = sony_init_ff(hdev); | ||
715 | if (ret < 0) | ||
716 | goto err_stop; | ||
717 | |||
666 | return 0; | 718 | return 0; |
667 | err_stop: | 719 | err_stop: |
668 | hid_hw_stop(hdev); | 720 | hid_hw_stop(hdev); |