summaryrefslogtreecommitdiff
path: root/drivers/hid/usbhid
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-08-10 16:33:54 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-10 16:33:54 -0700
commitb7b8e3689aa0b2def48b8c6eb1df060902eb2c0a (patch)
tree13e70f87a3af6f71fcd65580054924966638170e /drivers/hid/usbhid
parentfc80c51fd4b23ec007e88d4c688f2cac1b8648e7 (diff)
parente6b6e19a4be74fb3b96f66d478ed69a088e4d11c (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - fix for some modern devices that return multi-byte battery report, from Grant Likely - fix for devices with Resolution Multiplier, from Peter Hutterer - device probing speed increase, from Dmitry Torokhov - ThinkPad 10 Ultrabook Keyboard support, from Hans de Goede - other small assorted fixes and device ID additions * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: quirks: add NOGET quirk for Logitech GROUP HID: Replace HTTP links with HTTPS ones HID: udraw-ps3: Replace HTTP links with HTTPS ones HID: mcp2221: Replace HTTP links with HTTPS ones HID: input: Fix devices that return multiple bytes in battery report HID: lenovo: Fix spurious F23 key press report during resume from suspend HID: lenovo: Add ThinkPad 10 Ultrabook Keyboard fn_lock support HID: lenovo: Add ThinkPad 10 Ultrabook Keyboard support HID: lenovo: Rename fn_lock sysfs attr handlers to make them generic HID: lenovo: Factor out generic parts of the LED code HID: lenovo: Merge tpkbd and cptkbd data structures HID: intel-ish-hid: Replace PCI_DEV_FLAGS_NO_D3 with pci_save_state HID: Wiimote: Treat the d-pad as an analogue stick HID: input: do not run GET_REPORT unless there's a Resolution Multiplier HID: usbhid: remove redundant assignment to variable retval HID: usbhid: do not sleep when opening device
Diffstat (limited to 'drivers/hid/usbhid')
-rw-r--r--drivers/hid/usbhid/hid-core.c55
-rw-r--r--drivers/hid/usbhid/usbhid.h2
2 files changed, 32 insertions, 25 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 17a638f15082..492dd641a25d 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -26,6 +26,7 @@
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/string.h>
+#include <linux/timekeeping.h>
#include <linux/usb.h>
@@ -95,6 +96,18 @@ static int hid_start_in(struct hid_device *hid)
set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
} else {
clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
+
+ if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
+ /*
+ * In case events are generated while nobody was
+ * listening, some are released when the device
+ * is re-opened. Wait 50 msec for the queue to
+ * empty before allowing events to go through
+ * hid.
+ */
+ usbhid->input_start_time =
+ ktime_add_ms(ktime_get_coarse(), 50);
+ }
}
}
spin_unlock_irqrestore(&usbhid->lock, flags);
@@ -280,20 +293,23 @@ static void hid_irq_in(struct urb *urb)
if (!test_bit(HID_OPENED, &usbhid->iofl))
break;
usbhid_mark_busy(usbhid);
- if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
- hid_input_report(urb->context, HID_INPUT_REPORT,
- urb->transfer_buffer,
- urb->actual_length, 1);
- /*
- * autosuspend refused while keys are pressed
- * because most keyboards don't wake up when
- * a key is released
- */
- if (hid_check_keys_pressed(hid))
- set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
- else
- clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
+ if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
+ if (ktime_before(ktime_get_coarse(),
+ usbhid->input_start_time))
+ break;
+ clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
}
+ hid_input_report(urb->context, HID_INPUT_REPORT,
+ urb->transfer_buffer, urb->actual_length, 1);
+ /*
+ * autosuspend refused while keys are pressed
+ * because most keyboards don't wake up when
+ * a key is released
+ */
+ if (hid_check_keys_pressed(hid))
+ set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
+ else
+ clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
break;
case -EPIPE: /* stall */
usbhid_mark_busy(usbhid);
@@ -720,17 +736,6 @@ static int usbhid_open(struct hid_device *hid)
usb_autopm_put_interface(usbhid->intf);
- /*
- * In case events are generated while nobody was listening,
- * some are released when the device is re-opened.
- * Wait 50 msec for the queue to empty before allowing events
- * to go through hid.
- */
- if (res == 0)
- msleep(50);
-
- clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
-
Done:
mutex_unlock(&usbhid->mutex);
return res;
@@ -1667,7 +1672,7 @@ struct usb_interface *usbhid_find_interface(int minor)
static int __init hid_init(void)
{
- int retval = -ENOMEM;
+ int retval;
retval = hid_quirks_init(quirks_param, BUS_USB, MAX_USBHID_BOOT_QUIRKS);
if (retval)
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h
index 75fe85d3d27a..c6ad684d099a 100644
--- a/drivers/hid/usbhid/usbhid.h
+++ b/drivers/hid/usbhid/usbhid.h
@@ -13,6 +13,7 @@
#include <linux/types.h>
#include <linux/slab.h>
+#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/timer.h>
@@ -83,6 +84,7 @@ struct usbhid_device {
struct mutex mutex; /* start/stop/open/close */
spinlock_t lock; /* fifo spinlock */
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
+ ktime_t input_start_time; /* When to start handling input */
struct timer_list io_retry; /* Retry timer */
unsigned long stop_retry; /* Time to give up, in jiffies */
unsigned int retry_delay; /* Delay length in ms */