mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 17:41:50 +00:00
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
8 changed files with 49 additions and 42 deletions
|
@ -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);
|
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,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
||||||
USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },
|
USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
||||||
|
|
|
@ -728,6 +728,9 @@
|
||||||
#define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
|
#define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
|
||||||
#define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085
|
#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_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_VENDOR_ID_LG 0x1fd2
|
||||||
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
#define USB_DEVICE_ID_LG_MULTITOUCH 0x0064
|
||||||
|
|
|
@ -29,7 +29,7 @@ static __u8 *macally_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
return 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,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
|
||||||
USB_DEVICE_ID_MACALLY_IKEY_KEYBOARD) },
|
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_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_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_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_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_C077), HID_QUIRK_ALWAYS_POLL },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
|
{ 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");
|
dev_err(&client->dev, "failed to change power setting.\n");
|
||||||
|
|
||||||
set_pwr_exit:
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,15 +454,6 @@ static int i2c_hid_hwreset(struct i2c_client *client)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
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");
|
i2c_hid_dbg(ihid, "resetting...\n");
|
||||||
|
|
||||||
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/timekeeping.h>
|
|
||||||
|
|
||||||
#include <linux/usb.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);
|
set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
|
||||||
} else {
|
} else {
|
||||||
clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
|
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);
|
spin_unlock_irqrestore(&usbhid->lock, flags);
|
||||||
|
@ -293,23 +280,20 @@ static void hid_irq_in(struct urb *urb)
|
||||||
if (!test_bit(HID_OPENED, &usbhid->iofl))
|
if (!test_bit(HID_OPENED, &usbhid->iofl))
|
||||||
break;
|
break;
|
||||||
usbhid_mark_busy(usbhid);
|
usbhid_mark_busy(usbhid);
|
||||||
if (test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
|
||||||
if (ktime_before(ktime_get_coarse(),
|
hid_input_report(urb->context, HID_INPUT_REPORT,
|
||||||
usbhid->input_start_time))
|
urb->transfer_buffer,
|
||||||
break;
|
urb->actual_length, 1);
|
||||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
/*
|
||||||
|
* 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);
|
||||||
}
|
}
|
||||||
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;
|
break;
|
||||||
case -EPIPE: /* stall */
|
case -EPIPE: /* stall */
|
||||||
usbhid_mark_busy(usbhid);
|
usbhid_mark_busy(usbhid);
|
||||||
|
@ -736,6 +720,17 @@ static int usbhid_open(struct hid_device *hid)
|
||||||
|
|
||||||
usb_autopm_put_interface(usbhid->intf);
|
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:
|
Done:
|
||||||
mutex_unlock(&usbhid->mutex);
|
mutex_unlock(&usbhid->mutex);
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -519,12 +519,16 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case HIDIOCGUSAGE:
|
case HIDIOCGUSAGE:
|
||||||
|
if (uref->usage_index >= field->report_count)
|
||||||
|
goto inval;
|
||||||
uref->value = field->value[uref->usage_index];
|
uref->value = field->value[uref->usage_index];
|
||||||
if (copy_to_user(user_arg, uref, sizeof(*uref)))
|
if (copy_to_user(user_arg, uref, sizeof(*uref)))
|
||||||
goto fault;
|
goto fault;
|
||||||
goto goodreturn;
|
goto goodreturn;
|
||||||
|
|
||||||
case HIDIOCSUSAGE:
|
case HIDIOCSUSAGE:
|
||||||
|
if (uref->usage_index >= field->report_count)
|
||||||
|
goto inval;
|
||||||
field->value[uref->usage_index] = uref->value;
|
field->value[uref->usage_index] = uref->value;
|
||||||
goto goodreturn;
|
goto goodreturn;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/ktime.h>
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
|
@ -84,7 +83,6 @@ struct usbhid_device {
|
||||||
struct mutex mutex; /* start/stop/open/close */
|
struct mutex mutex; /* start/stop/open/close */
|
||||||
spinlock_t lock; /* fifo spinlock */
|
spinlock_t lock; /* fifo spinlock */
|
||||||
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
|
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 */
|
struct timer_list io_retry; /* Retry timer */
|
||||||
unsigned long stop_retry; /* Time to give up, in jiffies */
|
unsigned long stop_retry; /* Time to give up, in jiffies */
|
||||||
unsigned int retry_delay; /* Delay length in ms */
|
unsigned int retry_delay; /* Delay length in ms */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue