| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * HID driver for Sony / PS2 / PS3 / PS4 BD devices. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 13 | 14 | */ |
|---|
| 14 | 15 | |
|---|
| 15 | 16 | /* |
|---|
| 16 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 17 | | - * under the terms of the GNU General Public License as published by the Free |
|---|
| 18 | | - * Software Foundation; either version 2 of the License, or (at your option) |
|---|
| 19 | | - * any later version. |
|---|
| 20 | 17 | */ |
|---|
| 21 | 18 | |
|---|
| 22 | 19 | /* |
|---|
| .. | .. |
|---|
| 58 | 55 | #define FUTUREMAX_DANCE_MAT BIT(13) |
|---|
| 59 | 56 | #define NSG_MR5U_REMOTE_BT BIT(14) |
|---|
| 60 | 57 | #define NSG_MR7U_REMOTE_BT BIT(15) |
|---|
| 58 | +#define SHANWAN_GAMEPAD BIT(16) |
|---|
| 61 | 59 | |
|---|
| 62 | 60 | #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) |
|---|
| 63 | 61 | #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) |
|---|
| .. | .. |
|---|
| 1511 | 1509 | */ |
|---|
| 1512 | 1510 | static int sixaxis_set_operational_usb(struct hid_device *hdev) |
|---|
| 1513 | 1511 | { |
|---|
| 1512 | + struct sony_sc *sc = hid_get_drvdata(hdev); |
|---|
| 1514 | 1513 | const int buf_size = |
|---|
| 1515 | 1514 | max(SIXAXIS_REPORT_0xF2_SIZE, SIXAXIS_REPORT_0xF5_SIZE); |
|---|
| 1516 | 1515 | u8 *buf; |
|---|
| .. | .. |
|---|
| 1540 | 1539 | |
|---|
| 1541 | 1540 | /* |
|---|
| 1542 | 1541 | * But the USB interrupt would cause SHANWAN controllers to |
|---|
| 1543 | | - * start rumbling non-stop. |
|---|
| 1542 | + * start rumbling non-stop, so skip step 3 for these controllers. |
|---|
| 1544 | 1543 | */ |
|---|
| 1545 | | - if (strcmp(hdev->name, "SHANWAN PS3 GamePad")) { |
|---|
| 1546 | | - ret = hid_hw_output_report(hdev, buf, 1); |
|---|
| 1547 | | - if (ret < 0) { |
|---|
| 1548 | | - hid_info(hdev, "can't set operational mode: step 3, ignoring\n"); |
|---|
| 1549 | | - ret = 0; |
|---|
| 1550 | | - } |
|---|
| 1544 | + if (sc->quirks & SHANWAN_GAMEPAD) |
|---|
| 1545 | + goto out; |
|---|
| 1546 | + |
|---|
| 1547 | + ret = hid_hw_output_report(hdev, buf, 1); |
|---|
| 1548 | + if (ret < 0) { |
|---|
| 1549 | + hid_info(hdev, "can't set operational mode: step 3, ignoring\n"); |
|---|
| 1550 | + ret = 0; |
|---|
| 1551 | 1551 | } |
|---|
| 1552 | 1552 | |
|---|
| 1553 | 1553 | out: |
|---|
| .. | .. |
|---|
| 2118 | 2118 | } |
|---|
| 2119 | 2119 | } |
|---|
| 2120 | 2120 | |
|---|
| 2121 | | - hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report, |
|---|
| 2122 | | - sizeof(struct sixaxis_output_report), |
|---|
| 2123 | | - HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
|---|
| 2121 | + /* SHANWAN controllers require output reports via intr channel */ |
|---|
| 2122 | + if (sc->quirks & SHANWAN_GAMEPAD) |
|---|
| 2123 | + hid_hw_output_report(sc->hdev, (u8 *)report, |
|---|
| 2124 | + sizeof(struct sixaxis_output_report)); |
|---|
| 2125 | + else |
|---|
| 2126 | + hid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report, |
|---|
| 2127 | + sizeof(struct sixaxis_output_report), |
|---|
| 2128 | + HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
|---|
| 2124 | 2129 | } |
|---|
| 2125 | 2130 | |
|---|
| 2126 | 2131 | static void dualshock4_send_output_report(struct sony_sc *sc) |
|---|
| .. | .. |
|---|
| 2842 | 2847 | if (!strcmp(hdev->name, "FutureMax Dance Mat")) |
|---|
| 2843 | 2848 | quirks |= FUTUREMAX_DANCE_MAT; |
|---|
| 2844 | 2849 | |
|---|
| 2850 | + if (!strcmp(hdev->name, "SHANWAN PS3 GamePad")) |
|---|
| 2851 | + quirks |= SHANWAN_GAMEPAD; |
|---|
| 2852 | + |
|---|
| 2845 | 2853 | sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); |
|---|
| 2846 | 2854 | if (sc == NULL) { |
|---|
| 2847 | 2855 | hid_err(hdev, "can't alloc sony descriptor\n"); |
|---|