diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index aa3c103d0894..e49c3f648cc3 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1087,13 +1087,15 @@ config HID_SONY help Support for - * Sony PS3 6-axis controllers + * Sixaxis controllers for PS3 * Buzz controllers - * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) - * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) - * Guitar Hero Live PS3, Wii U and PS4 guitar dongles - * Guitar Hero PS3 and PC guitar dongles + * Blu-ray Disc Remote Control for PS3 + * Logitech Harmony adapter for PS3 + * Guitar Hero Live PS3, Wii U and PS4 guitars + * Guitar Hero PS3 and PC guitars + * Rock Band 1, 2 and 3 PS3 and Wii instruments * Rock Band 4 PS4 and PS5 guitars + * DJ Hero Turntable for PS3 config SONY_FF bool "Sony PS2/3/4 accessories force feedback support" diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 91d650afdff3..27789d3bf130 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -667,6 +667,18 @@ #define USB_DEVICE_ID_UGCI_FLYING 0x0020 #define USB_DEVICE_ID_UGCI_FIGHTING 0x0030 +#define USB_VENDOR_ID_HARMONIX 0x1bad +#define USB_DEVICE_ID_HARMONIX_WII_RB1_GUITAR 0x0004 +#define USB_DEVICE_ID_HARMONIX_WII_RB2_GUITAR 0x3010 +#define USB_DEVICE_ID_HARMONIX_WII_RB1_DRUMS 0x0005 +#define USB_DEVICE_ID_HARMONIX_WII_RB2_DRUMS 0x3110 +#define USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_DRUMS_MODE 0x3138 +#define USB_DEVICE_ID_HARMONIX_WII_RB3_MUSTANG_GUITAR 0x3430 +#define USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_MUSTANG_MODE 0x3438 +#define USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_SQUIER_MODE 0x3538 +#define USB_DEVICE_ID_HARMONIX_WII_RB3_KEYBOARD 0x3330 +#define USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_KEYBOARD_MODE 0x3338 + #define USB_VENDOR_ID_HP 0x03f0 #define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A 0x464a #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a @@ -1301,8 +1313,18 @@ #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 #define USB_VENDOR_ID_SONY_RHYTHM 0x12ba -#define USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE 0x074b -#define USB_DEVICE_ID_SONY_PS3_GUITAR_DONGLE 0x0100 +#define USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE 0x074b +#define USB_DEVICE_ID_SONY_PS3_GH_GUITAR 0x0100 +#define USB_DEVICE_ID_SONY_PS3_GH_DRUMS 0x0120 +#define USB_DEVICE_ID_SONY_PS3_DJH_TURNTABLE 0x0140 +#define USB_DEVICE_ID_SONY_PS3_RB_GUITAR 0x0200 +#define USB_DEVICE_ID_SONY_PS3_RB_DRUMS 0x0210 +#define USB_DEVICE_ID_SONY_PS3_RB3_MPA_DRUMS_MODE 0x0218 +#define USB_DEVICE_ID_SONY_PS3_RB3_MUSTANG_GUITAR 0x2430 +#define USB_DEVICE_ID_SONY_PS3_RB3_MPA_MUSTANG_MODE 0x2438 +#define USB_DEVICE_ID_SONY_PS3_RB3_MPA_SQUIER_MODE 0x2538 +#define USB_DEVICE_ID_SONY_PS3_RB3_KEYBOARD 0x2330 +#define USB_DEVICE_ID_SONY_PS3_RB3_MPA_KEYBOARD_MODE 0x2338 #define USB_VENDOR_ID_SINO_LITE 0x1345 #define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index eb811b1fb80f..9e88c9d6c6dc 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -692,22 +692,54 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, #endif #if IS_ENABLED(CONFIG_HID_SONY) + { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS4_GIBSON_SG) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS4_GIBSON_SG_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS5_GIBSON_SG) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS5_GIBSON_SG_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB1_DRUMS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB1_GUITAR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB2_DRUMS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB2_GUITAR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_DRUMS_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_KEYBOARD_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_MUSTANG_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_SQUIER_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MUSTANG_GUITAR) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_PS4_STRATOCASTER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS4_JAGUAR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS4_RIFFMASTER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS5_RIFFMASTER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_GUITAR_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_REDOCTANE, USB_DEVICE_ID_REDOCTANE_PS4_GHLIVE_DONGLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR5U_REMOTE) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_DJH_TURNTABLE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GH_DRUMS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GH_GUITAR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_KEYBOARD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_DRUMS_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_KEYBOARD_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_MUSTANG_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_SQUIER_MODE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MUSTANG_GUITAR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB_DRUMS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB_GUITAR) }, #endif #if IS_ENABLED(CONFIG_HID_SPEEDLINK) { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index a89af14e4acc..b5e724676c1d 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * HID driver for Sony / PS2 / PS3 / PS4 BD devices. + * HID driver for Sony / PS2 / PS3 BD / PS4 / PS5 devices. * * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik @@ -12,9 +12,10 @@ * Copyright (c) 2014-2016 Frank Praznik * Copyright (c) 2018 Todd Kelner * Copyright (c) 2020-2021 Pascal Giard - * Copyright (c) 2020 Sanjay Govind + * Copyright (c) 2020-2026 Sanjay Govind * Copyright (c) 2021 Daniel Nguyen * Copyright (c) 2026 Rosalie Wanders + * Copyright (c) 2026 Brenton Simpson */ /* @@ -59,12 +60,15 @@ #define NSG_MR5U_REMOTE_BT BIT(11) #define NSG_MR7U_REMOTE_BT BIT(12) #define SHANWAN_GAMEPAD BIT(13) -#define GH_GUITAR_CONTROLLER BIT(14) -#define GHL_GUITAR_PS3WIIU BIT(15) -#define GHL_GUITAR_PS4 BIT(16) -#define RB4_GUITAR_PS4_USB BIT(17) -#define RB4_GUITAR_PS4_BT BIT(18) -#define RB4_GUITAR_PS5 BIT(19) +#define INSTRUMENT BIT(14) +#define GH_GUITAR_TILT BIT(15) +#define GHL_GUITAR_PS3WIIU BIT(16) +#define GHL_GUITAR_PS4 BIT(17) +#define RB4_GUITAR_PS4_USB BIT(18) +#define RB4_GUITAR_PS4_BT BIT(19) +#define RB4_GUITAR_PS5 BIT(20) +#define RB3_PRO_INSTRUMENT BIT(21) +#define DJH_TURNTABLE BIT(22) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) @@ -72,7 +76,8 @@ NAVIGATION_CONTROLLER_BT) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ MOTION_CONTROLLER | NAVIGATION_CONTROLLER) -#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) +#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER |\ + RB4_GUITAR_PS5) #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | MOTION_CONTROLLER) #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT) #define NSG_MRXU_REMOTE (NSG_MR5U_REMOTE_BT | NSG_MR7U_REMOTE_BT) @@ -87,6 +92,10 @@ #define GHL_GUITAR_POKE_INTERVAL 8 /* In seconds */ #define GUITAR_TILT_USAGE 44 +#define TURNTABLE_EFFECTS_KNOB_USAGE 44 +#define TURNTABLE_PLATTER_BUTTONS_USAGE 45 +#define TURNTABLE_CROSS_FADER_USAGE 46 + /* 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! @@ -427,20 +436,25 @@ static const unsigned int rb4_absmap[] = { [0x31] = ABS_Y, }; -static const unsigned int rb4_keymap[] = { - [0x1] = BTN_WEST, /* Square */ - [0x2] = BTN_SOUTH, /* Cross */ - [0x3] = BTN_EAST, /* Circle */ - [0x4] = BTN_NORTH, /* Triangle */ - [0x5] = BTN_TL, /* L1 */ - [0x6] = BTN_TR, /* R1 */ - [0x7] = BTN_TL2, /* L2 */ - [0x8] = BTN_TR2, /* R2 */ - [0x9] = BTN_SELECT, /* Share */ - [0xa] = BTN_START, /* Options */ - [0xb] = BTN_THUMBL, /* L3 */ - [0xc] = BTN_THUMBR, /* R3 */ - [0xd] = BTN_MODE, /* PS */ +static const unsigned int ps3_turntable_absmap[] = { + [0x32] = ABS_X, + [0x35] = ABS_Y, +}; + +static const unsigned int instrument_keymap[] = { + [0x1] = BTN_WEST, + [0x2] = BTN_SOUTH, + [0x3] = BTN_EAST, + [0x4] = BTN_NORTH, + [0x5] = BTN_TL, + [0x6] = BTN_TR, + [0x7] = BTN_TL2, + [0x8] = BTN_TR2, + [0x9] = BTN_SELECT, + [0xa] = BTN_START, + [0xb] = BTN_THUMBL, + [0xc] = BTN_THUMBR, + [0xd] = BTN_MODE, }; static enum power_supply_property sony_battery_props[] = { @@ -457,6 +471,7 @@ struct sixaxis_led { u8 duty_off; /* % of duty_length the led is off (0xff means 100%) */ u8 duty_on; /* % of duty_length the led is on (0xff mean 100%) */ } __packed; +static_assert(sizeof(struct sixaxis_led) == 5); struct sixaxis_rumble { u8 padding; @@ -465,6 +480,7 @@ struct sixaxis_rumble { u8 left_duration; /* Left motor duration (0xff means forever) */ u8 left_motor_force; /* left (large) motor, supports force values from 0 to 255 */ } __packed; +static_assert(sizeof(struct sixaxis_rumble) == 5); struct sixaxis_output_report { u8 report_id; @@ -474,11 +490,13 @@ struct sixaxis_output_report { struct sixaxis_led led[4]; /* LEDx at (4 - x) */ struct sixaxis_led _reserved; /* LED5, not actually soldered */ } __packed; +static_assert(sizeof(struct sixaxis_output_report) == 36); union sixaxis_output_report_01 { struct sixaxis_output_report data; u8 buf[36]; }; +static_assert(sizeof(union sixaxis_output_report_01) == 36); struct motion_output_report_02 { u8 type, zero; @@ -486,10 +504,12 @@ struct motion_output_report_02 { u8 zero2; u8 rumble; }; +static_assert(sizeof(struct motion_output_report_02) == 7); #define SIXAXIS_REPORT_0xF2_SIZE 17 #define SIXAXIS_REPORT_0xF5_SIZE 8 #define MOTION_REPORT_0x02_SIZE 49 +#define PRO_INSTRUMENT_0x00_SIZE 8 #define SENSOR_SUFFIX " Motion Sensors" #define TOUCHPAD_SUFFIX " Touchpad" @@ -515,7 +535,7 @@ struct sony_sc { struct led_classdev *leds[MAX_LEDS]; unsigned long quirks; struct work_struct state_worker; - void (*send_output_report)(struct sony_sc *); + void (*send_output_report)(struct sony_sc *sc); struct power_supply *battery; struct power_supply_desc battery_desc; int device_id; @@ -539,6 +559,9 @@ struct sony_sc { /* GH Live */ struct urb *ghl_urb; struct timer_list ghl_poke_timer; + + /* Rock Band 3 Pro Instruments */ + unsigned long rb3_pro_poke_jiffies; }; static void sony_set_leds(struct sony_sc *sc); @@ -589,11 +612,11 @@ static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev, pipe = usb_sndctrlpipe(usbdev, 0); cr = devm_kzalloc(&sc->hdev->dev, sizeof(*cr), GFP_ATOMIC); - if (cr == NULL) + if (!cr) return -ENOMEM; databuf = devm_kzalloc(&sc->hdev->dev, poke_size, GFP_ATOMIC); - if (databuf == NULL) + if (!databuf) return -ENOMEM; cr->bRequestType = @@ -610,6 +633,88 @@ static int ghl_init_urb(struct sony_sc *sc, struct usb_device *usbdev, return 0; } + + +/* + * Sending HID_REQ_SET_REPORT enables the full report. Without this + * Rock Band 3 Pro instruments only report navigation events + */ +static int rb3_pro_instrument_enable_full_report(struct sony_sc *sc) +{ + struct hid_device *hdev = sc->hdev; + static const u8 report[] = { 0x00, 0xE9, 0x00, 0x89, 0x1B, + 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x89, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xE9, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 }; + u8 *buf; + int ret; + + buf = kmemdup(report, sizeof(report), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), + HID_FEATURE_REPORT, HID_REQ_SET_REPORT); + + kfree(buf); + + return ret; +} + +static int djh_turntable_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) { + unsigned int abs = usage->hid & HID_USAGE; + + if (abs == TURNTABLE_CROSS_FADER_USAGE) { + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RX); + return 1; + } else if (abs == TURNTABLE_EFFECTS_KNOB_USAGE) { + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RY); + return 1; + } else if (abs == TURNTABLE_PLATTER_BUTTONS_USAGE) { + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, ABS_RZ); + return 1; + } + } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { + unsigned int abs = usage->hid & HID_USAGE; + + if (abs >= ARRAY_SIZE(ps3_turntable_absmap)) + return -1; + + abs = ps3_turntable_absmap[abs]; + + hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs); + return 1; + } + return 0; +} + +static int instrument_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { + unsigned int key = usage->hid & HID_USAGE; + + if (key >= ARRAY_SIZE(instrument_keymap)) + return 0; + + key = instrument_keymap[key]; + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); + return 1; + } + + return 0; +} + static int gh_guitar_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) @@ -629,16 +734,7 @@ static int rb4_guitar_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { - if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) { - unsigned int key = usage->hid & HID_USAGE; - - if (key >= ARRAY_SIZE(rb4_keymap)) - return 0; - - key = rb4_keymap[key]; - hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); - return 1; - } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { + if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) { unsigned int abs = usage->hid & HID_USAGE; /* Let the HID parser deal with the HAT. */ @@ -855,6 +951,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) static const u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; unsigned long flags; int offset; + u8 index; u8 battery_capacity; int battery_status; @@ -870,7 +967,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, u8 *rd, int size) battery_capacity = 100; battery_status = (rd[offset] & 0x01) ? POWER_SUPPLY_STATUS_FULL : POWER_SUPPLY_STATUS_CHARGING; } else { - u8 index = rd[offset] <= 5 ? rd[offset] : 5; + index = rd[offset] <= 5 ? rd[offset] : 5; battery_capacity = sixaxis_battery_capacity[index]; battery_status = POWER_SUPPLY_STATUS_DISCHARGING; } @@ -908,7 +1005,7 @@ static void nsg_mrxu_parse_report(struct sony_sc *sc, u8 *rd, int size) * the touch-related data starts at offset 2. * For the first byte, bit 0 is set when touchpad button is pressed. * Bit 2 is set when a touch is active and the drag (Fn) key is pressed. - * This drag key is mapped to BTN_LEFT. It is operational only when a + * This drag key is mapped to BTN_LEFT. It is operational only when a * touch point is active. * Bit 4 is set when only the first touch point is active. * Bit 6 is set when only the second touch point is active. @@ -991,6 +1088,12 @@ static void rb4_ps4_guitar_parse_report(struct sony_sc *sc, u8 *rd, int size) static void rb4_ps5_guitar_parse_report(struct sony_sc *sc, u8 *rd, int size) { + u8 charging_status; + u8 battery_data; + u8 battery_capacity; + u8 battery_status; + unsigned long flags; + /* * Rock Band 4 PS5 guitars have whammy and * tilt functionality, they're located at @@ -1003,6 +1106,37 @@ static void rb4_ps5_guitar_parse_report(struct sony_sc *sc, u8 *rd, int size) input_report_abs(sc->input_dev, ABS_Z, rd[41]); input_report_abs(sc->input_dev, ABS_RZ, rd[42]); + /* + * Rock Band 4 PS5 guitars also report the + * battery status and level at byte 30. + */ + charging_status = (rd[30] >> 4) & 0x0F; + battery_data = rd[30] & 0x0F; + + switch (charging_status) { + case 0x0: + battery_capacity = min(battery_data * 10 + 5, 100); + battery_status = POWER_SUPPLY_STATUS_DISCHARGING; + break; + case 0x1: + battery_capacity = min(battery_data * 10 + 5, 100); + battery_status = POWER_SUPPLY_STATUS_CHARGING; + break; + case 0x2: + battery_capacity = 100; + battery_status = POWER_SUPPLY_STATUS_FULL; + break; + default: + battery_capacity = 0; + battery_status = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + + spin_lock_irqsave(&sc->lock, flags); + sc->battery_capacity = battery_capacity; + sc->battery_status = battery_status; + spin_unlock_irqrestore(&sc->lock, flags); + input_sync(sc->input_dev); } @@ -1052,6 +1186,17 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, return 1; } + /* Rock Band 3 PS3 Pro instruments set rd[24] to 0xE0 when they're + * sending full reports, and 0x02 when only sending navigation. + */ + if ((sc->quirks & RB3_PRO_INSTRUMENT) && rd[24] == 0x02) { + /* Only attempt to enable full report every 8 seconds */ + if (time_after(jiffies, sc->rb3_pro_poke_jiffies)) { + sc->rb3_pro_poke_jiffies = jiffies + secs_to_jiffies(8); + rb3_pro_instrument_enable_full_report(sc); + } + } + if (sc->defer_initialization) { sc->defer_initialization = 0; sony_schedule_work(sc, SONY_WORKER_STATE); @@ -1065,6 +1210,7 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, unsigned long **bit, int *max) { struct sony_sc *sc = hid_get_drvdata(hdev); + int ret; if (sc->quirks & BUZZ_CONTROLLER) { unsigned int key = usage->hid & HID_USAGE; @@ -1098,9 +1244,19 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, if (sc->quirks & SIXAXIS_CONTROLLER) return sixaxis_mapping(hdev, hi, field, usage, bit, max); - if (sc->quirks & GH_GUITAR_CONTROLLER) + /* INSTRUMENT quirk is used as a base mapping for instruments */ + if (sc->quirks & INSTRUMENT) { + ret = instrument_mapping(hdev, hi, field, usage, bit, max); + if (ret != 0) + return ret; + } + + if (sc->quirks & GH_GUITAR_TILT) return gh_guitar_mapping(hdev, hi, field, usage, bit, max); + if (sc->quirks & DJH_TURNTABLE) + return djh_turntable_mapping(hdev, hi, field, usage, bit, max); + if (sc->quirks & (RB4_GUITAR_PS4_USB | RB4_GUITAR_PS4_BT)) return rb4_guitar_mapping(hdev, hi, field, usage, bit, max); @@ -1153,19 +1309,18 @@ static int sony_register_touchpad(struct sony_sc *sc, int touch_count, input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0); if (touch_major > 0) { - input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MAJOR, + input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MAJOR, 0, touch_major, 0, 0); if (touch_minor > 0) - input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MINOR, + input_set_abs_params(sc->touchpad, ABS_MT_TOUCH_MINOR, 0, touch_minor, 0, 0); if (orientation > 0) - input_set_abs_params(sc->touchpad, ABS_MT_ORIENTATION, + input_set_abs_params(sc->touchpad, ABS_MT_ORIENTATION, 0, orientation, 0, 0); } - if (sc->quirks & NSG_MRXU_REMOTE) { + if (sc->quirks & NSG_MRXU_REMOTE) __set_bit(EV_REL, sc->touchpad->evbit); - } ret = input_mt_init_slots(sc->touchpad, touch_count, INPUT_MT_POINTER); if (ret < 0) @@ -1320,7 +1475,7 @@ static void sixaxis_set_leds_from_id(struct sony_sc *sc) int id = sc->device_id; - BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); + BUILD_BUG_ON(ARRAY_SIZE(sixaxis_leds[0]) > MAX_LEDS); if (id < 0) return; @@ -1338,7 +1493,7 @@ static void buzz_set_leds(struct sony_sc *sc) struct hid_report, list); s32 *value = report->field[0]->value; - BUILD_BUG_ON(MAX_LEDS < 4); + BUILD_BUG_ON(4 > MAX_LEDS); value[0] = 0x00; value[1] = sc->led_state[0] ? 0xff : 0x00; @@ -1535,15 +1690,12 @@ static int sony_leds_init(struct sony_sc *sc) name_sz = strlen(dev_name(&hdev->dev)) + strlen(color_name_str[n]) + 2; led = devm_kzalloc(&hdev->dev, sizeof(struct led_classdev) + name_sz, GFP_KERNEL); - if (!led) { - hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); + if (!led) return -ENOMEM; - } name = (void *)(&led[1]); if (use_color_names) - snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), - color_name_str[n]); + snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), color_name_str[n]); else snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); led->name = name; @@ -2060,6 +2212,19 @@ static int sony_input_configured(struct hid_device *hdev, } sony_init_output_report(sc, sixaxis_send_output_report); + } else if (sc->quirks & RB3_PRO_INSTRUMENT) { + /* + * Rock Band 3 PS3 Pro Instruments also do not handle HID Output + * Reports on the interrupt EP like they should, so we need to force + * HID output reports to use HID_REQ_SET_REPORT on the Control EP. + * + * There is also another issue about HID Output Reports via USB, + * these instruments do not want the report_id as part of the data + * packet, so we have to discard buf[0] when sending the actual + * control message, even for numbered reports. + */ + hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; + hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { /* * The Sony Sixaxis does not handle HID Output Reports on the @@ -2176,10 +2341,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) quirks |= SHANWAN_GAMEPAD; sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); - if (sc == NULL) { - hid_err(hdev, "can't alloc sony descriptor\n"); + if (!sc) return -ENOMEM; - } spin_lock_init(&sc->lock); @@ -2227,6 +2390,9 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err; } + if (sc->quirks & RB3_PRO_INSTRUMENT) + sc->rb3_pro_poke_jiffies = 0; + if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { if (!hid_is_usb(hdev)) { ret = -EINVAL; @@ -2364,35 +2530,82 @@ static const struct hid_device_id sony_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_NSG_MR7U_REMOTE), .driver_data = NSG_MR7U_REMOTE_BT }, /* Guitar Hero Live PS3 and Wii U guitar dongles */ - { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE_DONGLE), - .driver_data = GHL_GUITAR_PS3WIIU | GH_GUITAR_CONTROLLER }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3WIIU_GHLIVE), + .driver_data = GHL_GUITAR_PS3WIIU | GH_GUITAR_TILT | INSTRUMENT }, /* Guitar Hero PC 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 }, + .driver_data = GH_GUITAR_TILT | INSTRUMENT }, + /* Guitar Hero PS3 Guitar Dongle */ + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GH_GUITAR), + .driver_data = GH_GUITAR_TILT | INSTRUMENT }, + /* Guitar Hero PS3 Drum Dongle */ + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_GH_DRUMS), + .driver_data = INSTRUMENT }, + /* DJ Hero PS3 Guitar Dongle */ + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_DJH_TURNTABLE), + .driver_data = DJH_TURNTABLE | INSTRUMENT }, /* 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 }, + .driver_data = GHL_GUITAR_PS4 | GH_GUITAR_TILT | INSTRUMENT }, + /* Rock Band 1 Wii instruments */ + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB1_GUITAR), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB1_DRUMS), + .driver_data = INSTRUMENT }, + /* Rock Band 2 Wii instruments */ + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB2_GUITAR), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB2_DRUMS), + .driver_data = INSTRUMENT }, + /* Rock Band 3 Wii instruments */ + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_DRUMS_MODE), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MUSTANG_GUITAR), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_MUSTANG_MODE), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_SQUIER_MODE), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_KEYBOARD), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_HARMONIX, USB_DEVICE_ID_HARMONIX_WII_RB3_MPA_KEYBOARD_MODE), + .driver_data = INSTRUMENT }, + /* Rock Band 3 PS3 instruments */ + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB_GUITAR), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB_DRUMS), + .driver_data = INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_DRUMS_MODE), + .driver_data = INSTRUMENT }, + /* Rock Band 3 PS3 Pro instruments */ + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MUSTANG_GUITAR), + .driver_data = INSTRUMENT | RB3_PRO_INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_MUSTANG_MODE), + .driver_data = INSTRUMENT | RB3_PRO_INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_SQUIER_MODE), + .driver_data = INSTRUMENT | RB3_PRO_INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_KEYBOARD), + .driver_data = INSTRUMENT | RB3_PRO_INSTRUMENT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY_RHYTHM, USB_DEVICE_ID_SONY_PS3_RB3_MPA_KEYBOARD_MODE), + .driver_data = INSTRUMENT | RB3_PRO_INSTRUMENT }, /* Rock Band 4 PS4 guitars */ { HID_USB_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS4_RIFFMASTER), - .driver_data = RB4_GUITAR_PS4_USB }, + .driver_data = RB4_GUITAR_PS4_USB | INSTRUMENT }, { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS4_GIBSON_SG), - .driver_data = RB4_GUITAR_PS4_USB }, + .driver_data = RB4_GUITAR_PS4_USB | INSTRUMENT }, { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS4_GIBSON_SG_DONGLE), - .driver_data = RB4_GUITAR_PS4_USB }, + .driver_data = RB4_GUITAR_PS4_USB | INSTRUMENT }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS4_JAGUAR), - .driver_data = RB4_GUITAR_PS4_BT }, + .driver_data = RB4_GUITAR_PS4_BT | INSTRUMENT }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_PS4_STRATOCASTER), - .driver_data = RB4_GUITAR_PS4_BT }, + .driver_data = RB4_GUITAR_PS4_BT | INSTRUMENT }, /* Rock Band 4 PS5 guitars */ { HID_USB_DEVICE(USB_VENDOR_ID_PDP, USB_DEVICE_ID_PDP_PS5_RIFFMASTER), - .driver_data = RB4_GUITAR_PS5 }, + .driver_data = RB4_GUITAR_PS5 | INSTRUMENT }, { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS5_GIBSON_SG), - .driver_data = RB4_GUITAR_PS5 }, + .driver_data = RB4_GUITAR_PS5 | INSTRUMENT }, { HID_USB_DEVICE(USB_VENDOR_ID_CRKD, USB_DEVICE_ID_CRKD_PS5_GIBSON_SG_DONGLE), - .driver_data = RB4_GUITAR_PS5 }, + .driver_data = RB4_GUITAR_PS5 | INSTRUMENT }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); @@ -2428,5 +2641,5 @@ static void __exit sony_exit(void) module_init(sony_init); module_exit(sony_exit); -MODULE_DESCRIPTION("HID driver for Sony / PS2 / PS3 / PS4 BD devices"); +MODULE_DESCRIPTION("HID driver for Sony / PS2 / PS3 BD / PS4 / PS5 devices"); MODULE_LICENSE("GPL");