diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2014-09-30 13:18:34 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2014-10-29 05:51:41 -0400 |
commit | 57ac86cf52e903d9e3e0f12b34c814cce6b65550 (patch) | |
tree | c03884a59ca748aa4ff607f6abeb593e1500b203 /drivers/hid | |
parent | 586bdc4e4f15fec37dc37167d6f314ea94aa14d1 (diff) |
HID: logitech-hidpp: add support of the first Logitech Wireless Touchpad
This touchpad differs from the T650 in several ways:
- the resolution is not correctly returned by the device
- it presents physical buttons, so the button flag in the raw touch report
is not filled.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Tested-by: Andrew de los Reyes <adlr@chromium.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-logitech-hidpp.c | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index f9a4ec0ff76d..17e27e98e442 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c | |||
@@ -38,6 +38,7 @@ MODULE_AUTHOR("Nestor Lopez Casado <nlopezcasad@logitech.com>"); | |||
38 | 38 | ||
39 | /* bits 1..20 are reserved for classes */ | 39 | /* bits 1..20 are reserved for classes */ |
40 | #define HIDPP_QUIRK_DELAYED_INIT BIT(21) | 40 | #define HIDPP_QUIRK_DELAYED_INIT BIT(21) |
41 | #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * There are two hidpp protocols in use, the first version hidpp10 is known | 44 | * There are two hidpp protocols in use, the first version hidpp10 is known |
@@ -596,6 +597,8 @@ static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev, | |||
596 | /* Touchpad HID++ devices */ | 597 | /* Touchpad HID++ devices */ |
597 | /* -------------------------------------------------------------------------- */ | 598 | /* -------------------------------------------------------------------------- */ |
598 | 599 | ||
600 | #define WTP_MANUAL_RESOLUTION 39 | ||
601 | |||
599 | struct wtp_data { | 602 | struct wtp_data { |
600 | struct input_dev *input; | 603 | struct input_dev *input; |
601 | u16 x_size, y_size; | 604 | u16 x_size, y_size; |
@@ -634,7 +637,10 @@ static void wtp_populate_input(struct hidpp_device *hidpp, | |||
634 | 637 | ||
635 | input_set_capability(input_dev, EV_KEY, BTN_LEFT); | 638 | input_set_capability(input_dev, EV_KEY, BTN_LEFT); |
636 | 639 | ||
637 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | 640 | if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) |
641 | input_set_capability(input_dev, EV_KEY, BTN_RIGHT); | ||
642 | else | ||
643 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||
638 | 644 | ||
639 | input_mt_init_slots(input_dev, wd->maxcontacts, INPUT_MT_POINTER | | 645 | input_mt_init_slots(input_dev, wd->maxcontacts, INPUT_MT_POINTER | |
640 | INPUT_MT_DROP_UNUSED); | 646 | INPUT_MT_DROP_UNUSED); |
@@ -676,7 +682,8 @@ static void wtp_send_raw_xy_event(struct hidpp_device *hidpp, | |||
676 | for (i = 0; i < 2; i++) | 682 | for (i = 0; i < 2; i++) |
677 | wtp_touch_event(wd, &(raw->fingers[i])); | 683 | wtp_touch_event(wd, &(raw->fingers[i])); |
678 | 684 | ||
679 | if (raw->end_of_frame) | 685 | if (raw->end_of_frame && |
686 | !(hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS)) | ||
680 | input_event(wd->input, EV_KEY, BTN_LEFT, raw->button); | 687 | input_event(wd->input, EV_KEY, BTN_LEFT, raw->button); |
681 | 688 | ||
682 | if (raw->end_of_frame || raw->finger_count <= 2) { | 689 | if (raw->end_of_frame || raw->finger_count <= 2) { |
@@ -736,9 +743,17 @@ static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size) | |||
736 | 743 | ||
737 | switch (data[0]) { | 744 | switch (data[0]) { |
738 | case 0x02: | 745 | case 0x02: |
739 | if (size < 21) | 746 | if (hidpp->quirks & HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS) { |
740 | return 1; | 747 | input_event(wd->input, EV_KEY, BTN_LEFT, |
741 | return wtp_mouse_raw_xy_event(hidpp, &data[7]); | 748 | !!(data[1] & 0x01)); |
749 | input_event(wd->input, EV_KEY, BTN_RIGHT, | ||
750 | !!(data[1] & 0x02)); | ||
751 | input_sync(wd->input); | ||
752 | } else { | ||
753 | if (size < 21) | ||
754 | return 1; | ||
755 | return wtp_mouse_raw_xy_event(hidpp, &data[7]); | ||
756 | } | ||
742 | case REPORT_ID_HIDPP_LONG: | 757 | case REPORT_ID_HIDPP_LONG: |
743 | if ((report->fap.feature_index != wd->mt_feature_index) || | 758 | if ((report->fap.feature_index != wd->mt_feature_index) || |
744 | (report->fap.funcindex_clientid != EVENT_TOUCHPAD_RAW_XY)) | 759 | (report->fap.funcindex_clientid != EVENT_TOUCHPAD_RAW_XY)) |
@@ -775,6 +790,8 @@ static int wtp_get_config(struct hidpp_device *hidpp) | |||
775 | wd->maxcontacts = raw_info.maxcontacts; | 790 | wd->maxcontacts = raw_info.maxcontacts; |
776 | wd->flip_y = raw_info.origin == TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT; | 791 | wd->flip_y = raw_info.origin == TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT; |
777 | wd->resolution = raw_info.res; | 792 | wd->resolution = raw_info.res; |
793 | if (!wd->resolution) | ||
794 | wd->resolution = WTP_MANUAL_RESOLUTION; | ||
778 | 795 | ||
779 | return 0; | 796 | return 0; |
780 | } | 797 | } |
@@ -1130,6 +1147,11 @@ static void hidpp_remove(struct hid_device *hdev) | |||
1130 | } | 1147 | } |
1131 | 1148 | ||
1132 | static const struct hid_device_id hidpp_devices[] = { | 1149 | static const struct hid_device_id hidpp_devices[] = { |
1150 | { /* wireless touchpad */ | ||
1151 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | ||
1152 | USB_VENDOR_ID_LOGITECH, 0x4011), | ||
1153 | .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT | | ||
1154 | HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS }, | ||
1133 | { /* wireless touchpad T650 */ | 1155 | { /* wireless touchpad T650 */ |
1134 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | 1156 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, |
1135 | USB_VENDOR_ID_LOGITECH, 0x4101), | 1157 | USB_VENDOR_ID_LOGITECH, 0x4101), |