Commit 74cb485f authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Jiri Kosina

HID: playstation: sanity check DualShock4 calibration data.

Some DualShock4 devices report invalid calibration data resulting
in kernel oopses due to division by zero during report handling.

The devices affected generally appear to be clone devices, which don't
implement all reports properly and don't populate proper calibration
data. The issue may have been seen on an official device with erased
calibration reports.

This patch prevents the crashes by essentially disabling calibration
when invalid values are detected.
Signed-off-by: default avatarRoderick Colenbrander <roderick.colenbrander@sony.com>
Tested-by: default avatarAlain Carlucci <alain.carlucci@gmail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent febb2c0d
...@@ -1737,6 +1737,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ...@@ -1737,6 +1737,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
int speed_2x; int speed_2x;
int range_2g; int range_2g;
int ret = 0; int ret = 0;
int i;
uint8_t *buf; uint8_t *buf;
if (ds4->base.hdev->bus == BUS_USB) { if (ds4->base.hdev->bus == BUS_USB) {
...@@ -1830,6 +1831,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ...@@ -1830,6 +1831,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S; ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus; ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
/*
* Sanity check gyro calibration data. This is needed to prevent crashes
* during report handling of virtual, clone or broken devices not implementing
* calibration data properly.
*/
for (i = 0; i < ARRAY_SIZE(ds4->gyro_calib_data); i++) {
if (ds4->gyro_calib_data[i].sens_denom == 0) {
hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
ds4->gyro_calib_data[i].abs_code);
ds4->gyro_calib_data[i].bias = 0;
ds4->gyro_calib_data[i].sens_numer = DS4_GYRO_RANGE;
ds4->gyro_calib_data[i].sens_denom = S16_MAX;
}
}
/* /*
* Set accelerometer calibration and normalization parameters. * Set accelerometer calibration and normalization parameters.
* Data values will be normalized to 1/DS4_ACC_RES_PER_G g. * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
...@@ -1852,6 +1868,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4) ...@@ -1852,6 +1868,21 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G; ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
ds4->accel_calib_data[2].sens_denom = range_2g; ds4->accel_calib_data[2].sens_denom = range_2g;
/*
* Sanity check accelerometer calibration data. This is needed to prevent crashes
* during report handling of virtual, clone or broken devices not implementing calibration
* data properly.
*/
for (i = 0; i < ARRAY_SIZE(ds4->accel_calib_data); i++) {
if (ds4->accel_calib_data[i].sens_denom == 0) {
hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
ds4->accel_calib_data[i].abs_code);
ds4->accel_calib_data[i].bias = 0;
ds4->accel_calib_data[i].sens_numer = DS4_ACC_RANGE;
ds4->accel_calib_data[i].sens_denom = S16_MAX;
}
}
err_free: err_free:
kfree(buf); kfree(buf);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment