Skip to content

Commit 91cf9a9

Browse files
committed
HID: logitech-hidpp: make .probe usbhid capable
The current custom solution for the G920 is not the best because hid_hw_start() is not called at the end of the .probe(). It means that any configuration retrieved after the initial hid_hw_start would not be exposed to user space without races. We can simply force hid_hw_start to just enable the transport layer by not using a connect_mask. This way, we can have a common path between USB, Unifying and Bluetooth devices. With this change, we can now support the non DJ receivers for low end devices, which will allow us to fetch the actual names of the paired device (instead of 'Logitech Wireless Receiver') Tested with a M185 with the non unifying receiver, a T650 and many other unifying devices, and the T651 over Bluetooth. Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent fe3ee1e commit 91cf9a9

File tree

1 file changed

+45
-41
lines changed

1 file changed

+45
-41
lines changed

drivers/hid/hid-logitech-hidpp.c

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3316,24 +3316,23 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
33163316
hid_warn(hdev, "Cannot allocate sysfs group for %s\n",
33173317
hdev->name);
33183318

3319-
if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
3320-
connect_mask &= ~HID_CONNECT_HIDINPUT;
3321-
3322-
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
3323-
ret = hid_hw_start(hdev, connect_mask);
3324-
if (ret) {
3325-
hid_err(hdev, "hw start failed\n");
3326-
goto hid_hw_start_fail;
3327-
}
3328-
ret = hid_hw_open(hdev);
3329-
if (ret < 0) {
3330-
dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
3331-
__func__, ret);
3332-
hid_hw_stop(hdev);
3333-
goto hid_hw_start_fail;
3334-
}
3319+
/*
3320+
* Plain USB connections need to actually call start and open
3321+
* on the transport driver to allow incoming data.
3322+
*/
3323+
ret = hid_hw_start(hdev, 0);
3324+
if (ret) {
3325+
hid_err(hdev, "hw start failed\n");
3326+
goto hid_hw_start_fail;
33353327
}
33363328

3329+
ret = hid_hw_open(hdev);
3330+
if (ret < 0) {
3331+
dev_err(&hdev->dev, "%s:hid_hw_open returned error:%d\n",
3332+
__func__, ret);
3333+
hid_hw_stop(hdev);
3334+
goto hid_hw_open_fail;
3335+
}
33373336

33383337
/* Allow incoming packets */
33393338
hid_device_io_start(hdev);
@@ -3347,7 +3346,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
33473346
if (!connected) {
33483347
ret = -ENODEV;
33493348
hid_err(hdev, "Device not connected");
3350-
goto hid_hw_open_failed;
3349+
goto hid_hw_init_fail;
33513350
}
33523351

33533352
hidpp_overwrite_name(hdev);
@@ -3356,37 +3355,36 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
33563355
if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
33573356
ret = wtp_get_config(hidpp);
33583357
if (ret)
3359-
goto hid_hw_open_failed;
3358+
goto hid_hw_init_fail;
33603359
} else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
33613360
ret = g920_get_config(hidpp);
33623361
if (ret)
3363-
goto hid_hw_open_failed;
3362+
goto hid_hw_init_fail;
33643363
}
33653364

3366-
/* Block incoming packets */
3367-
hid_device_io_stop(hdev);
3365+
hidpp_connect_event(hidpp);
33683366

3369-
if (!(hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
3370-
ret = hid_hw_start(hdev, connect_mask);
3371-
if (ret) {
3372-
hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
3373-
goto hid_hw_start_fail;
3374-
}
3375-
}
3367+
/* Reset the HID node state */
3368+
hid_device_io_stop(hdev);
3369+
hid_hw_close(hdev);
3370+
hid_hw_stop(hdev);
33763371

3377-
/* Allow incoming packets */
3378-
hid_device_io_start(hdev);
3372+
if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
3373+
connect_mask &= ~HID_CONNECT_HIDINPUT;
33793374

3380-
hidpp_connect_event(hidpp);
3375+
/* Now export the actual inputs and hidraw nodes to the world */
3376+
ret = hid_hw_start(hdev, connect_mask);
3377+
if (ret) {
3378+
hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
3379+
goto hid_hw_start_fail;
3380+
}
33813381

33823382
return ret;
33833383

3384-
hid_hw_open_failed:
3385-
hid_device_io_stop(hdev);
3386-
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
3387-
hid_hw_close(hdev);
3388-
hid_hw_stop(hdev);
3389-
}
3384+
hid_hw_init_fail:
3385+
hid_hw_close(hdev);
3386+
hid_hw_open_fail:
3387+
hid_hw_stop(hdev);
33903388
hid_hw_start_fail:
33913389
sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group);
33923390
cancel_work_sync(&hidpp->work);
@@ -3403,10 +3401,9 @@ static void hidpp_remove(struct hid_device *hdev)
34033401

34043402
sysfs_remove_group(&hdev->dev.kobj, &ps_attribute_group);
34053403

3406-
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
3404+
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)
34073405
hidpp_ff_deinit(hdev);
3408-
hid_hw_close(hdev);
3409-
}
3406+
34103407
hid_hw_stop(hdev);
34113408
cancel_work_sync(&hidpp->work);
34123409
mutex_destroy(&hidpp->send_mutex);
@@ -3470,7 +3467,14 @@ static const struct hid_device_id hidpp_devices[] = {
34703467

34713468
{ LDJ_DEVICE(HID_ANY_ID) },
34723469

3473-
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
3470+
{ /* Logitech G403 Gaming Mouse over USB */
3471+
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
3472+
{ /* Logitech G700 Gaming Mouse over USB */
3473+
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) },
3474+
{ /* Logitech G900 Gaming Mouse over USB */
3475+
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC081) },
3476+
{ /* Logitech G920 Wheel over USB */
3477+
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
34743478
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
34753479
{}
34763480
};

0 commit comments

Comments
 (0)