Re: [PATCH v1] HID: playstation: DS4: Fix calibration workaround for clone devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Max,

Thanks for your patch. For readability, I would rather not move a lot
of the ABS_X/ABS_RX related initialization code around. It is not my
preference, but I think keeping the lines were they are, but doing
this within the 'fail safe loops' is nicer:

ds4->gyro_calib_data[i].abs_code = ABS_RX + i;

Thanks,
Roderick

On Sun, Apr 14, 2024 at 9:12 AM Max Staudt <max@xxxxxxxxx> wrote:
>
> 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: a48a7cd85f55 ("HID: playstation: DS4: Don't fail on calibration data request")
> Signed-off-by: Max Staudt <max@xxxxxxxxx>
> ---
>  drivers/hid/hid-playstation.c | 63 ++++++++++++++++++-----------------
>  1 file changed, 33 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
> index edc46fc02e9a..998e79be45ac 100644
> --- a/drivers/hid/hid-playstation.c
> +++ b/drivers/hid/hid-playstation.c
> @@ -1787,7 +1787,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
>                 buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
>                 if (!buf) {
>                         ret = -ENOMEM;
> -                       goto no_buffer_tail_check;
> +                       goto transfer_failed;
>                 }
>
>                 /* We should normally receive the feature report data we asked
> @@ -1807,6 +1807,7 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
>
>                                 hid_warn(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
>                                 ret = -EILSEQ;
> +                               goto transfer_failed;
>                         } else {
>                                 break;
>                         }
> @@ -1815,17 +1816,19 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
>                 buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, GFP_KERNEL);
>                 if (!buf) {
>                         ret = -ENOMEM;
> -                       goto no_buffer_tail_check;
> +                       goto transfer_failed;
>                 }
>
>                 ret = ps_get_report(hdev, DS4_FEATURE_REPORT_CALIBRATION_BT, buf,
>                                 DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, true);
>
> -               if (ret)
> +               if (ret) {
>                         hid_warn(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
> +                       goto transfer_failed;
> +               }
>         }
>
> -       /* Parse buffer. If the transfer failed, this safely copies zeroes. */
> +       /* Transfer succeeded - parse the calibration data received. */
>         gyro_pitch_bias  = get_unaligned_le16(&buf[1]);
>         gyro_yaw_bias    = get_unaligned_le16(&buf[3]);
>         gyro_roll_bias   = get_unaligned_le16(&buf[5]);
> @@ -1854,71 +1857,71 @@ static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
>         acc_z_plus       = get_unaligned_le16(&buf[31]);
>         acc_z_minus      = get_unaligned_le16(&buf[33]);
>
> +       /* Done parsing the buffer, so let's free it. */
> +       kfree(buf);
> +
>         /*
>          * Set gyroscope calibration and normalization parameters.
>          * Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s.
>          */
>         speed_2x = (gyro_speed_plus + gyro_speed_minus);
> -       ds4->gyro_calib_data[0].abs_code = ABS_RX;
>         ds4->gyro_calib_data[0].bias = 0;
>         ds4->gyro_calib_data[0].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
>         ds4->gyro_calib_data[0].sens_denom = abs(gyro_pitch_plus - gyro_pitch_bias) +
>                         abs(gyro_pitch_minus - gyro_pitch_bias);
>
> -       ds4->gyro_calib_data[1].abs_code = ABS_RY;
>         ds4->gyro_calib_data[1].bias = 0;
>         ds4->gyro_calib_data[1].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
>         ds4->gyro_calib_data[1].sens_denom = abs(gyro_yaw_plus - gyro_yaw_bias) +
>                         abs(gyro_yaw_minus - gyro_yaw_bias);
>
> -       ds4->gyro_calib_data[2].abs_code = ABS_RZ;
>         ds4->gyro_calib_data[2].bias = 0;
>         ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
>         ds4->gyro_calib_data[2].sens_denom = abs(gyro_roll_plus - gyro_roll_bias) +
>                         abs(gyro_roll_minus - gyro_roll_bias);
>
> -       /* Done parsing the buffer, so let's free it. */
> -       kfree(buf);
> -
> -no_buffer_tail_check:
> -
> -       /*
> -        * 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.
>          * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
>          */
>         range_2g = acc_x_plus - acc_x_minus;
> -       ds4->accel_calib_data[0].abs_code = ABS_X;
>         ds4->accel_calib_data[0].bias = acc_x_plus - range_2g / 2;
>         ds4->accel_calib_data[0].sens_numer = 2*DS4_ACC_RES_PER_G;
>         ds4->accel_calib_data[0].sens_denom = range_2g;
>
>         range_2g = acc_y_plus - acc_y_minus;
> -       ds4->accel_calib_data[1].abs_code = ABS_Y;
>         ds4->accel_calib_data[1].bias = acc_y_plus - range_2g / 2;
>         ds4->accel_calib_data[1].sens_numer = 2*DS4_ACC_RES_PER_G;
>         ds4->accel_calib_data[1].sens_denom = range_2g;
>
>         range_2g = acc_z_plus - acc_z_minus;
> -       ds4->accel_calib_data[2].abs_code = ABS_Z;
>         ds4->accel_calib_data[2].bias = acc_z_plus - range_2g / 2;
>         ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
>         ds4->accel_calib_data[2].sens_denom = range_2g;
>
> +transfer_failed:
> +       ds4->gyro_calib_data[0].abs_code = ABS_RX;
> +       ds4->gyro_calib_data[1].abs_code = ABS_RY;
> +       ds4->gyro_calib_data[2].abs_code = ABS_RZ;
> +       ds4->accel_calib_data[0].abs_code = ABS_X;
> +       ds4->accel_calib_data[1].abs_code = ABS_Y;
> +       ds4->accel_calib_data[2].abs_code = ABS_Z;
> +
> +       /*
> +        * 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;
> +               }
> +       }
> +
>         /*
>          * Sanity check accelerometer calibration data. This is needed to prevent crashes
>          * during report handling of virtual, clone or broken devices not implementing calibration
> --
> 2.39.2
>
>





[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux