mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
Merge branches 'for-4.16/hid-quirks-cleanup/asus', 'for-4.16/hid-quirks-cleanup/elecom', 'for-4.16/hid-quirks-cleanup/ish', 'for-4.16/hid-quirks-cleanup/multitouch', 'for-4.16/hid-quirks-cleanup/pixart', 'for-4.16/hid-quirks-cleanup/rmi', 'for-4.16/hid-quirks-cleanup/sony' and 'for-4.16/hid-quirks-cleanup/toshiba' into for-linus
Pull assorted device driver fixes (ASUS, Elecom, Intel-ISH, Multitouch, PixArt, RMI, Sony and Toshiba) based on top the hid-quirks revamp.
This commit is contained in:
parent
a7acb31d6c
33edee4f3c
ac58eec2c5
7103f6b233
00720277a5
01cffe9ded
c5293409e1
169f15ab63
edfc3722cf
commit
790844941a
12 changed files with 314 additions and 63 deletions
|
@ -269,10 +269,11 @@ ABS_MT_ORIENTATION
|
||||||
The orientation of the touching ellipse. The value should describe a signed
|
The orientation of the touching ellipse. The value should describe a signed
|
||||||
quarter of a revolution clockwise around the touch center. The signed value
|
quarter of a revolution clockwise around the touch center. The signed value
|
||||||
range is arbitrary, but zero should be returned for an ellipse aligned with
|
range is arbitrary, but zero should be returned for an ellipse aligned with
|
||||||
the Y axis of the surface, a negative value when the ellipse is turned to
|
the Y axis (north) of the surface, a negative value when the ellipse is
|
||||||
the left, and a positive value when the ellipse is turned to the
|
turned to the left, and a positive value when the ellipse is turned to the
|
||||||
right. When completely aligned with the X axis, the range max should be
|
right. When aligned with the X axis in the positive direction, the range
|
||||||
returned.
|
max should be returned; when aligned with the X axis in the negative
|
||||||
|
direction, the range -max should be returned.
|
||||||
|
|
||||||
Touch ellipsis are symmetrical by default. For devices capable of true 360
|
Touch ellipsis are symmetrical by default. For devices capable of true 360
|
||||||
degree orientation, the reported orientation must exceed the range max to
|
degree orientation, the reported orientation must exceed the range max to
|
||||||
|
|
|
@ -280,6 +280,7 @@ config HID_ELECOM
|
||||||
---help---
|
---help---
|
||||||
Support for ELECOM devices:
|
Support for ELECOM devices:
|
||||||
- BM084 Bluetooth Mouse
|
- BM084 Bluetooth Mouse
|
||||||
|
- EX-G Trackball (Wired and wireless)
|
||||||
- DEFT Trackball (Wired and wireless)
|
- DEFT Trackball (Wired and wireless)
|
||||||
- HUGE Trackball (Wired and wireless)
|
- HUGE Trackball (Wired and wireless)
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* any later version.
|
* any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/dmi.h>
|
||||||
#include <linux/hid.h>
|
#include <linux/hid.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/input/mt.h>
|
#include <linux/input/mt.h>
|
||||||
|
@ -119,6 +120,24 @@ static const struct asus_touchpad_info asus_t100ta_tp = {
|
||||||
.max_contacts = 5,
|
.max_contacts = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct asus_touchpad_info asus_t100ha_tp = {
|
||||||
|
.max_x = 2640,
|
||||||
|
.max_y = 1320,
|
||||||
|
.res_x = 30, /* units/mm */
|
||||||
|
.res_y = 29, /* units/mm */
|
||||||
|
.contact_size = 5,
|
||||||
|
.max_contacts = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct asus_touchpad_info asus_t200ta_tp = {
|
||||||
|
.max_x = 3120,
|
||||||
|
.max_y = 1716,
|
||||||
|
.res_x = 30, /* units/mm */
|
||||||
|
.res_y = 28, /* units/mm */
|
||||||
|
.contact_size = 5,
|
||||||
|
.max_contacts = 5,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct asus_touchpad_info asus_t100chi_tp = {
|
static const struct asus_touchpad_info asus_t100chi_tp = {
|
||||||
.max_x = 2640,
|
.max_x = 2640,
|
||||||
.max_y = 1320,
|
.max_y = 1320,
|
||||||
|
@ -606,6 +625,16 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
|
|
||||||
if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) {
|
if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) {
|
||||||
drvdata->quirks = QUIRK_SKIP_INPUT_MAPPING;
|
drvdata->quirks = QUIRK_SKIP_INPUT_MAPPING;
|
||||||
|
/*
|
||||||
|
* The T100HA uses the same USB-ids as the T100TAF and
|
||||||
|
* the T200TA uses the same USB-ids as the T100TA, while
|
||||||
|
* both have different max x/y values as the T100TA[F].
|
||||||
|
*/
|
||||||
|
if (dmi_match(DMI_PRODUCT_NAME, "T100HAN"))
|
||||||
|
drvdata->tp = &asus_t100ha_tp;
|
||||||
|
else if (dmi_match(DMI_PRODUCT_NAME, "T200TA"))
|
||||||
|
drvdata->tp = &asus_t200ta_tp;
|
||||||
|
else
|
||||||
drvdata->tp = &asus_t100ta_tp;
|
drvdata->tp = &asus_t100ta_tp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,9 +715,10 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
|
hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
|
||||||
rdesc[55] = 0xdd;
|
rdesc[55] = 0xdd;
|
||||||
}
|
}
|
||||||
/* For the T100TA keyboard dock */
|
/* For the T100TA/T200TA keyboard dock */
|
||||||
if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
|
if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
|
||||||
*rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) {
|
(*rsize == 76 || *rsize == 101) &&
|
||||||
|
rdesc[73] == 0x81 && rdesc[74] == 0x01) {
|
||||||
hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
|
hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
|
||||||
rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
|
rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
|
||||||
}
|
}
|
||||||
|
@ -751,7 +781,10 @@ static const struct hid_device_id asus_devices[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||||
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3), QUIRK_G752_KEYBOARD },
|
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3), QUIRK_G752_KEYBOARD },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||||
USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
|
USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD),
|
||||||
|
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
|
||||||
|
USB_DEVICE_ID_ASUSTEK_T100TAF_KEYBOARD),
|
||||||
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
|
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
/*
|
/*
|
||||||
* HID driver for ELECOM devices.
|
* HID driver for ELECOM devices:
|
||||||
|
* - BM084 Bluetooth Mouse
|
||||||
|
* - EX-G Trackball (Wired and wireless)
|
||||||
|
* - DEFT Trackball (Wired and wireless)
|
||||||
|
* - HUGE Trackball (Wired and wireless)
|
||||||
|
*
|
||||||
* Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
|
* Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
|
||||||
* Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
|
* Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
* Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
* Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
||||||
* Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
|
* Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
|
||||||
|
* Copyright (c) 2017 Tomasz Kramkowski <tk@the-tk.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -19,6 +25,34 @@
|
||||||
|
|
||||||
#include "hid-ids.h"
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Certain ELECOM mice misreport their button count meaning that they only work
|
||||||
|
* correctly with the ELECOM mouse assistant software which is unavailable for
|
||||||
|
* Linux. A four extra INPUT reports and a FEATURE report are described by the
|
||||||
|
* report descriptor but it does not appear that these enable software to
|
||||||
|
* control what the extra buttons map to. The only simple and straightforward
|
||||||
|
* solution seems to involve fixing up the report descriptor.
|
||||||
|
*
|
||||||
|
* Report descriptor format:
|
||||||
|
* Positions 13, 15, 21 and 31 store the button bit count, button usage minimum,
|
||||||
|
* button usage maximum and padding bit count respectively.
|
||||||
|
*/
|
||||||
|
#define MOUSE_BUTTONS_MAX 8
|
||||||
|
static void mouse_button_fixup(struct hid_device *hdev,
|
||||||
|
__u8 *rdesc, unsigned int rsize,
|
||||||
|
int nbuttons)
|
||||||
|
{
|
||||||
|
if (rsize < 32 || rdesc[12] != 0x95 ||
|
||||||
|
rdesc[14] != 0x75 || rdesc[15] != 0x01 ||
|
||||||
|
rdesc[20] != 0x29 || rdesc[30] != 0x75)
|
||||||
|
return;
|
||||||
|
hid_info(hdev, "Fixing up Elecom mouse button count\n");
|
||||||
|
nbuttons = clamp(nbuttons, 0, MOUSE_BUTTONS_MAX);
|
||||||
|
rdesc[13] = nbuttons;
|
||||||
|
rdesc[21] = nbuttons;
|
||||||
|
rdesc[31] = MOUSE_BUTTONS_MAX - nbuttons;
|
||||||
|
}
|
||||||
|
|
||||||
static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
unsigned int *rsize)
|
unsigned int *rsize)
|
||||||
{
|
{
|
||||||
|
@ -31,45 +65,15 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
rdesc[47] = 0x00;
|
rdesc[47] = 0x00;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case USB_DEVICE_ID_ELECOM_EX_G_WIRED:
|
||||||
|
case USB_DEVICE_ID_ELECOM_EX_G_WIRELESS:
|
||||||
|
mouse_button_fixup(hdev, rdesc, *rsize, 6);
|
||||||
|
break;
|
||||||
case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
|
case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
|
||||||
case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
|
case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
|
||||||
case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
|
case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
|
||||||
case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
|
case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
|
||||||
/* The DEFT/HUGE trackball has eight buttons, but its descriptor
|
mouse_button_fixup(hdev, rdesc, *rsize, 8);
|
||||||
* only reports five, disabling the three Fn buttons on the top
|
|
||||||
* of the mouse.
|
|
||||||
*
|
|
||||||
* Apply the following diff to the descriptor:
|
|
||||||
*
|
|
||||||
* Collection (Physical), Collection (Physical),
|
|
||||||
* Report ID (1), Report ID (1),
|
|
||||||
* Report Count (5), -> Report Count (8),
|
|
||||||
* Report Size (1), Report Size (1),
|
|
||||||
* Usage Page (Button), Usage Page (Button),
|
|
||||||
* Usage Minimum (01h), Usage Minimum (01h),
|
|
||||||
* Usage Maximum (05h), -> Usage Maximum (08h),
|
|
||||||
* Logical Minimum (0), Logical Minimum (0),
|
|
||||||
* Logical Maximum (1), Logical Maximum (1),
|
|
||||||
* Input (Variable), Input (Variable),
|
|
||||||
* Report Count (1), -> Report Count (0),
|
|
||||||
* Report Size (3), Report Size (3),
|
|
||||||
* Input (Constant), Input (Constant),
|
|
||||||
* Report Size (16), Report Size (16),
|
|
||||||
* Report Count (2), Report Count (2),
|
|
||||||
* Usage Page (Desktop), Usage Page (Desktop),
|
|
||||||
* Usage (X), Usage (X),
|
|
||||||
* Usage (Y), Usage (Y),
|
|
||||||
* Logical Minimum (-32768), Logical Minimum (-32768),
|
|
||||||
* Logical Maximum (32767), Logical Maximum (32767),
|
|
||||||
* Input (Variable, Relative), Input (Variable, Relative),
|
|
||||||
* End Collection, End Collection,
|
|
||||||
*/
|
|
||||||
if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
|
|
||||||
hid_info(hdev, "Fixing up Elecom DEFT/HUGE Fn buttons\n");
|
|
||||||
rdesc[13] = 8; /* Button/Variable Report Count */
|
|
||||||
rdesc[21] = 8; /* Button/Variable Usage Maximum */
|
|
||||||
rdesc[29] = 0; /* Button/Constant Report Count */
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return rdesc;
|
return rdesc;
|
||||||
|
@ -77,6 +81,8 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||||
|
|
||||||
static const struct hid_device_id elecom_devices[] = {
|
static const struct hid_device_id elecom_devices[] = {
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
|
||||||
|
|
|
@ -178,7 +178,8 @@
|
||||||
#define USB_VENDOR_ID_ASUSTEK 0x0b05
|
#define USB_VENDOR_ID_ASUSTEK 0x0b05
|
||||||
#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
|
#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
|
||||||
#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
|
#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
|
||||||
#define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0
|
#define USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD 0x17e0
|
||||||
|
#define USB_DEVICE_ID_ASUSTEK_T100TAF_KEYBOARD 0x1807
|
||||||
#define USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD 0x8502
|
#define USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD 0x8502
|
||||||
#define USB_DEVICE_ID_ASUSTEK_T304_KEYBOARD 0x184a
|
#define USB_DEVICE_ID_ASUSTEK_T304_KEYBOARD 0x184a
|
||||||
#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
|
#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
|
||||||
|
@ -370,6 +371,8 @@
|
||||||
|
|
||||||
#define USB_VENDOR_ID_ELECOM 0x056e
|
#define USB_VENDOR_ID_ELECOM 0x056e
|
||||||
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
|
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
|
||||||
|
#define USB_DEVICE_ID_ELECOM_EX_G_WIRED 0x00fb
|
||||||
|
#define USB_DEVICE_ID_ELECOM_EX_G_WIRELESS 0x00fc
|
||||||
#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe
|
#define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe
|
||||||
#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff
|
#define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff
|
||||||
#define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c
|
#define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c
|
||||||
|
@ -535,6 +538,7 @@
|
||||||
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a
|
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A 0x0a4a
|
||||||
#define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A 0x0b4a
|
#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 0x134a
|
||||||
|
#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A 0x094a
|
||||||
|
|
||||||
#define USB_VENDOR_ID_HUION 0x256c
|
#define USB_VENDOR_ID_HUION 0x256c
|
||||||
#define USB_DEVICE_ID_HUION_TABLET 0x006e
|
#define USB_DEVICE_ID_HUION_TABLET 0x006e
|
||||||
|
@ -1156,6 +1160,7 @@
|
||||||
#define USB_VENDOR_ID_PRIMAX 0x0461
|
#define USB_VENDOR_ID_PRIMAX 0x0461
|
||||||
#define USB_DEVICE_ID_PRIMAX_MOUSE_4D22 0x4d22
|
#define USB_DEVICE_ID_PRIMAX_MOUSE_4D22 0x4d22
|
||||||
#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
|
#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
|
||||||
|
#define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72
|
||||||
|
|
||||||
|
|
||||||
#define USB_VENDOR_ID_RISO_KAGAKU 0x1294 /* Riso Kagaku Corp. */
|
#define USB_VENDOR_ID_RISO_KAGAKU 0x1294 /* Riso Kagaku Corp. */
|
||||||
|
|
|
@ -85,11 +85,12 @@ MODULE_LICENSE("GPL");
|
||||||
#define MT_IO_FLAGS_PENDING_SLOTS 2
|
#define MT_IO_FLAGS_PENDING_SLOTS 2
|
||||||
|
|
||||||
struct mt_slot {
|
struct mt_slot {
|
||||||
__s32 x, y, cx, cy, p, w, h;
|
__s32 x, y, cx, cy, p, w, h, a;
|
||||||
__s32 contactid; /* the device ContactID assigned to this slot */
|
__s32 contactid; /* the device ContactID assigned to this slot */
|
||||||
bool touch_state; /* is the touch valid? */
|
bool touch_state; /* is the touch valid? */
|
||||||
bool inrange_state; /* is the finger in proximity of the sensor? */
|
bool inrange_state; /* is the finger in proximity of the sensor? */
|
||||||
bool confidence_state; /* is the touch made by a finger? */
|
bool confidence_state; /* is the touch made by a finger? */
|
||||||
|
bool has_azimuth; /* the contact reports azimuth */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_class {
|
struct mt_class {
|
||||||
|
@ -119,6 +120,10 @@ struct mt_device {
|
||||||
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
||||||
int cc_index; /* contact count field index in the report */
|
int cc_index; /* contact count field index in the report */
|
||||||
int cc_value_index; /* contact count value index in the field */
|
int cc_value_index; /* contact count value index in the field */
|
||||||
|
int scantime_index; /* scantime field index in the report */
|
||||||
|
int scantime_val_index; /* scantime value index in the field */
|
||||||
|
int prev_scantime; /* scantime reported in the previous packet */
|
||||||
|
int left_button_state; /* left button state */
|
||||||
unsigned last_slot_field; /* the last field of a slot */
|
unsigned last_slot_field; /* the last field of a slot */
|
||||||
unsigned mt_report_id; /* the report ID of the multitouch device */
|
unsigned mt_report_id; /* the report ID of the multitouch device */
|
||||||
unsigned long initial_quirks; /* initial quirks state */
|
unsigned long initial_quirks; /* initial quirks state */
|
||||||
|
@ -582,6 +587,13 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
|
if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
|
||||||
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
|
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
|
||||||
cls->sn_height);
|
cls->sn_height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only set ABS_MT_ORIENTATION if it is not
|
||||||
|
* already set by the HID_DG_AZIMUTH usage.
|
||||||
|
*/
|
||||||
|
if (!test_bit(ABS_MT_ORIENTATION,
|
||||||
|
hi->input->absbit))
|
||||||
input_set_abs_params(hi->input,
|
input_set_abs_params(hi->input,
|
||||||
ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -599,6 +611,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
EV_MSC, MSC_TIMESTAMP);
|
EV_MSC, MSC_TIMESTAMP);
|
||||||
input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
|
input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
|
||||||
mt_store_field(usage, td, hi);
|
mt_store_field(usage, td, hi);
|
||||||
|
/* Ignore if indexes are out of bounds. */
|
||||||
|
if (field->index >= field->report->maxfield ||
|
||||||
|
usage->usage_index >= field->report_count)
|
||||||
|
return 1;
|
||||||
|
td->scantime_index = field->index;
|
||||||
|
td->scantime_val_index = usage->usage_index;
|
||||||
return 1;
|
return 1;
|
||||||
case HID_DG_CONTACTCOUNT:
|
case HID_DG_CONTACTCOUNT:
|
||||||
/* Ignore if indexes are out of bounds. */
|
/* Ignore if indexes are out of bounds. */
|
||||||
|
@ -608,6 +626,21 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
td->cc_index = field->index;
|
td->cc_index = field->index;
|
||||||
td->cc_value_index = usage->usage_index;
|
td->cc_value_index = usage->usage_index;
|
||||||
return 1;
|
return 1;
|
||||||
|
case HID_DG_AZIMUTH:
|
||||||
|
hid_map_usage(hi, usage, bit, max,
|
||||||
|
EV_ABS, ABS_MT_ORIENTATION);
|
||||||
|
/*
|
||||||
|
* Azimuth has the range of [0, MAX) representing a full
|
||||||
|
* revolution. Set ABS_MT_ORIENTATION to a quarter of
|
||||||
|
* MAX according the definition of ABS_MT_ORIENTATION
|
||||||
|
*/
|
||||||
|
input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
|
||||||
|
-field->logical_maximum / 4,
|
||||||
|
field->logical_maximum / 4,
|
||||||
|
cls->sn_move ?
|
||||||
|
field->logical_maximum / cls->sn_move : 0, 0);
|
||||||
|
mt_store_field(usage, td, hi);
|
||||||
|
return 1;
|
||||||
case HID_DG_CONTACTMAX:
|
case HID_DG_CONTACTMAX:
|
||||||
/* we don't set td->last_slot_field as contactcount and
|
/* we don't set td->last_slot_field as contactcount and
|
||||||
* contact max are global to the report */
|
* contact max are global to the report */
|
||||||
|
@ -700,6 +733,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
||||||
int wide = (s->w > s->h);
|
int wide = (s->w > s->h);
|
||||||
int major = max(s->w, s->h);
|
int major = max(s->w, s->h);
|
||||||
int minor = min(s->w, s->h);
|
int minor = min(s->w, s->h);
|
||||||
|
int orientation = wide;
|
||||||
|
|
||||||
|
if (s->has_azimuth)
|
||||||
|
orientation = s->a;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* divided by two to match visual scale of touch
|
* divided by two to match visual scale of touch
|
||||||
|
@ -716,7 +753,8 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
||||||
input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
|
input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
|
||||||
input_event(input, EV_ABS, ABS_MT_DISTANCE,
|
input_event(input, EV_ABS, ABS_MT_DISTANCE,
|
||||||
!s->touch_state);
|
!s->touch_state);
|
||||||
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
|
input_event(input, EV_ABS, ABS_MT_ORIENTATION,
|
||||||
|
orientation);
|
||||||
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
|
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
|
||||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
|
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
|
||||||
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
|
input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
|
||||||
|
@ -734,10 +772,16 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
|
||||||
*/
|
*/
|
||||||
static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
|
static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
|
||||||
{
|
{
|
||||||
|
__s32 cls = td->mtclass.name;
|
||||||
|
|
||||||
|
if (cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL)
|
||||||
|
input_event(input, EV_KEY, BTN_LEFT, td->left_button_state);
|
||||||
|
|
||||||
input_mt_sync_frame(input);
|
input_mt_sync_frame(input);
|
||||||
input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
|
input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
|
||||||
input_sync(input);
|
input_sync(input);
|
||||||
td->num_received = 0;
|
td->num_received = 0;
|
||||||
|
td->left_button_state = 0;
|
||||||
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
|
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
|
||||||
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
|
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
|
||||||
else
|
else
|
||||||
|
@ -778,9 +822,11 @@ static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
struct hid_usage *usage, __s32 value)
|
struct hid_usage *usage, __s32 value,
|
||||||
|
bool first_packet)
|
||||||
{
|
{
|
||||||
struct mt_device *td = hid_get_drvdata(hid);
|
struct mt_device *td = hid_get_drvdata(hid);
|
||||||
|
__s32 cls = td->mtclass.name;
|
||||||
__s32 quirks = td->mtclass.quirks;
|
__s32 quirks = td->mtclass.quirks;
|
||||||
struct input_dev *input = field->hidinput->input;
|
struct input_dev *input = field->hidinput->input;
|
||||||
|
|
||||||
|
@ -832,11 +878,49 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
break;
|
break;
|
||||||
case HID_DG_CONTACTCOUNT:
|
case HID_DG_CONTACTCOUNT:
|
||||||
break;
|
break;
|
||||||
|
case HID_DG_AZIMUTH:
|
||||||
|
/*
|
||||||
|
* Azimuth is counter-clockwise and ranges from [0, MAX)
|
||||||
|
* (a full revolution). Convert it to clockwise ranging
|
||||||
|
* [-MAX/2, MAX/2].
|
||||||
|
*
|
||||||
|
* Note that ABS_MT_ORIENTATION require us to report
|
||||||
|
* the limit of [-MAX/4, MAX/4], but the value can go
|
||||||
|
* out of range to [-MAX/2, MAX/2] to report an upside
|
||||||
|
* down ellipsis.
|
||||||
|
*/
|
||||||
|
if (value > field->logical_maximum / 2)
|
||||||
|
value -= field->logical_maximum;
|
||||||
|
td->curdata.a = -value;
|
||||||
|
td->curdata.has_azimuth = true;
|
||||||
|
break;
|
||||||
case HID_DG_TOUCH:
|
case HID_DG_TOUCH:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
/*
|
||||||
|
* For Win8 PTP touchpads we should only look at
|
||||||
|
* non finger/touch events in the first_packet of
|
||||||
|
* a (possible) multi-packet frame.
|
||||||
|
*/
|
||||||
|
if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||||
|
!first_packet)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For Win8 PTP touchpads we map both the clickpad click
|
||||||
|
* and any "external" left buttons to BTN_LEFT if a
|
||||||
|
* device claims to have both we need to report 1 for
|
||||||
|
* BTN_LEFT if either is pressed, so we or all values
|
||||||
|
* together and report the result in mt_sync_frame().
|
||||||
|
*/
|
||||||
|
if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||||
|
usage->type == EV_KEY && usage->code == BTN_LEFT) {
|
||||||
|
td->left_button_state |= value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (usage->type)
|
if (usage->type)
|
||||||
input_event(input, usage->type, usage->code,
|
input_event(input, usage->type, usage->code,
|
||||||
value);
|
value);
|
||||||
|
@ -855,9 +939,11 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
|
||||||
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||||
{
|
{
|
||||||
struct mt_device *td = hid_get_drvdata(hid);
|
struct mt_device *td = hid_get_drvdata(hid);
|
||||||
|
__s32 cls = td->mtclass.name;
|
||||||
struct hid_field *field;
|
struct hid_field *field;
|
||||||
|
bool first_packet;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
int r, n;
|
int r, n, scantime = 0;
|
||||||
|
|
||||||
/* sticky fingers release in progress, abort */
|
/* sticky fingers release in progress, abort */
|
||||||
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
|
||||||
|
@ -867,13 +953,31 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||||
* Includes multi-packet support where subsequent
|
* Includes multi-packet support where subsequent
|
||||||
* packets are sent with zero contactcount.
|
* packets are sent with zero contactcount.
|
||||||
*/
|
*/
|
||||||
|
if (td->scantime_index >= 0) {
|
||||||
|
field = report->field[td->scantime_index];
|
||||||
|
scantime = field->value[td->scantime_val_index];
|
||||||
|
}
|
||||||
if (td->cc_index >= 0) {
|
if (td->cc_index >= 0) {
|
||||||
struct hid_field *field = report->field[td->cc_index];
|
struct hid_field *field = report->field[td->cc_index];
|
||||||
int value = field->value[td->cc_value_index];
|
int value = field->value[td->cc_value_index];
|
||||||
if (value)
|
|
||||||
|
/*
|
||||||
|
* For Win8 PTPs the first packet (td->num_received == 0) may
|
||||||
|
* have a contactcount of 0 if there only is a button event.
|
||||||
|
* We double check that this is not a continuation packet
|
||||||
|
* of a possible multi-packet frame be checking that the
|
||||||
|
* timestamp has changed.
|
||||||
|
*/
|
||||||
|
if ((cls == MT_CLS_WIN_8 || cls == MT_CLS_WIN_8_DUAL) &&
|
||||||
|
td->num_received == 0 && td->prev_scantime != scantime)
|
||||||
|
td->num_expected = value;
|
||||||
|
/* A non 0 contact count always indicates a first packet */
|
||||||
|
else if (value)
|
||||||
td->num_expected = value;
|
td->num_expected = value;
|
||||||
}
|
}
|
||||||
|
td->prev_scantime = scantime;
|
||||||
|
|
||||||
|
first_packet = td->num_received == 0;
|
||||||
for (r = 0; r < report->maxfield; r++) {
|
for (r = 0; r < report->maxfield; r++) {
|
||||||
field = report->field[r];
|
field = report->field[r];
|
||||||
count = field->report_count;
|
count = field->report_count;
|
||||||
|
@ -883,7 +987,7 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
|
||||||
|
|
||||||
for (n = 0; n < count; n++)
|
for (n = 0; n < count; n++)
|
||||||
mt_process_mt_event(hid, field, &field->usage[n],
|
mt_process_mt_event(hid, field, &field->usage[n],
|
||||||
field->value[n]);
|
field->value[n], first_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (td->num_received >= td->num_expected)
|
if (td->num_received >= td->num_expected)
|
||||||
|
@ -1329,6 +1433,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
td->maxcontact_report_id = -1;
|
td->maxcontact_report_id = -1;
|
||||||
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
||||||
td->cc_index = -1;
|
td->cc_index = -1;
|
||||||
|
td->scantime_index = -1;
|
||||||
td->mt_report_id = -1;
|
td->mt_report_id = -1;
|
||||||
hid_set_drvdata(hdev, td);
|
hid_set_drvdata(hdev, td);
|
||||||
|
|
||||||
|
@ -1649,14 +1754,6 @@ static const struct hid_device_id mt_devices[] = {
|
||||||
MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
|
MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
|
||||||
USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
|
USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
|
||||||
|
|
||||||
/* Panasonic panels */
|
|
||||||
{ .driver_data = MT_CLS_PANASONIC,
|
|
||||||
MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
|
|
||||||
USB_DEVICE_ID_PANABOARD_UBT780) },
|
|
||||||
{ .driver_data = MT_CLS_PANASONIC,
|
|
||||||
MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
|
|
||||||
USB_DEVICE_ID_PANABOARD_UBT880) },
|
|
||||||
|
|
||||||
/* Novatek Panel */
|
/* Novatek Panel */
|
||||||
{ .driver_data = MT_CLS_NSMU,
|
{ .driver_data = MT_CLS_NSMU,
|
||||||
MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
|
MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
|
||||||
|
@ -1667,6 +1764,14 @@ static const struct hid_device_id mt_devices[] = {
|
||||||
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
|
||||||
USB_VENDOR_ID_NTRIG, 0x1b05) },
|
USB_VENDOR_ID_NTRIG, 0x1b05) },
|
||||||
|
|
||||||
|
/* Panasonic panels */
|
||||||
|
{ .driver_data = MT_CLS_PANASONIC,
|
||||||
|
MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
|
||||||
|
USB_DEVICE_ID_PANABOARD_UBT780) },
|
||||||
|
{ .driver_data = MT_CLS_PANASONIC,
|
||||||
|
MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
|
||||||
|
USB_DEVICE_ID_PANABOARD_UBT880) },
|
||||||
|
|
||||||
/* PixArt optical touch screen */
|
/* PixArt optical touch screen */
|
||||||
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
|
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
|
||||||
MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
|
MT_USB_DEVICE(USB_VENDOR_ID_PIXART,
|
||||||
|
|
|
@ -90,6 +90,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_0A4A), HID_QUIRK_ALWAYS_POLL },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
|
||||||
{ 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_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), 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_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
|
{ 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_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 },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
|
||||||
|
@ -284,7 +285,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
|
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD) },
|
||||||
|
@ -335,6 +335,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
#endif
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_HID_ELECOM)
|
#if IS_ENABLED(CONFIG_HID_ELECOM)
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRED) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_EX_G_WIRELESS) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
|
||||||
|
@ -561,6 +563,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||||
#if IS_ENABLED(CONFIG_HID_RMI)
|
#if IS_ENABLED(CONFIG_HID_RMI)
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_REZEL) },
|
||||||
#endif
|
#endif
|
||||||
#if IS_ENABLED(CONFIG_HID_ROCCAT)
|
#if IS_ENABLED(CONFIG_HID_ROCCAT)
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
|
||||||
|
@ -730,7 +733,6 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
|
||||||
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) },
|
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) },
|
||||||
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) },
|
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
|
||||||
|
@ -998,6 +1000,17 @@ bool hid_ignore(struct hid_device *hdev)
|
||||||
strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
|
strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
case USB_VENDOR_ID_ELAN:
|
||||||
|
/*
|
||||||
|
* Many Elan devices have a product id of 0x0401 and are handled
|
||||||
|
* by the elan_i2c input driver. But the ACPI HID ELAN0800 dev
|
||||||
|
* is not (and cannot be) handled by that driver ->
|
||||||
|
* Ignore all 0x0401 devs except for the ELAN0800 dev.
|
||||||
|
*/
|
||||||
|
if (hdev->product == 0x0401 &&
|
||||||
|
strncmp(hdev->name, "ELAN0800", 8) != 0)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdev->type == HID_TYPE_USBMOUSE &&
|
if (hdev->type == HID_TYPE_USBMOUSE &&
|
||||||
|
|
|
@ -731,6 +731,7 @@ static const struct hid_device_id rmi_id[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14),
|
{ HID_USB_DEVICE(USB_VENDOR_ID_RAZER, USB_DEVICE_ID_RAZER_BLADE_14),
|
||||||
.driver_data = RMI_DEVICE_HAS_PHYS_BUTTONS },
|
.driver_data = RMI_DEVICE_HAS_PHYS_BUTTONS },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X1_COVER) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_REZEL) },
|
||||||
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_RMI, HID_ANY_ID, HID_ANY_ID) },
|
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_RMI, HID_ANY_ID, HID_ANY_ID) },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
|
@ -473,6 +473,7 @@ struct motion_output_report_02 {
|
||||||
#define DS4_FEATURE_REPORT_0x02_SIZE 37
|
#define DS4_FEATURE_REPORT_0x02_SIZE 37
|
||||||
#define DS4_FEATURE_REPORT_0x05_SIZE 41
|
#define DS4_FEATURE_REPORT_0x05_SIZE 41
|
||||||
#define DS4_FEATURE_REPORT_0x81_SIZE 7
|
#define DS4_FEATURE_REPORT_0x81_SIZE 7
|
||||||
|
#define DS4_FEATURE_REPORT_0xA3_SIZE 49
|
||||||
#define DS4_INPUT_REPORT_0x11_SIZE 78
|
#define DS4_INPUT_REPORT_0x11_SIZE 78
|
||||||
#define DS4_OUTPUT_REPORT_0x05_SIZE 32
|
#define DS4_OUTPUT_REPORT_0x05_SIZE 32
|
||||||
#define DS4_OUTPUT_REPORT_0x11_SIZE 78
|
#define DS4_OUTPUT_REPORT_0x11_SIZE 78
|
||||||
|
@ -544,6 +545,8 @@ struct sony_sc {
|
||||||
struct power_supply *battery;
|
struct power_supply *battery;
|
||||||
struct power_supply_desc battery_desc;
|
struct power_supply_desc battery_desc;
|
||||||
int device_id;
|
int device_id;
|
||||||
|
unsigned fw_version;
|
||||||
|
unsigned hw_version;
|
||||||
u8 *output_report_dmabuf;
|
u8 *output_report_dmabuf;
|
||||||
|
|
||||||
#ifdef CONFIG_SONY_FF
|
#ifdef CONFIG_SONY_FF
|
||||||
|
@ -627,6 +630,29 @@ static ssize_t ds4_store_poll_interval(struct device *dev,
|
||||||
static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval,
|
static DEVICE_ATTR(bt_poll_interval, 0644, ds4_show_poll_interval,
|
||||||
ds4_store_poll_interval);
|
ds4_store_poll_interval);
|
||||||
|
|
||||||
|
static ssize_t sony_show_firmware_version(struct device *dev,
|
||||||
|
struct device_attribute
|
||||||
|
*attr, char *buf)
|
||||||
|
{
|
||||||
|
struct hid_device *hdev = to_hid_device(dev);
|
||||||
|
struct sony_sc *sc = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "0x%04x\n", sc->fw_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(firmware_version, 0444, sony_show_firmware_version, NULL);
|
||||||
|
|
||||||
|
static ssize_t sony_show_hardware_version(struct device *dev,
|
||||||
|
struct device_attribute
|
||||||
|
*attr, char *buf)
|
||||||
|
{
|
||||||
|
struct hid_device *hdev = to_hid_device(dev);
|
||||||
|
struct sony_sc *sc = hid_get_drvdata(hdev);
|
||||||
|
|
||||||
|
return snprintf(buf, PAGE_SIZE, "0x%04x\n", sc->hw_version);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(hardware_version, 0444, sony_show_hardware_version, NULL);
|
||||||
|
|
||||||
static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
|
static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc,
|
||||||
unsigned int *rsize)
|
unsigned int *rsize)
|
||||||
|
@ -1646,6 +1672,31 @@ static void dualshock4_calibration_work(struct work_struct *work)
|
||||||
spin_unlock_irqrestore(&sc->lock, flags);
|
spin_unlock_irqrestore(&sc->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dualshock4_get_version_info(struct sony_sc *sc)
|
||||||
|
{
|
||||||
|
u8 *buf;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
buf = kmalloc(DS4_FEATURE_REPORT_0xA3_SIZE, GFP_KERNEL);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = hid_hw_raw_request(sc->hdev, 0xA3, buf,
|
||||||
|
DS4_FEATURE_REPORT_0xA3_SIZE,
|
||||||
|
HID_FEATURE_REPORT,
|
||||||
|
HID_REQ_GET_REPORT);
|
||||||
|
if (ret < 0) {
|
||||||
|
kfree(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc->hw_version = get_unaligned_le16(&buf[35]);
|
||||||
|
sc->fw_version = get_unaligned_le16(&buf[41]);
|
||||||
|
|
||||||
|
kfree(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void sixaxis_set_leds_from_id(struct sony_sc *sc)
|
static void sixaxis_set_leds_from_id(struct sony_sc *sc)
|
||||||
{
|
{
|
||||||
static const u8 sixaxis_leds[10][4] = {
|
static const u8 sixaxis_leds[10][4] = {
|
||||||
|
@ -2619,6 +2670,28 @@ static int sony_input_configured(struct hid_device *hdev,
|
||||||
goto err_stop;
|
goto err_stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dualshock4_get_version_info(sc);
|
||||||
|
if (ret < 0) {
|
||||||
|
hid_err(sc->hdev, "Failed to get version data from Dualshock 4\n");
|
||||||
|
goto err_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = device_create_file(&sc->hdev->dev, &dev_attr_firmware_version);
|
||||||
|
if (ret) {
|
||||||
|
/* Make zero for cleanup reasons of sysfs entries. */
|
||||||
|
sc->fw_version = 0;
|
||||||
|
sc->hw_version = 0;
|
||||||
|
hid_err(sc->hdev, "can't create sysfs firmware_version attribute err: %d\n", ret);
|
||||||
|
goto err_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = device_create_file(&sc->hdev->dev, &dev_attr_hardware_version);
|
||||||
|
if (ret) {
|
||||||
|
sc->hw_version = 0;
|
||||||
|
hid_err(sc->hdev, "can't create sysfs hardware_version attribute err: %d\n", ret);
|
||||||
|
goto err_stop;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Dualshock 4 touchpad supports 2 touches and has a
|
* The Dualshock 4 touchpad supports 2 touches and has a
|
||||||
* resolution of 1920x942 (44.86 dots/mm).
|
* resolution of 1920x942 (44.86 dots/mm).
|
||||||
|
@ -2695,6 +2768,10 @@ static int sony_input_configured(struct hid_device *hdev,
|
||||||
*/
|
*/
|
||||||
if (sc->ds4_bt_poll_interval)
|
if (sc->ds4_bt_poll_interval)
|
||||||
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
|
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
|
||||||
|
if (sc->fw_version)
|
||||||
|
device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
|
||||||
|
if (sc->hw_version)
|
||||||
|
device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
|
||||||
if (sc->quirks & SONY_LED_SUPPORT)
|
if (sc->quirks & SONY_LED_SUPPORT)
|
||||||
sony_leds_remove(sc);
|
sony_leds_remove(sc);
|
||||||
if (sc->quirks & SONY_BATTERY_SUPPORT)
|
if (sc->quirks & SONY_BATTERY_SUPPORT)
|
||||||
|
@ -2796,6 +2873,12 @@ static void sony_remove(struct hid_device *hdev)
|
||||||
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
|
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
|
||||||
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
|
device_remove_file(&sc->hdev->dev, &dev_attr_bt_poll_interval);
|
||||||
|
|
||||||
|
if (sc->fw_version)
|
||||||
|
device_remove_file(&sc->hdev->dev, &dev_attr_firmware_version);
|
||||||
|
|
||||||
|
if (sc->hw_version)
|
||||||
|
device_remove_file(&sc->hdev->dev, &dev_attr_hardware_version);
|
||||||
|
|
||||||
sony_cancel_work_sync(sc);
|
sony_cancel_work_sync(sc);
|
||||||
|
|
||||||
kfree(sc->output_report_dmabuf);
|
kfree(sc->output_report_dmabuf);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#define SPT_Ax_DEVICE_ID 0x9D35
|
#define SPT_Ax_DEVICE_ID 0x9D35
|
||||||
#define CNL_Ax_DEVICE_ID 0x9DFC
|
#define CNL_Ax_DEVICE_ID 0x9DFC
|
||||||
#define GLK_Ax_DEVICE_ID 0x31A2
|
#define GLK_Ax_DEVICE_ID 0x31A2
|
||||||
|
#define CNL_H_DEVICE_ID 0xA37C
|
||||||
|
|
||||||
#define REVISION_ID_CHT_A0 0x6
|
#define REVISION_ID_CHT_A0 0x6
|
||||||
#define REVISION_ID_CHT_Ax_SI 0x0
|
#define REVISION_ID_CHT_Ax_SI 0x0
|
||||||
|
|
|
@ -37,6 +37,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)},
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_Ax_DEVICE_ID)},
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
|
||||||
|
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_H_DEVICE_ID)},
|
||||||
{0, }
|
{0, }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
|
||||||
|
|
|
@ -281,6 +281,7 @@ struct hid_item {
|
||||||
|
|
||||||
#define HID_DG_DEVICECONFIG 0x000d000e
|
#define HID_DG_DEVICECONFIG 0x000d000e
|
||||||
#define HID_DG_DEVICESETTINGS 0x000d0023
|
#define HID_DG_DEVICESETTINGS 0x000d0023
|
||||||
|
#define HID_DG_AZIMUTH 0x000d003f
|
||||||
#define HID_DG_CONFIDENCE 0x000d0047
|
#define HID_DG_CONFIDENCE 0x000d0047
|
||||||
#define HID_DG_WIDTH 0x000d0048
|
#define HID_DG_WIDTH 0x000d0048
|
||||||
#define HID_DG_HEIGHT 0x000d0049
|
#define HID_DG_HEIGHT 0x000d0049
|
||||||
|
|
Loading…
Reference in a new issue