Skip to content

Commit a74749e

Browse files
committed
Merge branch 'for-6.3/logitech' into for-linus
- HID++ fixes for scroll wheel, protocol and debug (Bastien Nocera) - add support of Logitech G923 Xbox Edition steering wheel (Walt Holman)
2 parents 0f7566c + 1b136ae commit a74749e

File tree

3 files changed

+99
-61
lines changed

3 files changed

+99
-61
lines changed

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9217,6 +9217,13 @@ L: [email protected]
92179217
S: Maintained
92189218
F: drivers/hid/hid-logitech-*
92199219

9220+
HID++ LOGITECH DRIVERS
9221+
R: Filipe Laíns <[email protected]>
9222+
R: Bastien Nocera <[email protected]>
9223+
9224+
S: Maintained
9225+
F: drivers/hid/hid-logitech-hidpp.c
9226+
92209227
HID PLAYSTATION DRIVER
92219228
M: Roderick Colenbrander <[email protected]>
92229229

drivers/hid/hid-ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,7 @@
825825
#define USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO 0xc22e
826826
#define USB_DEVICE_ID_LOGITECH_G29_WHEEL 0xc24f
827827
#define USB_DEVICE_ID_LOGITECH_G920_WHEEL 0xc262
828+
#define USB_DEVICE_ID_LOGITECH_G923_XBOX_WHEEL 0xc26e
828829
#define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D 0xc283
829830
#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
830831
#define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940 0xc287

drivers/hid/hid-logitech-hidpp.c

Lines changed: 91 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@
3030
MODULE_LICENSE("GPL");
3131
MODULE_AUTHOR("Benjamin Tissoires <[email protected]>");
3232
MODULE_AUTHOR("Nestor Lopez Casado <[email protected]>");
33-
34-
static bool disable_raw_mode;
35-
module_param(disable_raw_mode, bool, 0644);
36-
MODULE_PARM_DESC(disable_raw_mode,
37-
"Disable Raw mode reporting for touchpads and keep firmware gestures.");
33+
MODULE_AUTHOR("Bastien Nocera <[email protected]>");
3834

3935
static bool disable_tap_to_click;
4036
module_param(disable_tap_to_click, bool, 0644);
@@ -71,12 +67,13 @@ MODULE_PARM_DESC(disable_tap_to_click,
7167
/* bits 2..20 are reserved for classes */
7268
/* #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) disabled */
7369
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
74-
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
70+
#define HIDPP_QUIRK_DELAYED_INIT BIT(23)
7571
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
7672
#define HIDPP_QUIRK_UNIFYING BIT(25)
7773
#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26)
7874
#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27)
7975
#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28)
76+
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(29)
8077

8178
/* These are just aliases for now */
8279
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
@@ -87,8 +84,6 @@ MODULE_PARM_DESC(disable_tap_to_click,
8784
HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL | \
8885
HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL)
8986

90-
#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
91-
9287
#define HIDPP_CAPABILITY_HIDPP10_BATTERY BIT(0)
9388
#define HIDPP_CAPABILITY_HIDPP20_BATTERY BIT(1)
9489
#define HIDPP_CAPABILITY_BATTERY_MILEAGE BIT(2)
@@ -225,6 +220,16 @@ struct hidpp_device {
225220
#define HIDPP_ERROR_INVALID_PARAM_VALUE 0x0b
226221
#define HIDPP_ERROR_WRONG_PIN_CODE 0x0c
227222
/* HID++ 2.0 error codes */
223+
#define HIDPP20_ERROR_NO_ERROR 0x00
224+
#define HIDPP20_ERROR_UNKNOWN 0x01
225+
#define HIDPP20_ERROR_INVALID_ARGS 0x02
226+
#define HIDPP20_ERROR_OUT_OF_RANGE 0x03
227+
#define HIDPP20_ERROR_HW_ERROR 0x04
228+
#define HIDPP20_ERROR_LOGITECH_INTERNAL 0x05
229+
#define HIDPP20_ERROR_INVALID_FEATURE_INDEX 0x06
230+
#define HIDPP20_ERROR_INVALID_FUNCTION_ID 0x07
231+
#define HIDPP20_ERROR_BUSY 0x08
232+
#define HIDPP20_ERROR_UNSUPPORTED 0x09
228233
#define HIDPP20_ERROR 0xff
229234

230235
static void hidpp_connect_event(struct hidpp_device *hidpp_dev);
@@ -279,6 +284,7 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
279284
struct hidpp_report *response)
280285
{
281286
int ret;
287+
int max_retries = 3;
282288

283289
mutex_lock(&hidpp->send_mutex);
284290

@@ -291,34 +297,39 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp,
291297
*/
292298
*response = *message;
293299

294-
ret = __hidpp_send_report(hidpp->hid_dev, message);
300+
for (; max_retries != 0; max_retries--) {
301+
ret = __hidpp_send_report(hidpp->hid_dev, message);
295302

296-
if (ret) {
297-
dbg_hid("__hidpp_send_report returned err: %d\n", ret);
298-
memset(response, 0, sizeof(struct hidpp_report));
299-
goto exit;
300-
}
303+
if (ret) {
304+
dbg_hid("__hidpp_send_report returned err: %d\n", ret);
305+
memset(response, 0, sizeof(struct hidpp_report));
306+
goto exit;
307+
}
301308

302-
if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
303-
5*HZ)) {
304-
dbg_hid("%s:timeout waiting for response\n", __func__);
305-
memset(response, 0, sizeof(struct hidpp_report));
306-
ret = -ETIMEDOUT;
307-
}
309+
if (!wait_event_timeout(hidpp->wait, hidpp->answer_available,
310+
5*HZ)) {
311+
dbg_hid("%s:timeout waiting for response\n", __func__);
312+
memset(response, 0, sizeof(struct hidpp_report));
313+
ret = -ETIMEDOUT;
314+
}
308315

309-
if (response->report_id == REPORT_ID_HIDPP_SHORT &&
310-
response->rap.sub_id == HIDPP_ERROR) {
311-
ret = response->rap.params[1];
312-
dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
313-
goto exit;
314-
}
316+
if (response->report_id == REPORT_ID_HIDPP_SHORT &&
317+
response->rap.sub_id == HIDPP_ERROR) {
318+
ret = response->rap.params[1];
319+
dbg_hid("%s:got hidpp error %02X\n", __func__, ret);
320+
goto exit;
321+
}
315322

316-
if ((response->report_id == REPORT_ID_HIDPP_LONG ||
317-
response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
318-
response->fap.feature_index == HIDPP20_ERROR) {
319-
ret = response->fap.params[1];
320-
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
321-
goto exit;
323+
if ((response->report_id == REPORT_ID_HIDPP_LONG ||
324+
response->report_id == REPORT_ID_HIDPP_VERY_LONG) &&
325+
response->fap.feature_index == HIDPP20_ERROR) {
326+
ret = response->fap.params[1];
327+
if (ret != HIDPP20_ERROR_BUSY) {
328+
dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret);
329+
goto exit;
330+
}
331+
dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret);
332+
}
322333
}
323334

324335
exit:
@@ -334,8 +345,13 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
334345
struct hidpp_report *message;
335346
int ret;
336347

337-
if (param_count > sizeof(message->fap.params))
348+
if (param_count > sizeof(message->fap.params)) {
349+
hid_dbg(hidpp->hid_dev,
350+
"Invalid number of parameters passed to command (%d != %llu)\n",
351+
param_count,
352+
(unsigned long long) sizeof(message->fap.params));
338353
return -EINVAL;
354+
}
339355

340356
message = kzalloc(sizeof(struct hidpp_report), GFP_KERNEL);
341357
if (!message)
@@ -3436,11 +3452,17 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
34363452
ret = hidpp10_enable_scrolling_acceleration(hidpp);
34373453
multiplier = 8;
34383454
}
3439-
if (ret)
3455+
if (ret) {
3456+
hid_dbg(hidpp->hid_dev,
3457+
"Could not enable hi-res scrolling: %d\n", ret);
34403458
return ret;
3459+
}
34413460

3442-
if (multiplier == 0)
3461+
if (multiplier == 0) {
3462+
hid_dbg(hidpp->hid_dev,
3463+
"Invalid multiplier 0 from device, setting it to 1\n");
34433464
multiplier = 1;
3465+
}
34443466

34453467
hidpp->vertical_wheel_counter.wheel_multiplier = multiplier;
34463468
hid_dbg(hidpp->hid_dev, "wheel multiplier = %d\n", multiplier);
@@ -3472,14 +3494,8 @@ static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp)
34723494
hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scrolling\n");
34733495
}
34743496
} else {
3475-
struct hidpp_report response;
3476-
3477-
ret = hidpp_send_rap_command_sync(hidpp,
3478-
REPORT_ID_HIDPP_SHORT,
3479-
HIDPP_GET_REGISTER,
3480-
HIDPP_ENABLE_FAST_SCROLL,
3481-
NULL, 0, &response);
3482-
if (!ret) {
3497+
/* We cannot detect fast scrolling support on HID++ 1.0 devices */
3498+
if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) {
34833499
hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL;
34843500
hid_dbg(hidpp->hid_dev, "Detected HID++ 1.0 fast scroll\n");
34853501
}
@@ -4002,7 +4018,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
40024018
if (hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL)
40034019
hi_res_scroll_enable(hidpp);
40044020

4005-
if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input)
4021+
if (!(hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) || hidpp->delayed_input)
40064022
/* if the input nodes are already created, we can stop now */
40074023
return;
40084024

@@ -4107,6 +4123,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
41074123
bool connected;
41084124
unsigned int connect_mask = HID_CONNECT_DEFAULT;
41094125
struct hidpp_ff_private_data data;
4126+
bool will_restart = false;
41104127

41114128
/* report_fixup needs drvdata to be set before we call hid_parse */
41124129
hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
@@ -4147,11 +4164,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
41474164
hidpp_application_equals(hdev, HID_GD_KEYBOARD))
41484165
hidpp->quirks |= HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS;
41494166

4150-
if (disable_raw_mode) {
4151-
hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;
4152-
hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT;
4153-
}
4154-
41554167
if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
41564168
ret = wtp_allocate(hdev, id);
41574169
if (ret)
@@ -4162,6 +4174,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
41624174
return ret;
41634175
}
41644176

4177+
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT ||
4178+
hidpp->quirks & HIDPP_QUIRK_UNIFYING)
4179+
will_restart = true;
4180+
41654181
INIT_WORK(&hidpp->work, delayed_work_cb);
41664182
mutex_init(&hidpp->send_mutex);
41674183
init_waitqueue_head(&hidpp->wait);
@@ -4176,7 +4192,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
41764192
* Plain USB connections need to actually call start and open
41774193
* on the transport driver to allow incoming data.
41784194
*/
4179-
ret = hid_hw_start(hdev, 0);
4195+
ret = hid_hw_start(hdev, will_restart ? 0 : connect_mask);
41804196
if (ret) {
41814197
hid_err(hdev, "hw start failed\n");
41824198
goto hid_hw_start_fail;
@@ -4213,6 +4229,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
42134229
hidpp->wireless_feature_index = 0;
42144230
else if (ret)
42154231
goto hid_hw_init_fail;
4232+
ret = 0;
42164233
}
42174234

42184235
if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
@@ -4227,19 +4244,21 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
42274244

42284245
hidpp_connect_event(hidpp);
42294246

4230-
/* Reset the HID node state */
4231-
hid_device_io_stop(hdev);
4232-
hid_hw_close(hdev);
4233-
hid_hw_stop(hdev);
4247+
if (will_restart) {
4248+
/* Reset the HID node state */
4249+
hid_device_io_stop(hdev);
4250+
hid_hw_close(hdev);
4251+
hid_hw_stop(hdev);
42344252

4235-
if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
4236-
connect_mask &= ~HID_CONNECT_HIDINPUT;
4253+
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
4254+
connect_mask &= ~HID_CONNECT_HIDINPUT;
42374255

4238-
/* Now export the actual inputs and hidraw nodes to the world */
4239-
ret = hid_hw_start(hdev, connect_mask);
4240-
if (ret) {
4241-
hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
4242-
goto hid_hw_start_fail;
4256+
/* Now export the actual inputs and hidraw nodes to the world */
4257+
ret = hid_hw_start(hdev, connect_mask);
4258+
if (ret) {
4259+
hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
4260+
goto hid_hw_start_fail;
4261+
}
42434262
}
42444263

42454264
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
@@ -4297,9 +4316,15 @@ static const struct hid_device_id hidpp_devices[] = {
42974316
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
42984317
USB_DEVICE_ID_LOGITECH_T651),
42994318
.driver_data = HIDPP_QUIRK_CLASS_WTP },
4319+
{ /* Mouse Logitech Anywhere MX */
4320+
LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
43004321
{ /* Mouse logitech M560 */
43014322
LDJ_DEVICE(0x402d),
43024323
.driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
4324+
{ /* Mouse Logitech M705 (firmware RQM17) */
4325+
LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
4326+
{ /* Mouse Logitech Performance MX */
4327+
LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
43034328
{ /* Keyboard logitech K400 */
43044329
LDJ_DEVICE(0x4024),
43054330
.driver_data = HIDPP_QUIRK_CLASS_K400 },
@@ -4348,6 +4373,9 @@ static const struct hid_device_id hidpp_devices[] = {
43484373
{ /* Logitech G920 Wheel over USB */
43494374
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
43504375
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
4376+
{ /* Logitech G923 Wheel (Xbox version) over USB */
4377+
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G923_XBOX_WHEEL),
4378+
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS },
43514379
{ /* Logitech G Pro Gaming Mouse over USB */
43524380
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
43534381

@@ -4367,6 +4395,8 @@ static const struct hid_device_id hidpp_devices[] = {
43674395
{ /* MX Ergo trackball over Bluetooth */
43684396
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) },
43694397
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e) },
4398+
{ /* Signature M650 over Bluetooth */
4399+
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) },
43704400
{ /* MX Master 3 mouse over Bluetooth */
43714401
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023) },
43724402
{}

0 commit comments

Comments
 (0)