UPSTREAM: HID: hid-input: allow input_configured callback return errors When configuring input device via input_configured callback we may encounter errors (for example input_mt_init_slots() may fail). Instead of continuing with half-initialized input device let's allow driver indicate failures. Signed-off-by: Jaikumar Ganesh <jaikumarg@android.com> Signed-off-by: Arve Hjønnevåg <arve@android.com> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Reviewed-by: David Herrmann <dh.herrmann@gmail.com> Acked-by: Nikolai Kondrashov <Nikolai.Kondrashov@redhat.com> Acked-by: Andrew Duggan <aduggan@synaptics.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Change-Id: I3494c1937b84ff6cd654aef25b5c803aff69f61d (cherry picked from commit 9154301a47b33bdc273d8254c407792524367558) Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c index 0e6a42d..07cbc70 100644 --- a/drivers/hid/hid-appleir.c +++ b/drivers/hid/hid-appleir.c
@@ -256,7 +256,7 @@ return 0; } -static void appleir_input_configured(struct hid_device *hid, +static int appleir_input_configured(struct hid_device *hid, struct hid_input *hidinput) { struct input_dev *input_dev = hidinput->input; @@ -275,6 +275,8 @@ for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) set_bit(appleir->keymap[i], input_dev->keybit); clear_bit(KEY_RESERVED, input_dev->keybit); + + return 0; } static int appleir_input_mapping(struct hid_device *hid,
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c index 4e49462..aad8c16 100644 --- a/drivers/hid/hid-elo.c +++ b/drivers/hid/hid-elo.c
@@ -37,7 +37,7 @@ module_param(use_fw_quirk, bool, S_IRUGO); MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)"); -static void elo_input_configured(struct hid_device *hdev, +static int elo_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { struct input_dev *input = hidinput->input; @@ -45,6 +45,8 @@ set_bit(BTN_TOUCH, input->keybit); set_bit(ABS_PRESSURE, input->absbit); input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); + + return 0; } static void elo_process_data(struct input_dev *input, const u8 *data, int size)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 725f22c..d538ea9e 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c
@@ -1448,8 +1448,9 @@ * UGCI) cram a lot of unrelated inputs into the * same interface. */ hidinput->report = report; - if (drv->input_configured) - drv->input_configured(hid, hidinput); + if (drv->input_configured && + drv->input_configured(hid, hidinput)) + goto out_cleanup; if (input_register_device(hidinput->input)) goto out_cleanup; hidinput = NULL; @@ -1470,8 +1471,9 @@ } if (hidinput) { - if (drv->input_configured) - drv->input_configured(hid, hidinput); + if (drv->input_configured && + drv->input_configured(hid, hidinput)) + goto out_cleanup; if (input_register_device(hidinput->input)) goto out_cleanup; }
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 29a74c1..d6fa496 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c
@@ -471,18 +471,22 @@ return 0; } -static void magicmouse_input_configured(struct hid_device *hdev, +static int magicmouse_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct magicmouse_sc *msc = hid_get_drvdata(hdev); + int ret; - int ret = magicmouse_setup_input(msc->input, hdev); + ret = magicmouse_setup_input(msc->input, hdev); if (ret) { hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); /* clean msc->input to notify probe() of the failure */ msc->input = NULL; + return ret; } + + return 0; }
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 9080e33..437be8e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c
@@ -711,12 +711,13 @@ mt_sync_frame(td, report->field[0]->hidinput->input); } -static void mt_touch_input_configured(struct hid_device *hdev, +static int mt_touch_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; struct input_dev *input = hi->input; + int ret; if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; @@ -731,9 +732,12 @@ if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) td->mt_flags |= INPUT_MT_DROP_UNUSED; - input_mt_init_slots(input, td->maxcontacts, td->mt_flags); + ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags); + if (ret) + return ret; td->mt_flags = 0; + return 0; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, @@ -887,15 +891,19 @@ cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; } -static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) +static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct mt_device *td = hid_get_drvdata(hdev); char *name; const char *suffix = NULL; struct hid_field *field = hi->report->field[0]; + int ret; - if (hi->report->id == td->mt_report_id) - mt_touch_input_configured(hdev, hi); + if (hi->report->id == td->mt_report_id) { + ret = mt_touch_input_configured(hdev, hi); + if (ret) + return ret; + } /* * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" @@ -946,6 +954,8 @@ hi->input->name = name; } } + + return 0; } static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 600f207..756d1ef 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c
@@ -859,14 +859,14 @@ return 1; } -static void ntrig_input_configured(struct hid_device *hid, +static int ntrig_input_configured(struct hid_device *hid, struct hid_input *hidinput) { struct input_dev *input = hidinput->input; if (hidinput->report->maxfield < 1) - return; + return 0; switch (hidinput->report->field[0]->application) { case HID_DG_PEN: @@ -890,6 +890,8 @@ "N-Trig MultiTouch"; break; } + + return 0; } static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 3cccff7..a7effa4 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c
@@ -799,7 +799,7 @@ return 0; } -static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) +static int rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) { struct rmi_data *data = hid_get_drvdata(hdev); struct input_dev *input = hi->input; @@ -811,7 +811,7 @@ hid_dbg(hdev, "Opening low level driver\n"); ret = hid_hw_open(hdev); if (ret) - return; + return ret; /* Allow incoming hid reports */ hid_device_io_start(hdev); @@ -849,7 +849,9 @@ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0); input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0); - input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER); + ret = input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER); + if (ret < 0) + goto exit; if (data->button_count) { __set_bit(EV_KEY, input->evbit); @@ -865,6 +867,7 @@ exit: hid_device_io_stop(hdev); hid_hw_close(hdev); + return ret; } static int rmi_input_mapping(struct hid_device *hdev,
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index bc4269e..1e08214 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c
@@ -1100,20 +1100,27 @@ return 0; } -static void sony_input_configured(struct hid_device *hdev, +static int sony_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { struct sony_sc *sc = hid_get_drvdata(hdev); + int ret; /* * The Dualshock 4 touchpad supports 2 touches and has a * resolution of 1920x942 (44.86 dots/mm). */ if (sc->quirks & DUALSHOCK4_CONTROLLER) { - if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0) + ret = sony_register_touchpad(hidinput, 2, 1920, 942); + if (ret) { hid_err(sc->hdev, - "Unable to initialize multi-touch slots\n"); + "Unable to initialize multi-touch slots: %d\n", + ret); + return ret; + } } + + return 0; } /*
diff --git a/include/linux/hid.h b/include/linux/hid.h index 78ea9bf..15680809 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h
@@ -670,8 +670,8 @@ int (*input_mapped)(struct hid_device *hdev, struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max); - void (*input_configured)(struct hid_device *hdev, - struct hid_input *hidinput); + int (*input_configured)(struct hid_device *hdev, + struct hid_input *hidinput); void (*feature_mapping)(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage);