Commit ccf1e162 authored by Roderick Colenbrander's avatar Roderick Colenbrander Committed by Jiri Kosina
Browse files

HID: playstation: sanity check DualSense calibration data.



Make sure calibration values are defined to prevent potential kernel
crashes. This fixes a hypothetical issue for virtual or clone devices
inspired by a similar fix for DS4.

Signed-off-by: default avatarRoderick Colenbrander <roderick.colenbrander@sony.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 74cb485f
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -944,6 +944,7 @@ ATTRIBUTE_GROUPS(ps_device);

static int dualsense_get_calibration_data(struct dualsense *ds)
{
	struct hid_device *hdev = ds->base.hdev;
	short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
	short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
	short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
@@ -954,6 +955,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
	int speed_2x;
	int range_2g;
	int ret = 0;
	int i;
	uint8_t *buf;

	buf = kzalloc(DS_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
@@ -1005,6 +1007,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
	ds->gyro_calib_data[2].sens_numer = speed_2x*DS_GYRO_RES_PER_DEG_S;
	ds->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(ds->gyro_calib_data); i++) {
		if (ds->gyro_calib_data[i].sens_denom == 0) {
			hid_warn(hdev, "Invalid gyro calibration data for axis (%d), disabling calibration.",
					ds->gyro_calib_data[i].abs_code);
			ds->gyro_calib_data[i].bias = 0;
			ds->gyro_calib_data[i].sens_numer = DS_GYRO_RANGE;
			ds->gyro_calib_data[i].sens_denom = S16_MAX;
		}
	}

	/*
	 * Set accelerometer calibration and normalization parameters.
	 * Data values will be normalized to 1/DS_ACC_RES_PER_G g.
@@ -1027,6 +1044,21 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
	ds->accel_calib_data[2].sens_numer = 2*DS_ACC_RES_PER_G;
	ds->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(ds->accel_calib_data); i++) {
		if (ds->accel_calib_data[i].sens_denom == 0) {
			hid_warn(hdev, "Invalid accelerometer calibration data for axis (%d), disabling calibration.",
					ds->accel_calib_data[i].abs_code);
			ds->accel_calib_data[i].bias = 0;
			ds->accel_calib_data[i].sens_numer = DS_ACC_RANGE;
			ds->accel_calib_data[i].sens_denom = S16_MAX;
		}
	}

err_free:
	kfree(buf);
	return ret;