Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - regression fix / revert of a commit that intended to reduce probing delay by ~50ms, but introduced a race that causes quite a few devices not to enumerate, or get stuck on first IRQ - buffer overflow fix in hiddev, from Peilin Ye * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: Revert "HID: usbhid: do not sleep when opening device" HID: hiddev: Fix slab-out-of-bounds write in hiddev_ioctl_usage() HID: quirks: Always poll three more Lenovo PixArt mice HID: i2c-hid: Always sleep 60ms after I2C_HID_PWR_ON commands HID: macally: Constify macally_id_table HID: cougar: Constify cougar_id_table
This commit is contained in:
commit
b9aa527ae3
|
@ -321,7 +321,7 @@ static const struct kernel_param_ops cougar_g6_is_space_ops = {
|
|||
};
|
||||
module_param_cb(g6_is_space, &cougar_g6_is_space_ops, &g6_is_space, 0644);
|
||||
|
||||
static struct hid_device_id cougar_id_table[] = {
|
||||
static const struct hid_device_id cougar_id_table[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
||||
USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
||||
|
|
|
@ -728,6 +728,9 @@
|
|||
#define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
|
||||
#define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085
|
||||
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d
|
||||
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019
|
||||
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e
|
||||
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093 0x6093
|
||||
|
||||
#define USB_VENDOR_ID_LG 0x1fd2
|
||||
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
||||
|
|
|
@ -29,7 +29,7 @@ static __u8 *macally_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
|||
return rdesc;
|
||||
}
|
||||
|
||||
static struct hid_device_id macally_id_table[] = {
|
||||
static const struct hid_device_id macally_id_table[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
||||
USB_DEVICE_ID_MACALLY_IKEY_KEYBOARD) },
|
||||
{ }
|
||||
|
|
|
@ -105,6 +105,9 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
|
||||
|
|
|
@ -420,6 +420,19 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)
|
|||
dev_err(&client->dev, "failed to change power setting.\n");
|
||||
|
||||
set_pwr_exit:
|
||||
|
||||
/*
|
||||
* The HID over I2C specification states that if a DEVICE needs time
|
||||
* after the PWR_ON request, it should utilise CLOCK stretching.
|
||||
* However, it has been observered that the Windows driver provides a
|
||||
* 1ms sleep between the PWR_ON and RESET requests.
|
||||
* According to Goodix Windows even waits 60 ms after (other?)
|
||||
* PWR_ON requests. Testing has confirmed that several devices
|
||||
* will not work properly without a delay after a PWR_ON request.
|
||||
*/
|
||||
if (!ret && power_state == I2C_HID_PWR_ON)
|
||||
msleep(60);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -441,15 +454,6 @@ static int i2c_hid_hwreset(struct i2c_client *client)
|
|||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* The HID over I2C specification states that if a DEVICE needs time
|
||||
* after the PWR_ON request, it should utilise CLOCK stretching.
|
||||
* However, it has been observered that the Windows driver provides a
|
||||
* 1ms sleep between the PWR_ON and RESET requests and that some devices
|
||||
* rely on this.
|
||||
*/
|
||||
usleep_range(1000, 5000);
|
||||
|
||||
i2c_hid_dbg(ihid, "resetting...\n");
|
||||
|
||||
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/timekeeping.h>
|
||||
|
||||
#include <linux/usb.h>
|
||||
|
||||
|
@ -96,18 +95,6 @@ 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);
|
||||
|
@ -293,14 +280,10 @@ 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)) {
|
||||
if (ktime_before(ktime_get_coarse(),
|
||||
usbhid->input_start_time))
|
||||
break;
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
}
|
||||
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||
hid_input_report(urb->context, HID_INPUT_REPORT,
|
||||
urb->transfer_buffer, urb->actual_length, 1);
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length, 1);
|
||||
/*
|
||||
* autosuspend refused while keys are pressed
|
||||
* because most keyboards don't wake up when
|
||||
|
@ -310,6 +293,7 @@ static void hid_irq_in(struct urb *urb)
|
|||
set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
|
||||
else
|
||||
clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
|
||||
}
|
||||
break;
|
||||
case -EPIPE: /* stall */
|
||||
usbhid_mark_busy(usbhid);
|
||||
|
@ -736,6 +720,17 @@ 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;
|
||||
|
|
|
@ -519,12 +519,16 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
|
|||
|
||||
switch (cmd) {
|
||||
case HIDIOCGUSAGE:
|
||||
if (uref->usage_index >= field->report_count)
|
||||
goto inval;
|
||||
uref->value = field->value[uref->usage_index];
|
||||
if (copy_to_user(user_arg, uref, sizeof(*uref)))
|
||||
goto fault;
|
||||
goto goodreturn;
|
||||
|
||||
case HIDIOCSUSAGE:
|
||||
if (uref->usage_index >= field->report_count)
|
||||
goto inval;
|
||||
field->value[uref->usage_index] = uref->value;
|
||||
goto goodreturn;
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timer.h>
|
||||
|
@ -84,7 +83,6 @@ 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 */
|
||||
|
|
Loading…
Reference in New Issue