提交 231bc539 编写于 作者: L Linus Torvalds

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

Pull HID fixes from Jiri Kosina:

 - memory leak fix in usbhid from Anirudh Rayabharam

 - additions for a few new recognized generic key IDs from Dmitry
   Torokhov

 - Asus T101HA and Dell K15A quirks from Hans de Goede

 - memory leak fix in amd_sfh from Basavaraj Natikar

 - Win8 compatibility and Stylus fixes in multitouch driver from
   Ahelenia Ziemiańska

 - NULL pointer dereference fix in hid-magicmouse from Johan Hovold

 - assorted other small fixes and device ID additions

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (33 commits)
  HID: asus: Cleanup Asus T101HA keyboard-dock handling
  HID: magicmouse: fix NULL-deref on disconnect
  HID: intel-ish-hid: ipc: Add Alder Lake device IDs
  HID: i2c-hid: fix format string mismatch
  HID: amd_sfh: Fix memory leak in amd_sfh_work
  HID: amd_sfh: Use devm_kzalloc() instead of kzalloc()
  HID: ft260: improve error handling of ft260_hid_feature_report_get()
  HID: magicmouse: fix crash when disconnecting Magic Trackpad 2
  HID: gt683r: add missing MODULE_DEVICE_TABLE
  HID: pidff: fix error return code in hid_pidff_init()
  HID: logitech-hidpp: initialize level variable
  HID: multitouch: Disable event reporting on suspend on the Asus T101HA touchpad
  HID: core: Remove extraneous empty line before EXPORT_SYMBOL_GPL(hid_check_keys_pressed)
  HID: hid-sensor-custom: Process failure of sensor_hub_set_feature()
  HID: i2c-hid: Skip ELAN power-on command after reset
  HID: usbhid: fix info leak in hid_submit_ctrl
  HID: Add BUS_VIRTUAL to hid_connect logging
  HID: multitouch: set Stylus suffix for Stylus-application devices, too
  HID: multitouch: require Finger field to mark Win8 reports as MT
  HID: remove the unnecessary redefinition of a macro
  ...
...@@ -93,11 +93,11 @@ menu "Special HID drivers" ...@@ -93,11 +93,11 @@ menu "Special HID drivers"
depends on HID depends on HID
config HID_A4TECH config HID_A4TECH
tristate "A4 tech mice" tristate "A4TECH mice"
depends on HID depends on HID
default !EXPERT default !EXPERT
help help
Support for A4 tech X5 and WOP-35 / Trust 450L mice. Support for some A4TECH mice with two scroll wheels.
config HID_ACCUTOUCH config HID_ACCUTOUCH
tristate "Accutouch touch device" tristate "Accutouch touch device"
...@@ -922,6 +922,21 @@ config HID_SAMSUNG ...@@ -922,6 +922,21 @@ config HID_SAMSUNG
help help
Support for Samsung InfraRed remote control or keyboards. Support for Samsung InfraRed remote control or keyboards.
config HID_SEMITEK
tristate "Semitek USB keyboards"
depends on HID
help
Support for Semitek USB keyboards that are not fully compliant
with the HID standard.
There are many variants, including:
- GK61, GK64, GK68, GK84, GK96, etc.
- SK61, SK64, SK68, SK84, SK96, etc.
- Dierya DK61/DK66
- Tronsmart TK09R
- Woo-dy
- X-Bows Nature/Knight
config HID_SONY config HID_SONY
tristate "Sony PS2/3/4 accessories" tristate "Sony PS2/3/4 accessories"
depends on USB_HID depends on USB_HID
......
...@@ -106,6 +106,7 @@ obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ ...@@ -106,6 +106,7 @@ obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
obj-$(CONFIG_HID_RMI) += hid-rmi.o obj-$(CONFIG_HID_RMI) += hid-rmi.o
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SEMITEK) += hid-semitek.o
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
obj-$(CONFIG_HID_SONY) += hid-sony.o obj-$(CONFIG_HID_SONY) += hid-sony.o
obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o
......
...@@ -88,6 +88,7 @@ static void amd_sfh_work(struct work_struct *work) ...@@ -88,6 +88,7 @@ static void amd_sfh_work(struct work_struct *work)
sensor_index = req_node->sensor_idx; sensor_index = req_node->sensor_idx;
report_id = req_node->report_id; report_id = req_node->report_id;
node_type = req_node->report_type; node_type = req_node->report_type;
kfree(req_node);
if (node_type == HID_FEATURE_REPORT) { if (node_type == HID_FEATURE_REPORT) {
report_size = get_feature_report(sensor_index, report_id, report_size = get_feature_report(sensor_index, report_id,
...@@ -142,7 +143,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -142,7 +143,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
int rc, i; int rc, i;
dev = &privdata->pdev->dev; dev = &privdata->pdev->dev;
cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL); cl_data = devm_kzalloc(dev, sizeof(*cl_data), GFP_KERNEL);
if (!cl_data) if (!cl_data)
return -ENOMEM; return -ENOMEM;
...@@ -175,12 +176,12 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -175,12 +176,12 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
rc = -EINVAL; rc = -EINVAL;
goto cleanup; goto cleanup;
} }
cl_data->feature_report[i] = kzalloc(feature_report_size, GFP_KERNEL); cl_data->feature_report[i] = devm_kzalloc(dev, feature_report_size, GFP_KERNEL);
if (!cl_data->feature_report[i]) { if (!cl_data->feature_report[i]) {
rc = -ENOMEM; rc = -ENOMEM;
goto cleanup; goto cleanup;
} }
cl_data->input_report[i] = kzalloc(input_report_size, GFP_KERNEL); cl_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
if (!cl_data->input_report[i]) { if (!cl_data->input_report[i]) {
rc = -ENOMEM; rc = -ENOMEM;
goto cleanup; goto cleanup;
...@@ -189,7 +190,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -189,7 +190,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
info.sensor_idx = cl_idx; info.sensor_idx = cl_idx;
info.dma_address = cl_data->sensor_dma_addr[i]; info.dma_address = cl_data->sensor_dma_addr[i];
cl_data->report_descr[i] = kzalloc(cl_data->report_descr_sz[i], GFP_KERNEL); cl_data->report_descr[i] =
devm_kzalloc(dev, cl_data->report_descr_sz[i], GFP_KERNEL);
if (!cl_data->report_descr[i]) { if (!cl_data->report_descr[i]) {
rc = -ENOMEM; rc = -ENOMEM;
goto cleanup; goto cleanup;
...@@ -214,11 +216,11 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -214,11 +216,11 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
cl_data->sensor_virt_addr[i], cl_data->sensor_virt_addr[i],
cl_data->sensor_dma_addr[i]); cl_data->sensor_dma_addr[i]);
} }
kfree(cl_data->feature_report[i]); devm_kfree(dev, cl_data->feature_report[i]);
kfree(cl_data->input_report[i]); devm_kfree(dev, cl_data->input_report[i]);
kfree(cl_data->report_descr[i]); devm_kfree(dev, cl_data->report_descr[i]);
} }
kfree(cl_data); devm_kfree(dev, cl_data);
return rc; return rc;
} }
...@@ -241,6 +243,5 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata) ...@@ -241,6 +243,5 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
cl_data->sensor_dma_addr[i]); cl_data->sensor_dma_addr[i]);
} }
} }
kfree(cl_data);
return 0; return 0;
} }
...@@ -162,9 +162,6 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data) ...@@ -162,9 +162,6 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data)
int i; int i;
for (i = 0; i < cli_data->num_hid_devices; ++i) { for (i = 0; i < cli_data->num_hid_devices; ++i) {
kfree(cli_data->feature_report[i]);
kfree(cli_data->input_report[i]);
kfree(cli_data->report_descr[i]);
if (cli_data->hid_sensor_hubs[i]) { if (cli_data->hid_sensor_hubs[i]) {
kfree(cli_data->hid_sensor_hubs[i]->driver_data); kfree(cli_data->hid_sensor_hubs[i]->driver_data);
hid_destroy_device(cli_data->hid_sensor_hubs[i]); hid_destroy_device(cli_data->hid_sensor_hubs[i]);
......
...@@ -147,6 +147,8 @@ static const struct hid_device_id a4_devices[] = { ...@@ -147,6 +147,8 @@ static const struct hid_device_id a4_devices[] = {
.driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, .driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649), { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649),
.driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, .driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_NB_95),
.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, a4_devices); MODULE_DEVICE_TABLE(hid, a4_devices);
......
...@@ -79,10 +79,9 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad"); ...@@ -79,10 +79,9 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_T100_KEYBOARD BIT(6) #define QUIRK_T100_KEYBOARD BIT(6)
#define QUIRK_T100CHI BIT(7) #define QUIRK_T100CHI BIT(7)
#define QUIRK_G752_KEYBOARD BIT(8) #define QUIRK_G752_KEYBOARD BIT(8)
#define QUIRK_T101HA_DOCK BIT(9) #define QUIRK_T90CHI BIT(9)
#define QUIRK_T90CHI BIT(10) #define QUIRK_MEDION_E1239T BIT(10)
#define QUIRK_MEDION_E1239T BIT(11) #define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
#define QUIRK_ROG_NKEY_KEYBOARD BIT(12)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \ #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \ QUIRK_NO_INIT_REPORTS | \
...@@ -335,7 +334,7 @@ static int asus_raw_event(struct hid_device *hdev, ...@@ -335,7 +334,7 @@ static int asus_raw_event(struct hid_device *hdev,
if (drvdata->quirks & QUIRK_MEDION_E1239T) if (drvdata->quirks & QUIRK_MEDION_E1239T)
return asus_e1239t_event(drvdata, data, size); return asus_e1239t_event(drvdata, data, size);
if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) {
/* /*
* Skip these report ID, the device emits a continuous stream associated * Skip these report ID, the device emits a continuous stream associated
* with the AURA mode it is in which looks like an 'echo'. * with the AURA mode it is in which looks like an 'echo'.
...@@ -355,6 +354,16 @@ static int asus_raw_event(struct hid_device *hdev, ...@@ -355,6 +354,16 @@ static int asus_raw_event(struct hid_device *hdev,
return -1; return -1;
} }
} }
if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) {
/*
* G713 and G733 send these codes on some keypresses, depending on
* the key pressed it can trigger a shutdown event if not caught.
*/
if(data[0] == 0x02 && data[1] == 0x30) {
return -1;
}
}
} }
return 0; return 0;
...@@ -1072,11 +1081,6 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1072,11 +1081,6 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret; return ret;
} }
/* use hid-multitouch for T101HA touchpad */
if (id->driver_data & QUIRK_T101HA_DOCK &&
hdev->collection->usage == HID_GD_MOUSE)
return -ENODEV;
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) { if (ret) {
hid_err(hdev, "Asus hw start failed: %d\n", ret); hid_err(hdev, "Asus hw start failed: %d\n", ret);
...@@ -1230,8 +1234,6 @@ static const struct hid_device_id asus_devices[] = { ...@@ -1230,8 +1234,6 @@ 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_T100TAF_KEYBOARD), 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_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD), QUIRK_T101HA_DOCK },
{ 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) },
{ 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) },
...@@ -1239,6 +1241,12 @@ static const struct hid_device_id asus_devices[] = { ...@@ -1239,6 +1241,12 @@ static const struct hid_device_id asus_devices[] = {
USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI }, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI },
{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE_MEDION_E1239T), { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE_MEDION_E1239T),
QUIRK_MEDION_E1239T }, QUIRK_MEDION_E1239T },
/*
* Note bind to the HID_GROUP_GENERIC group, so that we only bind to the keyboard
* part, while letting hid-multitouch.c handle the touchpad.
*/
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, asus_devices); MODULE_DEVICE_TABLE(hid, asus_devices);
......
...@@ -2005,6 +2005,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) ...@@ -2005,6 +2005,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
case BUS_I2C: case BUS_I2C:
bus = "I2C"; bus = "I2C";
break; break;
case BUS_VIRTUAL:
bus = "VIRTUAL";
break;
default: default:
bus = "<UNKNOWN>"; bus = "<UNKNOWN>";
} }
...@@ -2588,7 +2591,6 @@ int hid_check_keys_pressed(struct hid_device *hid) ...@@ -2588,7 +2591,6 @@ int hid_check_keys_pressed(struct hid_device *hid)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(hid_check_keys_pressed); EXPORT_SYMBOL_GPL(hid_check_keys_pressed);
static int __init hid_init(void) static int __init hid_init(void)
......
...@@ -930,6 +930,9 @@ static const char *keys[KEY_MAX + 1] = { ...@@ -930,6 +930,9 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_APPSELECT] = "AppSelect", [KEY_APPSELECT] = "AppSelect",
[KEY_SCREENSAVER] = "ScreenSaver", [KEY_SCREENSAVER] = "ScreenSaver",
[KEY_VOICECOMMAND] = "VoiceCommand", [KEY_VOICECOMMAND] = "VoiceCommand",
[KEY_ASSISTANT] = "Assistant",
[KEY_KBD_LAYOUT_NEXT] = "KbdLayoutNext",
[KEY_EMOJI_PICKER] = "EmojiPicker",
[KEY_BRIGHTNESS_MIN] = "BrightnessMin", [KEY_BRIGHTNESS_MIN] = "BrightnessMin",
[KEY_BRIGHTNESS_MAX] = "BrightnessMax", [KEY_BRIGHTNESS_MAX] = "BrightnessMax",
[KEY_BRIGHTNESS_AUTO] = "BrightnessAuto", [KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
......
...@@ -201,7 +201,7 @@ struct ft260_i2c_write_request_report { ...@@ -201,7 +201,7 @@ struct ft260_i2c_write_request_report {
u8 address; /* 7-bit I2C address */ u8 address; /* 7-bit I2C address */
u8 flag; /* I2C transaction condition */ u8 flag; /* I2C transaction condition */
u8 length; /* data payload length */ u8 length; /* data payload length */
u8 data[60]; /* data payload */ u8 data[FT260_WR_DATA_MAX]; /* data payload */
} __packed; } __packed;
struct ft260_i2c_read_request_report { struct ft260_i2c_read_request_report {
...@@ -249,7 +249,10 @@ static int ft260_hid_feature_report_get(struct hid_device *hdev, ...@@ -249,7 +249,10 @@ static int ft260_hid_feature_report_get(struct hid_device *hdev,
ret = hid_hw_raw_request(hdev, report_id, buf, len, HID_FEATURE_REPORT, ret = hid_hw_raw_request(hdev, report_id, buf, len, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT); HID_REQ_GET_REPORT);
memcpy(data, buf, len); if (likely(ret == len))
memcpy(data, buf, len);
else if (ret >= 0)
ret = -EIO;
kfree(buf); kfree(buf);
return ret; return ret;
} }
...@@ -298,7 +301,7 @@ static int ft260_xfer_status(struct ft260_device *dev) ...@@ -298,7 +301,7 @@ static int ft260_xfer_status(struct ft260_device *dev)
ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS, ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,
(u8 *)&report, sizeof(report)); (u8 *)&report, sizeof(report));
if (ret < 0) { if (unlikely(ret < 0)) {
hid_err(hdev, "failed to retrieve status: %d\n", ret); hid_err(hdev, "failed to retrieve status: %d\n", ret);
return ret; return ret;
} }
...@@ -429,6 +432,9 @@ static int ft260_smbus_write(struct ft260_device *dev, u8 addr, u8 cmd, ...@@ -429,6 +432,9 @@ static int ft260_smbus_write(struct ft260_device *dev, u8 addr, u8 cmd,
struct ft260_i2c_write_request_report *rep = struct ft260_i2c_write_request_report *rep =
(struct ft260_i2c_write_request_report *)dev->write_buf; (struct ft260_i2c_write_request_report *)dev->write_buf;
if (data_len >= sizeof(rep->data))
return -EINVAL;
rep->address = addr; rep->address = addr;
rep->data[0] = cmd; rep->data[0] = cmd;
rep->length = data_len + 1; rep->length = data_len + 1;
...@@ -721,10 +727,9 @@ static int ft260_get_system_config(struct hid_device *hdev, ...@@ -721,10 +727,9 @@ static int ft260_get_system_config(struct hid_device *hdev,
ret = ft260_hid_feature_report_get(hdev, FT260_SYSTEM_SETTINGS, ret = ft260_hid_feature_report_get(hdev, FT260_SYSTEM_SETTINGS,
(u8 *)cfg, len); (u8 *)cfg, len);
if (ret != len) { if (ret < 0) {
hid_err(hdev, "failed to retrieve system status\n"); hid_err(hdev, "failed to retrieve system status\n");
if (ret >= 0) return ret;
return -EIO;
} }
return 0; return 0;
} }
...@@ -777,8 +782,8 @@ static int ft260_byte_show(struct hid_device *hdev, int id, u8 *cfg, int len, ...@@ -777,8 +782,8 @@ static int ft260_byte_show(struct hid_device *hdev, int id, u8 *cfg, int len,
int ret; int ret;
ret = ft260_hid_feature_report_get(hdev, id, cfg, len); ret = ft260_hid_feature_report_get(hdev, id, cfg, len);
if (ret != len && ret >= 0) if (ret < 0)
return -EIO; return ret;
return scnprintf(buf, PAGE_SIZE, "%hi\n", *field); return scnprintf(buf, PAGE_SIZE, "%hi\n", *field);
} }
...@@ -789,8 +794,8 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len, ...@@ -789,8 +794,8 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
int ret; int ret;
ret = ft260_hid_feature_report_get(hdev, id, cfg, len); ret = ft260_hid_feature_report_get(hdev, id, cfg, len);
if (ret != len && ret >= 0) if (ret < 0)
return -EIO; return ret;
return scnprintf(buf, PAGE_SIZE, "%hi\n", le16_to_cpu(*field)); return scnprintf(buf, PAGE_SIZE, "%hi\n", le16_to_cpu(*field));
} }
...@@ -941,10 +946,8 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -941,10 +946,8 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = ft260_hid_feature_report_get(hdev, FT260_CHIP_VERSION, ret = ft260_hid_feature_report_get(hdev, FT260_CHIP_VERSION,
(u8 *)&version, sizeof(version)); (u8 *)&version, sizeof(version));
if (ret != sizeof(version)) { if (ret < 0) {
hid_err(hdev, "failed to retrieve chip version\n"); hid_err(hdev, "failed to retrieve chip version\n");
if (ret >= 0)
ret = -EIO;
goto err_hid_close; goto err_hid_close;
} }
......
...@@ -54,6 +54,7 @@ static const struct hid_device_id gt683r_led_id[] = { ...@@ -54,6 +54,7 @@ static const struct hid_device_id gt683r_led_id[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, gt683r_led_id);
static void gt683r_brightness_set(struct led_classdev *led_cdev, static void gt683r_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness) enum led_brightness brightness)
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
#define USB_DEVICE_ID_A4TECH_X5_005D 0x000a #define USB_DEVICE_ID_A4TECH_X5_005D 0x000a
#define USB_DEVICE_ID_A4TECH_RP_649 0x001a #define USB_DEVICE_ID_A4TECH_RP_649 0x001a
#define USB_DEVICE_ID_A4TECH_NB_95 0x022b
#define USB_VENDOR_ID_AASHIMA 0x06d6 #define USB_VENDOR_ID_AASHIMA 0x06d6
#define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025
...@@ -299,8 +300,6 @@ ...@@ -299,8 +300,6 @@
#define USB_VENDOR_ID_CORSAIR 0x1b1c #define USB_VENDOR_ID_CORSAIR 0x1b1c
#define USB_DEVICE_ID_CORSAIR_K90 0x1b02 #define USB_DEVICE_ID_CORSAIR_K90 0x1b02
#define USB_VENDOR_ID_CORSAIR 0x1b1c
#define USB_DEVICE_ID_CORSAIR_K70R 0x1b09 #define USB_DEVICE_ID_CORSAIR_K70R 0x1b09
#define USB_DEVICE_ID_CORSAIR_K95RGB 0x1b11 #define USB_DEVICE_ID_CORSAIR_K95RGB 0x1b11
#define USB_DEVICE_ID_CORSAIR_M65RGB 0x1b12 #define USB_DEVICE_ID_CORSAIR_M65RGB 0x1b12
...@@ -751,6 +750,7 @@ ...@@ -751,6 +750,7 @@
#define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085
#define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 #define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3
#define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 #define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5
#define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E 0x600e
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019 #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019
#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E 0x602e
...@@ -1051,6 +1051,7 @@ ...@@ -1051,6 +1051,7 @@
#define USB_DEVICE_ID_SAITEK_X52 0x075c #define USB_DEVICE_ID_SAITEK_X52 0x075c
#define USB_DEVICE_ID_SAITEK_X52_2 0x0255 #define USB_DEVICE_ID_SAITEK_X52_2 0x0255
#define USB_DEVICE_ID_SAITEK_X52_PRO 0x0762 #define USB_DEVICE_ID_SAITEK_X52_PRO 0x0762
#define USB_DEVICE_ID_SAITEK_X65 0x0b6a
#define USB_VENDOR_ID_SAMSUNG 0x0419 #define USB_VENDOR_ID_SAMSUNG 0x0419
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
...@@ -1060,6 +1061,9 @@ ...@@ -1060,6 +1061,9 @@
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023 #define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD2 0x0027 #define USB_DEVICE_ID_SEMICO_USB_KEYKOARD2 0x0027
#define USB_VENDOR_ID_SEMITEK 0x1ea7
#define USB_DEVICE_ID_SEMITEK_KEYBOARD 0x0907
#define USB_VENDOR_ID_SENNHEISER 0x1395 #define USB_VENDOR_ID_SENNHEISER 0x1395
#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c #define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c
...@@ -1161,6 +1165,7 @@ ...@@ -1161,6 +1165,7 @@
#define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819 #define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819
#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968
#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710
#define USB_DEVICE_ID_SYNAPTICS_DELL_K15A 0x6e21
#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002 0x73f4 #define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002 0x73f4
#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f5 #define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003 0x73f5
#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7
......
...@@ -964,6 +964,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -964,6 +964,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break; case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break; case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break;
case 0x0d9: map_key_clear(KEY_EMOJI_PICKER); break;
case 0x0e0: map_abs_clear(ABS_VOLUME); break; case 0x0e0: map_abs_clear(ABS_VOLUME); break;
case 0x0e2: map_key_clear(KEY_MUTE); break; case 0x0e2: map_key_clear(KEY_MUTE); break;
case 0x0e5: map_key_clear(KEY_BASSBOOST); break; case 0x0e5: map_key_clear(KEY_BASSBOOST); break;
......
...@@ -1263,6 +1263,7 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage, ...@@ -1263,6 +1263,7 @@ static int hidpp20_battery_map_status_voltage(u8 data[3], int *voltage,
int status; int status;
long flags = (long) data[2]; long flags = (long) data[2];
*level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
if (flags & 0x80) if (flags & 0x80)
switch (flags & 0x07) { switch (flags & 0x07) {
......
...@@ -693,7 +693,7 @@ static int magicmouse_probe(struct hid_device *hdev, ...@@ -693,7 +693,7 @@ static int magicmouse_probe(struct hid_device *hdev,
if (id->vendor == USB_VENDOR_ID_APPLE && if (id->vendor == USB_VENDOR_ID_APPLE &&
id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 && id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
hdev->type != HID_TYPE_USBMOUSE) hdev->type != HID_TYPE_USBMOUSE)
return 0; return -ENODEV;
msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL); msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
if (msc == NULL) { if (msc == NULL) {
...@@ -779,7 +779,10 @@ static int magicmouse_probe(struct hid_device *hdev, ...@@ -779,7 +779,10 @@ static int magicmouse_probe(struct hid_device *hdev,
static void magicmouse_remove(struct hid_device *hdev) static void magicmouse_remove(struct hid_device *hdev)
{ {
struct magicmouse_sc *msc = hid_get_drvdata(hdev); struct magicmouse_sc *msc = hid_get_drvdata(hdev);
cancel_delayed_work_sync(&msc->work);
if (msc)
cancel_delayed_work_sync(&msc->work);
hid_hw_stop(hdev); hid_hw_stop(hdev);
} }
......
...@@ -70,6 +70,7 @@ MODULE_LICENSE("GPL"); ...@@ -70,6 +70,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_WIN8_PTP_BUTTONS BIT(18) #define MT_QUIRK_WIN8_PTP_BUTTONS BIT(18)
#define MT_QUIRK_SEPARATE_APP_REPORT BIT(19) #define MT_QUIRK_SEPARATE_APP_REPORT BIT(19)
#define MT_QUIRK_FORCE_MULTI_INPUT BIT(20) #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20)
#define MT_QUIRK_DISABLE_WAKEUP BIT(21)
#define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHSCREEN 0x02
#define MT_INPUTMODE_TOUCHPAD 0x03 #define MT_INPUTMODE_TOUCHPAD 0x03
...@@ -191,6 +192,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); ...@@ -191,6 +192,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
#define MT_CLS_EXPORT_ALL_INPUTS 0x0013 #define MT_CLS_EXPORT_ALL_INPUTS 0x0013
/* reserved 0x0014 */ /* reserved 0x0014 */
#define MT_CLS_WIN_8_FORCE_MULTI_INPUT 0x0015 #define MT_CLS_WIN_8_FORCE_MULTI_INPUT 0x0015
#define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016
/* vendor specific classes */ /* vendor specific classes */
#define MT_CLS_3M 0x0101 #define MT_CLS_3M 0x0101
...@@ -283,6 +285,15 @@ static const struct mt_class mt_classes[] = { ...@@ -283,6 +285,15 @@ static const struct mt_class mt_classes[] = {
MT_QUIRK_WIN8_PTP_BUTTONS | MT_QUIRK_WIN8_PTP_BUTTONS |
MT_QUIRK_FORCE_MULTI_INPUT, MT_QUIRK_FORCE_MULTI_INPUT,
.export_all_inputs = true }, .export_all_inputs = true },
{ .name = MT_CLS_WIN_8_DISABLE_WAKEUP,
.quirks = MT_QUIRK_ALWAYS_VALID |
MT_QUIRK_IGNORE_DUPLICATES |
MT_QUIRK_HOVERING |
MT_QUIRK_CONTACT_CNT_ACCURATE |
MT_QUIRK_STICKY_FINGERS |
MT_QUIRK_WIN8_PTP_BUTTONS |
MT_QUIRK_DISABLE_WAKEUP,
.export_all_inputs = true },
/* /*
* vendor specific classes * vendor specific classes
...@@ -604,9 +615,13 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, ...@@ -604,9 +615,13 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td,
if (!(HID_MAIN_ITEM_VARIABLE & field->flags)) if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
continue; continue;
for (n = 0; n < field->report_count; n++) { if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) {
if (field->usage[n].hid == HID_DG_CONTACTID) for (n = 0; n < field->report_count; n++) {
rdata->is_mt_collection = true; if (field->usage[n].hid == HID_DG_CONTACTID) {
rdata->is_mt_collection = true;
break;
}
}
} }
} }
...@@ -759,7 +774,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -759,7 +774,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 1; return 1;
case HID_DG_CONFIDENCE: case HID_DG_CONFIDENCE:
if ((cls->name == MT_CLS_WIN_8 || if ((cls->name == MT_CLS_WIN_8 ||
cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT) && cls->name == MT_CLS_WIN_8_FORCE_MULTI_INPUT ||
cls->name == MT_CLS_WIN_8_DISABLE_WAKEUP) &&
(field->application == HID_DG_TOUCHPAD || (field->application == HID_DG_TOUCHPAD ||
field->application == HID_DG_TOUCHSCREEN)) field->application == HID_DG_TOUCHSCREEN))
app->quirks |= MT_QUIRK_CONFIDENCE; app->quirks |= MT_QUIRK_CONFIDENCE;
...@@ -1576,13 +1592,13 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -1576,13 +1592,13 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
/* we do not set suffix = "Touchscreen" */ /* we do not set suffix = "Touchscreen" */
hi->input->name = hdev->name; hi->input->name = hdev->name;
break; break;
case HID_DG_STYLUS:
/* force BTN_STYLUS to allow tablet matching in udev */
__set_bit(BTN_STYLUS, hi->input->keybit);
break;
case HID_VD_ASUS_CUSTOM_MEDIA_KEYS: case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
suffix = "Custom Media Keys"; suffix = "Custom Media Keys";
break; break;
case HID_DG_STYLUS:
/* force BTN_STYLUS to allow tablet matching in udev */
__set_bit(BTN_STYLUS, hi->input->keybit);
fallthrough;
case HID_DG_PEN: case HID_DG_PEN:
suffix = "Stylus"; suffix = "Stylus";
break; break;
...@@ -1749,8 +1765,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1749,8 +1765,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int mt_suspend(struct hid_device *hdev, pm_message_t state) static int mt_suspend(struct hid_device *hdev, pm_message_t state)
{ {
struct mt_device *td = hid_get_drvdata(hdev);
/* High latency is desirable for power savings during S3/S0ix */ /* High latency is desirable for power savings during S3/S0ix */
mt_set_modes(hdev, HID_LATENCY_HIGH, true, true); if (td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP)
mt_set_modes(hdev, HID_LATENCY_HIGH, false, false);
else
mt_set_modes(hdev, HID_LATENCY_HIGH, true, true);
return 0; return 0;
} }
...@@ -1809,6 +1831,12 @@ static const struct hid_device_id mt_devices[] = { ...@@ -1809,6 +1831,12 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_ANTON, MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
USB_DEVICE_ID_ANTON_TOUCH_PAD) }, USB_DEVICE_ID_ANTON_TOUCH_PAD) },
/* Asus T101HA */
{ .driver_data = MT_CLS_WIN_8_DISABLE_WAKEUP,
HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD) },
/* Asus T304UA */ /* Asus T304UA */
{ .driver_data = MT_CLS_ASUS, { .driver_data = MT_CLS_ASUS,
HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
......
...@@ -110,6 +110,7 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -110,6 +110,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E), HID_QUIRK_ALWAYS_POLL }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E), HID_QUIRK_ALWAYS_POLL },
...@@ -158,6 +159,7 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -158,6 +159,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X65), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
...@@ -176,6 +178,7 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -176,6 +178,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K15A), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
...@@ -211,6 +214,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -211,6 +214,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_NB_95) },
#endif #endif
#if IS_ENABLED(CONFIG_HID_ACCUTOUCH) #if IS_ENABLED(CONFIG_HID_ACCUTOUCH)
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_ACCUTOUCH_2216) },
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* HID driver for Semitek keyboards
*
* Copyright (c) 2021 Benjamin Moody
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
static __u8 *semitek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
/* In the report descriptor for interface 2, fix the incorrect
description of report ID 0x04 (the report contains a
bitmask, not an array of keycodes.) */
if (*rsize == 0xcb && rdesc[0x83] == 0x81 && rdesc[0x84] == 0x00) {
hid_info(hdev, "fixing up Semitek report descriptor\n");
rdesc[0x84] = 0x02;
}
return rdesc;
}
static const struct hid_device_id semitek_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMITEK, USB_DEVICE_ID_SEMITEK_KEYBOARD) },
{ }
};
MODULE_DEVICE_TABLE(hid, semitek_devices);
static struct hid_driver semitek_driver = {
.name = "semitek",
.id_table = semitek_devices,
.report_fixup = semitek_report_fixup,
};
module_hid_driver(semitek_driver);
MODULE_LICENSE("GPL");
...@@ -387,7 +387,7 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr, ...@@ -387,7 +387,7 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr,
struct hid_sensor_custom *sensor_inst = dev_get_drvdata(dev); struct hid_sensor_custom *sensor_inst = dev_get_drvdata(dev);
int index, field_index, usage; int index, field_index, usage;
char name[HID_CUSTOM_NAME_LENGTH]; char name[HID_CUSTOM_NAME_LENGTH];
int value; int value, ret;
if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage, if (sscanf(attr->attr.name, "feature-%x-%x-%s", &index, &usage,
name) == 3) { name) == 3) {
...@@ -403,8 +403,10 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr, ...@@ -403,8 +403,10 @@ static ssize_t store_value(struct device *dev, struct device_attribute *attr,
report_id = sensor_inst->fields[field_index].attribute. report_id = sensor_inst->fields[field_index].attribute.
report_id; report_id;
sensor_hub_set_feature(sensor_inst->hsdev, report_id, ret = sensor_hub_set_feature(sensor_inst->hsdev, report_id,
index, sizeof(value), &value); index, sizeof(value), &value);
if (ret)
return ret;
} else } else
return -EINVAL; return -EINVAL;
......
...@@ -209,16 +209,21 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, ...@@ -209,16 +209,21 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
buffer_size = buffer_size / sizeof(__s32); buffer_size = buffer_size / sizeof(__s32);
if (buffer_size) { if (buffer_size) {
for (i = 0; i < buffer_size; ++i) { for (i = 0; i < buffer_size; ++i) {
hid_set_field(report->field[field_index], i, ret = hid_set_field(report->field[field_index], i,
(__force __s32)cpu_to_le32(*buf32)); (__force __s32)cpu_to_le32(*buf32));
if (ret)
goto done_proc;
++buf32; ++buf32;
} }
} }
if (remaining_bytes) { if (remaining_bytes) {
value = 0; value = 0;
memcpy(&value, (u8 *)buf32, remaining_bytes); memcpy(&value, (u8 *)buf32, remaining_bytes);
hid_set_field(report->field[field_index], i, ret = hid_set_field(report->field[field_index], i,
(__force __s32)cpu_to_le32(value)); (__force __s32)cpu_to_le32(value));
if (ret)
goto done_proc;
} }
hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT); hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
hid_hw_wait(hsdev->hdev); hid_hw_wait(hsdev->hdev);
......
...@@ -312,7 +312,7 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i ...@@ -312,7 +312,7 @@ static int thrustmaster_probe(struct hid_device *hdev, const struct hid_device_i
} }
tm_wheel->change_request = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); tm_wheel->change_request = kzalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
if (!tm_wheel->model_request) { if (!tm_wheel->change_request) {
ret = -ENOMEM; ret = -ENOMEM;
goto error5; goto error5;
} }
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#define I2C_HID_QUIRK_BOGUS_IRQ BIT(4) #define I2C_HID_QUIRK_BOGUS_IRQ BIT(4)
#define I2C_HID_QUIRK_RESET_ON_RESUME BIT(5) #define I2C_HID_QUIRK_RESET_ON_RESUME BIT(5)
#define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(6) #define I2C_HID_QUIRK_BAD_INPUT_SIZE BIT(6)
#define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET BIT(7)
/* flags */ /* flags */
...@@ -178,6 +179,11 @@ static const struct i2c_hid_quirks { ...@@ -178,6 +179,11 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_RESET_ON_RESUME }, I2C_HID_QUIRK_RESET_ON_RESUME },
{ USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720, { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
I2C_HID_QUIRK_BAD_INPUT_SIZE }, I2C_HID_QUIRK_BAD_INPUT_SIZE },
/*
* Sending the wakeup after reset actually break ELAN touchscreen controller
*/
{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET },
{ 0, 0 } { 0, 0 }
}; };
...@@ -461,7 +467,8 @@ static int i2c_hid_hwreset(struct i2c_client *client) ...@@ -461,7 +467,8 @@ static int i2c_hid_hwreset(struct i2c_client *client)
} }
/* At least some SIS devices need this after reset */ /* At least some SIS devices need this after reset */
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON); if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
out_unlock: out_unlock:
mutex_unlock(&ihid->reset_lock); mutex_unlock(&ihid->reset_lock);
...@@ -990,8 +997,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, ...@@ -990,8 +997,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
hid->product = le16_to_cpu(ihid->hdesc.wProductID); hid->product = le16_to_cpu(ihid->hdesc.wProductID);
snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
client->name, hid->vendor, hid->product); client->name, (u16)hid->vendor, (u16)hid->product);
strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#define EHL_Ax_DEVICE_ID 0x4BB3 #define EHL_Ax_DEVICE_ID 0x4BB3
#define TGL_LP_DEVICE_ID 0xA0FC #define TGL_LP_DEVICE_ID 0xA0FC
#define TGL_H_DEVICE_ID 0x43FC #define TGL_H_DEVICE_ID 0x43FC
#define ADL_S_DEVICE_ID 0x7AF8
#define ADL_P_DEVICE_ID 0x51FC
#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
......
...@@ -39,6 +39,8 @@ static const struct pci_device_id ish_pci_tbl[] = { ...@@ -39,6 +39,8 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_H_DEVICE_ID)}, {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_H_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_S_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_P_DEVICE_ID)},
{0, } {0, }
}; };
MODULE_DEVICE_TABLE(pci, ish_pci_tbl); MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
......
...@@ -168,9 +168,9 @@ int surface_hid_device_add(struct surface_hid_device *shid) ...@@ -168,9 +168,9 @@ int surface_hid_device_add(struct surface_hid_device *shid)
shid->hid->dev.parent = shid->dev; shid->hid->dev.parent = shid->dev;
shid->hid->bus = BUS_HOST; shid->hid->bus = BUS_HOST;
shid->hid->vendor = cpu_to_le16(shid->attrs.vendor); shid->hid->vendor = get_unaligned_le16(&shid->attrs.vendor);
shid->hid->product = cpu_to_le16(shid->attrs.product); shid->hid->product = get_unaligned_le16(&shid->attrs.product);
shid->hid->version = cpu_to_le16(shid->hid_desc.hid_version); shid->hid->version = get_unaligned_le16(&shid->hid_desc.hid_version);
shid->hid->country = shid->hid_desc.country_code; shid->hid->country = shid->hid_desc.country_code;
snprintf(shid->hid->name, sizeof(shid->hid->name), "Microsoft Surface %04X:%04X", snprintf(shid->hid->name, sizeof(shid->hid->name), "Microsoft Surface %04X:%04X",
......
...@@ -374,7 +374,7 @@ static int hid_submit_ctrl(struct hid_device *hid) ...@@ -374,7 +374,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report; raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
dir = usbhid->ctrl[usbhid->ctrltail].dir; dir = usbhid->ctrl[usbhid->ctrltail].dir;
len = ((report->size - 1) >> 3) + 1 + (report->id > 0); len = hid_report_len(report);
if (dir == USB_DIR_OUT) { if (dir == USB_DIR_OUT) {
usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
usbhid->urbctrl->transfer_buffer_length = len; usbhid->urbctrl->transfer_buffer_length = len;
......
...@@ -1292,6 +1292,7 @@ int hid_pidff_init(struct hid_device *hid) ...@@ -1292,6 +1292,7 @@ int hid_pidff_init(struct hid_device *hid)
if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
error = -EPERM;
hid_notice(hid, hid_notice(hid,
"device does not support device managed pool\n"); "device does not support device managed pool\n");
goto fail; goto fail;
......
...@@ -1167,8 +1167,7 @@ static inline void hid_hw_wait(struct hid_device *hdev) ...@@ -1167,8 +1167,7 @@ static inline void hid_hw_wait(struct hid_device *hdev)
*/ */
static inline u32 hid_report_len(struct hid_report *report) static inline u32 hid_report_len(struct hid_report *report)
{ {
/* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ return DIV_ROUND_UP(report->size, 8) + (report->id > 0);
return ((report->size - 1) >> 3) + 1 + (report->id > 0);
} }
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
......
...@@ -611,6 +611,7 @@ ...@@ -611,6 +611,7 @@
#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ #define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */
#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ #define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */
#define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */ #define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */
#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */
#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ #define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */
#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ #define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册