@@ -46,6 +46,7 @@ struct ps_device {
46
46
uint32_t fw_version ;
47
47
48
48
int (* parse_report )(struct ps_device * dev , struct hid_report * report , u8 * data , int size );
49
+ void (* remove )(struct ps_device * dev );
49
50
};
50
51
51
52
/* Calibration data for playstation motion sensors. */
@@ -107,6 +108,9 @@ struct ps_led_info {
107
108
#define DS_STATUS_CHARGING GENMASK(7, 4)
108
109
#define DS_STATUS_CHARGING_SHIFT 4
109
110
111
+ /* Feature version from DualSense Firmware Info report. */
112
+ #define DS_FEATURE_VERSION (major , minor ) ((major & 0xff) << 8 | (minor & 0xff))
113
+
110
114
/*
111
115
* Status of a DualSense touch point contact.
112
116
* Contact IDs, with highest bit set are 'inactive'
@@ -125,6 +129,7 @@ struct ps_led_info {
125
129
#define DS_OUTPUT_VALID_FLAG1_RELEASE_LEDS BIT(3)
126
130
#define DS_OUTPUT_VALID_FLAG1_PLAYER_INDICATOR_CONTROL_ENABLE BIT(4)
127
131
#define DS_OUTPUT_VALID_FLAG2_LIGHTBAR_SETUP_CONTROL_ENABLE BIT(1)
132
+ #define DS_OUTPUT_VALID_FLAG2_COMPATIBLE_VIBRATION2 BIT(2)
128
133
#define DS_OUTPUT_POWER_SAVE_CONTROL_MIC_MUTE BIT(4)
129
134
#define DS_OUTPUT_LIGHTBAR_SETUP_LIGHT_OUT BIT(1)
130
135
@@ -142,6 +147,9 @@ struct dualsense {
142
147
struct input_dev * sensors ;
143
148
struct input_dev * touchpad ;
144
149
150
+ /* Update version is used as a feature/capability version. */
151
+ uint16_t update_version ;
152
+
145
153
/* Calibration data for accelerometer and gyroscope. */
146
154
struct ps_calibration_data accel_calib_data [3 ];
147
155
struct ps_calibration_data gyro_calib_data [3 ];
@@ -152,6 +160,7 @@ struct dualsense {
152
160
uint32_t sensor_timestamp_us ;
153
161
154
162
/* Compatible rumble state */
163
+ bool use_vibration_v2 ;
155
164
bool update_rumble ;
156
165
uint8_t motor_left ;
157
166
uint8_t motor_right ;
@@ -174,6 +183,7 @@ struct dualsense {
174
183
struct led_classdev player_leds [5 ];
175
184
176
185
struct work_struct output_worker ;
186
+ bool output_worker_initialized ;
177
187
void * output_report_dmabuf ;
178
188
uint8_t output_seq ; /* Sequence number for output report. */
179
189
};
@@ -299,6 +309,7 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
299
309
{0 , 0 },
300
310
};
301
311
312
+ static inline void dualsense_schedule_work (struct dualsense * ds );
302
313
static void dualsense_set_lightbar (struct dualsense * ds , uint8_t red , uint8_t green , uint8_t blue );
303
314
304
315
/*
@@ -789,6 +800,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
789
800
return ret ;
790
801
}
791
802
803
+
792
804
static int dualsense_get_firmware_info (struct dualsense * ds )
793
805
{
794
806
uint8_t * buf ;
@@ -808,6 +820,15 @@ static int dualsense_get_firmware_info(struct dualsense *ds)
808
820
ds -> base .hw_version = get_unaligned_le32 (& buf [24 ]);
809
821
ds -> base .fw_version = get_unaligned_le32 (& buf [28 ]);
810
822
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
+
811
832
err_free :
812
833
kfree (buf );
813
834
return ret ;
@@ -878,7 +899,7 @@ static int dualsense_player_led_set_brightness(struct led_classdev *led, enum le
878
899
ds -> update_player_leds = true;
879
900
spin_unlock_irqrestore (& ds -> base .lock , flags );
880
901
881
- schedule_work ( & ds -> output_worker );
902
+ dualsense_schedule_work ( ds );
882
903
883
904
return 0 ;
884
905
}
@@ -922,6 +943,16 @@ static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_
922
943
}
923
944
}
924
945
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
+
925
956
/*
926
957
* Helper function to send DualSense output reports. Applies a CRC at the end of a report
927
958
* for Bluetooth reports.
@@ -960,7 +991,10 @@ static void dualsense_output_worker(struct work_struct *work)
960
991
if (ds -> update_rumble ) {
961
992
/* Select classic rumble style haptics and enable it. */
962
993
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 ;
964
998
common -> motor_left = ds -> motor_left ;
965
999
common -> motor_right = ds -> motor_right ;
966
1000
ds -> update_rumble = false;
@@ -1082,7 +1116,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
1082
1116
spin_unlock_irqrestore (& ps_dev -> lock , flags );
1083
1117
1084
1118
/* Schedule updating of microphone state at hardware level. */
1085
- schedule_work ( & ds -> output_worker );
1119
+ dualsense_schedule_work ( ds );
1086
1120
}
1087
1121
ds -> last_btn_mic_state = btn_mic_state ;
1088
1122
@@ -1197,10 +1231,22 @@ static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_ef
1197
1231
ds -> motor_right = effect -> u .rumble .weak_magnitude / 256 ;
1198
1232
spin_unlock_irqrestore (& ds -> base .lock , flags );
1199
1233
1200
- schedule_work ( & ds -> output_worker );
1234
+ dualsense_schedule_work ( ds );
1201
1235
return 0 ;
1202
1236
}
1203
1237
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
+
1204
1250
static int dualsense_reset_leds (struct dualsense * ds )
1205
1251
{
1206
1252
struct dualsense_output_report report ;
@@ -1237,7 +1283,7 @@ static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t gr
1237
1283
ds -> lightbar_blue = blue ;
1238
1284
spin_unlock_irqrestore (& ds -> base .lock , flags );
1239
1285
1240
- schedule_work ( & ds -> output_worker );
1286
+ dualsense_schedule_work ( ds );
1241
1287
}
1242
1288
1243
1289
static void dualsense_set_player_leds (struct dualsense * ds )
@@ -1260,7 +1306,7 @@ static void dualsense_set_player_leds(struct dualsense *ds)
1260
1306
1261
1307
ds -> update_player_leds = true;
1262
1308
ds -> player_leds_state = player_ids [player_id ];
1263
- schedule_work ( & ds -> output_worker );
1309
+ dualsense_schedule_work ( ds );
1264
1310
}
1265
1311
1266
1312
static struct ps_device * dualsense_create (struct hid_device * hdev )
@@ -1299,7 +1345,9 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
1299
1345
ps_dev -> battery_capacity = 100 ; /* initial value until parse_report. */
1300
1346
ps_dev -> battery_status = POWER_SUPPLY_STATUS_UNKNOWN ;
1301
1347
ps_dev -> parse_report = dualsense_parse_report ;
1348
+ ps_dev -> remove = dualsense_remove ;
1302
1349
INIT_WORK (& ds -> output_worker , dualsense_output_worker );
1350
+ ds -> output_worker_initialized = true;
1303
1351
hid_set_drvdata (hdev , ds );
1304
1352
1305
1353
max_output_report_size = sizeof (struct dualsense_output_report_bt );
@@ -1320,6 +1368,21 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
1320
1368
return ERR_PTR (ret );
1321
1369
}
1322
1370
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
+
1323
1386
ret = ps_devices_list_add (ps_dev );
1324
1387
if (ret )
1325
1388
return ERR_PTR (ret );
@@ -1436,7 +1499,8 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
1436
1499
goto err_stop ;
1437
1500
}
1438
1501
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 ) {
1440
1504
dev = dualsense_create (hdev );
1441
1505
if (IS_ERR (dev )) {
1442
1506
hid_err (hdev , "Failed to create dualsense.\n" );
@@ -1461,13 +1525,18 @@ static void ps_remove(struct hid_device *hdev)
1461
1525
ps_devices_list_remove (dev );
1462
1526
ps_device_release_player_id (dev );
1463
1527
1528
+ if (dev -> remove )
1529
+ dev -> remove (dev );
1530
+
1464
1531
hid_hw_close (hdev );
1465
1532
hid_hw_stop (hdev );
1466
1533
}
1467
1534
1468
1535
static const struct hid_device_id ps_devices [] = {
1469
1536
{ HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER ) },
1470
1537
{ 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 ) },
1471
1540
{ }
1472
1541
};
1473
1542
MODULE_DEVICE_TABLE (hid , ps_devices );
0 commit comments