Re: [PATCH v4] HID: wacom: avoid divide exception in dropped-packet calculation

From: Jason Gerecke

Date: Fri Nov 06 2026 - 13:47:25 EST


On Fri, Nov 6, 2026 at 4:04 AM Aldo Ariel Panzardo <qwe.aldo@xxxxxxxxx> wrote:
>
> The dropped-packet calculation uses a modulo against sequence_size
> (logical_maximum - logical_minimum + 1). When a HID descriptor
> declares a sequence field whose logical range spans all 32-bit
> values, sequence_size wraps to zero and the modulo triggers a
> divide exception.
>
> Replace the division-based calculation with a branch that computes
> the forward distance through the sequence range directly, as
> suggested by Jason Gerecke. This keeps the existing int types and
> avoids the divide-by-zero without any 64-bit arithmetic.
>
> Fixes: 359673ea3a20 ("HID: wacom: Support sequence numbers smaller than 16-bit")
> Cc: stable@xxxxxxxxxxxxxxx
> Suggested-by: Jason Gerecke <jason.gerecke@xxxxxxxxx>
> Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@xxxxxxxxx>

Much happier with this version! Thanks!!

Reviewed-by: Jason Gerecke <jason.gerecke@xxxxxxxxx>

Jason (she/they)
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....

> ---
>
> Changes in v4:
> - Replace s64 arithmetic with a branch-based helper that computes
> the forward wrapped distance directly, as suggested by Jason Gerecke.
> Keeps sequence_number as int; no type changes needed.
>
> Changes in v3:
> - Replace raw s64 modulo with div64_s64()-based remainder to avoid
> __moddi3 link failure on 32-bit architectures (i386, arm32).
>
> Changes in v2:
> - Normalize logical_maximum/value as unsigned when logical_minimum >= 0,
> matching HID parser signedness. Store sequence state as s64.
>
> drivers/hid/wacom_wac.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index 361738b..1d3ae94 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -2426,6 +2426,13 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
> }
> }
>
> +static int wacom_hid_wrapped_dist(int after, int before, int min, int max)
> +{
> + if (after >= before)
> + return after - before;
> + return (max - before) + (after - min) + 1;
> +}
> +
> static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
> struct hid_usage *usage, __s32 value)
> {
> @@ -2551,8 +2558,11 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
> case WACOM_HID_WD_SEQUENCENUMBER:
> if (wacom_wac->hid_data.sequence_number != value &&
> wacom_wac->hid_data.sequence_number >= 0) {
> - int sequence_size = field->logical_maximum - field->logical_minimum + 1;
> - int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
> + int drop_count = wacom_hid_wrapped_dist(
> + value,
> + wacom_wac->hid_data.sequence_number,
> + field->logical_minimum,
> + field->logical_maximum);
> hid_warn(hdev, "Dropped %d packets", drop_count);
> }
> wacom_wac->hid_data.sequence_number = value + 1;
> --
> 2.53.0
>