diff options
author | Jiri Kosina <jkosina@suse.cz> | 2021-09-01 22:03:18 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2021-09-01 22:03:18 +0200 |
commit | 854a95877f4d95b65918cb126fdc0c84ea564676 (patch) | |
tree | 5e9fffcc1a4a92916c8c26ba6efafa56f394c7b2 /drivers/hid/hid-sony.c | |
parent | Merge branch 'for-5.15/magicmouse' into for-linus (diff) | |
parent | HID: sony: support for the ghlive ps4 dongles (diff) | |
download | linux-854a95877f4d95b65918cb126fdc0c84ea564676.tar.xz linux-854a95877f4d95b65918cb126fdc0c84ea564676.zip |
Merge branch 'for-5.15/sony' into for-linus
- Support for GHLive PS4 dongles
Diffstat (limited to 'drivers/hid/hid-sony.c')
-rw-r--r-- | drivers/hid/hid-sony.c | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index a2fef59063a6..d1b107d547f5 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -11,8 +11,9 @@ * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com> * Copyright (c) 2018 Todd Kelner - * Copyright (c) 2020 Pascal Giard <pascal.giard@etsmtl.ca> + * Copyright (c) 2020-2021 Pascal Giard <pascal.giard@etsmtl.ca> * Copyright (c) 2020 Sanjay Govind <sanjay.govind9@gmail.com> + * Copyright (c) 2021 Daniel Nguyen <daniel.nguyen.1@ens.etsmtl.ca> */ /* @@ -62,6 +63,7 @@ #define SHANWAN_GAMEPAD BIT(16) #define GH_GUITAR_CONTROLLER BIT(17) #define GHL_GUITAR_PS3WIIU BIT(18) +#define GHL_GUITAR_PS4 BIT(19) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) @@ -85,18 +87,27 @@ #define NSG_MRXU_MAX_X 1667 #define NSG_MRXU_MAX_Y 1868 -#define GHL_GUITAR_POKE_INTERVAL 10 /* In seconds */ +/* The PS3/Wii U dongles require a poke every 10 seconds, but the PS4 + * requires one every 8 seconds. Using 8 seconds for all for simplicity. + */ +#define GHL_GUITAR_POKE_INTERVAL 8 /* In seconds */ #define GUITAR_TILT_USAGE 44 -/* Magic value and data taken from GHLtarUtility: +/* Magic data taken from GHLtarUtility: * https://github.com/ghlre/GHLtarUtility/blob/master/PS3Guitar.cs * Note: The Wii U and PS3 dongles happen to share the same! */ -static const u16 ghl_ps3wiiu_magic_value = 0x201; static const char ghl_ps3wiiu_magic_data[] = { 0x02, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* Magic data for the PS4 dongles sniffed with a USB protocol + * analyzer. + */ +static const char ghl_ps4_magic_data[] = { + 0x30, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + /* PS/3 Motion controller */ static u8 motion_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ @@ -642,14 +653,14 @@ static void ghl_magic_poke(struct timer_list *t) hid_err(sc->hdev, "usb_submit_urb failed: %d", ret); } -static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev) +static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev, + const char ghl_magic_data[], u16 poke_size) { struct usb_ctrlrequest *cr; - u16 poke_size; u8 *databuf; unsigned int pipe; + u16 ghl_magic_value = (((HID_OUTPUT_REPORT + 1) << 8) | ghl_magic_data[0]); - poke_size = ARRAY_SIZE(ghl_ps3wiiu_magic_data); pipe = usb_sndctrlpipe(usbdev, 0); cr = devm_kzalloc(&sc->hdev->dev, sizeof(*cr), GFP_ATOMIC); @@ -663,10 +674,10 @@ static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev) cr->bRequestType = USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT; cr->bRequest = USB_REQ_SET_CONFIGURATION; - cr->wValue = cpu_to_le16(ghl_ps3wiiu_magic_value); + cr->wValue = cpu_to_le16(ghl_magic_value); cr->wIndex = 0; cr->wLength = cpu_to_le16(poke_size); - memcpy(databuf, ghl_ps3wiiu_magic_data, poke_size); + memcpy(databuf, ghl_magic_data, poke_size); usb_fill_control_urb( sc->ghl_urb, usbdev, pipe, (unsigned char *) cr, databuf, poke_size, @@ -3031,11 +3042,17 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) return -ENODEV; } - if (sc->quirks & GHL_GUITAR_PS3WIIU) { + if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC); if (!sc->ghl_urb) return -ENOMEM; - ret = ghl_init_urb(sc, usbdev); + + if (sc->quirks & GHL_GUITAR_PS3WIIU) + ret = ghl_init_urb(sc, usbdev, ghl_ps3wiiu_magic_data, + ARRAY_SIZE(ghl_ps3wiiu_magic_data)); + else if (sc->quirks & GHL_GUITAR_PS4) + ret = ghl_init_urb(sc, usbdev, ghl_ps4_magic_data, + ARRAY_SIZE(ghl_ps4_magic_data)); if (ret) { hid_err(hdev, "error preparing URB\n"); return ret; @@ -3053,7 +3070,7 @@ static void sony_remove(struct hid_device *hdev) { struct sony_sc *sc = hid_get_drvdata(hdev); - if (sc->quirks & GHL_GUITAR_PS3WIIU) { + if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { del_timer_sync(&sc->ghl_poke_timer); usb_free_urb(sc->ghl_urb); } @@ -3173,11 +3190,14 @@ static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE), .driver_data = GHL_GUITAR_PS3WIIU | GH_GUITAR_CONTROLLER }, /* Guitar Hero PC Guitar Dongle */ - { HID_USB_DEVICE(USB_VENDOR_ID_ACTIVISION, USB_DEVICE_ID_ACTIVISION_GUITAR_DONGLE), + { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_GUITAR_DONGLE), .driver_data = GH_GUITAR_CONTROLLER }, /* Guitar Hero PS3 World Tour Guitar Dongle */ { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GUITAR_DONGLE), .driver_data = GH_GUITAR_CONTROLLER }, + /* Guitar Hero Live PS4 guitar dongles */ + { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE), + .driver_data = GHL_GUITAR_PS4 | GH_GUITAR_CONTROLLER }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); |