[PATCH 03/21] HID: axff: 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() with HID_CONNECT_DEFAULT. 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-axff.c | 40 ++++++++++++----------------------------
 1 file changed, 12 insertions(+), 28 deletions(-)

diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index 3c5c2bf02425..2f46447086df 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -59,30 +59,24 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect
 	return 0;
 }
 
-static int axff_init(struct hid_device *hid)
+static int ax_input_configured(struct hid_device *hid, struct hid_input *hidinput)
 {
 	struct axff_device *axff;
 	struct hid_report *report;
-	struct hid_input *hidinput;
-	struct list_head *report_list =&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct input_dev *dev;
+	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct input_dev *dev = hidinput->input;
 	int field_count = 0;
 	int i, j;
 	int error;
 
-	if (list_empty(&hid->inputs)) {
-		hid_err(hid, "no inputs found\n");
-		return -ENODEV;
-	}
-	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
-	dev = hidinput->input;
+	if (!list_is_first(&hidinput->list, &hid->inputs))
+		return 0;
 
-	if (list_empty(report_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;
 	}
-
-	report = list_first_entry(report_list, struct hid_report, list);
 	for (i = 0; i < report->maxfield; i++) {
 		for (j = 0; j < report->field[i]->report_count; j++) {
 			report->field[i]->value[j] = 0x00;
@@ -100,13 +94,13 @@ static int axff_init(struct hid_device *hid)
 	if (!axff)
 		return -ENOMEM;
 
+	axff->report = report;
 	set_bit(FF_RUMBLE, dev->ffbit);
 
 	error = input_ff_create_memless(dev, axff, axff_play);
 	if (error)
 		goto err_free_mem;
 
-	axff->report = report;
 	hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT);
 
 	hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun <[email protected]>\n");
@@ -118,7 +112,8 @@ static int axff_init(struct hid_device *hid)
 	return error;
 }
 #else
-static inline int axff_init(struct hid_device *hid)
+static inline int ax_input_configured(struct hid_device *hid,
+				      struct hid_input *hidinput)
 {
 	return 0;
 }
@@ -136,23 +131,11 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		return error;
 	}
 
-	error = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	error = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (error) {
 		hid_err(hdev, "hw start failed\n");
 		return error;
 	}
-
-	error = axff_init(hdev);
-	if (error) {
-		/*
-		 * Do not fail device initialization completely as device
-		 * may still be partially operable, just warn.
-		 */
-		hid_warn(hdev,
-			 "Failed to enable force feedback support, error: %d\n",
-			 error);
-	}
-
 	/*
 	 * We need to start polling device right away, otherwise
 	 * it will go into a coma.
@@ -185,6 +168,7 @@ static struct hid_driver ax_driver = {
 	.id_table	= ax_devices,
 	.probe		= ax_probe,
 	.remove		= ax_remove,
+	.input_configured = ax_input_configured,
 };
 module_hid_driver(ax_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.