mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 07:04:10 +08: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
@ -269,10 +269,11 @@ ABS_MT_ORIENTATION
|
||||
The orientation of the touching ellipse. The value should describe a signed
|
||||
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
|
||||
the Y axis of the surface, a negative value when the ellipse is 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
|
||||
returned.
|
||||
the Y axis (north) of the surface, a negative value when the ellipse is
|
||||
turned to the left, and a positive value when the ellipse is turned to the
|
||||
right. When aligned with the X axis in the positive direction, the range
|
||||
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
|
||||
degree orientation, the reported orientation must exceed the range max to
|
||||
|
@ -280,6 +280,7 @@ config HID_ELECOM
|
||||
---help---
|
||||
Support for ELECOM devices:
|
||||
- BM084 Bluetooth Mouse
|
||||
- EX-G Trackball (Wired and wireless)
|
||||
- DEFT Trackball (Wired and wireless)
|
||||
- HUGE Trackball (Wired and wireless)
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/input/mt.h>
|
||||
@ -119,6 +120,24 @@ static const struct asus_touchpad_info asus_t100ta_tp = {
|
||||
.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 = {
|
||||
.max_x = 2640,
|
||||
.max_y = 1320,
|
||||
@ -606,7 +625,17 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
|
||||
if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) {
|
||||
drvdata->quirks = QUIRK_SKIP_INPUT_MAPPING;
|
||||
drvdata->tp = &asus_t100ta_tp;
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
rdesc[55] = 0xdd;
|
||||
}
|
||||
/* For the T100TA keyboard dock */
|
||||
/* For the T100TA/T200TA keyboard dock */
|
||||
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");
|
||||
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,
|
||||
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3), QUIRK_G752_KEYBOARD },
|
||||
{ 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 },
|
||||
{ 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) },
|
||||
|
@ -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) 2016 Yuxuan Shui <yshuiv7@gmail.com>
|
||||
* Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
|
||||
* 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"
|
||||
|
||||
/*
|
||||
* 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,
|
||||
unsigned int *rsize)
|
||||
{
|
||||
@ -31,45 +65,15 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
rdesc[47] = 0x00;
|
||||
}
|
||||
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_WIRELESS:
|
||||
case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
|
||||
case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
|
||||
/* The DEFT/HUGE trackball has eight buttons, but its descriptor
|
||||
* 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 */
|
||||
}
|
||||
mouse_button_fixup(hdev, rdesc, *rsize, 8);
|
||||
break;
|
||||
}
|
||||
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[] = {
|
||||
{ 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_WIRELESS) },
|
||||
{ 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_DEVICE_ID_ASUSTEK_LCM 0x1726
|
||||
#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_T304_KEYBOARD 0x184a
|
||||
#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
|
||||
@ -370,6 +371,8 @@
|
||||
|
||||
#define USB_VENDOR_ID_ELECOM 0x056e
|
||||
#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_WIRELESS 0x00ff
|
||||
#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_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_VENDOR_ID_HUION 0x256c
|
||||
#define USB_DEVICE_ID_HUION_TABLET 0x006e
|
||||
@ -1156,6 +1160,7 @@
|
||||
#define USB_VENDOR_ID_PRIMAX 0x0461
|
||||
#define USB_DEVICE_ID_PRIMAX_MOUSE_4D22 0x4d22
|
||||
#define USB_DEVICE_ID_PRIMAX_KEYBOARD 0x4e05
|
||||
#define USB_DEVICE_ID_PRIMAX_REZEL 0x4e72
|
||||
|
||||
|
||||
#define USB_VENDOR_ID_RISO_KAGAKU 0x1294 /* Riso Kagaku Corp. */
|
||||
|
@ -85,11 +85,12 @@ MODULE_LICENSE("GPL");
|
||||
#define MT_IO_FLAGS_PENDING_SLOTS 2
|
||||
|
||||
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 */
|
||||
bool touch_state; /* is the touch valid? */
|
||||
bool inrange_state; /* is the finger in proximity of the sensor? */
|
||||
bool confidence_state; /* is the touch made by a finger? */
|
||||
bool has_azimuth; /* the contact reports azimuth */
|
||||
};
|
||||
|
||||
struct mt_class {
|
||||
@ -119,6 +120,10 @@ struct mt_device {
|
||||
unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */
|
||||
int cc_index; /* contact count field index in the report */
|
||||
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 mt_report_id; /* the report ID of the multitouch device */
|
||||
unsigned long initial_quirks; /* initial quirks state */
|
||||
@ -582,8 +587,15 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
|
||||
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
|
||||
cls->sn_height);
|
||||
input_set_abs_params(hi->input,
|
||||
ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
ABS_MT_ORIENTATION, 0, 1, 0, 0);
|
||||
}
|
||||
mt_store_field(usage, td, hi);
|
||||
return 1;
|
||||
@ -599,6 +611,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
EV_MSC, MSC_TIMESTAMP);
|
||||
input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP);
|
||||
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;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
/* 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_value_index = usage->usage_index;
|
||||
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:
|
||||
/* we don't set td->last_slot_field as contactcount and
|
||||
* 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 major = max(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
|
||||
@ -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_DISTANCE,
|
||||
!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_TOUCH_MAJOR, major);
|
||||
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)
|
||||
{
|
||||
__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_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp);
|
||||
input_sync(input);
|
||||
td->num_received = 0;
|
||||
td->left_button_state = 0;
|
||||
if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags))
|
||||
set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags);
|
||||
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,
|
||||
struct hid_usage *usage, __s32 value)
|
||||
struct hid_usage *usage, __s32 value,
|
||||
bool first_packet)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
__s32 cls = td->mtclass.name;
|
||||
__s32 quirks = td->mtclass.quirks;
|
||||
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;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
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:
|
||||
/* do nothing */
|
||||
break;
|
||||
|
||||
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)
|
||||
input_event(input, usage->type, usage->code,
|
||||
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)
|
||||
{
|
||||
struct mt_device *td = hid_get_drvdata(hid);
|
||||
__s32 cls = td->mtclass.name;
|
||||
struct hid_field *field;
|
||||
bool first_packet;
|
||||
unsigned count;
|
||||
int r, n;
|
||||
int r, n, scantime = 0;
|
||||
|
||||
/* sticky fingers release in progress, abort */
|
||||
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
|
||||
* 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) {
|
||||
struct hid_field *field = report->field[td->cc_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->prev_scantime = scantime;
|
||||
|
||||
first_packet = td->num_received == 0;
|
||||
for (r = 0; r < report->maxfield; r++) {
|
||||
field = report->field[r];
|
||||
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++)
|
||||
mt_process_mt_event(hid, field, &field->usage[n],
|
||||
field->value[n]);
|
||||
field->value[n], first_packet);
|
||||
}
|
||||
|
||||
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->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
|
||||
td->cc_index = -1;
|
||||
td->scantime_index = -1;
|
||||
td->mt_report_id = -1;
|
||||
hid_set_drvdata(hdev, td);
|
||||
|
||||
@ -1649,14 +1754,6 @@ static const struct hid_device_id mt_devices[] = {
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
|
||||
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 */
|
||||
{ .driver_data = MT_CLS_NSMU,
|
||||
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,
|
||||
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 */
|
||||
{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,
|
||||
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_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_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 },
|
||||
@ -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_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_T100_KEYBOARD) },
|
||||
{ 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_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
|
||||
#if IS_ENABLED(CONFIG_HID_ELECOM)
|
||||
{ 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_WIRELESS) },
|
||||
{ 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)
|
||||
{ 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_PRIMAX, USB_DEVICE_ID_PRIMAX_REZEL) },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HID_ROCCAT)
|
||||
{ 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_EM_LT20) },
|
||||
{ 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_ETT, USB_DEVICE_ID_TC5UH) },
|
||||
{ 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)
|
||||
return true;
|
||||
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 &&
|
||||
|
@ -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),
|
||||
.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_PRIMAX, USB_DEVICE_ID_PRIMAX_REZEL) },
|
||||
{ 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_0x05_SIZE 41
|
||||
#define DS4_FEATURE_REPORT_0x81_SIZE 7
|
||||
#define DS4_FEATURE_REPORT_0xA3_SIZE 49
|
||||
#define DS4_INPUT_REPORT_0x11_SIZE 78
|
||||
#define DS4_OUTPUT_REPORT_0x05_SIZE 32
|
||||
#define DS4_OUTPUT_REPORT_0x11_SIZE 78
|
||||
@ -544,6 +545,8 @@ struct sony_sc {
|
||||
struct power_supply *battery;
|
||||
struct power_supply_desc battery_desc;
|
||||
int device_id;
|
||||
unsigned fw_version;
|
||||
unsigned hw_version;
|
||||
u8 *output_report_dmabuf;
|
||||
|
||||
#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,
|
||||
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,
|
||||
unsigned int *rsize)
|
||||
@ -1646,6 +1672,31 @@ static void dualshock4_calibration_work(struct work_struct *work)
|
||||
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 const u8 sixaxis_leds[10][4] = {
|
||||
@ -2619,6 +2670,28 @@ static int sony_input_configured(struct hid_device *hdev,
|
||||
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
|
||||
* resolution of 1920x942 (44.86 dots/mm).
|
||||
@ -2695,6 +2768,10 @@ err_stop:
|
||||
*/
|
||||
if (sc->ds4_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)
|
||||
sony_leds_remove(sc);
|
||||
if (sc->quirks & SONY_BATTERY_SUPPORT)
|
||||
@ -2796,6 +2873,12 @@ static void sony_remove(struct hid_device *hdev)
|
||||
if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
|
||||
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);
|
||||
|
||||
kfree(sc->output_report_dmabuf);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define SPT_Ax_DEVICE_ID 0x9D35
|
||||
#define CNL_Ax_DEVICE_ID 0x9DFC
|
||||
#define GLK_Ax_DEVICE_ID 0x31A2
|
||||
#define CNL_H_DEVICE_ID 0xA37C
|
||||
|
||||
#define REVISION_ID_CHT_A0 0x6
|
||||
#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, CNL_Ax_DEVICE_ID)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, GLK_Ax_DEVICE_ID)},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_H_DEVICE_ID)},
|
||||
{0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
|
||||
|
@ -281,6 +281,7 @@ struct hid_item {
|
||||
|
||||
#define HID_DG_DEVICECONFIG 0x000d000e
|
||||
#define HID_DG_DEVICESETTINGS 0x000d0023
|
||||
#define HID_DG_AZIMUTH 0x000d003f
|
||||
#define HID_DG_CONFIDENCE 0x000d0047
|
||||
#define HID_DG_WIDTH 0x000d0048
|
||||
#define HID_DG_HEIGHT 0x000d0049
|
||||
|
Loading…
Reference in New Issue
Block a user