Hello,
Today I connected a partially broken DS4 via USB and got a kernel
panic with a division by zero in the hid-sony driver.
The issue is caused by sens_denom=0 in the sensor calibration data,
which triggers a division by zero when dualshock4_parse_report() is
invoked, the division happens in the mult_frac() macro.
This patch applies a workaround that allows the DS4 to be used even
with a broken sensor: if the denominator sent by the device is zero,
it is replaced with 1 and a warning is emitted.
Signed-off-by: Alain Carlucci <alain.carlucci@xxxxxxxxx>
---
drivers/hid/hid-sony.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 13125997a..f8b05cb29 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -1714,6 +1714,7 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc)
short acc_z_plus, acc_z_minus;
int speed_2x;
int range_2g;
+ int calib_id;
/* For Bluetooth we use a different request, which supports CRC.
* Note: in Bluetooth mode feature report 0x02 also changes the state
@@ -1858,6 +1859,23 @@ static int dualshock4_get_calibration_data(struct sony_sc *sc)
sc->ds4_calib_data[5].sens_numer = 2*DS4_ACC_RES_PER_G;
sc->ds4_calib_data[5].sens_denom = range_2g;
+ for (calib_id = 0; calib_id < 6; calib_id++) {
+ /* Ensure there are no denominators equal to zero to prevent
+ * crashes while dividing by that number.
+ */
+
+ if (sc->ds4_calib_data[calib_id].sens_denom != 0) {
+ /* Denominator OK, skip this */
+ continue;
+ }
+
+ sc->ds4_calib_data[calib_id].sens_denom = 1;
+
+ hid_warn(sc->hdev,
+ "DualShock 4 USB dongle: invalid calibration for sensor %d\n",
+ calib_id);
+ }
+
err_stop:
kfree(buf);
return ret;
--
2.39.0