Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - functional regression fix for some of the Logitech unifying devices, from Hans de Goede - race condition fix in hid-sony for bug severely affecting Valve/Android deployments, from Roderick Colenbrander - several fixes for issues found by syzbot/kasan, from Oliver Neukum and Hillf Danton - functional regression fix for Wacom Cintiq device, from Aaron Armstrong Skomra - a few other assorted device-specific quirks * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: sony: Fix race condition between rumble and device remove. HID: hiddev: do cleanup in failure of opening a device HID: hiddev: avoid opening a disconnected device HID: input: fix a4tech horizontal wheel custom usage HID: Add quirk for HP X1200 PIXART OEM mouse HID: holtek: test for sanity of intfdata HID: wacom: fix bit shift for Cintiq Companion 2 HID: quirks: Set the INCREMENT_USAGE_ON_DUPLICATE quirk on Saitek X52 HID: logitech-dj: Really fix return value of logi_dj_recv_query_hidpp_devices HID: Add 044f:b320 ThrustMaster, Inc. 2 in 1 DT HID: logitech-dj: add the Powerplay receiver HID: logitech-hidpp: add USB PID for a few more supported mice HID: logitech-dj: rename "gaming" receiver to "lightspeed"
This commit is contained in:
commit
f4eb1423e4
|
@ -23,12 +23,36 @@
|
|||
#define A4_2WHEEL_MOUSE_HACK_7 0x01
|
||||
#define A4_2WHEEL_MOUSE_HACK_B8 0x02
|
||||
|
||||
#define A4_WHEEL_ORIENTATION (HID_UP_GENDESK | 0x000000b8)
|
||||
|
||||
struct a4tech_sc {
|
||||
unsigned long quirks;
|
||||
unsigned int hw_wheel;
|
||||
__s32 delayed_value;
|
||||
};
|
||||
|
||||
static int a4_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
struct a4tech_sc *a4 = hid_get_drvdata(hdev);
|
||||
|
||||
if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8 &&
|
||||
usage->hid == A4_WHEEL_ORIENTATION) {
|
||||
/*
|
||||
* We do not want to have this usage mapped to anything as it's
|
||||
* nonstandard and doesn't really behave like an HID report.
|
||||
* It's only selecting the orientation (vertical/horizontal) of
|
||||
* the previous mouse wheel report. The input_events will be
|
||||
* generated once both reports are recorded in a4_event().
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
|
@ -52,8 +76,7 @@ static int a4_event(struct hid_device *hdev, struct hid_field *field,
|
|||
struct a4tech_sc *a4 = hid_get_drvdata(hdev);
|
||||
struct input_dev *input;
|
||||
|
||||
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
|
||||
!usage->type)
|
||||
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
|
||||
return 0;
|
||||
|
||||
input = field->hidinput->input;
|
||||
|
@ -64,7 +87,7 @@ static int a4_event(struct hid_device *hdev, struct hid_field *field,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (usage->hid == 0x000100b8) {
|
||||
if (usage->hid == A4_WHEEL_ORIENTATION) {
|
||||
input_event(input, EV_REL, value ? REL_HWHEEL :
|
||||
REL_WHEEL, a4->delayed_value);
|
||||
input_event(input, EV_REL, value ? REL_HWHEEL_HI_RES :
|
||||
|
@ -131,6 +154,7 @@ MODULE_DEVICE_TABLE(hid, a4_devices);
|
|||
static struct hid_driver a4_driver = {
|
||||
.name = "a4tech",
|
||||
.id_table = a4_devices,
|
||||
.input_mapping = a4_input_mapping,
|
||||
.input_mapped = a4_input_mapped,
|
||||
.event = a4_event,
|
||||
.probe = a4_probe,
|
||||
|
|
|
@ -123,9 +123,14 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
|
|||
|
||||
/* Locate the boot interface, to receive the LED change events */
|
||||
struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0);
|
||||
struct hid_device *boot_hid;
|
||||
struct hid_input *boot_hid_input;
|
||||
|
||||
struct hid_device *boot_hid = usb_get_intfdata(boot_interface);
|
||||
struct hid_input *boot_hid_input = list_first_entry(&boot_hid->inputs,
|
||||
if (unlikely(boot_interface == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
boot_hid = usb_get_intfdata(boot_interface);
|
||||
boot_hid_input = list_first_entry(&boot_hid->inputs,
|
||||
struct hid_input, list);
|
||||
|
||||
return boot_hid_input->input->event(boot_hid_input->input, type, code,
|
||||
|
|
|
@ -568,6 +568,7 @@
|
|||
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
|
||||
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE 0x134a
|
||||
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A 0x094a
|
||||
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641 0x0641
|
||||
|
||||
#define USB_VENDOR_ID_HUION 0x256c
|
||||
#define USB_DEVICE_ID_HUION_TABLET 0x006e
|
||||
|
@ -768,7 +769,8 @@
|
|||
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER 0xc52f
|
||||
#define USB_DEVICE_ID_LOGITECH_UNIFYING_RECEIVER_2 0xc532
|
||||
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534
|
||||
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING 0xc539
|
||||
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED 0xc539
|
||||
#define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a
|
||||
#define USB_DEVICE_ID_SPACETRAVELLER 0xc623
|
||||
#define USB_DEVICE_ID_SPACENAVIGATOR 0xc626
|
||||
#define USB_DEVICE_ID_DINOVO_DESKTOP 0xc704
|
||||
|
@ -989,6 +991,7 @@
|
|||
#define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7
|
||||
#define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa
|
||||
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
|
||||
#define USB_DEVICE_ID_SAITEK_X52 0x075c
|
||||
|
||||
#define USB_VENDOR_ID_SAMSUNG 0x0419
|
||||
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
|
||||
|
|
|
@ -1125,7 +1125,7 @@ static int logi_dj_recv_query_hidpp_devices(struct dj_receiver_dev *djrcv_dev)
|
|||
HID_REQ_SET_REPORT);
|
||||
|
||||
kfree(hidpp_report);
|
||||
return retval;
|
||||
return (retval < 0) ? retval : 0;
|
||||
}
|
||||
|
||||
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
|
||||
|
@ -1832,13 +1832,17 @@ static const struct hid_device_id logi_dj_receivers[] = {
|
|||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2),
|
||||
.driver_data = recvr_type_hidpp},
|
||||
{ /* Logitech gaming receiver (0xc539) */
|
||||
{ /* Logitech lightspeed receiver (0xc539) */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_GAMING),
|
||||
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED),
|
||||
.driver_data = recvr_type_gaming_hidpp},
|
||||
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER),
|
||||
.driver_data = recvr_type_27mhz},
|
||||
{ /* Logitech powerplay receiver (0xc53a) */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY),
|
||||
.driver_data = recvr_type_gaming_hidpp},
|
||||
{ /* Logitech 27 MHz HID++ 1.0 receiver (0xc517) */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_S510_RECEIVER_2),
|
||||
|
|
|
@ -3749,15 +3749,45 @@ static const struct hid_device_id hidpp_devices[] = {
|
|||
|
||||
{ L27MHZ_DEVICE(HID_ANY_ID) },
|
||||
|
||||
{ /* Logitech G403 Gaming Mouse over USB */
|
||||
{ /* Logitech G203/Prodigy Gaming Mouse */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC084) },
|
||||
{ /* Logitech G302 Gaming Mouse */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07F) },
|
||||
{ /* Logitech G303 Gaming Mouse */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC080) },
|
||||
{ /* Logitech G400 Gaming Mouse */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07E) },
|
||||
{ /* Logitech G403 Wireless Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
|
||||
{ /* Logitech G403 Gaming Mouse */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC083) },
|
||||
{ /* Logitech G403 Hero Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08F) },
|
||||
{ /* Logitech G502 Proteus Core Gaming Mouse */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07D) },
|
||||
{ /* Logitech G502 Proteus Spectrum Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC332) },
|
||||
{ /* Logitech G502 Hero Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08B) },
|
||||
{ /* Logitech G700 Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC06B) },
|
||||
{ /* Logitech G700s Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC07C) },
|
||||
{ /* Logitech G703 Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
|
||||
{ /* Logitech G703 Hero Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC090) },
|
||||
{ /* Logitech G900 Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC081) },
|
||||
{ /* Logitech G903 Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC086) },
|
||||
{ /* Logitech G903 Hero Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC091) },
|
||||
{ /* Logitech G920 Wheel over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),
|
||||
.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS},
|
||||
{ /* Logitech G Pro Gaming Mouse over USB */
|
||||
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
|
||||
|
||||
{ /* MX5000 keyboard over Bluetooth */
|
||||
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
|
||||
|
|
|
@ -92,6 +92,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
|
||||
|
@ -141,6 +142,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPAD), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
|
||||
|
|
|
@ -585,10 +585,14 @@ static void sony_set_leds(struct sony_sc *sc);
|
|||
static inline void sony_schedule_work(struct sony_sc *sc,
|
||||
enum sony_worker which)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
switch (which) {
|
||||
case SONY_WORKER_STATE:
|
||||
if (!sc->defer_initialization)
|
||||
spin_lock_irqsave(&sc->lock, flags);
|
||||
if (!sc->defer_initialization && sc->state_worker_initialized)
|
||||
schedule_work(&sc->state_worker);
|
||||
spin_unlock_irqrestore(&sc->lock, flags);
|
||||
break;
|
||||
case SONY_WORKER_HOTPLUG:
|
||||
if (sc->hotplug_worker_initialized)
|
||||
|
@ -2558,13 +2562,18 @@ static inline void sony_init_output_report(struct sony_sc *sc,
|
|||
|
||||
static inline void sony_cancel_work_sync(struct sony_sc *sc)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (sc->hotplug_worker_initialized)
|
||||
cancel_work_sync(&sc->hotplug_worker);
|
||||
if (sc->state_worker_initialized)
|
||||
if (sc->state_worker_initialized) {
|
||||
spin_lock_irqsave(&sc->lock, flags);
|
||||
sc->state_worker_initialized = 0;
|
||||
spin_unlock_irqrestore(&sc->lock, flags);
|
||||
cancel_work_sync(&sc->state_worker);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int sony_input_configured(struct hid_device *hdev,
|
||||
struct hid_input *hidinput)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define THRUSTMASTER_DEVICE_ID_2_IN_1_DT 0xb320
|
||||
|
||||
static const signed short ff_rumble[] = {
|
||||
FF_RUMBLE,
|
||||
-1
|
||||
|
@ -76,6 +78,7 @@ static int tmff_play(struct input_dev *dev, void *data,
|
|||
struct hid_field *ff_field = tmff->ff_field;
|
||||
int x, y;
|
||||
int left, right; /* Rumbling */
|
||||
int motor_swap;
|
||||
|
||||
switch (effect->type) {
|
||||
case FF_CONSTANT:
|
||||
|
@ -100,6 +103,13 @@ static int tmff_play(struct input_dev *dev, void *data,
|
|||
ff_field->logical_minimum,
|
||||
ff_field->logical_maximum);
|
||||
|
||||
/* 2-in-1 strong motor is left */
|
||||
if (hid->product == THRUSTMASTER_DEVICE_ID_2_IN_1_DT) {
|
||||
motor_swap = left;
|
||||
left = right;
|
||||
right = motor_swap;
|
||||
}
|
||||
|
||||
dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
|
||||
ff_field->value[0] = left;
|
||||
ff_field->value[1] = right;
|
||||
|
@ -226,6 +236,8 @@ static const struct hid_device_id tm_devices[] = {
|
|||
.driver_data = (unsigned long)ff_rumble },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304), /* FireStorm Dual Power 2 (and 3) */
|
||||
.driver_data = (unsigned long)ff_rumble },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, THRUSTMASTER_DEVICE_ID_2_IN_1_DT), /* Dual Trigger 2-in-1 */
|
||||
.driver_data = (unsigned long)ff_rumble },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323), /* Dual Trigger 3-in-1 (PC Mode) */
|
||||
.driver_data = (unsigned long)ff_rumble },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324), /* Dual Trigger 3-in-1 (PS3 Mode) */
|
||||
|
|
|
@ -284,6 +284,14 @@ static int hiddev_open(struct inode *inode, struct file *file)
|
|||
spin_unlock_irq(&list->hiddev->list_lock);
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
/*
|
||||
* recheck exist with existance lock held to
|
||||
* avoid opening a disconnected device
|
||||
*/
|
||||
if (!list->hiddev->exist) {
|
||||
res = -ENODEV;
|
||||
goto bail_unlock;
|
||||
}
|
||||
if (!list->hiddev->open++)
|
||||
if (list->hiddev->exist) {
|
||||
struct hid_device *hid = hiddev->hid;
|
||||
|
@ -300,6 +308,10 @@ bail_normal_power:
|
|||
hid_hw_power(hid, PM_HINT_NORMAL);
|
||||
bail_unlock:
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
spin_lock_irq(&list->hiddev->list_lock);
|
||||
list_del(&list->node);
|
||||
spin_unlock_irq(&list->hiddev->list_lock);
|
||||
bail:
|
||||
file->private_data = NULL;
|
||||
vfree(list);
|
||||
|
|
|
@ -533,14 +533,14 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
|
|||
*/
|
||||
buttons = (data[4] << 1) | (data[3] & 0x01);
|
||||
} else if (features->type == CINTIQ_COMPANION_2) {
|
||||
/* d-pad right -> data[4] & 0x10
|
||||
* d-pad up -> data[4] & 0x20
|
||||
* d-pad left -> data[4] & 0x40
|
||||
* d-pad down -> data[4] & 0x80
|
||||
* d-pad center -> data[3] & 0x01
|
||||
/* d-pad right -> data[2] & 0x10
|
||||
* d-pad up -> data[2] & 0x20
|
||||
* d-pad left -> data[2] & 0x40
|
||||
* d-pad down -> data[2] & 0x80
|
||||
* d-pad center -> data[1] & 0x01
|
||||
*/
|
||||
buttons = ((data[2] >> 4) << 7) |
|
||||
((data[1] & 0x04) << 6) |
|
||||
((data[1] & 0x04) << 4) |
|
||||
((data[2] & 0x0F) << 2) |
|
||||
(data[1] & 0x03);
|
||||
} else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
|
||||
|
|
Loading…
Reference in New Issue