Skip to content

Commit 7457bc1

Browse files
jwrdegoedebentiss
authored andcommitted
HID: logitech-hidpp: add support for HID++ 1.0 extra mouse buttons reports
Some mice have extra buttons which are only reported through HID++ 1.0 extra mouse buttons reports, this commit adds support for this and automatically enables this support for all 27 MHz mice. Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 4a79bcc commit 7457bc1

File tree

1 file changed

+76
-1
lines changed

1 file changed

+76
-1
lines changed

drivers/hid/hid-logitech-hidpp.c

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ MODULE_PARM_DESC(disable_tap_to_click,
7272
#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27)
7373
#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28)
7474
#define HIDPP_QUIRK_HIDPP_WHEELS BIT(29)
75+
#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30)
7576

7677
/* These are just aliases for now */
7778
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
@@ -2792,6 +2793,64 @@ static void hidpp10_wheel_populate_input(struct hidpp_device *hidpp,
27922793
__set_bit(REL_HWHEEL_HI_RES, input_dev->relbit);
27932794
}
27942795

2796+
/* -------------------------------------------------------------------------- */
2797+
/* HID++1.0 mice which use HID++ reports for extra mouse buttons */
2798+
/* -------------------------------------------------------------------------- */
2799+
static int hidpp10_extra_mouse_buttons_connect(struct hidpp_device *hidpp)
2800+
{
2801+
return hidpp10_set_register(hidpp, HIDPP_REG_ENABLE_REPORTS, 0,
2802+
HIDPP_ENABLE_MOUSE_EXTRA_BTN_REPORT,
2803+
HIDPP_ENABLE_MOUSE_EXTRA_BTN_REPORT);
2804+
}
2805+
2806+
static int hidpp10_extra_mouse_buttons_raw_event(struct hidpp_device *hidpp,
2807+
u8 *data, int size)
2808+
{
2809+
int i;
2810+
2811+
if (!hidpp->input)
2812+
return -EINVAL;
2813+
2814+
if (size < 7)
2815+
return 0;
2816+
2817+
if (data[0] != REPORT_ID_HIDPP_SHORT ||
2818+
data[2] != HIDPP_SUB_ID_MOUSE_EXTRA_BTNS)
2819+
return 0;
2820+
2821+
/*
2822+
* Buttons are either delivered through the regular mouse report *or*
2823+
* through the extra buttons report. At least for button 6 how it is
2824+
* delivered differs per receiver firmware version. Even receivers with
2825+
* the same usb-id show different behavior, so we handle both cases.
2826+
*/
2827+
for (i = 0; i < 8; i++)
2828+
input_report_key(hidpp->input, BTN_MOUSE + i,
2829+
(data[3] & (1 << i)));
2830+
2831+
/* Some mice report events on button 9+, use BTN_MISC */
2832+
for (i = 0; i < 8; i++)
2833+
input_report_key(hidpp->input, BTN_MISC + i,
2834+
(data[4] & (1 << i)));
2835+
2836+
input_sync(hidpp->input);
2837+
return 1;
2838+
}
2839+
2840+
static void hidpp10_extra_mouse_buttons_populate_input(
2841+
struct hidpp_device *hidpp, struct input_dev *input_dev)
2842+
{
2843+
/* BTN_MOUSE - BTN_MOUSE+7 are set already by the descriptor */
2844+
__set_bit(BTN_0, input_dev->keybit);
2845+
__set_bit(BTN_1, input_dev->keybit);
2846+
__set_bit(BTN_2, input_dev->keybit);
2847+
__set_bit(BTN_3, input_dev->keybit);
2848+
__set_bit(BTN_4, input_dev->keybit);
2849+
__set_bit(BTN_5, input_dev->keybit);
2850+
__set_bit(BTN_6, input_dev->keybit);
2851+
__set_bit(BTN_7, input_dev->keybit);
2852+
}
2853+
27952854
/* -------------------------------------------------------------------------- */
27962855
/* High-resolution scroll wheels */
27972856
/* -------------------------------------------------------------------------- */
@@ -2879,6 +2938,9 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
28792938

28802939
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_WHEELS)
28812940
hidpp10_wheel_populate_input(hidpp, input);
2941+
2942+
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS)
2943+
hidpp10_extra_mouse_buttons_populate_input(hidpp, input);
28822944
}
28832945

28842946
static int hidpp_input_configured(struct hid_device *hdev,
@@ -2956,6 +3018,12 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
29563018
return ret;
29573019
}
29583020

3021+
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS) {
3022+
ret = hidpp10_extra_mouse_buttons_raw_event(hidpp, data, size);
3023+
if (ret != 0)
3024+
return ret;
3025+
}
3026+
29593027
return 0;
29603028
}
29613029

@@ -3209,6 +3277,12 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
32093277
return;
32103278
}
32113279

3280+
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS) {
3281+
ret = hidpp10_extra_mouse_buttons_connect(hidpp);
3282+
if (ret)
3283+
return;
3284+
}
3285+
32123286
/* the device is already connected, we can ask for its name and
32133287
* protocol */
32143288
if (!hidpp->protocol_major) {
@@ -3374,7 +3448,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
33743448

33753449
if (id->group == HID_GROUP_LOGITECH_27MHZ_DEVICE &&
33763450
hidpp_application_equals(hdev, HID_GD_MOUSE))
3377-
hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS;
3451+
hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS |
3452+
HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS;
33783453

33793454
if (disable_raw_mode) {
33803455
hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;

0 commit comments

Comments
 (0)