mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 11:03:07 -04:00
HID: axff: move FF initialization to .input_configured()
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 <dmitry.torokhov@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
This commit is contained in:
committed by
Jiri Kosina
parent
225c308128
commit
4e5abba2d2
@@ -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 <x0r@dv-life.ru>\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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user