aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-09-30 13:18:34 -0400
committerJiri Kosina <jkosina@suse.cz>2014-10-29 05:51:41 -0400
commit57ac86cf52e903d9e3e0f12b34c814cce6b65550 (patch)
treec03884a59ca748aa4ff607f6abeb593e1500b203 /drivers/hid
parent586bdc4e4f15fec37dc37167d6f314ea94aa14d1 (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.c32
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
599struct wtp_data { 602struct 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
1132static const struct hid_device_id hidpp_devices[] = { 1149static 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),