Skip to content

Commit a08c22c

Browse files
ecsvJiri Kosina
authored andcommitted
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 <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent ae2aa3a commit a08c22c

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

drivers/hid/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,14 @@ config HID_SONY
613613
* Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
614614
* Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
615615

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+
616624
config HID_SPEEDLINK
617625
tristate "Speedlink VAD Cezanne mouse support"
618626
depends on HID

drivers/hid/hid-sony.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,54 @@ static void buzz_remove(struct hid_device *hdev)
614614
drv_data->extra = NULL;
615615
}
616616

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+
617665
static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
618666
{
619667
int ret;
@@ -663,6 +711,10 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
663711
if (ret < 0)
664712
goto err_stop;
665713

714+
ret = sony_init_ff(hdev);
715+
if (ret < 0)
716+
goto err_stop;
717+
666718
return 0;
667719
err_stop:
668720
hid_hw_stop(hdev);

0 commit comments

Comments
 (0)