@@ -27,6 +27,11 @@ static DEFINE_IDA(ps_player_id_allocator);
2727
2828#define HID_PLAYSTATION_VERSION_PATCH 0x8000
2929
30+ enum PS_TYPE {
31+ PS_TYPE_PS4_DUALSHOCK4 ,
32+ PS_TYPE_PS5_DUALSENSE ,
33+ };
34+
3035/* Base class for playstation devices. */
3136struct ps_device {
3237 struct list_head list ;
@@ -287,6 +292,8 @@ struct dualsense_output_report {
287292
288293#define DS4_INPUT_REPORT_USB 0x01
289294#define DS4_INPUT_REPORT_USB_SIZE 64
295+ #define DS4_INPUT_REPORT_BT_MINIMAL 0x01
296+ #define DS4_INPUT_REPORT_BT_MINIMAL_SIZE 10
290297#define DS4_INPUT_REPORT_BT 0x11
291298#define DS4_INPUT_REPORT_BT_SIZE 78
292299#define DS4_OUTPUT_REPORT_USB 0x05
@@ -1778,8 +1785,10 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
17781785 int retries ;
17791786
17801787 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+ }
17831792
17841793 /* We should normally receive the feature report data we asked
17851794 * for, but hidraw applications such as Steam can issue feature
@@ -1796,26 +1805,30 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
17961805 continue ;
17971806 }
17981807
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 );
18001809 ret = - EILSEQ ;
1801- goto err_free ;
1810+ goto transfer_failed ;
18021811 } else {
18031812 break ;
18041813 }
18051814 }
18061815 } else { /* Bluetooth */
18071816 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+ }
18101821
18111822 ret = ps_get_report (hdev , DS4_FEATURE_REPORT_CALIBRATION_BT , buf ,
18121823 DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE , true);
1824+
18131825 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 ;
18161828 }
18171829 }
18181830
1831+ /* Transfer succeeded - parse the calibration data received. */
18191832 gyro_pitch_bias = get_unaligned_le16 (& buf [1 ]);
18201833 gyro_yaw_bias = get_unaligned_le16 (& buf [3 ]);
18211834 gyro_roll_bias = get_unaligned_le16 (& buf [5 ]);
@@ -1844,6 +1857,9 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18441857 acc_z_plus = get_unaligned_le16 (& buf [31 ]);
18451858 acc_z_minus = get_unaligned_le16 (& buf [33 ]);
18461859
1860+ /* Done parsing the buffer, so let's free it. */
1861+ kfree (buf );
1862+
18471863 /*
18481864 * Set gyroscope calibration and normalization parameters.
18491865 * 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)
18671883 ds4 -> gyro_calib_data [2 ].sens_denom = abs (gyro_roll_plus - gyro_roll_bias ) +
18681884 abs (gyro_roll_minus - gyro_roll_bias );
18691885
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-
18851886 /*
18861887 * Set accelerometer calibration and normalization parameters.
18871888 * 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)
19041905 ds4 -> accel_calib_data [2 ].sens_numer = 2 * DS4_ACC_RES_PER_G ;
19051906 ds4 -> accel_calib_data [2 ].sens_denom = range_2g ;
19061907
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+
19071925 /*
19081926 * Sanity check accelerometer calibration data. This is needed to prevent crashes
19091927 * during report handling of virtual, clone or broken devices not implementing calibration
19101928 * data properly.
19111929 */
19121930 for (i = 0 ; i < ARRAY_SIZE (ds4 -> accel_calib_data ); i ++ ) {
19131931 if (ds4 -> accel_calib_data [i ].sens_denom == 0 ) {
1932+ ds4 -> accel_calib_data [i ].abs_code = ABS_X + i ;
19141933 hid_warn (hdev , "Invalid accelerometer calibration data for axis (%d), disabling calibration." ,
19151934 ds4 -> accel_calib_data [i ].abs_code );
19161935 ds4 -> accel_calib_data [i ].bias = 0 ;
@@ -1919,8 +1938,6 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
19191938 }
19201939 }
19211940
1922- err_free :
1923- kfree (buf );
19241941 return ret ;
19251942}
19261943
@@ -2037,8 +2054,9 @@ static int dualshock4_led_set_blink(struct led_classdev *led, unsigned long *del
20372054
20382055 dualshock4_schedule_work (ds4 );
20392056
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 ;
20422060
20432061 return 0 ;
20442062}
@@ -2065,6 +2083,13 @@ static int dualshock4_led_set_brightness(struct led_classdev *led, enum led_brig
20652083 break ;
20662084 case 3 :
20672085 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+ }
20682093 }
20692094
20702095 ds4 -> update_lightbar = true;
@@ -2182,6 +2207,7 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
21822207 int battery_status , i , j ;
21832208 uint16_t sensor_timestamp ;
21842209 unsigned long flags ;
2210+ bool is_minimal = false;
21852211
21862212 /*
21872213 * 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 *
22092235 ds4_report = & bt -> common ;
22102236 num_touch_reports = bt -> num_touch_reports ;
22112237 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;
22122250 } else {
22132251 hid_err (hdev , "Unhandled reportID=%d\n" , report -> id );
22142252 return -1 ;
@@ -2242,6 +2280,9 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *
22422280 input_report_key (ds4 -> gamepad , BTN_MODE , ds4_report -> buttons [2 ] & DS_BUTTONS2_PS_HOME );
22432281 input_sync (ds4 -> gamepad );
22442282
2283+ if (is_minimal )
2284+ return 0 ;
2285+
22452286 /* Parse and calibrate gyroscope data. */
22462287 for (i = 0 ; i < ARRAY_SIZE (ds4_report -> gyro ); i ++ ) {
22472288 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)
25502591
25512592 ret = dualshock4_get_firmware_info (ds4 );
25522593 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" );
25552596 }
25562597
25572598 ret = ps_devices_list_add (ps_dev );
@@ -2560,8 +2601,8 @@ static struct ps_device *dualshock4_create(struct hid_device *hdev)
25602601
25612602 ret = dualshock4_get_calibration_data (ds4 );
25622603 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" ) ;
25652606 }
25662607
25672608 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)
26552696 goto err_stop ;
26562697 }
26572698
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 ) {
26612700 dev = dualshock4_create (hdev );
26622701 if (IS_ERR (dev )) {
26632702 hid_err (hdev , "Failed to create dualshock4.\n" );
26642703 ret = PTR_ERR (dev );
26652704 goto err_close ;
26662705 }
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 ) {
26692707 dev = dualsense_create (hdev );
26702708 if (IS_ERR (dev )) {
26712709 hid_err (hdev , "Failed to create dualsense.\n" );
@@ -2699,16 +2737,26 @@ static void ps_remove(struct hid_device *hdev)
26992737
27002738static const struct hid_device_id ps_devices [] = {
27012739 /* 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+
27072751 /* 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 },
27122760 { }
27132761};
27142762MODULE_DEVICE_TABLE (hid , ps_devices );
0 commit comments