| From cdc790dc8e568d3478cdf4bc3146b40ca66258ac Mon Sep 17 00:00:00 2001 |
| From: Hans de Goede <hdegoede@redhat.com> |
| Date: Sat, 20 Apr 2019 13:22:10 +0200 |
| Subject: HID: logitech-hidpp: use RAP instead of FAP to get the protocol |
| version |
| |
| [ Upstream commit 096377525cdb8251e4656085efc988bdf733fb4c ] |
| |
| According to the logitech_hidpp_2.0_specification_draft_2012-06-04.pdf doc: |
| https://lekensteyn.nl/files/logitech/logitech_hidpp_2.0_specification_draft_2012-06-04.pdf |
| |
| We should use a register-access-protocol request using the short input / |
| output report ids. This is necessary because 27MHz HID++ receivers have |
| a max-packetsize on their HIP++ endpoint of 8, so they cannot support |
| long reports. Using a feature-access-protocol request (which is always |
| long or very-long) with these will cause a timeout error, followed by |
| the hidpp driver treating the device as not being HID++ capable. |
| |
| This commit fixes this by switching to using a rap request to get the |
| protocol version. |
| |
| Besides being tested with a (046d:c517) 27MHz receiver with various |
| 27MHz keyboards and mice, this has also been tested to not cause |
| regressions on a non-unifying dual-HID++ nano receiver (046d:c534) with |
| k270 and m185 HID++-2.0 devices connected and on a unifying/dj receiver |
| (046d:c52b) with a HID++-2.0 Logitech Rechargeable Touchpad T650. |
| |
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> |
| Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/hid/hid-logitech-hidpp.c | 17 +++++++++++++---- |
| 1 file changed, 13 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c |
| index 5fd97860aec4d..3666e5064d0d3 100644 |
| --- a/drivers/hid/hid-logitech-hidpp.c |
| +++ b/drivers/hid/hid-logitech-hidpp.c |
| @@ -414,13 +414,16 @@ static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, |
| |
| static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) |
| { |
| + const u8 ping_byte = 0x5a; |
| + u8 ping_data[3] = { 0, 0, ping_byte }; |
| struct hidpp_report response; |
| int ret; |
| |
| - ret = hidpp_send_fap_command_sync(hidpp, |
| + ret = hidpp_send_rap_command_sync(hidpp, |
| + REPORT_ID_HIDPP_SHORT, |
| HIDPP_PAGE_ROOT_IDX, |
| CMD_ROOT_GET_PROTOCOL_VERSION, |
| - NULL, 0, &response); |
| + ping_data, sizeof(ping_data), &response); |
| |
| if (ret == HIDPP_ERROR_INVALID_SUBID) { |
| hidpp->protocol_major = 1; |
| @@ -440,8 +443,14 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) |
| if (ret) |
| return ret; |
| |
| - hidpp->protocol_major = response.fap.params[0]; |
| - hidpp->protocol_minor = response.fap.params[1]; |
| + if (response.rap.params[2] != ping_byte) { |
| + hid_err(hidpp->hid_dev, "%s: ping mismatch 0x%02x != 0x%02x\n", |
| + __func__, response.rap.params[2], ping_byte); |
| + return -EPROTO; |
| + } |
| + |
| + hidpp->protocol_major = response.rap.params[0]; |
| + hidpp->protocol_minor = response.rap.params[1]; |
| |
| return ret; |
| } |
| -- |
| 2.20.1 |
| |