aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2013-11-09 13:25:57 -0500
committerJiri Kosina <jkosina@suse.cz>2013-11-11 05:25:46 -0500
commita08c22c0df0ad23d0df10ae1a9df26643589b3cc (patch)
tree476d2fe040e9337b70f73587c56f27890059ae08 /drivers/hid
parentae2aa3a512fa5f50f67feba9e66bc2efb394bd63 (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/Kconfig8
-rw-r--r--drivers/hid/hid-sony.c52
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
616config 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
616config HID_SPEEDLINK 624config 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
618static 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
648static 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
659static int sony_init_ff(struct hid_device *hdev)
660{
661 return 0;
662}
663#endif
664
617static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 665static 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;
667err_stop: 719err_stop:
668 hid_hw_stop(hdev); 720 hid_hw_stop(hdev);