summaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-03-14 17:56:15 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2024-03-14 17:56:15 +0100
commit3e78a6c0d3e02e4cf881dc84c5127e9990f939d6 (patch)
treea23819b38950e840438a2bda77485d6361706966 /drivers/hid
parentMerge tag 'auxdisplay-v6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff)
parentMerge branch 'for-6.9/wacom' into for-linus (diff)
downloadlinux-3e78a6c0d3e02e4cf881dc84c5127e9990f939d6.tar.xz
linux-3e78a6c0d3e02e4cf881dc84c5127e9990f939d6.zip
Merge tag 'hid-for-linus-2024031301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - support for the following Bluetooth devices from Samsung: Samsung wireless {Keyboard, GamePad, Action Mouse, Book Cover, Universal Keyboard, HOGP Keyboard} (Sandeep C S) - second version of code for applying proper quirk depending on firmware version for lenovo/cptkbd (Mikhail Khvainitski) - lenovo/cptkbd firmware-dependent quirk (Mikhail Khvainitski) - assorted fixes and optimizations for amd-sfh (Basavaraj Natikar) - dead code and dead data structures removal (Jiri Slaby, Jiapeng Chong) * tag 'hid-for-linus-2024031301' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (25 commits) HID: amd_sfh: Set the AMD SFH driver to depend on x86 HID: input: avoid polling stylus battery on Chromebook Pompom HID: amd_sfh: Extend MP2 register access to SFH HID: amd_sfh: Improve boot time when SFH is available HID: amd_sfh: Avoid disabling the interrupt HID: amd_sfh: Update HPD sensor structure elements HID: amd_sfh: Increase sensor command timeout HID: intel-ish-hid: ipc: Add Arrow Lake PCI device ID HID: nintendo: Remove some unused functions HID: hid-prodikeys: remove struct pk_device HID: hid-prodikeys: remove unused struct pcmidi_snd members HID: hid-multitouch: remove unused mt_application::dev_time HID: hid-lg3ff: remove unused struct lg3ff_device HID: protect hid_device::bpf by CONFIG_HID_BPF HID: wacom: remove unused hid_data::pressure HID: apple: remove unused members from struct apple_sc_backlight HID: wacom: Clean up use of struct->wacom_wac HID: samsung: Add Samsung wireless bookcover and universal keyboard support HID: samsung: Add Samsung wireless action mouse support HID: samsung: Add Samsung wireless gamepad support ...
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/amd-sfh-hid/Kconfig1
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_common.h16
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_pcie.c118
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_pcie.h6
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c2
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c4
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c10
-rw-r--r--drivers/hid/hid-apple.c1
-rw-r--r--drivers/hid/hid-ids.h8
-rw-r--r--drivers/hid/hid-input.c2
-rw-r--r--drivers/hid/hid-lenovo.c57
-rw-r--r--drivers/hid/hid-lg3ff.c4
-rw-r--r--drivers/hid/hid-multitouch.c1
-rw-r--r--drivers/hid/hid-nintendo.c22
-rw-r--r--drivers/hid/hid-prodikeys.c115
-rw-r--r--drivers/hid/hid-samsung.c437
-rw-r--r--drivers/hid/intel-ish-hid/ipc/hw-ish.h1
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c1
-rw-r--r--drivers/hid/wacom_wac.c8
-rw-r--r--drivers/hid/wacom_wac.h1
20 files changed, 621 insertions, 194 deletions
diff --git a/drivers/hid/amd-sfh-hid/Kconfig b/drivers/hid/amd-sfh-hid/Kconfig
index af752dd3a340..329de5e12c1a 100644
--- a/drivers/hid/amd-sfh-hid/Kconfig
+++ b/drivers/hid/amd-sfh-hid/Kconfig
@@ -6,6 +6,7 @@ menu "AMD SFH HID Support"
config AMD_SFH_HID
tristate "AMD Sensor Fusion Hub"
depends on HID
+ depends on X86
help
If you say yes to this option, support will be included for the
AMD Sensor Fusion Hub.
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index a1950bc6e6ce..e5620d7db569 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -19,6 +19,9 @@
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
+#define AMD_C2P_MSG_V1(regno) (0x10900 + ((regno) * 4))
+#define AMD_P2C_MSG_V1(regno) (0x10500 + ((regno) * 4))
+
#define SENSOR_ENABLED 4
#define SENSOR_DISABLED 5
@@ -53,6 +56,9 @@ struct amd_mp2_dev {
/* mp2 active control status */
u32 mp2_acs;
struct sfh_dev_status dev_en;
+ struct work_struct work;
+ u8 init_done;
+ u8 rver;
};
struct amd_mp2_ops {
@@ -79,4 +85,14 @@ void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata);
int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata);
void amd_sfh_clear_intr(struct amd_mp2_dev *privdata);
int amd_sfh_irq_init(struct amd_mp2_dev *privdata);
+
+static inline u64 amd_get_c2p_val(struct amd_mp2_dev *mp2, u32 idx)
+{
+ return mp2->rver == 1 ? AMD_C2P_MSG_V1(idx) : AMD_C2P_MSG(idx);
+}
+
+static inline u64 amd_get_p2c_val(struct amd_mp2_dev *mp2, u32 idx)
+{
+ return mp2->rver == 1 ? AMD_P2C_MSG_V1(idx) : AMD_P2C_MSG(idx);
+}
#endif
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index 2530fa98b568..9e97c26c4482 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -10,6 +10,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
+#include <linux/devm-helpers.h>
#include <linux/dma-mapping.h>
#include <linux/dmi.h>
#include <linux/interrupt.h>
@@ -35,15 +36,17 @@ static int sensor_mask_override = -1;
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
+static bool intr_disable = true;
+
static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
{
union cmd_response cmd_resp;
- /* Get response with status within a max of 1600 ms timeout */
+ /* Get response with status within a max of 10 seconds timeout */
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
(cmd_resp.response_v2.response == sensor_sts &&
cmd_resp.response_v2.status == 0 && (sid == 0xff ||
- cmd_resp.response_v2.sensor_id == sid)), 500, 1600000))
+ cmd_resp.response_v2.sensor_id == sid)), 500, 10000000))
return cmd_resp.response_v2.response;
return SENSOR_DISABLED;
@@ -55,7 +58,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen
cmd_base.ul = 0;
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
- cmd_base.cmd_v2.intr_disable = 1;
+ cmd_base.cmd_v2.intr_disable = intr_disable;
cmd_base.cmd_v2.period = info.period;
cmd_base.cmd_v2.sensor_id = info.sensor_idx;
cmd_base.cmd_v2.length = 16;
@@ -73,7 +76,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
cmd_base.ul = 0;
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
- cmd_base.cmd_v2.intr_disable = 1;
+ cmd_base.cmd_v2.intr_disable = intr_disable;
cmd_base.cmd_v2.period = 0;
cmd_base.cmd_v2.sensor_id = sensor_idx;
cmd_base.cmd_v2.length = 16;
@@ -87,7 +90,7 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
union sfh_cmd_base cmd_base;
cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
- cmd_base.cmd_v2.intr_disable = 1;
+ cmd_base.cmd_v2.intr_disable = intr_disable;
cmd_base.cmd_v2.period = 0;
cmd_base.cmd_v2.sensor_id = 0;
@@ -96,9 +99,9 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
{
- if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
- writel(0, privdata->mmio + AMD_P2C_MSG(4));
- writel(0xf, privdata->mmio + AMD_P2C_MSG(5));
+ if (readl(privdata->mmio + amd_get_p2c_val(privdata, 4))) {
+ writel(0, privdata->mmio + amd_get_p2c_val(privdata, 4));
+ writel(0xf, privdata->mmio + amd_get_p2c_val(privdata, 5));
}
}
@@ -292,6 +295,26 @@ int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
return 0;
}
+static int mp2_disable_intr(const struct dmi_system_id *id)
+{
+ intr_disable = false;
+ return 0;
+}
+
+static const struct dmi_system_id dmi_sfh_table[] = {
+ {
+ /*
+ * https://bugzilla.kernel.org/show_bug.cgi?id=218104
+ */
+ .callback = mp2_disable_intr,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook x360 435 G7"),
+ },
+ },
+ {}
+};
+
static const struct dmi_system_id dmi_nodevs[] = {
{
/*
@@ -307,6 +330,48 @@ static const struct dmi_system_id dmi_nodevs[] = {
{ }
};
+static void sfh1_1_init_work(struct work_struct *work)
+{
+ struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work);
+ struct pci_dev *pdev = mp2->pdev;
+ int rc;
+
+ rc = mp2->sfh1_1_ops->init(mp2);
+ if (rc) {
+ dev_err(&pdev->dev, "sfh1_1_init failed err %d\n", rc);
+ return;
+ }
+
+ amd_sfh_clear_intr(mp2);
+ mp2->init_done = 1;
+}
+
+static void sfh_init_work(struct work_struct *work)
+{
+ struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work);
+ struct pci_dev *pdev = mp2->pdev;
+ int rc;
+
+ rc = amd_sfh_hid_client_init(mp2);
+ if (rc) {
+ amd_sfh_clear_intr(mp2);
+ dev_err(&pdev->dev, "amd_sfh_hid_client_init failed err %d\n", rc);
+ return;
+ }
+
+ amd_sfh_clear_intr(mp2);
+ mp2->init_done = 1;
+}
+
+static void amd_sfh_remove(struct pci_dev *pdev)
+{
+ struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
+
+ flush_work(&mp2->work);
+ if (mp2->init_done)
+ mp2->mp2_ops->remove(mp2);
+}
+
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct amd_mp2_dev *privdata;
@@ -315,6 +380,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
if (dmi_first_match(dmi_nodevs))
return -ENODEV;
+ dmi_check_system(dmi_sfh_table);
+
privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
if (!privdata)
return -ENOMEM;
@@ -343,10 +410,15 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
privdata->sfh1_1_ops = (const struct amd_sfh1_1_ops *)id->driver_data;
if (privdata->sfh1_1_ops) {
- rc = privdata->sfh1_1_ops->init(privdata);
+ if (boot_cpu_data.x86 >= 0x1A)
+ privdata->rver = 1;
+
+ rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh1_1_init_work);
if (rc)
return rc;
- goto init_done;
+
+ schedule_work(&privdata->work);
+ return 0;
}
mp2_select_ops(privdata);
@@ -357,33 +429,34 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
return rc;
}
- rc = amd_sfh_hid_client_init(privdata);
+ rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh_init_work);
if (rc) {
amd_sfh_clear_intr(privdata);
- if (rc != -EOPNOTSUPP)
- dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
return rc;
}
-init_done:
- amd_sfh_clear_intr(privdata);
-
- return devm_add_action_or_reset(&pdev->dev, privdata->mp2_ops->remove, privdata);
+ schedule_work(&privdata->work);
+ return 0;
}
static void amd_sfh_shutdown(struct pci_dev *pdev)
{
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
- if (mp2 && mp2->mp2_ops)
- mp2->mp2_ops->stop_all(mp2);
+ if (mp2) {
+ flush_work(&mp2->work);
+ if (mp2->init_done)
+ mp2->mp2_ops->stop_all(mp2);
+ }
}
static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
{
struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
- mp2->mp2_ops->resume(mp2);
+ flush_work(&mp2->work);
+ if (mp2->init_done)
+ mp2->mp2_ops->resume(mp2);
return 0;
}
@@ -392,7 +465,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
{
struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
- mp2->mp2_ops->suspend(mp2);
+ flush_work(&mp2->work);
+ if (mp2->init_done)
+ mp2->mp2_ops->suspend(mp2);
return 0;
}
@@ -414,6 +489,7 @@ static struct pci_driver amd_mp2_pci_driver = {
.probe = amd_mp2_pci_probe,
.driver.pm = &amd_mp2_pm_ops,
.shutdown = amd_sfh_shutdown,
+ .remove = amd_sfh_remove,
};
module_pci_driver(amd_mp2_pci_driver);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
index 70add75fc506..05e400a4a83e 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
@@ -90,10 +90,10 @@ enum mem_use_type {
struct hpd_status {
union {
struct {
- u32 human_presence_report : 4;
- u32 human_presence_actual : 4;
- u32 probablity : 8;
u32 object_distance : 16;
+ u32 probablity : 8;
+ u32 human_presence_actual : 4;
+ u32 human_presence_report : 4;
} shpd;
u32 val;
};
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
index 33fbdde8aff0..c8916afefa62 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -251,7 +251,7 @@ static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
break;
case HPD_IDX:
get_common_inputs(&hpd_input.common_property, report_id);
- hpdstatus.val = readl(mp2->mmio + AMD_C2P_MSG(4));
+ hpdstatus.val = readl(mp2->mmio + amd_get_c2p_val(mp2, 4));
hpd_input.human_presence = hpdstatus.shpd.presence;
report_size = sizeof(hpd_input);
memcpy(input_report, &hpd_input, sizeof(hpd_input));
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index 9dbe6f4cb294..5b24d5f63701 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -172,7 +172,7 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
if (rc)
goto cleanup;
- writel(0, privdata->mmio + AMD_P2C_MSG(0));
+ writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0));
mp2_ops->start(privdata, info);
status = amd_sfh_wait_for_response
(privdata, cl_data->sensor_idx[i], ENABLE_SENSOR);
@@ -298,7 +298,7 @@ static void amd_sfh_set_ops(struct amd_mp2_dev *mp2)
int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
{
- u32 phy_base = readl(mp2->mmio + AMD_C2P_MSG(22));
+ u32 phy_base = readl(mp2->mmio + amd_get_c2p_val(mp2, 22));
struct device *dev = &mp2->pdev->dev;
struct sfh_base_info binfo;
int rc;
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
index ae36312bc236..2de2668a0277 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -20,7 +20,7 @@ static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
struct sfh_cmd_response cmd_resp;
/* Get response with status within a max of 10000 ms timeout */
- if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
+ if (!readl_poll_timeout(mp2->mmio + amd_get_p2c_val(mp2, 0), cmd_resp.resp,
(cmd_resp.response.response == 0 &&
cmd_resp.response.cmd_id == cmd_id && (sid == 0xff ||
cmd_resp.response.sensor_id == sid)), 500, 10000000))
@@ -39,7 +39,7 @@ static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor
cmd_base.cmd.sub_cmd_value = 1;
cmd_base.cmd.sensor_id = info.sensor_idx;
- writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
+ writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));
}
static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
@@ -52,8 +52,8 @@ static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
cmd_base.cmd.sub_cmd_value = 1;
cmd_base.cmd.sensor_id = sensor_idx;
- writeq(0x0, privdata->mmio + AMD_C2P_MSG(1));
- writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
+ writeq(0x0, privdata->mmio + amd_get_c2p_val(privdata, 1));
+ writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));
}
static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)
@@ -66,7 +66,7 @@ static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)
/* 0xf indicates all sensors */
cmd_base.cmd.sensor_id = 0xf;
- writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
+ writel(cmd_base.ul, privdata->mmio + amd_get_c2p_val(privdata, 0));
}
static struct amd_mp2_ops amd_sfh_ops = {
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index b9c7c0ed7bcc..bd022e004356 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -79,7 +79,6 @@ struct apple_non_apple_keyboard {
struct apple_sc_backlight {
struct led_classdev cdev;
struct hid_device *hdev;
- unsigned short backlight_off, backlight_on_min, backlight_on_max;
};
struct apple_sc {
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 828a5c022c64..8376fb5e2d0b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -430,6 +430,7 @@
#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED
#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE
#define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG 0x2D02
+#define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81
#define USB_VENDOR_ID_ELECOM 0x056e
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
@@ -1146,8 +1147,15 @@
#define USB_DEVICE_ID_SAITEK_X65 0x0b6a
#define USB_VENDOR_ID_SAMSUNG 0x0419
+#define USB_VENDOR_ID_SAMSUNG_ELECTRONICS 0x04e8
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600
+#define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD 0x7021
+#define USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD 0xa000
+#define USB_DEVICE_ID_SAMSUNG_WIRELESS_ACTIONMOUSE 0xa004
+#define USB_DEVICE_ID_SAMSUNG_WIRELESS_BOOKCOVER 0xa005
+#define USB_DEVICE_ID_SAMSUNG_WIRELESS_UNIVERSAL_KBD 0xa006
+#define USB_DEVICE_ID_SAMSUNG_WIRELESS_MULTI_HOGP_KBD 0xa064
#define USB_VENDOR_ID_SEMICO 0x1a2c
#define USB_DEVICE_ID_SEMICO_USB_KEYKOARD 0x0023
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index c8b20d44b147..e03d300d2bac 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -411,6 +411,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
HID_BATTERY_QUIRK_IGNORE },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG),
HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM),
+ HID_BATTERY_QUIRK_AVOID_QUERY },
{}
};
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
index 149a3c74346b..f86c1ea83a03 100644
--- a/drivers/hid/hid-lenovo.c
+++ b/drivers/hid/hid-lenovo.c
@@ -54,10 +54,10 @@ struct lenovo_drvdata {
/* 0: Up
* 1: Down (undecided)
* 2: Scrolling
- * 3: Patched firmware, disable workaround
*/
u8 middlebutton_state;
bool fn_lock;
+ bool middleclick_workaround_cptkbd;
};
#define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
@@ -621,6 +621,36 @@ static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
return count;
}
+static ssize_t attr_middleclick_workaround_show_cptkbd(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ cptkbd_data->middleclick_workaround_cptkbd);
+}
+
+static ssize_t attr_middleclick_workaround_store_cptkbd(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
+ int value;
+
+ if (kstrtoint(buf, 10, &value))
+ return -EINVAL;
+ if (value < 0 || value > 1)
+ return -EINVAL;
+
+ cptkbd_data->middleclick_workaround_cptkbd = !!value;
+
+ return count;
+}
+
static struct device_attribute dev_attr_fn_lock =
__ATTR(fn_lock, S_IWUSR | S_IRUGO,
@@ -632,10 +662,16 @@ static struct device_attribute dev_attr_sensitivity_cptkbd =
attr_sensitivity_show_cptkbd,
attr_sensitivity_store_cptkbd);
+static struct device_attribute dev_attr_middleclick_workaround_cptkbd =
+ __ATTR(middleclick_workaround, S_IWUSR | S_IRUGO,
+ attr_middleclick_workaround_show_cptkbd,
+ attr_middleclick_workaround_store_cptkbd);
+
static struct attribute *lenovo_attributes_cptkbd[] = {
&dev_attr_fn_lock.attr,
&dev_attr_sensitivity_cptkbd.attr,
+ &dev_attr_middleclick_workaround_cptkbd.attr,
NULL
};
@@ -686,23 +722,7 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
{
struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
- if (cptkbd_data->middlebutton_state != 3) {
- /* REL_X and REL_Y events during middle button pressed
- * are only possible on patched, bug-free firmware
- * so set middlebutton_state to 3
- * to never apply workaround anymore
- */
- if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD &&
- cptkbd_data->middlebutton_state == 1 &&
- usage->type == EV_REL &&
- (usage->code == REL_X || usage->code == REL_Y)) {
- cptkbd_data->middlebutton_state = 3;
- /* send middle button press which was hold before */
- input_event(field->hidinput->input,
- EV_KEY, BTN_MIDDLE, 1);
- input_sync(field->hidinput->input);
- }
-
+ if (cptkbd_data->middleclick_workaround_cptkbd) {
/* "wheel" scroll events */
if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
usage->code == REL_HWHEEL)) {
@@ -1166,6 +1186,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
cptkbd_data->middlebutton_state = 0;
cptkbd_data->fn_lock = true;
cptkbd_data->sensitivity = 0x05;
+ cptkbd_data->middleclick_workaround_cptkbd = true;
lenovo_features_set_cptkbd(hdev);
ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c
index b7e1949f3cf7..109735b89b7a 100644
--- a/drivers/hid/hid-lg3ff.c
+++ b/drivers/hid/hid-lg3ff.c
@@ -41,10 +41,6 @@
* I'm sure these are effects that I don't know enough about them
*/
-struct lg3ff_device {
- struct hid_report *report;
-};
-
static int hid_lg3ff_play(struct input_dev *dev, void *data,
struct ff_effect *effect)
{
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 3e91e4d6ba6f..04a014cd2a2f 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -130,7 +130,6 @@ struct mt_application {
* > 1 means hybrid (multitouch) protocol
*/
- __s32 dev_time; /* the scan time provided by the device */
unsigned long jiffies; /* the frame's jiffies */
int timestamp; /* the timestamp to be sent */
int prev_scantime; /* scantime reported previously */
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index ccc4032fb2b0..ab5953fc2436 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -667,16 +667,6 @@ struct joycon_ctlr {
* These helpers are most useful early during the HID probe or in conjunction
* with the capability helpers below.
*/
-static inline bool joycon_device_is_left_joycon(struct joycon_ctlr *ctlr)
-{
- return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONL;
-}
-
-static inline bool joycon_device_is_right_joycon(struct joycon_ctlr *ctlr)
-{
- return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_JOYCONR;
-}
-
static inline bool joycon_device_is_procon(struct joycon_ctlr *ctlr)
{
return ctlr->hdev->product == USB_DEVICE_ID_NINTENDO_PROCON;
@@ -764,18 +754,6 @@ static inline bool joycon_type_is_right_nescon(struct joycon_ctlr *ctlr)
return ctlr->ctlr_type == JOYCON_CTLR_TYPE_NESR;
}
-static inline bool joycon_type_has_left_controls(struct joycon_ctlr *ctlr)
-{
- return joycon_type_is_left_joycon(ctlr) ||
- joycon_type_is_procon(ctlr);
-}
-
-static inline bool joycon_type_has_right_controls(struct joycon_ctlr *ctlr)
-{
- return joycon_type_is_right_joycon(ctlr) ||
- joycon_type_is_procon(ctlr);
-}
-
static inline bool joycon_type_is_any_joycon(struct joycon_ctlr *ctlr)
{
return joycon_type_is_left_joycon(ctlr) ||
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index c16d2ba6ea16..a593ed62c969 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -32,13 +32,6 @@
struct pcmidi_snd;
-struct pk_device {
- unsigned long quirks;
-
- struct hid_device *hdev;
- struct pcmidi_snd *pm; /* pcmidi device context */
-};
-
struct pcmidi_sustain {
unsigned long in_use;
struct pcmidi_snd *pm;
@@ -50,7 +43,7 @@ struct pcmidi_sustain {
#define PCMIDI_SUSTAINED_MAX 32
struct pcmidi_snd {
- struct pk_device *pk;
+ struct hid_device *hdev;
unsigned short ifnum;
struct hid_report *pcmidi_report6;
struct input_dev *input_ep82;
@@ -66,9 +59,7 @@ struct pcmidi_snd {
struct snd_card *card;
struct snd_rawmidi *rwmidi;
struct snd_rawmidi_substream *in_substream;
- struct snd_rawmidi_substream *out_substream;
unsigned long in_triggered;
- unsigned long out_active;
};
#define PK_QUIRK_NOGET 0x00010000
@@ -100,11 +91,11 @@ static ssize_t show_channel(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hid_device *hdev = to_hid_device(dev);
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
- dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel);
+ dbg_hid("pcmidi sysfs read channel=%u\n", pm->midi_channel);
- return sprintf(buf, "%u (min:%u, max:%u)\n", pk->pm->midi_channel,
+ return sprintf(buf, "%u (min:%u, max:%u)\n", pm->midi_channel,
PCMIDI_CHANNEL_MIN, PCMIDI_CHANNEL_MAX);
}
@@ -113,13 +104,13 @@ static ssize_t store_channel(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct hid_device *hdev = to_hid_device(dev);
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
unsigned channel = 0;
if (sscanf(buf, "%u", &channel) > 0 && channel <= PCMIDI_CHANNEL_MAX) {
dbg_hid("pcmidi sysfs write channel=%u\n", channel);
- pk->pm->midi_channel = channel;
+ pm->midi_channel = channel;
return strlen(buf);
}
return -EINVAL;
@@ -137,11 +128,11 @@ static ssize_t show_sustain(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hid_device *hdev = to_hid_device(dev);
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
- dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain);
+ dbg_hid("pcmidi sysfs read sustain=%u\n", pm->midi_sustain);
- return sprintf(buf, "%u (off:%u, max:%u (ms))\n", pk->pm->midi_sustain,
+ return sprintf(buf, "%u (off:%u, max:%u (ms))\n", pm->midi_sustain,
PCMIDI_SUSTAIN_MIN, PCMIDI_SUSTAIN_MAX);
}
@@ -150,15 +141,14 @@ static ssize_t store_sustain(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct hid_device *hdev = to_hid_device(dev);
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
unsigned sustain = 0;
if (sscanf(buf, "%u", &sustain) > 0 && sustain <= PCMIDI_SUSTAIN_MAX) {
dbg_hid("pcmidi sysfs write sustain=%u\n", sustain);
- pk->pm->midi_sustain = sustain;
- pk->pm->midi_sustain_mode =
- (0 == sustain || !pk->pm->midi_mode) ? 0 : 1;
+ pm->midi_sustain = sustain;
+ pm->midi_sustain_mode = (0 == sustain || !pm->midi_mode) ? 0 : 1;
return strlen(buf);
}
return -EINVAL;
@@ -176,11 +166,11 @@ static ssize_t show_octave(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hid_device *hdev = to_hid_device(dev);
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
- dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave);
+ dbg_hid("pcmidi sysfs read octave=%d\n", pm->midi_octave);
- return sprintf(buf, "%d (min:%d, max:%d)\n", pk->pm->midi_octave,
+ return sprintf(buf, "%d (min:%d, max:%d)\n", pm->midi_octave,
PCMIDI_OCTAVE_MIN, PCMIDI_OCTAVE_MAX);
}
@@ -189,14 +179,14 @@ static ssize_t store_octave(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct hid_device *hdev = to_hid_device(dev);
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
int octave = 0;
if (sscanf(buf, "%d", &octave) > 0 &&
octave >= PCMIDI_OCTAVE_MIN && octave <= PCMIDI_OCTAVE_MAX) {
dbg_hid("pcmidi sysfs write octave=%d\n", octave);
- pk->pm->midi_octave = octave;
+ pm->midi_octave = octave;
return strlen(buf);
}
return -EINVAL;
@@ -270,7 +260,7 @@ static void stop_sustain_timers(struct pcmidi_snd *pm)
static int pcmidi_get_output_report(struct pcmidi_snd *pm)
{
- struct hid_device *hdev = pm->pk->hdev;
+ struct hid_device *hdev = pm->hdev;
struct hid_report *report;
list_for_each_entry(report,
@@ -295,7 +285,7 @@ static int pcmidi_get_output_report(struct pcmidi_snd *pm)
static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state)
{
- struct hid_device *hdev = pm->pk->hdev;
+ struct hid_device *hdev = pm->hdev;
struct hid_report *report = pm->pcmidi_report6;
report->field[0]->value[0] = 0x01;
report->field[0]->value[1] = state;
@@ -622,7 +612,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
/* Setup sound card */
- err = snd_card_new(&pm->pk->hdev->dev, index[dev], id[dev],
+ err = snd_card_new(&pm->hdev->dev, index[dev], id[dev],
THIS_MODULE, 0, &card);
if (err < 0) {
pk_error("failed to create pc-midi sound card\n");
@@ -660,7 +650,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
&pcmidi_in_ops);
/* create sysfs variables */
- err = device_create_file(&pm->pk->hdev->dev,
+ err = device_create_file(&pm->hdev->dev,
sysfs_device_attr_channel);
if (err < 0) {
pk_error("failed to create sysfs attribute channel: error %d\n",
@@ -668,7 +658,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
goto fail;
}
- err = device_create_file(&pm->pk->hdev->dev,
+ err = device_create_file(&pm->hdev->dev,
sysfs_device_attr_sustain);
if (err < 0) {
pk_error("failed to create sysfs attribute sustain: error %d\n",
@@ -676,7 +666,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
goto fail_attr_sustain;
}
- err = device_create_file(&pm->pk->hdev->dev,
+ err = device_create_file(&pm->hdev->dev,
sysfs_device_attr_octave);
if (err < 0) {
pk_error("failed to create sysfs attribute octave: error %d\n",
@@ -706,11 +696,11 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
fail_register:
stop_sustain_timers(pm);
- device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_octave);
+ device_remove_file(&pm->hdev->dev, sysfs_device_attr_octave);
fail_attr_octave:
- device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_sustain);
+ device_remove_file(&pm->hdev->dev, sysfs_device_attr_sustain);
fail_attr_sustain:
- device_remove_file(&pm->pk->hdev->dev, sysfs_device_attr_channel);
+ device_remove_file(&pm->hdev->dev, sysfs_device_attr_channel);
fail:
if (pm->card) {
snd_card_free(pm->card);
@@ -724,12 +714,9 @@ static int pcmidi_snd_terminate(struct pcmidi_snd *pm)
if (pm->card) {
stop_sustain_timers(pm);
- device_remove_file(&pm->pk->hdev->dev,
- sysfs_device_attr_channel);
- device_remove_file(&pm->pk->hdev->dev,
- sysfs_device_attr_sustain);
- device_remove_file(&pm->pk->hdev->dev,
- sysfs_device_attr_octave);
+ device_remove_file(&pm->hdev->dev, sysfs_device_attr_channel);
+ device_remove_file(&pm->hdev->dev, sysfs_device_attr_sustain);
+ device_remove_file(&pm->hdev->dev, sysfs_device_attr_octave);
snd_card_disconnect(pm->card);
snd_card_free_when_closed(pm->card);
@@ -759,10 +746,7 @@ static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- struct pk_device *pk = hid_get_drvdata(hdev);
- struct pcmidi_snd *pm;
-
- pm = pk->pm;
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
if (HID_UP_MSVENDOR == (usage->hid & HID_USAGE_PAGE) &&
1 == pm->ifnum) {
@@ -777,16 +761,16 @@ static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi,
static int pk_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
- struct pk_device *pk = hid_get_drvdata(hdev);
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
int ret = 0;
- if (1 == pk->pm->ifnum) {
+ if (1 == pm->ifnum) {
if (report->id == data[0])
switch (report->id) {
case 0x01: /* midi keys (qwerty)*/
case 0x03: /* midi keyboard (musical)*/
case 0x04: /* extra/midi keys (qwerty)*/
- ret = pcmidi_handle_report(pk->pm,
+ ret = pcmidi_handle_report(pm,
report->id, data, size);
break;
}
@@ -801,8 +785,7 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
struct usb_interface *intf;
unsigned short ifnum;
unsigned long quirks = id->driver_data;
- struct pk_device *pk;
- struct pcmidi_snd *pm = NULL;
+ struct pcmidi_snd *pm;
if (!hid_is_usb(hdev))
return -EINVAL;
@@ -810,26 +793,16 @@ static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
intf = to_usb_interface(hdev->dev.parent);
ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
- pk = kzalloc(sizeof(*pk), GFP_KERNEL);
- if (pk == NULL) {
- hid_err(hdev, "can't alloc descriptor\n");
- return -ENOMEM;
- }
-
- pk->hdev = hdev;
-
pm = kzalloc(sizeof(*pm), GFP_KERNEL);
if (pm == NULL) {
hid_err(hdev, "can't alloc descriptor\n");
- ret = -ENOMEM;
- goto err_free_pk;
+ return -ENOMEM;
}
- pm->pk = pk;
- pk->pm = pm;
+ pm->hdev = hdev;
pm->ifnum = ifnum;
- hid_set_drvdata(hdev, pk);
+ hid_set_drvdata(hdev, pm);
ret = hid_parse(hdev);
if (ret) {
@@ -856,26 +829,18 @@ err_stop:
hid_hw_stop(hdev);
err_free:
kfree(pm);
-err_free_pk:
- kfree(pk);
return ret;
}
static void pk_remove(struct hid_device *hdev)
{
- struct pk_device *pk = hid_get_drvdata(hdev);
- struct pcmidi_snd *pm;
-
- pm = pk->pm;
- if (pm) {
- pcmidi_snd_terminate(pm);
- kfree(pm);
- }
+ struct pcmidi_snd *pm = hid_get_drvdata(hdev);
+ pcmidi_snd_terminate(pm);
hid_hw_stop(hdev);
- kfree(pk);
+ kfree(pm);
}
static const struct hid_device_id pk_devices[] = {
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c
index cf5992e97094..08fb25b8459a 100644
--- a/drivers/hid/hid-samsung.c
+++ b/drivers/hid/hid-samsung.c
@@ -58,33 +58,25 @@ static inline void samsung_irda_dev_trace(struct hid_device *hdev,
static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
- if (*rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 &&
- rdesc[177] == 0x75 && rdesc[178] == 0x30 &&
- rdesc[179] == 0x95 && rdesc[180] == 0x01 &&
+ if (*rsize == 184 && !memcmp(&rdesc[175], "\x25\x40\x75\x30\x95\x01", 6) &&
rdesc[182] == 0x40) {
samsung_irda_dev_trace(hdev, 184);
rdesc[176] = 0xff;
rdesc[178] = 0x08;
rdesc[180] = 0x06;
rdesc[182] = 0x42;
- } else
- if (*rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 &&
- rdesc[194] == 0x25 && rdesc[195] == 0x12) {
+ } else if (*rsize == 203 && !memcmp(&rdesc[192], "\x15\x00\x25\x12", 4)) {
samsung_irda_dev_trace(hdev, 203);
- rdesc[193] = 0x1;
- rdesc[195] = 0xf;
- } else
- if (*rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 &&
- rdesc[126] == 0x25 && rdesc[127] == 0x11) {
+ rdesc[193] = 0x01;
+ rdesc[195] = 0x0f;
+ } else if (*rsize == 135 && !memcmp(&rdesc[124], "\x15\x00\x25\x11", 4)) {
samsung_irda_dev_trace(hdev, 135);
- rdesc[125] = 0x1;
- rdesc[127] = 0xe;
- } else
- if (*rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 &&
- rdesc[162] == 0x25 && rdesc[163] == 0x01) {
+ rdesc[125] = 0x01;
+ rdesc[127] = 0x0e;
+ } else if (*rsize == 171 && !memcmp(&rdesc[160], "\x15\x00\x25\x01", 4)) {
samsung_irda_dev_trace(hdev, 171);
- rdesc[161] = 0x1;
- rdesc[163] = 0x3;
+ rdesc[161] = 0x01;
+ rdesc[163] = 0x03;
}
return rdesc;
}
@@ -99,7 +91,7 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev,
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
- if (1 != ifnum || HID_UP_CONSUMER != (usage->hid & HID_USAGE_PAGE))
+ if (ifnum != 1 || HID_UP_CONSUMER != (usage->hid & HID_USAGE_PAGE))
return 0;
dbg_hid("samsung wireless keyboard/mouse input mapping event [0x%x]\n",
@@ -107,17 +99,39 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev,
switch (usage->hid & HID_USAGE) {
/* report 2 */
- case 0x183: samsung_kbd_mouse_map_key_clear(KEY_MEDIA); break;
- case 0x195: samsung_kbd_mouse_map_key_clear(KEY_EMAIL); break;
- case 0x196: samsung_kbd_mouse_map_key_clear(KEY_CALC); break;
- case 0x197: samsung_kbd_mouse_map_key_clear(KEY_COMPUTER); break;
- case 0x22b: samsung_kbd_mouse_map_key_clear(KEY_SEARCH); break;
- case 0x22c: samsung_kbd_mouse_map_key_clear(KEY_WWW); break;
- case 0x22d: samsung_kbd_mouse_map_key_clear(KEY_BACK); break;
- case 0x22e: samsung_kbd_mouse_map_key_clear(KEY_FORWARD); break;
- case 0x22f: samsung_kbd_mouse_map_key_clear(KEY_FAVORITES); break;
- case 0x230: samsung_kbd_mouse_map_key_clear(KEY_REFRESH); break;
- case 0x231: samsung_kbd_mouse_map_key_clear(KEY_STOP); break;
+ case 0x183:
+ samsung_kbd_mouse_map_key_clear(KEY_MEDIA);
+ break;
+ case 0x195:
+ samsung_kbd_mouse_map_key_clear(KEY_EMAIL);
+ break;
+ case 0x196:
+ samsung_kbd_mouse_map_key_clear(KEY_CALC);
+ break;
+ case 0x197:
+ samsung_kbd_mouse_map_key_clear(KEY_COMPUTER);
+ break;
+ case 0x22b:
+ samsung_kbd_mouse_map_key_clear(KEY_SEARCH);
+ break;
+ case 0x22c:
+ samsung_kbd_mouse_map_key_clear(KEY_WWW);
+ break;
+ case 0x22d:
+ samsung_kbd_mouse_map_key_clear(KEY_BACK);
+ break;
+ case 0x22e:
+ samsung_kbd_mouse_map_key_clear(KEY_FORWARD);
+ break;
+ case 0x22f:
+ samsung_kbd_mouse_map_key_clear(KEY_FAVORITES);
+ break;
+ case 0x230:
+ samsung_kbd_mouse_map_key_clear(KEY_REFRESH);
+ break;
+ case 0x231:
+ samsung_kbd_mouse_map_key_clear(KEY_STOP);
+ break;
default:
return 0;
}
@@ -125,10 +139,340 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev,
return 1;
}
+static int samsung_kbd_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (!(HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE) ||
+ HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)))
+ return 0;
+
+ dbg_hid("samsung wireless keyboard input mapping event [0x%x]\n",
+ usage->hid & HID_USAGE);
+
+ if (HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)) {
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0x32:
+ samsung_kbd_mouse_map_key_clear(KEY_BACKSLASH);
+ break;
+ case 0x64:
+ samsung_kbd_mouse_map_key_clear(KEY_102ND);
+ break;
+ /* Only for BR keyboard */
+ case 0x87:
+ samsung_kbd_mouse_map_key_clear(KEY_RO);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ if (HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)) {
+ switch (usage->hid & HID_USAGE) {
+ /* report 2 */
+ /* MENU */
+ case 0x040:
+ samsung_kbd_mouse_map_key_clear(KEY_MENU);
+ break;
+ case 0x18a:
+ samsung_kbd_mouse_map_key_clear(KEY_MAIL);
+ break;
+ case 0x196:
+ samsung_kbd_mouse_map_key_clear(KEY_WWW);
+ break;
+ case 0x19e:
+ samsung_kbd_mouse_map_key_clear(KEY_SCREENLOCK);
+ break;
+ case 0x221:
+ samsung_kbd_mouse_map_key_clear(KEY_SEARCH);
+ break;
+ case 0x223:
+ samsung_kbd_mouse_map_key_clear(KEY_HOMEPAGE);
+ break;
+ /* Smtart Voice Key */
+ case 0x300:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY13);
+ break;
+ /* RECENTAPPS */
+ case 0x301:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY1);
+ break;
+ /* APPLICATION */
+ case 0x302:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY2);
+ break;
+ /* Voice search */
+ case 0x305:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY4);
+ break;
+ /* QPANEL on/off */
+ case 0x306:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY5);
+ break;
+ /* SIP on/off */
+ case 0x307:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY3);
+ break;
+ /* LANG */
+ case 0x308:
+ samsung_kbd_mouse_map_key_clear(KEY_LANGUAGE);
+ break;
+ case 0x30a:
+ samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN);
+ break;
+ case 0x30b:
+ samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int samsung_gamepad_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (!(HID_UP_BUTTON == (usage->hid & HID_USAGE_PAGE) ||
+ HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)))
+ return 0;
+
+ dbg_hid("samsung wireless gamepad input mapping event [0x%x], %ld, %ld, [0x%x]\n",
+ usage->hid & HID_USAGE, hi->input->evbit[0], hi->input->absbit[0], usage->hid & HID_USAGE_PAGE);
+
+ if (HID_UP_BUTTON == (usage->hid & HID_USAGE_PAGE)) {
+ switch (usage->hid & HID_USAGE) {
+ case 0x01:
+ samsung_kbd_mouse_map_key_clear(BTN_A);
+ break;
+ case 0x02:
+ samsung_kbd_mouse_map_key_clear(BTN_B);
+ break;
+ case 0x03:
+ samsung_kbd_mouse_map_key_clear(BTN_C);
+ break;
+ case 0x04:
+ samsung_kbd_mouse_map_key_clear(BTN_X);
+ break;
+ case 0x05:
+ samsung_kbd_mouse_map_key_clear(BTN_Y);
+ break;
+ case 0x06:
+ samsung_kbd_mouse_map_key_clear(BTN_Z);
+ break;
+ case 0x07:
+ samsung_kbd_mouse_map_key_clear(BTN_TL);
+ break;
+ case 0x08:
+ samsung_kbd_mouse_map_key_clear(BTN_TR);
+ break;
+ case 0x09:
+ samsung_kbd_mouse_map_key_clear(BTN_TL2);
+ break;
+ case 0x0a:
+ samsung_kbd_mouse_map_key_clear(BTN_TR2);
+ break;
+ case 0x0b:
+ samsung_kbd_mouse_map_key_clear(BTN_SELECT);
+ break;
+ case 0x0c:
+ samsung_kbd_mouse_map_key_clear(BTN_START);
+ break;
+ case 0x0d:
+ samsung_kbd_mouse_map_key_clear(BTN_MODE);
+ break;
+ case 0x0e:
+ samsung_kbd_mouse_map_key_clear(BTN_THUMBL);
+ break;
+ case 0x0f:
+ samsung_kbd_mouse_map_key_clear(BTN_THUMBR);
+ break;
+ case 0x10:
+ samsung_kbd_mouse_map_key_clear(0x13f);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ if (HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)) {
+ switch (usage->hid & HID_USAGE) {
+ case 0x040:
+ samsung_kbd_mouse_map_key_clear(KEY_MENU);
+ break;
+ case 0x223:
+ samsung_kbd_mouse_map_key_clear(KEY_HOMEPAGE);
+ break;
+ case 0x224:
+ samsung_kbd_mouse_map_key_clear(KEY_BACK);
+ break;
+
+ /* Screen Capture */
+ case 0x303:
+ samsung_kbd_mouse_map_key_clear(KEY_SYSRQ);
+ break;
+
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int samsung_actionmouse_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+
+ dbg_hid("samsung wireless actionmouse input mapping event [0x%x], [0x%x], %ld, %ld, [0x%x]\n",
+ usage->hid, usage->hid & HID_USAGE, hi->input->evbit[0], hi->input->absbit[0],
+ usage->hid & HID_USAGE_PAGE);
+
+ if (((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) && ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON))
+ return 0;
+
+ switch (usage->hid & HID_USAGE) {
+ case 0x301:
+ samsung_kbd_mouse_map_key_clear(254);
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int samsung_universal_kbd_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
+ unsigned long **bit, int *max)
+{
+ if (!(HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE) ||
+ HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)))
+ return 0;
+
+ dbg_hid("samsung wireless keyboard input mapping event [0x%x]\n",
+ usage->hid & HID_USAGE);
+
+ if (HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)) {
+ set_bit(EV_REP, hi->input->evbit);
+ switch (usage->hid & HID_USAGE) {
+ case 0x32:
+ samsung_kbd_mouse_map_key_clear(KEY_BACKSLASH);
+ break;
+ case 0x64:
+ samsung_kbd_mouse_map_key_clear(KEY_102ND);
+ break;
+ /* Only for BR keyboard */
+ case 0x87:
+ samsung_kbd_mouse_map_key_clear(KEY_RO);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ if (HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)) {
+ switch (usage->hid & HID_USAGE) {
+ /* report 2 */
+ /* MENU */
+ case 0x040:
+ samsung_kbd_mouse_map_key_clear(KEY_MENU);
+ break;
+ case 0x18a:
+ samsung_kbd_mouse_map_key_clear(KEY_MAIL);
+ break;
+ case 0x196:
+ samsung_kbd_mouse_map_key_clear(KEY_WWW);
+ break;
+ case 0x19e:
+ samsung_kbd_mouse_map_key_clear(KEY_SCREENLOCK);
+ break;
+ case 0x221:
+ samsung_kbd_mouse_map_key_clear(KEY_SEARCH);
+ break;
+ case 0x223:
+ samsung_kbd_mouse_map_key_clear(KEY_HOMEPAGE);
+ break;
+ /* RECENTAPPS */
+ case 0x301:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY1);
+ break;
+ /* APPLICATION */
+ case 0x302:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY2);
+ break;
+ /* Voice search */
+ case 0x305:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY4);
+ break;
+ /* QPANEL on/off */
+ case 0x306:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY5);
+ break;
+ /* SIP on/off */
+ case 0x307:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY3);
+ break;
+ /* LANG */
+ case 0x308:
+ samsung_kbd_mouse_map_key_clear(KEY_LANGUAGE);
+ break;
+ case 0x30a:
+ samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN);
+ break;
+ case 0x070:
+ samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN);
+ break;
+ case 0x30b:
+ samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP);
+ break;
+ case 0x06f:
+ samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP);
+ break;
+ /* S-Finder */
+ case 0x304:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY7);
+ break;
+ /* Screen Capture */
+ case 0x303:
+ samsung_kbd_mouse_map_key_clear(KEY_SYSRQ);
+ break;
+ /* Multi Window */
+ case 0x309:
+ samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY9);
+ break;
+ /* HotKey App 1 */
+ case 0x071:
+ samsung_kbd_mouse_map_key_clear(0x2f5);
+ break;
+ /* HotKey App 2 */
+ case 0x072:
+ samsung_kbd_mouse_map_key_clear(0x2f6);
+ break;
+ /* HotKey App 3 */
+ case 0x073:
+ samsung_kbd_mouse_map_key_clear(0x2f7);
+ break;
+ /* Dex */
+ case 0x06e:
+ samsung_kbd_mouse_map_key_clear(0x2bd);
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
- if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product)
+ if (hdev->product == USB_DEVICE_ID_SAMSUNG_IR_REMOTE && hid_is_usb(hdev))
rdesc = samsung_irda_report_fixup(hdev, rdesc, rsize);
return rdesc;
}
@@ -139,9 +483,24 @@ static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi,
{
int ret = 0;
- if (USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE == hdev->product)
+ if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE && hid_is_usb(hdev))
ret = samsung_kbd_mouse_input_mapping(hdev,
hi, field, usage, bit, max);
+ else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD)
+ ret = samsung_kbd_input_mapping(hdev,
+ hi, field, usage, bit, max);
+ else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD)
+ ret = samsung_gamepad_input_mapping(hdev,
+ hi, field, usage, bit, max);
+ else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_ACTIONMOUSE)
+ ret = samsung_actionmouse_input_mapping(hdev,
+ hi, field, usage, bit, max);
+ else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_UNIVERSAL_KBD)
+ ret = samsung_universal_kbd_input_mapping(hdev,
+ hi, field, usage, bit, max);
+ else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_MULTI_HOGP_KBD)
+ ret = samsung_universal_kbd_input_mapping(hdev,
+ hi, field, usage, bit, max);
return ret;
}
@@ -152,16 +511,17 @@ static int samsung_probe(struct hid_device *hdev,
int ret;
unsigned int cmask = HID_CONNECT_DEFAULT;
- if (!hid_is_usb(hdev))
- return -EINVAL;
-
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
goto err_free;
}
- if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) {
+ if (hdev->product == USB_DEVICE_ID_SAMSUNG_IR_REMOTE) {
+ if (!hid_is_usb(hdev)) {
+ ret = -EINVAL;
+ goto err_free;
+ }
if (hdev->rsize == 184) {
/* disable hidinput, force hiddev */
cmask = (cmask & ~HID_CONNECT_HIDINPUT) |
@@ -183,6 +543,11 @@ err_free:
static const struct hid_device_id samsung_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_ACTIONMOUSE) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_UNIVERSAL_KBD) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_MULTI_HOGP_KBD) },
{ }
};
MODULE_DEVICE_TABLE(hid, samsung_devices);
diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
index e99f3a3c65e1..f89b300417d7 100644
--- a/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ b/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -34,6 +34,7 @@
#define RPL_S_DEVICE_ID 0x7A78
#define MTL_P_DEVICE_ID 0x7E45
#define ARL_H_DEVICE_ID 0x7745
+#define ARL_S_DEVICE_ID 0x7F78
#define REVISION_ID_CHT_A0 0x6
#define REVISION_ID_CHT_Ax_SI 0x0
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 65e7eeb2fa64..56bd4f02f319 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -45,6 +45,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ARL_H_DEVICE_ID)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ARL_S_DEVICE_ID)},
{0, }
};
MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index fbe10fbc5769..a44367aef621 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2990,11 +2990,11 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
wacom_wac_battery_pre_report(hdev, report);
- if (pad_in_hid_field && wacom->wacom_wac.pad_input)
+ if (pad_in_hid_field && wacom_wac->pad_input)
wacom_wac_pad_pre_report(hdev, report);
- if (pen_in_hid_field && wacom->wacom_wac.pen_input)
+ if (pen_in_hid_field && wacom_wac->pen_input)
wacom_wac_pen_pre_report(hdev, report);
- if (finger_in_hid_field && wacom->wacom_wac.touch_input)
+ if (finger_in_hid_field && wacom_wac->touch_input)
wacom_wac_finger_pre_report(hdev, report);
for (r = 0; r < report->maxfield; r++) {
@@ -3010,7 +3010,7 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report)
wacom_wac_battery_report(hdev, report);
- if (true_pad && wacom->wacom_wac.pad_input)
+ if (true_pad && wacom_wac->pad_input)
wacom_wac_pad_report(hdev, report, field);
}
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index e63b1e806e34..6ec499841f70 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -309,7 +309,6 @@ struct hid_data {
bool confidence;
int x;
int y;
- int pressure;
int width;
int height;
int id;