@@ -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. */
@@ -174,6 +175,7 @@ struct dualsense {
174
175
struct led_classdev player_leds [5 ];
175
176
176
177
struct work_struct output_worker ;
178
+ bool output_worker_initialized ;
177
179
void * output_report_dmabuf ;
178
180
uint8_t output_seq ; /* Sequence number for output report. */
179
181
};
@@ -299,6 +301,7 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
299
301
{0 , 0 },
300
302
};
301
303
304
+ static inline void dualsense_schedule_work (struct dualsense * ds );
302
305
static void dualsense_set_lightbar (struct dualsense * ds , uint8_t red , uint8_t green , uint8_t blue );
303
306
304
307
/*
@@ -789,6 +792,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
789
792
return ret ;
790
793
}
791
794
795
+
792
796
static int dualsense_get_firmware_info (struct dualsense * ds )
793
797
{
794
798
uint8_t * buf ;
@@ -878,7 +882,7 @@ static int dualsense_player_led_set_brightness(struct led_classdev *led, enum le
878
882
ds -> update_player_leds = true;
879
883
spin_unlock_irqrestore (& ds -> base .lock , flags );
880
884
881
- schedule_work ( & ds -> output_worker );
885
+ dualsense_schedule_work ( ds );
882
886
883
887
return 0 ;
884
888
}
@@ -922,6 +926,16 @@ static void dualsense_init_output_report(struct dualsense *ds, struct dualsense_
922
926
}
923
927
}
924
928
929
+ static inline void dualsense_schedule_work (struct dualsense * ds )
930
+ {
931
+ unsigned long flags ;
932
+
933
+ spin_lock_irqsave (& ds -> base .lock , flags );
934
+ if (ds -> output_worker_initialized )
935
+ schedule_work (& ds -> output_worker );
936
+ spin_unlock_irqrestore (& ds -> base .lock , flags );
937
+ }
938
+
925
939
/*
926
940
* Helper function to send DualSense output reports. Applies a CRC at the end of a report
927
941
* for Bluetooth reports.
@@ -1082,7 +1096,7 @@ static int dualsense_parse_report(struct ps_device *ps_dev, struct hid_report *r
1082
1096
spin_unlock_irqrestore (& ps_dev -> lock , flags );
1083
1097
1084
1098
/* Schedule updating of microphone state at hardware level. */
1085
- schedule_work ( & ds -> output_worker );
1099
+ dualsense_schedule_work ( ds );
1086
1100
}
1087
1101
ds -> last_btn_mic_state = btn_mic_state ;
1088
1102
@@ -1197,10 +1211,22 @@ static int dualsense_play_effect(struct input_dev *dev, void *data, struct ff_ef
1197
1211
ds -> motor_right = effect -> u .rumble .weak_magnitude / 256 ;
1198
1212
spin_unlock_irqrestore (& ds -> base .lock , flags );
1199
1213
1200
- schedule_work ( & ds -> output_worker );
1214
+ dualsense_schedule_work ( ds );
1201
1215
return 0 ;
1202
1216
}
1203
1217
1218
+ static void dualsense_remove (struct ps_device * ps_dev )
1219
+ {
1220
+ struct dualsense * ds = container_of (ps_dev , struct dualsense , base );
1221
+ unsigned long flags ;
1222
+
1223
+ spin_lock_irqsave (& ds -> base .lock , flags );
1224
+ ds -> output_worker_initialized = false;
1225
+ spin_unlock_irqrestore (& ds -> base .lock , flags );
1226
+
1227
+ cancel_work_sync (& ds -> output_worker );
1228
+ }
1229
+
1204
1230
static int dualsense_reset_leds (struct dualsense * ds )
1205
1231
{
1206
1232
struct dualsense_output_report report ;
@@ -1237,7 +1263,7 @@ static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t gr
1237
1263
ds -> lightbar_blue = blue ;
1238
1264
spin_unlock_irqrestore (& ds -> base .lock , flags );
1239
1265
1240
- schedule_work ( & ds -> output_worker );
1266
+ dualsense_schedule_work ( ds );
1241
1267
}
1242
1268
1243
1269
static void dualsense_set_player_leds (struct dualsense * ds )
@@ -1260,7 +1286,7 @@ static void dualsense_set_player_leds(struct dualsense *ds)
1260
1286
1261
1287
ds -> update_player_leds = true;
1262
1288
ds -> player_leds_state = player_ids [player_id ];
1263
- schedule_work ( & ds -> output_worker );
1289
+ dualsense_schedule_work ( ds );
1264
1290
}
1265
1291
1266
1292
static struct ps_device * dualsense_create (struct hid_device * hdev )
@@ -1299,7 +1325,9 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
1299
1325
ps_dev -> battery_capacity = 100 ; /* initial value until parse_report. */
1300
1326
ps_dev -> battery_status = POWER_SUPPLY_STATUS_UNKNOWN ;
1301
1327
ps_dev -> parse_report = dualsense_parse_report ;
1328
+ ps_dev -> remove = dualsense_remove ;
1302
1329
INIT_WORK (& ds -> output_worker , dualsense_output_worker );
1330
+ ds -> output_worker_initialized = true;
1303
1331
hid_set_drvdata (hdev , ds );
1304
1332
1305
1333
max_output_report_size = sizeof (struct dualsense_output_report_bt );
@@ -1461,6 +1489,9 @@ static void ps_remove(struct hid_device *hdev)
1461
1489
ps_devices_list_remove (dev );
1462
1490
ps_device_release_player_id (dev );
1463
1491
1492
+ if (dev -> remove )
1493
+ dev -> remove (dev );
1494
+
1464
1495
hid_hw_close (hdev );
1465
1496
hid_hw_stop (hdev );
1466
1497
}
0 commit comments