diff --git a/patch/kernel/rk35xx-legacy/001-hid-sony.patch b/patch/kernel/rk35xx-legacy/001-hid-sony.patch new file mode 100644 index 0000000000..6d001c38e9 --- /dev/null +++ b/patch/kernel/rk35xx-legacy/001-hid-sony.patch @@ -0,0 +1,111 @@ +Signed-off-by: Ivan Mironov +--- + drivers/hid/hid-sony.c | 72 ++++++++++++++++++++++++++++++------------ + 1 file changed, 52 insertions(+), 20 deletions(-) + +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index e3a557dc9ffd..97df12180e45 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -491,6 +491,7 @@ struct motion_output_report_02 { + + #define DS4_FEATURE_REPORT_0x02_SIZE 37 + #define DS4_FEATURE_REPORT_0x05_SIZE 41 ++#define DS4_FEATURE_REPORT_0x12_SIZE 16 + #define DS4_FEATURE_REPORT_0x81_SIZE 7 + #define DS4_FEATURE_REPORT_0xA3_SIZE 49 + #define DS4_INPUT_REPORT_0x11_SIZE 78 +@@ -2593,6 +2594,53 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) + return 0; + } + ++static int sony_get_usb_ds4_devaddr(struct sony_sc *sc) ++{ ++ u8 *buf = NULL; ++ int ret; ++ ++ buf = kmalloc(max(DS4_FEATURE_REPORT_0x12_SIZE, DS4_FEATURE_REPORT_0x81_SIZE), GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ /* ++ * The MAC address of a DS4 controller connected via USB can be ++ * retrieved with feature report 0x81. The address begins at ++ * offset 1. ++ */ ++ ret = hid_hw_raw_request(sc->hdev, 0x81, buf, ++ DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, ++ HID_REQ_GET_REPORT); ++ if (ret == DS4_FEATURE_REPORT_0x81_SIZE) { ++ memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); ++ goto out_free; ++ } ++ dbg_hid("%s: hid_hw_raw_request(..., 0x81, ...) returned %d\n", __func__, ret); ++ ++ /* ++ * Some variants do not implement feature report 0x81 at all. ++ * Fortunately, feature report 0x12 also contains the MAC address of ++ * a controller. ++ */ ++ ret = hid_hw_raw_request(sc->hdev, 0x12, buf, ++ DS4_FEATURE_REPORT_0x12_SIZE, HID_FEATURE_REPORT, ++ HID_REQ_GET_REPORT); ++ if (ret == DS4_FEATURE_REPORT_0x12_SIZE) { ++ memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); ++ goto out_free; ++ } ++ dbg_hid("%s: hid_hw_raw_request(..., 0x12, ...) returned %d\n", __func__, ret); ++ ++ hid_err(sc->hdev, "failed to retrieve feature reports 0x81 and 0x12 with the DualShock 4 MAC address\n"); ++ ret = ret < 0 ? ret : -EINVAL; ++ ++out_free: ++ ++ kfree(buf); ++ ++ return ret; ++} ++ + static int sony_check_add(struct sony_sc *sc) + { + u8 *buf = NULL; +@@ -2613,26 +2661,9 @@ static int sony_check_add(struct sony_sc *sc) + return 0; + } + } else if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) { +- buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL); +- if (!buf) +- return -ENOMEM; +- +- /* +- * The MAC address of a DS4 controller connected via USB can be +- * retrieved with feature report 0x81. The address begins at +- * offset 1. +- */ +- ret = hid_hw_raw_request(sc->hdev, 0x81, buf, +- DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT, +- HID_REQ_GET_REPORT); +- +- if (ret != DS4_FEATURE_REPORT_0x81_SIZE) { +- hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); +- ret = ret < 0 ? ret : -EINVAL; +- goto out_free; +- } +- +- memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); ++ ret = sony_get_usb_ds4_devaddr(sc); ++ if (ret < 0) ++ return ret; + + snprintf(sc->hdev->uniq, sizeof(sc->hdev->uniq), + "%pMR", sc->mac_address); +@@ -2670,6 +2701,7 @@ static int sony_check_add(struct sony_sc *sc) + return 0; + } + ++ dbg_hid("%s: retrieved MAC address: %s\n", __func__, sc->hdev->uniq); + ret = sony_check_add_dev_list(sc); + + out_free: +-- +2.29.2 \ No newline at end of file