Skip to content

Commit 586bdc4

Browse files
bentissJiri Kosina
authored andcommitted
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 <[email protected]> Tested-by: Andrew de los Reyes <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent c39e3d5 commit 586bdc4

File tree

1 file changed

+103
-2
lines changed

1 file changed

+103
-2
lines changed

drivers/hid/hid-logitech-hidpp.c

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,9 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp, u8 *name_length)
471471
#define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100
472472

473473
#define CMD_TOUCHPAD_GET_RAW_INFO 0x01
474+
#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21
475+
476+
#define EVENT_TOUCHPAD_RAW_XY 0x00
474477

475478
#define TOUCHPAD_RAW_XY_ORIGIN_LOWER_LEFT 0x01
476479
#define TOUCHPAD_RAW_XY_ORIGIN_UPPER_LEFT 0x03
@@ -530,6 +533,59 @@ static int hidpp_touchpad_get_raw_info(struct hidpp_device *hidpp,
530533
return ret;
531534
}
532535

536+
static 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+
557+
static 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+
574+
static 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+
533589
/* ************************************************************************** */
534590
/* */
535591
/* Device Support */
@@ -672,11 +728,28 @@ static int wtp_raw_event(struct hid_device *hdev, u8 *data, int size)
672728
{
673729
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
674730
struct wtp_data *wd = hidpp->private_data;
731+
struct hidpp_report *report = (struct hidpp_report *)data;
732+
struct hidpp_touchpad_raw_xy raw;
675733

676-
if (!wd || !wd->input || (data[0] != 0x02) || size < 21)
734+
if (!wd || !wd->input)
677735
return 1;
678736

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;
680753
}
681754

682755
static 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)
721794
return 0;
722795
};
723796

797+
static 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+
724818
/* -------------------------------------------------------------------------- */
725819
/* Generic HID++ devices */
726820
/* -------------------------------------------------------------------------- */
@@ -897,6 +991,9 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
897991
char *name, *devm_name;
898992
u8 name_length;
899993

994+
if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)
995+
wtp_connect(hdev, connected);
996+
900997
if (!connected || hidpp->delayed_input)
901998
return;
902999

@@ -1033,6 +1130,10 @@ static void hidpp_remove(struct hid_device *hdev)
10331130
}
10341131

10351132
static 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 },
10361137
{ /* wireless touchpad T651 */
10371138
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
10381139
USB_DEVICE_ID_LOGITECH_T651),

0 commit comments

Comments
 (0)