Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bd88dd3 authored by Frank Praznik's avatar Frank Praznik Committed by Jiri Kosina
Browse files

HID: sony: Add force-feedback support for the Dualshock 4



Adds the Dualshock 4 to the HID device list and enables force-feedback.

Adds a Dualshock 4 specific worker function since the Dualshock 4 needs a
different report than the Sixaxis.

The right motor in the Dualshock 4 is variable so the full rumble value
is now passed to the worker function and clamped there if necessary.

Signed-off-by: default avatarFrank Praznik <frank.praznik@oh.rr.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 8cd5fcda
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1831,6 +1831,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
+1 −0
Original line number Diff line number Diff line
@@ -766,6 +766,7 @@
#define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE	0x0374
#define USB_DEVICE_ID_SONY_PS3_BDREMOTE		0x0306
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER	0x05c4
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER	0x042f
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER		0x0002
#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER	0x1000
+36 −3
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@
#define SIXAXIS_CONTROLLER_BT   BIT(2)
#define BUZZ_CONTROLLER         BIT(3)
#define PS3REMOTE		BIT(4)
#define DUALSHOCK4_CONTROLLER   BIT(5)

#define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER_USB | BUZZ_CONTROLLER)

@@ -630,7 +631,7 @@ static void sony_state_worker(struct work_struct *work)
	};

#ifdef CONFIG_SONY_FF
	buf[3] = sc->right;
	buf[3] = sc->right ? 1 : 0;
	buf[5] = sc->left;
#endif

@@ -640,6 +641,29 @@ static void sony_state_worker(struct work_struct *work)
					HID_OUTPUT_REPORT);
}

static void dualshock4_state_worker(struct work_struct *work)
{
	struct sony_sc *sc = container_of(work, struct sony_sc, state_worker);
	unsigned char buf[] = {
		0x05,
		0x03, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00,
		0x00,
	};

#ifdef CONFIG_SONY_FF
	buf[4] = sc->right;
	buf[5] = sc->left;
#endif

	sc->hdev->hid_output_raw_report(sc->hdev, buf, sizeof(buf),
					HID_OUTPUT_REPORT);
}

#ifdef CONFIG_SONY_FF
static int sony_play_effect(struct input_dev *dev, void *data,
			    struct ff_effect *effect)
@@ -651,7 +675,7 @@ static int sony_play_effect(struct input_dev *dev, void *data,
		return 0;

	sc->left = effect->u.rumble.strong_magnitude / 256;
	sc->right = effect->u.rumble.weak_magnitude ? 1 : 0;
	sc->right = effect->u.rumble.weak_magnitude / 256;

	schedule_work(&sc->state_worker);
	return 0;
@@ -728,8 +752,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
	}
	else if (sc->quirks & SIXAXIS_CONTROLLER_BT)
		ret = sixaxis_set_operational_bt(hdev);
	else
	else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
		ret = 0;
		INIT_WORK(&sc->state_worker, dualshock4_state_worker);
	} else {
		ret = 0;
	}

	if (ret < 0)
		goto err_stop;
@@ -787,6 +815,11 @@ static const struct hid_device_id sony_devices[] = {
	/* Logitech Harmony Adapter for PS3 */
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3),
		.driver_data = PS3REMOTE },
	/* Sony Dualshock 4 controllers for PS4 */
	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
		.driver_data = DUALSHOCK4_CONTROLLER },
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
		.driver_data = DUALSHOCK4_CONTROLLER },
	{ }
};
MODULE_DEVICE_TABLE(hid, sony_devices);