Skip to content

Commit c1d6708

Browse files
jigpuJiri Kosina
authored andcommitted
HID: wacom: Do not register input devices until after hid_hw_start
If a input device is opened before hid_hw_start is called, events may not be received from the hardware. In the case of USB-backed devices, for example, the hid_hw_start function is responsible for filling in the URB which is submitted when the input device is opened. If a device is opened prematurely, polling will never start because the device will not have been in the correct state to send the URB. Because the wacom driver registers its input devices before calling hid_hw_start, there is a window of time where a device can be opened and end up in an inoperable state. Some ARM-based Chromebooks in particular reliably trigger this bug. This commit splits the wacom_register_inputs function into two pieces. One which is responsible for setting up the allocated inputs (and runs prior to hid_hw_start so that devices are ready for any input events they may end up receiving) and another which only registers the devices (and runs after hid_hw_start to ensure devices can be immediately opened without issue). Note that the functions to initialize the LEDs and remotes are also moved after hid_hw_start to maintain their own dependency chains. Fixes: 7704ac9 ("HID: wacom: implement generic HID handling for pen generic devices") Cc: [email protected] # v3.18+ Suggested-by: Dmitry Torokhov <[email protected]> Signed-off-by: Jason Gerecke <[email protected]> Tested-by: Dmitry Torokhov <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 411a20d commit c1d6708

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

drivers/hid/wacom_sys.c

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,7 +2087,7 @@ static int wacom_allocate_inputs(struct wacom *wacom)
20872087
return 0;
20882088
}
20892089

2090-
static int wacom_register_inputs(struct wacom *wacom)
2090+
static int wacom_setup_inputs(struct wacom *wacom)
20912091
{
20922092
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
20932093
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
@@ -2106,10 +2106,6 @@ static int wacom_register_inputs(struct wacom *wacom)
21062106
input_free_device(pen_input_dev);
21072107
wacom_wac->pen_input = NULL;
21082108
pen_input_dev = NULL;
2109-
} else {
2110-
error = input_register_device(pen_input_dev);
2111-
if (error)
2112-
goto fail;
21132109
}
21142110

21152111
error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac);
@@ -2118,10 +2114,6 @@ static int wacom_register_inputs(struct wacom *wacom)
21182114
input_free_device(touch_input_dev);
21192115
wacom_wac->touch_input = NULL;
21202116
touch_input_dev = NULL;
2121-
} else {
2122-
error = input_register_device(touch_input_dev);
2123-
if (error)
2124-
goto fail;
21252117
}
21262118

21272119
error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
@@ -2130,7 +2122,34 @@ static int wacom_register_inputs(struct wacom *wacom)
21302122
input_free_device(pad_input_dev);
21312123
wacom_wac->pad_input = NULL;
21322124
pad_input_dev = NULL;
2133-
} else {
2125+
}
2126+
2127+
return 0;
2128+
}
2129+
2130+
static int wacom_register_inputs(struct wacom *wacom)
2131+
{
2132+
struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
2133+
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
2134+
int error = 0;
2135+
2136+
pen_input_dev = wacom_wac->pen_input;
2137+
touch_input_dev = wacom_wac->touch_input;
2138+
pad_input_dev = wacom_wac->pad_input;
2139+
2140+
if (pen_input_dev) {
2141+
error = input_register_device(pen_input_dev);
2142+
if (error)
2143+
goto fail;
2144+
}
2145+
2146+
if (touch_input_dev) {
2147+
error = input_register_device(touch_input_dev);
2148+
if (error)
2149+
goto fail;
2150+
}
2151+
2152+
if (pad_input_dev) {
21342153
error = input_register_device(pad_input_dev);
21352154
if (error)
21362155
goto fail;
@@ -2383,6 +2402,20 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
23832402
if (error)
23842403
goto fail;
23852404

2405+
error = wacom_setup_inputs(wacom);
2406+
if (error)
2407+
goto fail;
2408+
2409+
if (features->type == HID_GENERIC)
2410+
connect_mask |= HID_CONNECT_DRIVER;
2411+
2412+
/* Regular HID work starts now */
2413+
error = hid_hw_start(hdev, connect_mask);
2414+
if (error) {
2415+
hid_err(hdev, "hw start failed\n");
2416+
goto fail;
2417+
}
2418+
23862419
error = wacom_register_inputs(wacom);
23872420
if (error)
23882421
goto fail;
@@ -2397,16 +2430,6 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
23972430
goto fail;
23982431
}
23992432

2400-
if (features->type == HID_GENERIC)
2401-
connect_mask |= HID_CONNECT_DRIVER;
2402-
2403-
/* Regular HID work starts now */
2404-
error = hid_hw_start(hdev, connect_mask);
2405-
if (error) {
2406-
hid_err(hdev, "hw start failed\n");
2407-
goto fail;
2408-
}
2409-
24102433
if (!wireless) {
24112434
/* Note that if query fails it is not a hard failure */
24122435
wacom_query_tablet_data(wacom);

0 commit comments

Comments
 (0)