aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2014-09-30 14:28:22 -0400
committerJiri Kosina <jkosina@suse.cz>2014-10-29 06:04:54 -0400
commitb905811a49bcd6e6726ce5bbb591f57aaddfd3be (patch)
treedd415409772741d9b45cf2f5d10fbf7a16d2b2f9
parent9578f41aeaee5010384f4f8484da1566e2ce4901 (diff)
HID: usbhid: prevent unwanted events to be sent when re-opening the device
When events occurs while no one is listening to the node (hid->open == 0 and usb_kill_urb() called) some events are still stacked somewhere in the USB (kernel or device?) stack. When the node gets reopened, these events are drained, and this results in spurious touch down/up, or mouse button clicks. The problem was spotted with touchscreens in fdo bug #81781 [1], but it actually occurs with any mouse using hid-generic or touchscreen. A way to reproduce it is to call: $ xinput disable 9 ; sleep 5 ; xinput enable 9 With 9 being the device ID for the touchscreen/mouse. During the "sleep", produce some touch events or click events. When "xinput enable" is called, at least one click is generated. This patch tries to fix this by draining the queue for 50 msec and during this time frame, not forwarding these old events to the hid layer. Hans completed the explanation: """ Devices like mice (basically any hid device) will have a fifo on the device side, when we stop submitting urbs to get hid reports from it, that fifo will fill up, and when we resume we will get whatever is there in that fifo. """ [1] https://bugs.freedesktop.org/show_bug.cgi?id=81781 Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/usbhid/hid-core.c36
-rw-r--r--drivers/hid/usbhid/usbhid.h1
2 files changed, 25 insertions, 12 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index ca6849a0121e..04e34b917045 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -278,18 +278,20 @@ static void hid_irq_in(struct urb *urb)
278 usbhid->retry_delay = 0; 278 usbhid->retry_delay = 0;
279 if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) 279 if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
280 break; 280 break;
281 hid_input_report(urb->context, HID_INPUT_REPORT, 281 if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
282 urb->transfer_buffer, 282 hid_input_report(urb->context, HID_INPUT_REPORT,
283 urb->actual_length, 1); 283 urb->transfer_buffer,
284 /* 284 urb->actual_length, 1);
285 * autosuspend refused while keys are pressed 285 /*
286 * because most keyboards don't wake up when 286 * autosuspend refused while keys are pressed
287 * a key is released 287 * because most keyboards don't wake up when
288 */ 288 * a key is released
289 if (hid_check_keys_pressed(hid)) 289 */
290 set_bit(HID_KEYS_PRESSED, &usbhid->iofl); 290 if (hid_check_keys_pressed(hid))
291 else 291 set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
292 clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); 292 else
293 clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
294 }
293 break; 295 break;
294 case -EPIPE: /* stall */ 296 case -EPIPE: /* stall */
295 usbhid_mark_busy(usbhid); 297 usbhid_mark_busy(usbhid);
@@ -688,6 +690,7 @@ int usbhid_open(struct hid_device *hid)
688 goto done; 690 goto done;
689 } 691 }
690 usbhid->intf->needs_remote_wakeup = 1; 692 usbhid->intf->needs_remote_wakeup = 1;
693 set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
691 res = hid_start_in(hid); 694 res = hid_start_in(hid);
692 if (res) { 695 if (res) {
693 if (res != -ENOSPC) { 696 if (res != -ENOSPC) {
@@ -701,6 +704,15 @@ int usbhid_open(struct hid_device *hid)
701 } 704 }
702 } 705 }
703 usb_autopm_put_interface(usbhid->intf); 706 usb_autopm_put_interface(usbhid->intf);
707
708 /*
709 * In case events are generated while nobody was listening,
710 * some are released when the device is re-opened.
711 * Wait 50 msec for the queue to empty before allowing events
712 * to go through hid.
713 */
714 msleep(50);
715 clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
704 } 716 }
705done: 717done:
706 mutex_unlock(&hid_open_mut); 718 mutex_unlock(&hid_open_mut);
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index f633c24ce28b..807922b49aa4 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -52,6 +52,7 @@ struct usb_interface *usbhid_find_interface(int minor);
52#define HID_STARTED 8 52#define HID_STARTED 8
53#define HID_KEYS_PRESSED 10 53#define HID_KEYS_PRESSED 10
54#define HID_NO_BANDWIDTH 11 54#define HID_NO_BANDWIDTH 11
55#define HID_RESUME_RUNNING 12
55 56
56/* 57/*
57 * USB-specific HID struct, to be pointed to 58 * USB-specific HID struct, to be pointed to