aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-09-30 13:18:33 -0400
committerJiri Kosina <jkosina@suse.cz>2014-10-29 05:51:41 -0400
commit586bdc4e4f15fec37dc37167d6f314ea94aa14d1 (patch)
tree3a29aad0a77f40c984ca854939c31e6bf6792b03 /drivers/hid
parentc39e3d5fc9dd3e16c6f59dd94d827540040de66d (diff)
HID: logitech-hidpp: Add Wireless Touchpad T650 support
All the bits are now in place to add the support of the Touchpad T650. The creation/population of the input device is delayed until the device is ready. The T650 uses the special HID++ reporting protocol, so activate this on connect. 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.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 9561a1f9b42b..f9a4ec0ff76d 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -471,6 +471,9 @@ out_err:
471#define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100 471#define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100
472 472
473#define CMD_TOUCHPAD_GET_RAW_INFO 0x01 473#define CMD_TOUCHPAD_GET_RAW_INFO 0x01
474#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21
475
476#define EVENT_TOUCHPAD_RAW_XY 0x00
474 477
475#define TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT 0x01 478#define TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT 0x01
476#define TOUCHPAD_RAW_XY_ORIGIN_UPPER_LEFT 0x03 479#define TOUCHPAD_RAW_XY_ORIGIN_UPPER_LEFT 0x03
@@ -530,6 +533,59 @@ static int hidpp_touchpad_get_raw_info(struct hidpp_device *hidpp,
530 return ret; 533 return ret;
531} 534}
532 535
536static int hidpp_touchpad_set_raw_report_state(struct hidpp_device *hidpp_dev,
537 u8 feature_index, bool send_raw_reports,
538 bool sensor_enhanced_settings)
539{
540 struct hidpp_report response;
541
542 /*
543 * Params:
544 * bit 0 - enable raw
545 * bit 1 - 16bit Z, no area
546 * bit 2 - enhanced sensitivity
547 * bit 3 - width, height (4 bits each) instead of area
548 * bit 4 - send raw + gestures (degrades smoothness)
549 * remaining bits - reserved
550 */
551 u8 params = send_raw_reports | (sensor_enhanced_settings << 2);
552
553 return hidpp_send_fap_command_sync(hidpp_dev, feature_index,
554 CMD_TOUCHPAD_SET_RAW_REPORT_STATE, &params, 1, &response);
555}
556
557static void hidpp_touchpad_touch_event(u8 *data,
558 struct hidpp_touchpad_raw_xy_finger *finger)
559{
560 u8 x_m = data[0] << 2;
561 u8 y_m = data[2] << 2;
562
563 finger->x = x_m << 6 | data[1];
564 finger->y = y_m << 6 | data[3];
565
566 finger->contact_type = data[0] >> 6;
567 finger->contact_status = data[2] >> 6;
568
569 finger->z = data[4];
570 finger->area = data[5];
571 finger->finger_id = data[6] >> 4;
572}
573
574static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev,
575 u8 *data, struct hidpp_touchpad_raw_xy *raw_xy)
576{
577 memset(raw_xy, 0, sizeof(struct hidpp_touchpad_raw_xy));
578 raw_xy->end_of_frame = data[8] & 0x01;
579 raw_xy->spurious_flag = (data[8] >> 1) & 0x01;
580 raw_xy->finger_count = data[15] & 0x0f;
581 raw_xy->button = (data[8] >> 2) & 0x01;
582
583 if (raw_xy->finger_count) {
584 hidpp_touchpad_touch_event(&data[2], &raw_xy->fingers[0]);
585 hidpp_touchpad_touch_event(&data[9], &raw_xy->fingers[1]);
586 }
587}
588
533/* ************************************************************************** */ 589/* ************************************************************************** */
534/* */ 590/* */
535/* Device Support */ 591/* Device Support */
@@ -672,11 +728,28 @@ static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size)
672{ 728{
673 struct hidpp_device *hidpp = hid_get_drvdata(hdev); 729 struct hidpp_device *hidpp = hid_get_drvdata(hdev);
674 struct wtp_data *wd = hidpp->private_data; 730 struct wtp_data *wd = hidpp->private_data;
731 struct hidpp_report *report = (struct hidpp_report *)data;
732 struct hidpp_touchpad_raw_xy raw;
675 733
676 if (!wd || !wd->input || (data[0] != 0x02) || size < 21) 734 if (!wd || !wd->input)
677 return 1; 735 return 1;
678 736
679 return wtp_mouse_raw_xy_event(hidpp, &data[7]); 737 switch (data[0]) {
738 case 0x02:
739 if (size < 21)
740 return 1;
741 return wtp_mouse_raw_xy_event(hidpp, &data[7]);
742 case REPORT_ID_HIDPP_LONG:
743 if ((report->fap.feature_index != wd->mt_feature_index) ||
744 (report->fap.funcindex_clientid != EVENT_TOUCHPAD_RAW_XY))
745 return 1;
746 hidpp_touchpad_raw_xy_event(hidpp, data + 4, &raw);
747
748 wtp_send_raw_xy_event(hidpp, &raw);
749 return 0;
750 }
751
752 return 0;
680} 753}
681 754
682static int wtp_get_config(struct hidpp_device *hidpp) 755static int wtp_get_config(struct hidpp_device *hidpp)
@@ -721,6 +794,27 @@ static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id)
721 return 0; 794 return 0;
722}; 795};
723 796
797static void wtp_connect(struct hid_device *hdev, bool connected)
798{
799 struct hidpp_device *hidpp = hid_get_drvdata(hdev);
800 struct wtp_data *wd = hidpp->private_data;
801 int ret;
802
803 if (!connected)
804 return;
805
806 if (!wd->x_size) {
807 ret = wtp_get_config(hidpp);
808 if (ret) {
809 hid_err(hdev, "Can not get wtp config: %d\n", ret);
810 return;
811 }
812 }
813
814 hidpp_touchpad_set_raw_report_state(hidpp, wd->mt_feature_index,
815 true, true);
816}
817
724/* -------------------------------------------------------------------------- */ 818/* -------------------------------------------------------------------------- */
725/* Generic HID++ devices */ 819/* Generic HID++ devices */
726/* -------------------------------------------------------------------------- */ 820/* -------------------------------------------------------------------------- */
@@ -897,6 +991,9 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
897 char *name, *devm_name; 991 char *name, *devm_name;
898 u8 name_length; 992 u8 name_length;
899 993
994 if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)
995 wtp_connect(hdev, connected);
996
900 if (!connected || hidpp->delayed_input) 997 if (!connected || hidpp->delayed_input)
901 return; 998 return;
902 999
@@ -1033,6 +1130,10 @@ static void hidpp_remove(struct hid_device *hdev)
1033} 1130}
1034 1131
1035static const struct hid_device_id hidpp_devices[] = { 1132static const struct hid_device_id hidpp_devices[] = {
1133 { /* wireless touchpad T650 */
1134 HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
1135 USB_VENDOR_ID_LOGITECH, 0x4101),
1136 .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT },
1036 { /* wireless touchpad T651 */ 1137 { /* wireless touchpad T651 */
1037 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 1138 HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
1038 USB_DEVICE_ID_LOGITECH_T651), 1139 USB_DEVICE_ID_LOGITECH_T651),