diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 074bc647509d..f0b16eb4a32a 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -70,6 +70,10 @@ static bool psmouse_smartscroll = true; module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); +static bool psmouse_a4tech_2wheels; +module_param_named(a4tech_workaround, psmouse_a4tech_2wheels, bool, 0644); +MODULE_PARM_DESC(a4tech_workaround, "A4Tech second scroll wheel workaround, 1 = enabled, 0 = disabled (default)."); + static unsigned int psmouse_resetafter = 5; module_param_named(resetafter, psmouse_resetafter, uint, 0644); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); @@ -150,6 +154,7 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) { struct input_dev *dev = psmouse->dev; u8 *packet = psmouse->packet; + int wheel; if (psmouse->pktcnt < psmouse->pktsize) return PSMOUSE_GOOD_DATA; @@ -175,8 +180,18 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) break; case 0x00: case 0xC0: - input_report_rel(dev, REL_WHEEL, - -sign_extend32(packet[3], 3)); + wheel = sign_extend32(packet[3], 3); + + /* + * Some A4Tech mice have two scroll wheels, with first + * one reporting +/-1 in the lower nibble, and second + * one reporting +/-2. + */ + if (psmouse_a4tech_2wheels && abs(wheel) > 1) + input_report_rel(dev, REL_HWHEEL, wheel / 2); + else + input_report_rel(dev, REL_WHEEL, -wheel); + input_report_key(dev, BTN_SIDE, BIT(4)); input_report_key(dev, BTN_EXTRA, BIT(5)); break;