提交 5e335542 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fixes from Jiri Kosina:

 - functional regression fix for sensor-hub driver from Hans de Goede

 - stop doing device reset for i2c-hid devices, which unbreaks some of
   them (and is in line with the specification), from Kai-Heng Feng

 - error handling fix for hid-core from Gustavo A. R. Silva

 - functional regression fix for some Elan panels from Benjamin
   Tissoires

 - a few new device ID additions and misc small fixes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: i2c-hid: Don't reset device upon system resume
  HID: sensor-hub: Restore fixup for Lenovo ThinkPad Helix 2 sensor hub report
  HID: core: fix NULL pointer dereference
  HID: core: fix grouping by application
  HID: multitouch: fix Elan panels with 2 input modes declaration
  HID: hid-saitek: Add device ID for RAT 7 Contagion
  HID: core: fix memory leak on probe
  HID: input: fix leaking custom input node name
  HID: add support for Apple Magic Keyboards
  HID: i2c-hid: Fix flooded incomplete report after S3 on Rayd touchscreen
  HID: intel-ish-hid: Enable Sunrise Point-H ish driver
...@@ -335,7 +335,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -335,7 +335,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage, struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max) unsigned long **bit, int *max)
{ {
if (usage->hid == (HID_UP_CUSTOM | 0x0003)) { if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
/* The fn key on Apple USB keyboards */ /* The fn key on Apple USB keyboards */
set_bit(EV_REP, hi->input->evbit); set_bit(EV_REP, hi->input->evbit);
hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN); hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
...@@ -472,6 +473,12 @@ static const struct hid_device_id apple_devices[] = { ...@@ -472,6 +473,12 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI),
.driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_ANSI),
.driver_data = APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_ANSI),
.driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
.driver_data = APPLE_HAS_FN }, .driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
......
...@@ -1000,7 +1000,7 @@ int hid_open_report(struct hid_device *device) ...@@ -1000,7 +1000,7 @@ int hid_open_report(struct hid_device *device)
parser = vzalloc(sizeof(struct hid_parser)); parser = vzalloc(sizeof(struct hid_parser));
if (!parser) { if (!parser) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto alloc_err;
} }
parser->device = device; parser->device = device;
...@@ -1039,6 +1039,7 @@ int hid_open_report(struct hid_device *device) ...@@ -1039,6 +1039,7 @@ int hid_open_report(struct hid_device *device)
hid_err(device, "unbalanced delimiter at end of report description\n"); hid_err(device, "unbalanced delimiter at end of report description\n");
goto err; goto err;
} }
kfree(parser->collection_stack);
vfree(parser); vfree(parser);
device->status |= HID_STAT_PARSED; device->status |= HID_STAT_PARSED;
return 0; return 0;
...@@ -1047,6 +1048,8 @@ int hid_open_report(struct hid_device *device) ...@@ -1047,6 +1048,8 @@ int hid_open_report(struct hid_device *device)
hid_err(device, "item fetching failed at offset %d\n", (int)(end - start)); hid_err(device, "item fetching failed at offset %d\n", (int)(end - start));
err: err:
kfree(parser->collection_stack);
alloc_err:
vfree(parser); vfree(parser);
hid_close_report(device); hid_close_report(device);
return ret; return ret;
......
...@@ -88,6 +88,7 @@ ...@@ -88,6 +88,7 @@
#define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101 #define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101
#define USB_VENDOR_ID_APPLE 0x05ac #define USB_VENDOR_ID_APPLE 0x05ac
#define BT_VENDOR_ID_APPLE 0x004c
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
#define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e
...@@ -157,6 +158,7 @@ ...@@ -157,6 +158,7 @@
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO 0x0256
#define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS 0x0257 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS 0x0257
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI 0x0267 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI 0x0267
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_ANSI 0x026c
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291 #define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291
#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292 #define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292
...@@ -528,9 +530,6 @@ ...@@ -528,9 +530,6 @@
#define I2C_VENDOR_ID_HANTICK 0x0911 #define I2C_VENDOR_ID_HANTICK 0x0911
#define I2C_PRODUCT_ID_HANTICK_5288 0x5288 #define I2C_PRODUCT_ID_HANTICK_5288 0x5288
#define I2C_VENDOR_ID_RAYD 0x2386
#define I2C_PRODUCT_ID_RAYD_3118 0x3118
#define USB_VENDOR_ID_HANWANG 0x0b57 #define USB_VENDOR_ID_HANWANG 0x0b57
#define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000
#define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff
...@@ -950,6 +949,7 @@ ...@@ -950,6 +949,7 @@
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
#define USB_DEVICE_ID_SAITEK_PS1000 0x0621 #define USB_DEVICE_ID_SAITEK_PS1000 0x0621
#define USB_DEVICE_ID_SAITEK_RAT7_OLD 0x0ccb #define USB_DEVICE_ID_SAITEK_RAT7_OLD 0x0ccb
#define USB_DEVICE_ID_SAITEK_RAT7_CONTAGION 0x0ccd
#define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7 #define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7
#define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa #define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0 #define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
......
...@@ -1582,6 +1582,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid, ...@@ -1582,6 +1582,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid,
input_dev->dev.parent = &hid->dev; input_dev->dev.parent = &hid->dev;
hidinput->input = input_dev; hidinput->input = input_dev;
hidinput->application = application;
list_add_tail(&hidinput->list, &hid->inputs); list_add_tail(&hidinput->list, &hid->inputs);
INIT_LIST_HEAD(&hidinput->reports); INIT_LIST_HEAD(&hidinput->reports);
...@@ -1677,8 +1678,7 @@ static struct hid_input *hidinput_match_application(struct hid_report *report) ...@@ -1677,8 +1678,7 @@ static struct hid_input *hidinput_match_application(struct hid_report *report)
struct hid_input *hidinput; struct hid_input *hidinput;
list_for_each_entry(hidinput, &hid->inputs, list) { list_for_each_entry(hidinput, &hid->inputs, list) {
if (hidinput->report && if (hidinput->application == report->application)
hidinput->report->application == report->application)
return hidinput; return hidinput;
} }
...@@ -1815,6 +1815,7 @@ void hidinput_disconnect(struct hid_device *hid) ...@@ -1815,6 +1815,7 @@ void hidinput_disconnect(struct hid_device *hid)
input_unregister_device(hidinput->input); input_unregister_device(hidinput->input);
else else
input_free_device(hidinput->input); input_free_device(hidinput->input);
kfree(hidinput->name);
kfree(hidinput); kfree(hidinput);
} }
......
...@@ -1375,7 +1375,8 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev, ...@@ -1375,7 +1375,8 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
struct hid_usage *usage, struct hid_usage *usage,
enum latency_mode latency, enum latency_mode latency,
bool surface_switch, bool surface_switch,
bool button_switch) bool button_switch,
bool *inputmode_found)
{ {
struct mt_device *td = hid_get_drvdata(hdev); struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass; struct mt_class *cls = &td->mtclass;
...@@ -1387,6 +1388,14 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev, ...@@ -1387,6 +1388,14 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
switch (usage->hid) { switch (usage->hid) {
case HID_DG_INPUTMODE: case HID_DG_INPUTMODE:
/*
* Some elan panels wrongly declare 2 input mode features,
* and silently ignore when we set the value in the second
* field. Skip the second feature and hope for the best.
*/
if (*inputmode_found)
return false;
if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) { if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) {
report_len = hid_report_len(report); report_len = hid_report_len(report);
buf = hid_alloc_report_buf(report, GFP_KERNEL); buf = hid_alloc_report_buf(report, GFP_KERNEL);
...@@ -1402,6 +1411,7 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev, ...@@ -1402,6 +1411,7 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev,
} }
field->value[index] = td->inputmode_value; field->value[index] = td->inputmode_value;
*inputmode_found = true;
return true; return true;
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
...@@ -1439,6 +1449,7 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency, ...@@ -1439,6 +1449,7 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
struct hid_usage *usage; struct hid_usage *usage;
int i, j; int i, j;
bool update_report; bool update_report;
bool inputmode_found = false;
rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
list_for_each_entry(rep, &rep_enum->report_list, list) { list_for_each_entry(rep, &rep_enum->report_list, list) {
...@@ -1457,7 +1468,8 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency, ...@@ -1457,7 +1468,8 @@ static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
usage, usage,
latency, latency,
surface_switch, surface_switch,
button_switch)) button_switch,
&inputmode_found))
update_report = true; update_report = true;
} }
} }
...@@ -1685,6 +1697,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1685,6 +1697,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
*/ */
hdev->quirks |= HID_QUIRK_INPUT_PER_APP; hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
if (id->group != HID_GROUP_MULTITOUCH_WIN_8)
hdev->quirks |= HID_QUIRK_MULTI_INPUT;
timer_setup(&td->release_timer, mt_expired_timeout, 0); timer_setup(&td->release_timer, mt_expired_timeout, 0);
ret = hid_parse(hdev); ret = hid_parse(hdev);
......
...@@ -183,6 +183,8 @@ static const struct hid_device_id saitek_devices[] = { ...@@ -183,6 +183,8 @@ static const struct hid_device_id saitek_devices[] = {
.driver_data = SAITEK_RELEASE_MODE_RAT7 }, .driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
.driver_data = SAITEK_RELEASE_MODE_RAT7 }, .driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_CONTAGION),
.driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9),
.driver_data = SAITEK_RELEASE_MODE_RAT7 }, .driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9), { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9),
......
...@@ -579,6 +579,28 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev) ...@@ -579,6 +579,28 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev)
} }
EXPORT_SYMBOL_GPL(sensor_hub_device_close); EXPORT_SYMBOL_GPL(sensor_hub_device_close);
static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
/*
* Checks if the report descriptor of Thinkpad Helix 2 has a logical
* minimum for magnetic flux axis greater than the maximum.
*/
if (hdev->product == USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA &&
*rsize == 2558 && rdesc[913] == 0x17 && rdesc[914] == 0x40 &&
rdesc[915] == 0x81 && rdesc[916] == 0x08 &&
rdesc[917] == 0x00 && rdesc[918] == 0x27 &&
rdesc[921] == 0x07 && rdesc[922] == 0x00) {
/* Sets negative logical minimum for mag x, y and z */
rdesc[914] = rdesc[935] = rdesc[956] = 0xc0;
rdesc[915] = rdesc[936] = rdesc[957] = 0x7e;
rdesc[916] = rdesc[937] = rdesc[958] = 0xf7;
rdesc[917] = rdesc[938] = rdesc[959] = 0xff;
}
return rdesc;
}
static int sensor_hub_probe(struct hid_device *hdev, static int sensor_hub_probe(struct hid_device *hdev,
const struct hid_device_id *id) const struct hid_device_id *id)
{ {
...@@ -743,6 +765,7 @@ static struct hid_driver sensor_hub_driver = { ...@@ -743,6 +765,7 @@ static struct hid_driver sensor_hub_driver = {
.probe = sensor_hub_probe, .probe = sensor_hub_probe,
.remove = sensor_hub_remove, .remove = sensor_hub_remove,
.raw_event = sensor_hub_raw_event, .raw_event = sensor_hub_raw_event,
.report_fixup = sensor_hub_report_fixup,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = sensor_hub_suspend, .suspend = sensor_hub_suspend,
.resume = sensor_hub_resume, .resume = sensor_hub_resume,
......
...@@ -170,8 +170,6 @@ static const struct i2c_hid_quirks { ...@@ -170,8 +170,6 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288, { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
{ I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118,
I2C_HID_QUIRK_RESEND_REPORT_DESCR },
{ USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH, { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
I2C_HID_QUIRK_RESEND_REPORT_DESCR }, I2C_HID_QUIRK_RESEND_REPORT_DESCR },
{ 0, 0 } { 0, 0 }
...@@ -1235,11 +1233,16 @@ static int i2c_hid_resume(struct device *dev) ...@@ -1235,11 +1233,16 @@ static int i2c_hid_resume(struct device *dev)
pm_runtime_enable(dev); pm_runtime_enable(dev);
enable_irq(client->irq); enable_irq(client->irq);
ret = i2c_hid_hwreset(client);
/* Instead of resetting device, simply powers the device on. This
* solves "incomplete reports" on Raydium devices 2386:3118 and
* 2386:4B33
*/
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
if (ret) if (ret)
return ret; return ret;
/* RAYDIUM device (2386:3118) need to re-send report descr cmd /* Some devices need to re-send report descr cmd
* after resume, after this it will be back normal. * after resume, after this it will be back normal.
* otherwise it issues too many incomplete reports. * otherwise it issues too many incomplete reports.
*/ */
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#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 CNL_H_DEVICE_ID 0xA37C
#define SPT_H_DEVICE_ID 0xA135
#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
......
...@@ -38,6 +38,7 @@ static const struct pci_device_id ish_pci_tbl[] = { ...@@ -38,6 +38,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
{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)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_H_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
{0, } {0, }
}; };
MODULE_DEVICE_TABLE(pci, ish_pci_tbl); MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
......
...@@ -526,6 +526,7 @@ struct hid_input { ...@@ -526,6 +526,7 @@ struct hid_input {
const char *name; const char *name;
bool registered; bool registered;
struct list_head reports; /* the list of reports */ struct list_head reports; /* the list of reports */
unsigned int application; /* application usage for this input */
}; };
enum hid_type { enum hid_type {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册