@@ -285,6 +285,8 @@ struct dualsense_output_report {
285
285
286
286
#define DS4_INPUT_REPORT_USB 0x01
287
287
#define DS4_INPUT_REPORT_USB_SIZE 64
288
+ #define DS4_OUTPUT_REPORT_USB 0x05
289
+ #define DS4_OUTPUT_REPORT_USB_SIZE 32
288
290
289
291
#define DS4_FEATURE_REPORT_CALIBRATION 0x02
290
292
#define DS4_FEATURE_REPORT_CALIBRATION_SIZE 37
@@ -306,6 +308,9 @@ struct dualsense_output_report {
306
308
/* Battery status within batery_status field. */
307
309
#define DS4_BATTERY_STATUS_FULL 11
308
310
311
+ /* Flags for DualShock4 output report. */
312
+ #define DS4_OUTPUT_VALID_FLAG0_MOTOR 0x01
313
+
309
314
/* DualShock4 hardware limits */
310
315
#define DS4_ACC_RES_PER_G 8192
311
316
#define DS4_ACC_RANGE (4*DS_ACC_RES_PER_G)
@@ -328,6 +333,14 @@ struct dualshock4 {
328
333
bool sensor_timestamp_initialized ;
329
334
uint32_t prev_sensor_timestamp ;
330
335
uint32_t sensor_timestamp_us ;
336
+
337
+ bool update_rumble ;
338
+ uint8_t motor_left ;
339
+ uint8_t motor_right ;
340
+
341
+ struct work_struct output_worker ;
342
+ bool output_worker_initialized ;
343
+ void * output_report_dmabuf ;
331
344
};
332
345
333
346
struct dualshock4_touch_point {
@@ -372,6 +385,45 @@ struct dualshock4_input_report_usb {
372
385
} __packed ;
373
386
static_assert (sizeof (struct dualshock4_input_report_usb ) == DS4_INPUT_REPORT_USB_SIZE );
374
387
388
+ /* Common data between Bluetooth and USB DualShock4 output reports. */
389
+ struct dualshock4_output_report_common {
390
+ uint8_t valid_flag0 ;
391
+ uint8_t valid_flag1 ;
392
+
393
+ uint8_t reserved ;
394
+
395
+ uint8_t motor_right ;
396
+ uint8_t motor_left ;
397
+
398
+ uint8_t lightbar_red ;
399
+ uint8_t lightbar_green ;
400
+ uint8_t lightbar_blue ;
401
+ uint8_t lightbar_blink_on ;
402
+ uint8_t lightbar_blink_off ;
403
+ } __packed ;
404
+
405
+ struct dualshock4_output_report_usb {
406
+ uint8_t report_id ; /* 0x5 */
407
+ struct dualshock4_output_report_common common ;
408
+ uint8_t reserved [21 ];
409
+ } __packed ;
410
+ static_assert (sizeof (struct dualshock4_output_report_usb ) == DS4_OUTPUT_REPORT_USB_SIZE );
411
+
412
+ /*
413
+ * The DualShock4 has a main output report used to control most features. It is
414
+ * largely the same between Bluetooth and USB except for different headers and CRC.
415
+ * This structure hide the differences between the two to simplify sending output reports.
416
+ */
417
+ struct dualshock4_output_report {
418
+ uint8_t * data ; /* Start of data */
419
+ uint8_t len ; /* Size of output report */
420
+
421
+ /* Points to USB data payload in case for a USB report else NULL. */
422
+ struct dualshock4_output_report_usb * usb ;
423
+ /* Points to common section of report, so past any headers. */
424
+ struct dualshock4_output_report_common * common ;
425
+ };
426
+
375
427
/*
376
428
* Common gamepad buttons across DualShock 3 / 4 and DualSense.
377
429
* Note: for device with a touchpad, touchpad button is not included
@@ -399,6 +451,7 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
399
451
};
400
452
401
453
static inline void dualsense_schedule_work (struct dualsense * ds );
454
+ static inline void dualshock4_schedule_work (struct dualshock4 * ds4 );
402
455
static void dualsense_set_lightbar (struct dualsense * ds , uint8_t red , uint8_t green , uint8_t blue );
403
456
404
457
/*
@@ -1692,6 +1745,49 @@ static int dualshock4_get_mac_address(struct dualshock4 *ds4)
1692
1745
return ret ;
1693
1746
}
1694
1747
1748
+ static void dualshock4_init_output_report (struct dualshock4 * ds4 ,
1749
+ struct dualshock4_output_report * rp , void * buf )
1750
+ {
1751
+ struct hid_device * hdev = ds4 -> base .hdev ;
1752
+
1753
+ if (hdev -> bus == BUS_USB ) {
1754
+ struct dualshock4_output_report_usb * usb = buf ;
1755
+
1756
+ memset (usb , 0 , sizeof (* usb ));
1757
+ usb -> report_id = DS4_OUTPUT_REPORT_USB ;
1758
+
1759
+ rp -> data = buf ;
1760
+ rp -> len = sizeof (* usb );
1761
+ rp -> usb = usb ;
1762
+ rp -> common = & usb -> common ;
1763
+ }
1764
+ }
1765
+
1766
+ static void dualshock4_output_worker (struct work_struct * work )
1767
+ {
1768
+ struct dualshock4 * ds4 = container_of (work , struct dualshock4 , output_worker );
1769
+ struct dualshock4_output_report report ;
1770
+ struct dualshock4_output_report_common * common ;
1771
+ unsigned long flags ;
1772
+
1773
+ dualshock4_init_output_report (ds4 , & report , ds4 -> output_report_dmabuf );
1774
+ common = report .common ;
1775
+
1776
+ spin_lock_irqsave (& ds4 -> base .lock , flags );
1777
+
1778
+ if (ds4 -> update_rumble ) {
1779
+ /* Select classic rumble style haptics and enable it. */
1780
+ common -> valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_MOTOR ;
1781
+ common -> motor_left = ds4 -> motor_left ;
1782
+ common -> motor_right = ds4 -> motor_right ;
1783
+ ds4 -> update_rumble = false;
1784
+ }
1785
+
1786
+ spin_unlock_irqrestore (& ds4 -> base .lock , flags );
1787
+
1788
+ hid_hw_output_report (ds4 -> base .hdev , report .data , report .len );
1789
+ }
1790
+
1695
1791
static int dualshock4_parse_report (struct ps_device * ps_dev , struct hid_report * report ,
1696
1792
u8 * data , int size )
1697
1793
{
@@ -1860,10 +1956,52 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
1860
1956
return 0 ;
1861
1957
}
1862
1958
1959
+ static int dualshock4_play_effect (struct input_dev * dev , void * data , struct ff_effect * effect )
1960
+ {
1961
+ struct hid_device * hdev = input_get_drvdata (dev );
1962
+ struct dualshock4 * ds4 = hid_get_drvdata (hdev );
1963
+ unsigned long flags ;
1964
+
1965
+ if (effect -> type != FF_RUMBLE )
1966
+ return 0 ;
1967
+
1968
+ spin_lock_irqsave (& ds4 -> base .lock , flags );
1969
+ ds4 -> update_rumble = true;
1970
+ ds4 -> motor_left = effect -> u .rumble .strong_magnitude / 256 ;
1971
+ ds4 -> motor_right = effect -> u .rumble .weak_magnitude / 256 ;
1972
+ spin_unlock_irqrestore (& ds4 -> base .lock , flags );
1973
+
1974
+ dualshock4_schedule_work (ds4 );
1975
+ return 0 ;
1976
+ }
1977
+
1978
+ static void dualshock4_remove (struct ps_device * ps_dev )
1979
+ {
1980
+ struct dualshock4 * ds4 = container_of (ps_dev , struct dualshock4 , base );
1981
+ unsigned long flags ;
1982
+
1983
+ spin_lock_irqsave (& ds4 -> base .lock , flags );
1984
+ ds4 -> output_worker_initialized = false;
1985
+ spin_unlock_irqrestore (& ds4 -> base .lock , flags );
1986
+
1987
+ cancel_work_sync (& ds4 -> output_worker );
1988
+ }
1989
+
1990
+ static inline void dualshock4_schedule_work (struct dualshock4 * ds4 )
1991
+ {
1992
+ unsigned long flags ;
1993
+
1994
+ spin_lock_irqsave (& ds4 -> base .lock , flags );
1995
+ if (ds4 -> output_worker_initialized )
1996
+ schedule_work (& ds4 -> output_worker );
1997
+ spin_unlock_irqrestore (& ds4 -> base .lock , flags );
1998
+ }
1999
+
1863
2000
static struct ps_device * dualshock4_create (struct hid_device * hdev )
1864
2001
{
1865
2002
struct dualshock4 * ds4 ;
1866
2003
struct ps_device * ps_dev ;
2004
+ uint8_t max_output_report_size ;
1867
2005
int ret ;
1868
2006
1869
2007
ds4 = devm_kzalloc (& hdev -> dev , sizeof (* ds4 ), GFP_KERNEL );
@@ -1882,8 +2020,16 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
1882
2020
ps_dev -> battery_capacity = 100 ; /* initial value until parse_report. */
1883
2021
ps_dev -> battery_status = POWER_SUPPLY_STATUS_UNKNOWN ;
1884
2022
ps_dev -> parse_report = dualshock4_parse_report ;
2023
+ ps_dev -> remove = dualshock4_remove ;
2024
+ INIT_WORK (& ds4 -> output_worker , dualshock4_output_worker );
2025
+ ds4 -> output_worker_initialized = true;
1885
2026
hid_set_drvdata (hdev , ds4 );
1886
2027
2028
+ max_output_report_size = sizeof (struct dualshock4_output_report_usb );
2029
+ ds4 -> output_report_dmabuf = devm_kzalloc (& hdev -> dev , max_output_report_size , GFP_KERNEL );
2030
+ if (!ds4 -> output_report_dmabuf )
2031
+ return ERR_PTR (- ENOMEM );
2032
+
1887
2033
ret = dualshock4_get_mac_address (ds4 );
1888
2034
if (ret ) {
1889
2035
hid_err (hdev , "Failed to get MAC address from DualShock4\n" );
@@ -1907,7 +2053,7 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
1907
2053
goto err ;
1908
2054
}
1909
2055
1910
- ds4 -> gamepad = ps_gamepad_create (hdev , NULL );
2056
+ ds4 -> gamepad = ps_gamepad_create (hdev , dualshock4_play_effect );
1911
2057
if (IS_ERR (ds4 -> gamepad )) {
1912
2058
ret = PTR_ERR (ds4 -> gamepad );
1913
2059
goto err ;
0 commit comments