diff mbox series

[v2] HID: sony: Fix SHANWAN PS3 GamePad rumbling on USB again

Message ID 20181229020228.29383-1-outmatch@gmail.com (mailing list archive)
State Superseded
Delegated to: Jiri Kosina
Headers show
Series [v2] HID: sony: Fix SHANWAN PS3 GamePad rumbling on USB again | expand

Commit Message

Hongye Yuan Dec. 29, 2018, 2:02 a.m. UTC
- SHANWAN DS3 clone gamepad requires HID Output Reports via Interrupt EP.
- Added a quirk for SHANWAN PS3 GamePad.

Signed-off-by: Hongye Yuan <outmatch@gmail.com>

---

Changes in V2:
  - Tidy up commit message and source line indention
  - Fixed inverted logic in sixaxis_set_operational_usb()
---
 drivers/hid/hid-sony.c | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

Comments

Bastien Nocera Dec. 29, 2018, 12:25 p.m. UTC | #1
On Sat, 2018-12-29 at 10:02 +0800, Hongye Yuan wrote:
> - SHANWAN DS3 clone gamepad requires HID Output Reports via Interrupt
> EP.
> - Added a quirk for SHANWAN PS3 GamePad.
> 
> Signed-off-by: Hongye Yuan <outmatch@gmail.com>

Any chance you could split this off into 2 patches? One for the quirk
addition (which you'd use in sixaxis_set_operational_usb()) and one to
make the rumble work again on those controllers?

Cheers

> 
> ---
> 
> Changes in V2:
>   - Tidy up commit message and source line indention
>   - Fixed inverted logic in sixaxis_set_operational_usb()
> ---
>  drivers/hid/hid-sony.c | 31 +++++++++++++++++++++----------
>  1 file changed, 21 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
> index 9671a4bad643..26fae90b931a 100644
> --- a/drivers/hid/hid-sony.c
> +++ b/drivers/hid/hid-sony.c
> @@ -58,6 +58,7 @@
>  #define FUTUREMAX_DANCE_MAT       BIT(13)
>  #define NSG_MR5U_REMOTE_BT        BIT(14)
>  #define NSG_MR7U_REMOTE_BT        BIT(15)
> +#define SHANWAN_GAMEPAD           BIT(16)
>  
>  #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB |
> SIXAXIS_CONTROLLER_BT)
>  #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB |
> MOTION_CONTROLLER_BT)
> @@ -1490,6 +1491,7 @@ static int sony_register_sensors(struct sony_sc
> *sc)
>   */
>  static int sixaxis_set_operational_usb(struct hid_device *hdev)
>  {
> +	struct sony_sc *sc = hid_get_drvdata(hdev);
>  	const int buf_size =
>  		max(SIXAXIS_REPORT_0xF2_SIZE,
> SIXAXIS_REPORT_0xF5_SIZE);
>  	u8 *buf;
> @@ -1519,14 +1521,15 @@ static int sixaxis_set_operational_usb(struct
> hid_device *hdev)
>  
>  	/*
>  	 * But the USB interrupt would cause SHANWAN controllers to
> -	 * start rumbling non-stop.
> +	 * start rumbling non-stop, so skip step 3 for these
> controllers.
>  	 */
> -	if (strcmp(hdev->name, "SHANWAN PS3 GamePad")) {
> -		ret = hid_hw_output_report(hdev, buf, 1);
> -		if (ret < 0) {
> -			hid_info(hdev, "can't set operational mode:
> step 3, ignoring\n");
> -			ret = 0;
> -		}
> +	if (sc->quirks & SHANWAN_GAMEPAD)
> +		goto out;
> +
> +	ret = hid_hw_output_report(hdev, buf, 1);
> +	if (ret < 0) {
> +		hid_info(hdev, "can't set operational mode: step 3,
> ignoring\n");
> +		ret = 0;
>  	}
>  
>  out:
> @@ -2097,9 +2100,14 @@ static void sixaxis_send_output_report(struct
> sony_sc *sc)
>  		}
>  	}
>  
> -	hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
> -			sizeof(struct sixaxis_output_report),
> -			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
> +	/* SHANWAN controllers require output reports via intr channel
> */
> +	if (sc->quirks & SHANWAN_GAMEPAD)
> +		hid_hw_output_report(sc->hdev, (u8 *)report,
> +				sizeof(struct sixaxis_output_report));
> +	else
> +		hid_hw_raw_request(sc->hdev, report->report_id, (u8
> *)report,
> +				sizeof(struct sixaxis_output_report),
> +				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
>  }
>  
>  static void dualshock4_send_output_report(struct sony_sc *sc)
> @@ -2811,6 +2819,9 @@ static int sony_probe(struct hid_device *hdev,
> const struct hid_device_id *id)
>  	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
>  		quirks |= FUTUREMAX_DANCE_MAT;
>  
> +	if (!strcmp(hdev->name, "SHANWAN PS3 GamePad"))
> +		quirks |= SHANWAN_GAMEPAD;
> +
>  	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
>  	if (sc == NULL) {
>  		hid_err(hdev, "can't alloc sony descriptor\n");
diff mbox series

Patch

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 9671a4bad643..26fae90b931a 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -58,6 +58,7 @@ 
 #define FUTUREMAX_DANCE_MAT       BIT(13)
 #define NSG_MR5U_REMOTE_BT        BIT(14)
 #define NSG_MR7U_REMOTE_BT        BIT(15)
+#define SHANWAN_GAMEPAD           BIT(16)
 
 #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)
 #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)
@@ -1490,6 +1491,7 @@  static int sony_register_sensors(struct sony_sc *sc)
  */
 static int sixaxis_set_operational_usb(struct hid_device *hdev)
 {
+	struct sony_sc *sc = hid_get_drvdata(hdev);
 	const int buf_size =
 		max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE);
 	u8 *buf;
@@ -1519,14 +1521,15 @@  static int sixaxis_set_operational_usb(struct hid_device *hdev)
 
 	/*
 	 * But the USB interrupt would cause SHANWAN controllers to
-	 * start rumbling non-stop.
+	 * start rumbling non-stop, so skip step 3 for these controllers.
 	 */
-	if (strcmp(hdev->name, "SHANWAN PS3 GamePad")) {
-		ret = hid_hw_output_report(hdev, buf, 1);
-		if (ret < 0) {
-			hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
-			ret = 0;
-		}
+	if (sc->quirks & SHANWAN_GAMEPAD)
+		goto out;
+
+	ret = hid_hw_output_report(hdev, buf, 1);
+	if (ret < 0) {
+		hid_info(hdev, "can't set operational mode: step 3, ignoring\n");
+		ret = 0;
 	}
 
 out:
@@ -2097,9 +2100,14 @@  static void sixaxis_send_output_report(struct sony_sc *sc)
 		}
 	}
 
-	hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
-			sizeof(struct sixaxis_output_report),
-			HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+	/* SHANWAN controllers require output reports via intr channel */
+	if (sc->quirks & SHANWAN_GAMEPAD)
+		hid_hw_output_report(sc->hdev, (u8 *)report,
+				sizeof(struct sixaxis_output_report));
+	else
+		hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,
+				sizeof(struct sixaxis_output_report),
+				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
 }
 
 static void dualshock4_send_output_report(struct sony_sc *sc)
@@ -2811,6 +2819,9 @@  static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
 		quirks |= FUTUREMAX_DANCE_MAT;
 
+	if (!strcmp(hdev->name, "SHANWAN PS3 GamePad"))
+		quirks |= SHANWAN_GAMEPAD;
+
 	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
 	if (sc == NULL) {
 		hid_err(hdev, "can't alloc sony descriptor\n");