Skip to content

Commit 334fe5d

Browse files
committed
Merge tag 'for-linus-2022102101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Benjamin Tissoires: - a 12 year old bug fix for the Apple Magic Trackpad v1 (José Expósito) - a fix for a potential crash on removal of the Playstation controllers (Roderick Colenbrander) - a few new device IDs and device-specific quirks, most notably support of the new Playstation DualSense Edge controller * tag 'for-linus-2022102101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: lenovo: Make array tp10ubkbd_led static const HID: saitek: add madcatz variant of MMO7 mouse device ID HID: playstation: support updated DualSense rumble mode. HID: playstation: add initial DualSense Edge controller support HID: playstation: stop DualSense output work on remove. HID: magicmouse: Do not set BTN_MOUSE on double report
2 parents bd8e963 + e66928a commit 334fe5d

File tree

6 files changed

+83
-9
lines changed

6 files changed

+83
-9
lines changed

drivers/hid/hid-ids.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@
867867
#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
868868
#define USB_DEVICE_ID_MADCATZ_RAT5 0x1705
869869
#define USB_DEVICE_ID_MADCATZ_RAT9 0x1709
870+
#define USB_DEVICE_ID_MADCATZ_MMO7 0x1713
870871

871872
#define USB_VENDOR_ID_MCC 0x09db
872873
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
@@ -1142,6 +1143,7 @@
11421143
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc
11431144
#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0
11441145
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER 0x0ce6
1146+
#define USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 0x0df2
11451147
#define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5
11461148
#define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f
11471149
#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002

drivers/hid/hid-lenovo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev,
985985
struct device *dev = led_cdev->dev->parent;
986986
struct hid_device *hdev = to_hid_device(dev);
987987
struct lenovo_drvdata *data_pointer = hid_get_drvdata(hdev);
988-
u8 tp10ubkbd_led[] = { TP10UBKBD_MUTE_LED, TP10UBKBD_MICMUTE_LED };
988+
static const u8 tp10ubkbd_led[] = { TP10UBKBD_MUTE_LED, TP10UBKBD_MICMUTE_LED };
989989
int led_nr = 0;
990990
int ret = 0;
991991

drivers/hid/hid-magicmouse.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ static int magicmouse_raw_event(struct hid_device *hdev,
480480
magicmouse_raw_event(hdev, report, data + 2, data[1]);
481481
magicmouse_raw_event(hdev, report, data + 2 + data[1],
482482
size - 2 - data[1]);
483-
break;
483+
return 0;
484484
default:
485485
return 0;
486486
}

drivers/hid/hid-playstation.c

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct ps_device {
4646
uint32_t fw_version;
4747

4848
int (*parse_report)(struct ps_device *dev, struct hid_report *report, u8 *data, int size);
49+
void (*remove)(struct ps_device *dev);
4950
};
5051

5152
/* Calibration data for playstation motion sensors. */
@@ -107,6 +108,9 @@ struct ps_led_info {
107108
#define DS_STATUS_CHARGING GENMASK(7, 4)
108109
#define DS_STATUS_CHARGING_SHIFT 4
109110

111+
/* Feature version from DualSense Firmware Info report. */
112+
#define DS_FEATURE_VERSION(major, minor) ((major & 0xff) << 8 | (minor & 0xff))
113+
110114
/*
111115
* Status of a DualSense touch point contact.
112116
* Contact IDs, with highest bit set are 'inactive'
@@ -125,6 +129,7 @@ struct ps_led_info {
125129
#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
126130
#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
127131
#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
132+
#define DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 BIT(2)
128133
#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
129134
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
130135

@@ -142,6 +147,9 @@ struct dualsense {
142147
struct input_dev *sensors;
143148
struct input_dev *touchpad;
144149

150+
/* Update version is used as a feature/capability version. */
151+
uint16_t update_version;
152+
145153
/* Calibration data for accelerometer and gyroscope. */
146154
struct ps_calibration_data accel_calib_data[3];
147155
struct ps_calibration_data gyro_calib_data[3];
@@ -152,6 +160,7 @@ struct dualsense {
152160
uint32_t sensor_timestamp_us;
153161

154162
/* Compatible rumble state */
163+
bool use_vibration_v2;
155164
bool update_rumble;
156165
uint8_t motor_left;
157166
uint8_t motor_right;
@@ -174,6 +183,7 @@ struct dualsense {
174183
struct led_classdev player_leds[5];
175184

176185
struct work_struct output_worker;
186+
bool output_worker_initialized;
177187
void *output_report_dmabuf;
178188
uint8_t output_seq; /* Sequence number for output report. */
179189
};
@@ -299,6 +309,7 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
299309
{0, 0},
300310
};
301311

312+
static inline void dualsense_schedule_work(struct dualsense *ds);
302313
static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue);
303314

304315
/*
@@ -789,6 +800,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
789800
return ret;
790801
}
791802

803+
792804
static int dualsense_get_firmware_info(struct dualsense *ds)
793805
{
794806
uint8_t *buf;
@@ -808,6 +820,15 @@ static int dualsense_get_firmware_info(struct dualsense *ds)
808820
ds->base.hw_version = get_unaligned_le32(&buf[24]);
809821
ds->base.fw_version = get_unaligned_le32(&buf[28]);
810822

823+
/* Update version is some kind of feature version. It is distinct from
824+
* the firmware version as there can be many different variations of a
825+
* controller over time with the same physical shell, but with different
826+
* PCBs and other internal changes. The update version (internal name) is
827+
* used as a means to detect what features are available and change behavior.
828+
* Note: the version is different between DualSense and DualSense Edge.
829+
*/
830+
ds->update_version = get_unaligned_le16(&buf[44]);
831+
811832
err_free:
812833
kfree(buf);
813834
return ret;
@@ -878,7 +899,7 @@ static int dualsense_player_led_set_brightness(struct led_classdev *led, enum le
878899
ds->update_player_leds = true;
879900
spin_unlock_irqrestore(&ds->base.lock, flags);
880901

881-
schedule_work(&ds->output_worker);
902+
dualsense_schedule_work(ds);
882903

883904
return 0;
884905
}
@@ -922,6 +943,16 @@ static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_
922943
}
923944
}
924945

946+
static inline void dualsense_schedule_work(struct dualsense *ds)
947+
{
948+
unsigned long flags;
949+
950+
spin_lock_irqsave(&ds->base.lock, flags);
951+
if (ds->output_worker_initialized)
952+
schedule_work(&ds->output_worker);
953+
spin_unlock_irqrestore(&ds->base.lock, flags);
954+
}
955+
925956
/*
926957
* Helper function to send DualSense output reports. Applies a CRC at the end of a report
927958
* for Bluetooth reports.
@@ -960,7 +991,10 @@ static void dualsense_output_worker(struct work_struct *work)
960991
if (ds->update_rumble) {
961992
/* Select classic rumble style haptics and enable it. */
962993
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_HAPTICS_SELECT;
963-
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
994+
if (ds->use_vibration_v2)
995+
common->valid_flag2 |= DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2;
996+
else
997+
common->valid_flag0 |= DS_OUTPUT_VALID_FLAG0_COMPATIBLE_VIBRATION;
964998
common->motor_left = ds->motor_left;
965999
common->motor_right = ds->motor_right;
9661000
ds->update_rumble = false;
@@ -1082,7 +1116,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
10821116
spin_unlock_irqrestore(&ps_dev->lock, flags);
10831117

10841118
/* Schedule updating of microphone state at hardware level. */
1085-
schedule_work(&ds->output_worker);
1119+
dualsense_schedule_work(ds);
10861120
}
10871121
ds->last_btn_mic_state = btn_mic_state;
10881122

@@ -1197,10 +1231,22 @@ static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_ef
11971231
ds->motor_right = effect->u.rumble.weak_magnitude / 256;
11981232
spin_unlock_irqrestore(&ds->base.lock, flags);
11991233

1200-
schedule_work(&ds->output_worker);
1234+
dualsense_schedule_work(ds);
12011235
return 0;
12021236
}
12031237

1238+
static void dualsense_remove(struct ps_device *ps_dev)
1239+
{
1240+
struct dualsense *ds = container_of(ps_dev, struct dualsense, base);
1241+
unsigned long flags;
1242+
1243+
spin_lock_irqsave(&ds->base.lock, flags);
1244+
ds->output_worker_initialized = false;
1245+
spin_unlock_irqrestore(&ds->base.lock, flags);
1246+
1247+
cancel_work_sync(&ds->output_worker);
1248+
}
1249+
12041250
static int dualsense_reset_leds(struct dualsense *ds)
12051251
{
12061252
struct dualsense_output_report report;
@@ -1237,7 +1283,7 @@ static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t gr
12371283
ds->lightbar_blue = blue;
12381284
spin_unlock_irqrestore(&ds->base.lock, flags);
12391285

1240-
schedule_work(&ds->output_worker);
1286+
dualsense_schedule_work(ds);
12411287
}
12421288

12431289
static void dualsense_set_player_leds(struct dualsense *ds)
@@ -1260,7 +1306,7 @@ static void dualsense_set_player_leds(struct dualsense *ds)
12601306

12611307
ds->update_player_leds = true;
12621308
ds->player_leds_state = player_ids[player_id];
1263-
schedule_work(&ds->output_worker);
1309+
dualsense_schedule_work(ds);
12641310
}
12651311

12661312
static struct ps_device *dualsense_create(struct hid_device *hdev)
@@ -1299,7 +1345,9 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
12991345
ps_dev->battery_capacity = 100; /* initial value until parse_report. */
13001346
ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
13011347
ps_dev->parse_report = dualsense_parse_report;
1348+
ps_dev->remove = dualsense_remove;
13021349
INIT_WORK(&ds->output_worker, dualsense_output_worker);
1350+
ds->output_worker_initialized = true;
13031351
hid_set_drvdata(hdev, ds);
13041352

13051353
max_output_report_size = sizeof(struct dualsense_output_report_bt);
@@ -1320,6 +1368,21 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
13201368
return ERR_PTR(ret);
13211369
}
13221370

1371+
/* Original DualSense firmware simulated classic controller rumble through
1372+
* its new haptics hardware. It felt different from classic rumble users
1373+
* were used to. Since then new firmwares were introduced to change behavior
1374+
* and make this new 'v2' behavior default on PlayStation and other platforms.
1375+
* The original DualSense requires a new enough firmware as bundled with PS5
1376+
* software released in 2021. DualSense edge supports it out of the box.
1377+
* Both devices also support the old mode, but it is not really used.
1378+
*/
1379+
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
1380+
/* Feature version 2.21 introduced new vibration method. */
1381+
ds->use_vibration_v2 = ds->update_version >= DS_FEATURE_VERSION(2, 21);
1382+
} else if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
1383+
ds->use_vibration_v2 = true;
1384+
}
1385+
13231386
ret = ps_devices_list_add(ps_dev);
13241387
if (ret)
13251388
return ERR_PTR(ret);
@@ -1436,7 +1499,8 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
14361499
goto err_stop;
14371500
}
14381501

1439-
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER) {
1502+
if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
1503+
hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
14401504
dev = dualsense_create(hdev);
14411505
if (IS_ERR(dev)) {
14421506
hid_err(hdev, "Failed to create dualsense.\n");
@@ -1461,13 +1525,18 @@ static void ps_remove(struct hid_device *hdev)
14611525
ps_devices_list_remove(dev);
14621526
ps_device_release_player_id(dev);
14631527

1528+
if (dev->remove)
1529+
dev->remove(dev);
1530+
14641531
hid_hw_close(hdev);
14651532
hid_hw_stop(hdev);
14661533
}
14671534

14681535
static const struct hid_device_id ps_devices[] = {
14691536
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
14701537
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
1538+
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
1539+
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
14711540
{ }
14721541
};
14731542
MODULE_DEVICE_TABLE(hid, ps_devices);

drivers/hid/hid-quirks.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
620620
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
621621
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
622622
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
623+
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_MMO7) },
623624
#endif
624625
#if IS_ENABLED(CONFIG_HID_SAMSUNG)
625626
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },

drivers/hid/hid-saitek.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@ static const struct hid_device_id saitek_devices[] = {
187187
.driver_data = SAITEK_RELEASE_MODE_RAT7 },
188188
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
189189
.driver_data = SAITEK_RELEASE_MODE_MMO7 },
190+
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_MMO7),
191+
.driver_data = SAITEK_RELEASE_MODE_MMO7 },
190192
{ }
191193
};
192194

0 commit comments

Comments
 (0)