@@ -27,6 +27,11 @@ static DEFINE_IDA(ps_player_id_allocator);
27
27
28
28
#define HID_PLAYSTATION_VERSION_PATCH 0x8000
29
29
30
+ enum PS_TYPE {
31
+ PS_TYPE_PS4_DUALSHOCK4 ,
32
+ PS_TYPE_PS5_DUALSENSE ,
33
+ };
34
+
30
35
/* Base class for playstation devices. */
31
36
struct ps_device {
32
37
struct list_head list ;
@@ -287,6 +292,8 @@ struct dualsense_output_report {
287
292
288
293
#define DS4_INPUT_REPORT_USB 0x01
289
294
#define DS4_INPUT_REPORT_USB_SIZE 64
295
+ #define DS4_INPUT_REPORT_BT_MINIMAL 0x01
296
+ #define DS4_INPUT_REPORT_BT_MINIMAL_SIZE 10
290
297
#define DS4_INPUT_REPORT_BT 0x11
291
298
#define DS4_INPUT_REPORT_BT_SIZE 78
292
299
#define DS4_OUTPUT_REPORT_USB 0x05
@@ -1778,8 +1785,10 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
1778
1785
int retries ;
1779
1786
1780
1787
buf = kzalloc (DS4_FEATURE_REPORT_CALIBRATION_SIZE , GFP_KERNEL );
1781
- if (!buf )
1782
- return - ENOMEM ;
1788
+ if (!buf ) {
1789
+ ret = - ENOMEM ;
1790
+ goto transfer_failed ;
1791
+ }
1783
1792
1784
1793
/* We should normally receive the feature report data we asked
1785
1794
* for, but hidraw applications such as Steam can issue feature
@@ -1796,26 +1805,30 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
1796
1805
continue ;
1797
1806
}
1798
1807
1799
- hid_err (hdev , "Failed to retrieve DualShock4 calibration info: %d\n" , ret );
1808
+ hid_warn (hdev , "Failed to retrieve DualShock4 calibration info: %d\n" , ret );
1800
1809
ret = - EILSEQ ;
1801
- goto err_free ;
1810
+ goto transfer_failed ;
1802
1811
} else {
1803
1812
break ;
1804
1813
}
1805
1814
}
1806
1815
} else { /* Bluetooth */
1807
1816
buf = kzalloc (DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE , GFP_KERNEL );
1808
- if (!buf )
1809
- return - ENOMEM ;
1817
+ if (!buf ) {
1818
+ ret = - ENOMEM ;
1819
+ goto transfer_failed ;
1820
+ }
1810
1821
1811
1822
ret = ps_get_report (hdev , DS4_FEATURE_REPORT_CALIBRATION_BT , buf ,
1812
1823
DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE , true);
1824
+
1813
1825
if (ret ) {
1814
- hid_err (hdev , "Failed to retrieve DualShock4 calibration info: %d\n" , ret );
1815
- goto err_free ;
1826
+ hid_warn (hdev , "Failed to retrieve DualShock4 calibration info: %d\n" , ret );
1827
+ goto transfer_failed ;
1816
1828
}
1817
1829
}
1818
1830
1831
+ /* Transfer succeeded - parse the calibration data received. */
1819
1832
gyro_pitch_bias = get_unaligned_le16 (& buf [1 ]);
1820
1833
gyro_yaw_bias = get_unaligned_le16 (& buf [3 ]);
1821
1834
gyro_roll_bias = get_unaligned_le16 (& buf [5 ]);
@@ -1844,6 +1857,9 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
1844
1857
acc_z_plus = get_unaligned_le16 (& buf [31 ]);
1845
1858
acc_z_minus = get_unaligned_le16 (& buf [33 ]);
1846
1859
1860
+ /* Done parsing the buffer, so let's free it. */
1861
+ kfree (buf );
1862
+
1847
1863
/*
1848
1864
* Set gyroscope calibration and normalization parameters.
1849
1865
* Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s.
@@ -1867,21 +1883,6 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
1867
1883
ds4 -> gyro_calib_data [2 ].sens_denom = abs (gyro_roll_plus - gyro_roll_bias ) +
1868
1884
abs (gyro_roll_minus - gyro_roll_bias );
1869
1885
1870
- /*
1871
- * Sanity check gyro calibration data. This is needed to prevent crashes
1872
- * during report handling of virtual, clone or broken devices not implementing
1873
- * calibration data properly.
1874
- */
1875
- for (i = 0 ; i < ARRAY_SIZE (ds4 -> gyro_calib_data ); i ++ ) {
1876
- if (ds4 -> gyro_calib_data [i ].sens_denom == 0 ) {
1877
- hid_warn (hdev , "Invalid gyro calibration data for axis (%d), disabling calibration." ,
1878
- ds4 -> gyro_calib_data [i ].abs_code );
1879
- ds4 -> gyro_calib_data [i ].bias = 0 ;
1880
- ds4 -> gyro_calib_data [i ].sens_numer = DS4_GYRO_RANGE ;
1881
- ds4 -> gyro_calib_data [i ].sens_denom = S16_MAX ;
1882
- }
1883
- }
1884
-
1885
1886
/*
1886
1887
* Set accelerometer calibration and normalization parameters.
1887
1888
* Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
@@ -1904,13 +1905,31 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
1904
1905
ds4 -> accel_calib_data [2 ].sens_numer = 2 * DS4_ACC_RES_PER_G ;
1905
1906
ds4 -> accel_calib_data [2 ].sens_denom = range_2g ;
1906
1907
1908
+ transfer_failed :
1909
+ /*
1910
+ * Sanity check gyro calibration data. This is needed to prevent crashes
1911
+ * during report handling of virtual, clone or broken devices not implementing
1912
+ * calibration data properly.
1913
+ */
1914
+ for (i = 0 ; i < ARRAY_SIZE (ds4 -> gyro_calib_data ); i ++ ) {
1915
+ if (ds4 -> gyro_calib_data [i ].sens_denom == 0 ) {
1916
+ ds4 -> gyro_calib_data [i ].abs_code = ABS_RX + i ;
1917
+ hid_warn (hdev , "Invalid gyro calibration data for axis (%d), disabling calibration." ,
1918
+ ds4 -> gyro_calib_data [i ].abs_code );
1919
+ ds4 -> gyro_calib_data [i ].bias = 0 ;
1920
+ ds4 -> gyro_calib_data [i ].sens_numer = DS4_GYRO_RANGE ;
1921
+ ds4 -> gyro_calib_data [i ].sens_denom = S16_MAX ;
1922
+ }
1923
+ }
1924
+
1907
1925
/*
1908
1926
* Sanity check accelerometer calibration data. This is needed to prevent crashes
1909
1927
* during report handling of virtual, clone or broken devices not implementing calibration
1910
1928
* data properly.
1911
1929
*/
1912
1930
for (i = 0 ; i < ARRAY_SIZE (ds4 -> accel_calib_data ); i ++ ) {
1913
1931
if (ds4 -> accel_calib_data [i ].sens_denom == 0 ) {
1932
+ ds4 -> accel_calib_data [i ].abs_code = ABS_X + i ;
1914
1933
hid_warn (hdev , "Invalid accelerometer calibration data for axis (%d), disabling calibration." ,
1915
1934
ds4 -> accel_calib_data [i ].abs_code );
1916
1935
ds4 -> accel_calib_data [i ].bias = 0 ;
@@ -1919,8 +1938,6 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
1919
1938
}
1920
1939
}
1921
1940
1922
- err_free :
1923
- kfree (buf );
1924
1941
return ret ;
1925
1942
}
1926
1943
@@ -2037,8 +2054,9 @@ static int dualshock4_led_set_blink(struct led_classdev *led, unsigned long *del
2037
2054
2038
2055
dualshock4_schedule_work (ds4 );
2039
2056
2040
- * delay_on = ds4 -> lightbar_blink_on ;
2041
- * delay_off = ds4 -> lightbar_blink_off ;
2057
+ /* Report scaled values back to LED subsystem */
2058
+ * delay_on = ds4 -> lightbar_blink_on * 10 ;
2059
+ * delay_off = ds4 -> lightbar_blink_off * 10 ;
2042
2060
2043
2061
return 0 ;
2044
2062
}
@@ -2065,6 +2083,13 @@ static int dualshock4_led_set_brightness(struct led_classdev *led, enum led_brig
2065
2083
break ;
2066
2084
case 3 :
2067
2085
ds4 -> lightbar_enabled = !!value ;
2086
+
2087
+ /* brightness = 0 also cancels blinking in Linux. */
2088
+ if (!ds4 -> lightbar_enabled ) {
2089
+ ds4 -> lightbar_blink_off = 0 ;
2090
+ ds4 -> lightbar_blink_on = 0 ;
2091
+ ds4 -> update_lightbar_blink = true;
2092
+ }
2068
2093
}
2069
2094
2070
2095
ds4 -> update_lightbar = true;
@@ -2182,6 +2207,7 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
2182
2207
int battery_status , i , j ;
2183
2208
uint16_t sensor_timestamp ;
2184
2209
unsigned long flags ;
2210
+ bool is_minimal = false;
2185
2211
2186
2212
/*
2187
2213
* DualShock4 in USB uses the full HID report for reportID 1, but
@@ -2209,6 +2235,18 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
2209
2235
ds4_report = & bt -> common ;
2210
2236
num_touch_reports = bt -> num_touch_reports ;
2211
2237
touch_reports = bt -> touch_reports ;
2238
+ } else if (hdev -> bus == BUS_BLUETOOTH &&
2239
+ report -> id == DS4_INPUT_REPORT_BT_MINIMAL &&
2240
+ size == DS4_INPUT_REPORT_BT_MINIMAL_SIZE ) {
2241
+ /* Some third-party pads never switch to the full 0x11 report.
2242
+ * The short 0x01 report is 10 bytes long:
2243
+ * u8 report_id == 0x01
2244
+ * u8 first_bytes_of_full_report[9]
2245
+ * So let's reuse the full report parser, and stop it after
2246
+ * parsing the buttons.
2247
+ */
2248
+ ds4_report = (struct dualshock4_input_report_common * )& data [1 ];
2249
+ is_minimal = true;
2212
2250
} else {
2213
2251
hid_err (hdev , "Unhandled reportID=%d\n" , report -> id );
2214
2252
return -1 ;
@@ -2242,6 +2280,9 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
2242
2280
input_report_key (ds4 -> gamepad , BTN_MODE , ds4_report -> buttons [2 ] & DS_BUTTONS2_PS_HOME );
2243
2281
input_sync (ds4 -> gamepad );
2244
2282
2283
+ if (is_minimal )
2284
+ return 0 ;
2285
+
2245
2286
/* Parse and calibrate gyroscope data. */
2246
2287
for (i = 0 ; i < ARRAY_SIZE (ds4_report -> gyro ); i ++ ) {
2247
2288
int raw_data = (short )le16_to_cpu (ds4_report -> gyro [i ]);
@@ -2550,8 +2591,8 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
2550
2591
2551
2592
ret = dualshock4_get_firmware_info (ds4 );
2552
2593
if (ret ) {
2553
- hid_err (hdev , "Failed to get firmware info from DualShock4\n" );
2554
- return ERR_PTR ( ret );
2594
+ hid_warn (hdev , "Failed to get firmware info from DualShock4\n" );
2595
+ hid_warn ( hdev , "HW/FW version data in sysfs will be invalid.\n" );
2555
2596
}
2556
2597
2557
2598
ret = ps_devices_list_add (ps_dev );
@@ -2560,8 +2601,8 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
2560
2601
2561
2602
ret = dualshock4_get_calibration_data (ds4 );
2562
2603
if (ret ) {
2563
- hid_err (hdev , "Failed to get calibration data from DualShock4\n" );
2564
- goto err ;
2604
+ hid_warn (hdev , "Failed to get calibration data from DualShock4\n" );
2605
+ hid_warn ( hdev , "Gyroscope and accelerometer will be inaccurate.\n" ) ;
2565
2606
}
2566
2607
2567
2608
ds4 -> gamepad = ps_gamepad_create (hdev , dualshock4_play_effect );
@@ -2655,17 +2696,14 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
2655
2696
goto err_stop ;
2656
2697
}
2657
2698
2658
- if (hdev -> product == USB_DEVICE_ID_SONY_PS4_CONTROLLER ||
2659
- hdev -> product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ||
2660
- hdev -> product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE ) {
2699
+ if (id -> driver_data == PS_TYPE_PS4_DUALSHOCK4 ) {
2661
2700
dev = dualshock4_create (hdev );
2662
2701
if (IS_ERR (dev )) {
2663
2702
hid_err (hdev , "Failed to create dualshock4.\n" );
2664
2703
ret = PTR_ERR (dev );
2665
2704
goto err_close ;
2666
2705
}
2667
- } else if (hdev -> product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
2668
- hdev -> product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 ) {
2706
+ } else if (id -> driver_data == PS_TYPE_PS5_DUALSENSE ) {
2669
2707
dev = dualsense_create (hdev );
2670
2708
if (IS_ERR (dev )) {
2671
2709
hid_err (hdev , "Failed to create dualsense.\n" );
@@ -2699,16 +2737,26 @@ static void ps_remove(struct hid_device *hdev)
2699
2737
2700
2738
static const struct hid_device_id ps_devices [] = {
2701
2739
/* Sony DualShock 4 controllers for PS4 */
2702
- { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER ) },
2703
- { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER ) },
2704
- { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ) },
2705
- { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ) },
2706
- { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE ) },
2740
+ { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER ),
2741
+ .driver_data = PS_TYPE_PS4_DUALSHOCK4 },
2742
+ { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER ),
2743
+ .driver_data = PS_TYPE_PS4_DUALSHOCK4 },
2744
+ { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ),
2745
+ .driver_data = PS_TYPE_PS4_DUALSHOCK4 },
2746
+ { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ),
2747
+ .driver_data = PS_TYPE_PS4_DUALSHOCK4 },
2748
+ { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE ),
2749
+ .driver_data = PS_TYPE_PS4_DUALSHOCK4 },
2750
+
2707
2751
/* Sony DualSense controllers for PS5 */
2708
- { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER ) },
2709
- { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER ) },
2710
- { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 ) },
2711
- { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 ) },
2752
+ { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER ),
2753
+ .driver_data = PS_TYPE_PS5_DUALSENSE },
2754
+ { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER ),
2755
+ .driver_data = PS_TYPE_PS5_DUALSENSE },
2756
+ { HID_BLUETOOTH_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 ),
2757
+ .driver_data = PS_TYPE_PS5_DUALSENSE },
2758
+ { HID_USB_DEVICE (USB_VENDOR_ID_SONY , USB_DEVICE_ID_SONY_PS5_CONTROLLER_2 ),
2759
+ .driver_data = PS_TYPE_PS5_DUALSENSE },
2712
2760
{ }
2713
2761
};
2714
2762
MODULE_DEVICE_TABLE (hid , ps_devices );
0 commit comments