[PATCH 13/21] HID: microsoft: move FF initialization to .input_configured()

Dmitry Torokhov <[email protected]>
Newsgroups org.kernel.vger.linux-kernel,org.kernel.vger.linux-doc,org.kernel.vger.linux-input
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.