Skip to content

Commit 947992c

Browse files
Max StaudtJiri Kosina
authored andcommitted
HID: playstation: DS4: Fix calibration workaround for clone devices
The logic in dualshock4_get_calibration_data() used uninitialised data in case of a failed kzalloc() for the transfer buffer. The solution is to group all business logic and all sanity checks together, and jump only to the latter in case of an error. While we're at it, factor out the axes' labelling, since it must happen either way for input_report_abs() to succeed later on. Thanks to Dan Carpenter for the Smatch static checker warning. Fixes: a48a7cd ("HID: playstation: DS4: Don't fail on calibration data request") Signed-off-by: Max Staudt <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 8f607e0 commit 947992c

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

drivers/hid/hid-playstation.c

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
17871787
buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
17881788
if (!buf) {
17891789
ret = -ENOMEM;
1790-
goto no_buffer_tail_check;
1790+
goto transfer_failed;
17911791
}
17921792

17931793
/* We should normally receive the feature report data we asked
@@ -1807,6 +1807,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18071807

18081808
hid_warn(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
18091809
ret = -EILSEQ;
1810+
goto transfer_failed;
18101811
} else {
18111812
break;
18121813
}
@@ -1815,17 +1816,19 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18151816
buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, GFP_KERNEL);
18161817
if (!buf) {
18171818
ret = -ENOMEM;
1818-
goto no_buffer_tail_check;
1819+
goto transfer_failed;
18191820
}
18201821

18211822
ret = ps_get_report(hdev, DS4_FEATURE_REPORT_CALIBRATION_BT, buf,
18221823
DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, true);
18231824

1824-
if (ret)
1825+
if (ret) {
18251826
hid_warn(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
1827+
goto transfer_failed;
1828+
}
18261829
}
18271830

1828-
/* Parse buffer. If the transfer failed, this safely copies zeroes. */
1831+
/* Transfer succeeded - parse the calibration data received. */
18291832
gyro_pitch_bias = get_unaligned_le16(&buf[1]);
18301833
gyro_yaw_bias = get_unaligned_le16(&buf[3]);
18311834
gyro_roll_bias = get_unaligned_le16(&buf[5]);
@@ -1854,6 +1857,9 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18541857
acc_z_plus = get_unaligned_le16(&buf[31]);
18551858
acc_z_minus = get_unaligned_le16(&buf[33]);
18561859

1860+
/* Done parsing the buffer, so let's free it. */
1861+
kfree(buf);
1862+
18571863
/*
18581864
* Set gyroscope calibration and normalization parameters.
18591865
* Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s.
@@ -1877,26 +1883,6 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
18771883
ds4->gyro_calib_data[2].sens_denom = abs(gyro_roll_plus - gyro_roll_bias) +
18781884
abs(gyro_roll_minus - gyro_roll_bias);
18791885

1880-
/* Done parsing the buffer, so let's free it. */
1881-
kfree(buf);
1882-
1883-
no_buffer_tail_check:
1884-
1885-
/*
1886-
* Sanity check gyro calibration data. This is needed to prevent crashes
1887-
* during report handling of virtual, clone or broken devices not implementing
1888-
* calibration data properly.
1889-
*/
1890-
for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
1891-
if (ds4->gyro_calib_data[i].sens_denom == 0) {
1892-
hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
1893-
ds4->gyro_calib_data[i].abs_code);
1894-
ds4->gyro_calib_data[i].bias = 0;
1895-
ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
1896-
ds4->gyro_calib_data[i].sens_denom = S16_MAX;
1897-
}
1898-
}
1899-
19001886
/*
19011887
* Set accelerometer calibration and normalization parameters.
19021888
* Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
@@ -1919,13 +1905,31 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
19191905
ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
19201906
ds4->accel_calib_data[2].sens_denom = range_2g;
19211907

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+
19221925
/*
19231926
* Sanity check accelerometer calibration data. This is needed to prevent crashes
19241927
* during report handling of virtual, clone or broken devices not implementing calibration
19251928
* data properly.
19261929
*/
19271930
for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
19281931
if (ds4->accel_calib_data[i].sens_denom == 0) {
1932+
ds4->accel_calib_data[i].abs_code = ABS_X + i;
19291933
hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
19301934
ds4->accel_calib_data[i].abs_code);
19311935
ds4->accel_calib_data[i].bias = 0;

0 commit comments

Comments
 (0)