[PATCH 17/21] HID: mayflash: 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-mf.c | 77 ++++++++++++++++++----------------------------------
 1 file changed, 27 insertions(+), 50 deletions(-)

diff --git a/drivers/hid/hid-mf.c b/drivers/hid/hid-mf.c
index 6ff54a1ec697..136e8b41d5f4 100644
--- a/drivers/hid/hid-mf.c
+++ b/drivers/hid/hid-mf.c
@@ -54,61 +54,45 @@ static int mf_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 	return 0;
 }
 
-static int mf_init(struct hid_device *hid)
+static int mf_input_configured(struct hid_device *hid, struct hid_input *hidinput)
 {
 	struct mf_device *mf;
-
 	struct list_head *report_list =
 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-
-	struct list_head *report_ptr;
 	struct hid_report *report;
-
-	struct list_head *input_ptr = &hid->inputs;
-	struct hid_input *input;
-
-	struct input_dev *dev;
-
+	struct input_dev *dev = hidinput->input;
 	int error;
 
-	/* Setup each of the four inputs */
-	list_for_each(report_ptr, report_list) {
-		report = list_entry(report_ptr, struct hid_report, list);
+	if (!list_is_first(&hidinput->list, &hid->inputs))
+		return 0;
 
-		if (report->maxfield < 1 || report->field[0]->report_count < 2) {
-			hid_err(hid, "Invalid report, this should never happen!\n");
-			return -ENODEV;
-		}
-
-		if (list_is_last(input_ptr, &hid->inputs)) {
-			hid_err(hid, "Missing input, this should never happen!\n");
-			return -ENODEV;
-		}
-
-		input_ptr = input_ptr->next;
-		input = list_entry(input_ptr, struct hid_input, list);
+	report = list_first_entry_or_null(report_list, struct hid_report, list);
+	if (!report) {
+		hid_err(hid, "no output reports found\n");
+		return -ENODEV;
+	}
 
-		mf = kzalloc_obj(struct mf_device);
-		if (!mf)
-			return -ENOMEM;
+	if (report->maxfield < 1 || report->field[0]->report_count < 2) {
+		hid_err(hid, "Invalid report, this should never happen!\n");
+		return -ENODEV;
+	}
 
-		dev = input->input;
-		set_bit(FF_RUMBLE, dev->ffbit);
+	mf = kzalloc_obj(struct mf_device);
+	if (!mf)
+		return -ENOMEM;
 
-		error = input_ff_create_memless(dev, mf, mf_play);
-		if (error) {
-			kfree(mf);
-			return error;
-		}
+	mf->report = report;
+	set_bit(FF_RUMBLE, dev->ffbit);
 
-		mf->report = report;
-		mf->report->field[0]->value[0] = 0x00;
-		mf->report->field[0]->value[1] = 0x00;
-		hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT);
+	error = input_ff_create_memless(dev, mf, mf_play);
+	if (error) {
+		kfree(mf);
+		return error;
 	}
 
-	hid_info(hid, "Force feedback for HJZ Mayflash game controller "
-		      "adapters by Marcel Hasler <[email protected]>\n");
+	mf->report->field[0]->value[0] = 0x00;
+	mf->report->field[0]->value[1] = 0x00;
+	hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT);
 
 	return 0;
 }
@@ -128,22 +112,14 @@ static int mf_probe(struct hid_device *hid, const struct hid_device_id *id)
 		return error;
 	}
 
-	error = hid_hw_start(hid, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	error = hid_hw_start(hid, HID_CONNECT_DEFAULT);
 	if (error) {
 		hid_err(hid, "HID hw start failed\n");
 		return error;
 	}
 
-	error = mf_init(hid);
-	if (error) {
-		hid_err(hid, "Force feedback init failed.\n");
-		hid_hw_stop(hid);
-		return error;
-	}
-
 	return 0;
 }
-
 static const struct hid_device_id mf_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3),
 		.driver_data = HID_QUIRK_MULTI_INPUT },
@@ -163,6 +139,7 @@ static struct hid_driver mf_driver = {
 	.name = "hid_mf",
 	.id_table = mf_devices,
 	.probe = mf_probe,
+	.input_configured = mf_input_configured,
 };
 module_hid_driver(mf_driver);
 

-- 
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.