Skip to content

Commit

Permalink
HID: sony: support for the ghlive ps4 dongles
Browse files Browse the repository at this point in the history
This commit adds support for the Guitar Hero Live PS4 dongles.

These dongles require a "magic" USB control message to be sent
every 8 seconds otherwise the dongle will not report events where
the strumbar is hit while a fret is being held.

Note that the GHL_GUITAR_POKE_INTERVAL is reduced to 8 seconds in order
to support PS3, Wii U, and PS4 GHL dongles.

Also note that the constant for vendor id 0x1430 has been renamed from
Activision to RedOctane as self-declared by the device.

Co-developed-by: Pascal Giard <pascal.giard@etsmtl.ca>
Signed-off-by: Pascal Giard <pascal.giard@etsmtl.ca>
Signed-off-by: Daniel Nguyen <daniel.nguyen.1@ens.etsmtl.ca>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Daniel Nguyen authored and Jiri Kosina committed Aug 20, 2021
1 parent df04fbe commit a4bfe13
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 17 deletions.
2 changes: 1 addition & 1 deletion drivers/hid/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ config HID_SONY
* Buzz controllers
* Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
* Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
* Guitar Hero Live PS3 and Wii U guitar dongles
* Guitar Hero Live PS3, Wii U and PS4 guitar dongles
* Guitar Hero PS3 and PC guitar dongles

config SONY_FF
Expand Down
7 changes: 4 additions & 3 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@
#define USB_VENDOR_ID_ACTIONSTAR 0x2101
#define USB_DEVICE_ID_ACTIONSTAR_1011 0x1011

#define USB_VENDOR_ID_ACTIVISION 0x1430
#define USB_DEVICE_ID_ACTIVISION_GUITAR_DONGLE 0x474c

#define USB_VENDOR_ID_ADS_TECH 0x06e1
#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X 0xa155

Expand Down Expand Up @@ -1018,6 +1015,10 @@
#define USB_VENDOR_ID_REALTEK 0x0bda
#define USB_DEVICE_ID_REALTEK_READER 0x0152

#define USB_VENDOR_ID_REDOCTANE 0x1430
#define USB_DEVICE_ID_REDOCTANE_GUITAR_DONGLE 0x474c
#define USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE 0x07bb

#define USB_VENDOR_ID_RETROUSB 0xf000
#define USB_DEVICE_ID_RETROUSB_SNES_RETROPAD 0x0003
#define USB_DEVICE_ID_RETROUSB_SNES_RETROPORT 0x00f1
Expand Down
46 changes: 33 additions & 13 deletions drivers/hid/hid-sony.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
*/

/*
Expand Down Expand Up @@ -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)
Expand All @@ -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), */
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -3030,11 +3041,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;
Expand All @@ -3052,7 +3069,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);
}
Expand Down Expand Up @@ -3172,11 +3189,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);
Expand Down

0 comments on commit a4bfe13

Please sign in to comment.