[PATCH 13/21] HID: microsoft: move FF initialization to .input_configured()
Dmitry Torokhov <[email protected]> Mon, 03 Aug 2026 11:46:38 -0700
| Newsgroups | org.kernel.vger.linux-input,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
The driver currently initializes force-feedback in its probe() function after calling hid_hw_start(). This is racy as the input device is already registered and visible to userspace at that point. Move the FF initialization to the .input_configured() callback to ensure the device is fully prepared before registration. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Dmitry Torokhov <[email protected]> --- drivers/hid/hid-microsoft.c | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 18ac21c0bcb2..a7d3493a6141 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -323,22 +323,17 @@ static int ms_play_effect(struct input_dev *dev, void *data, return 0; } -static int ms_init_ff(struct hid_device *hdev) +static int ms_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { - struct hid_input *hidinput; - struct input_dev *input_dev; struct ms_data *ms = hid_get_drvdata(hdev); - - if (list_empty(&hdev->inputs)) { - hid_err(hdev, "no inputs found\n"); - return -ENODEV; - } - hidinput = list_entry(hdev->inputs.next, struct hid_input, list); - input_dev = hidinput->input; + struct input_dev *input_dev = hidinput->input; if (!(ms->quirks & MS_QUIRK_FF)) return 0; + if (!list_is_first(&hidinput->list, &hdev->inputs)) + return 0; + ms->hdev = hdev; INIT_WORK(&ms->ff_worker, ms_ff_worker); @@ -352,16 +347,6 @@ static int ms_init_ff(struct hid_device *hdev) return input_ff_create_memless(input_dev, NULL, ms_play_effect); } -static void ms_remove_ff(struct hid_device *hdev) -{ - struct ms_data *ms = hid_get_drvdata(hdev); - - if (!(ms->quirks & MS_QUIRK_FF)) - return; - - cancel_work_sync(&ms->ff_worker); -} - static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) { unsigned long quirks = id->driver_data; @@ -385,29 +370,21 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = hid_parse(hdev); if (ret) { hid_err(hdev, "parse failed\n"); - goto err_free; + return ret; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ? HID_CONNECT_HIDINPUT_FORCE : 0)); if (ret) { hid_err(hdev, "hw start failed\n"); - goto err_free; + return ret; } - ret = ms_init_ff(hdev); - if (ret) - hid_err(hdev, "could not initialize ff, continuing anyway"); - return 0; -err_free: - return ret; } - static void ms_remove(struct hid_device *hdev) { hid_hw_stop(hdev); - ms_remove_ff(hdev); } static const struct hid_device_id ms_devices[] = { @@ -469,6 +446,7 @@ static struct hid_driver ms_driver = { .report_fixup = ms_report_fixup, .input_mapping = ms_input_mapping, .input_mapped = ms_input_mapped, + .input_configured = ms_input_configured, .event = ms_event, .probe = ms_probe, .remove = ms_remove, -- 2.55.0.629.g250fe7f194-goog