diff options
Diffstat (limited to 'drivers/hid')
23 files changed, 637 insertions, 216 deletions
diff --git a/drivers/hid/amd-sfh-hid/Kconfig b/drivers/hid/amd-sfh-hid/Kconfig index af752dd3a3..329de5e12c 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 a1950bc6e6..e5620d7db5 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 ce449da08e..9e97c26c44 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> @@ -41,11 +42,11 @@ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_ { 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; @@ -98,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)); } } @@ -329,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; @@ -367,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); @@ -381,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; } @@ -416,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; } @@ -438,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/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c index 33fbdde8af..c8916afefa 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 c89e6a2a58..c2f9fc1f20 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); @@ -308,7 +308,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 ae36312bc2..2de2668a02 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/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c index 470ae2c29c..e630caf644 100644 --- a/drivers/hid/bpf/hid_bpf_dispatch.c +++ b/drivers/hid/bpf/hid_bpf_dispatch.c @@ -176,9 +176,9 @@ __bpf_kfunc_end_defs(); * The following set contains all functions we agree BPF programs * can use. */ -BTF_SET8_START(hid_bpf_kfunc_ids) +BTF_KFUNCS_START(hid_bpf_kfunc_ids) BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL) -BTF_SET8_END(hid_bpf_kfunc_ids) +BTF_KFUNCS_END(hid_bpf_kfunc_ids) static const struct btf_kfunc_id_set hid_bpf_kfunc_set = { .owner = THIS_MODULE, @@ -487,12 +487,12 @@ static const struct btf_kfunc_id_set hid_bpf_fmodret_set = { }; /* for syscall HID-BPF */ -BTF_SET8_START(hid_bpf_syscall_kfunc_ids) +BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids) BTF_ID_FLAGS(func, hid_bpf_attach_prog) BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE) BTF_ID_FLAGS(func, hid_bpf_hw_request) -BTF_SET8_END(hid_bpf_syscall_kfunc_ids) +BTF_KFUNCS_END(hid_bpf_syscall_kfunc_ids) static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = { .owner = THIS_MODULE, diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index b9c7c0ed7b..bd022e0043 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-asus.c b/drivers/hid/hid-asus.c index 78cdfb8b9a..88cbb2fe6a 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -335,36 +335,20 @@ static int asus_raw_event(struct hid_device *hdev, if (drvdata->quirks & QUIRK_MEDION_E1239T) return asus_e1239t_event(drvdata, data, size); - if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) { + /* + * Skip these report ID, the device emits a continuous stream associated + * with the AURA mode it is in which looks like an 'echo'. + */ + if (report->id == FEATURE_KBD_LED_REPORT_ID1 || report->id == FEATURE_KBD_LED_REPORT_ID2) + return -1; + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { /* - * Skip these report ID, the device emits a continuous stream associated - * with the AURA mode it is in which looks like an 'echo'. + * G713 and G733 send these codes on some keypresses, depending on + * the key pressed it can trigger a shutdown event if not caught. */ - if (report->id == FEATURE_KBD_LED_REPORT_ID1 || - report->id == FEATURE_KBD_LED_REPORT_ID2) { + if (data[0] == 0x02 && data[1] == 0x30) { return -1; - /* Additional report filtering */ - } else if (report->id == FEATURE_KBD_REPORT_ID) { - /* - * G14 and G15 send these codes on some keypresses with no - * discernable reason for doing so. We'll filter them out to avoid - * unmapped warning messages later. - */ - if (data[1] == 0xea || data[1] == 0xec || data[1] == 0x02 || - data[1] == 0x8a || data[1] == 0x9e) { - 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; - } } - } if (drvdata->quirks & QUIRK_ROG_CLAYMORE_II_KEYBOARD) { @@ -1250,6 +1234,19 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[205] = 0x01; } + /* match many more n-key devices */ + if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && *rsize > 15) { + for (int i = 0; i < *rsize - 15; i++) { + /* offset to the count from 0x5a report part always 14 */ + if (rdesc[i] == 0x85 && rdesc[i + 1] == 0x5a && + rdesc[i + 14] == 0x95 && rdesc[i + 15] == 0x05) { + hid_info(hdev, "Fixing up Asus N-Key report descriptor\n"); + rdesc[i + 15] = 0x01; + break; + } + } + } + return rdesc; } @@ -1319,4 +1316,4 @@ static struct hid_driver asus_driver = { }; module_hid_driver(asus_driver); -MODULE_LICENSE("GPL");
\ No newline at end of file +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index de7a477d66..751a73ae7d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1448,7 +1448,6 @@ static void implement(const struct hid_device *hid, u8 *report, hid_warn(hid, "%s() called with too large value %d (n: %d)! (%s)\n", __func__, value, n, current->comm); - WARN_ON(1); value &= m; } } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 175b668008..68b0f39dea 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -823,6 +823,7 @@ #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_T651 0xb00c #define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309 +#define USB_DEVICE_ID_LOGITECH_CASA_TOUCHPAD 0xbb00 #define USB_DEVICE_ID_LOGITECH_C007 0xc007 #define USB_DEVICE_ID_LOGITECH_C077 0xc077 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 @@ -1147,8 +1148,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-lg3ff.c b/drivers/hid/hid-lg3ff.c index b7e1949f3c..109735b89b 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-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 3c3c497b6b..37958edec5 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -1284,8 +1284,10 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, */ msleep(50); - if (retval) + if (retval) { + kfree(dj_report); return retval; + } } /* diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3e91e4d6ba..56fc78841f 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 */ @@ -2082,6 +2081,12 @@ static const struct hid_device_id mt_devices[] = { USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB) }, + /* Logitech devices */ + { .driver_data = MT_CLS_NSMU, + HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_CASA_TOUCHPAD) }, + /* MosArt panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, MT_USB_DEVICE(USB_VENDOR_ID_ASUS, diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c index 4b2c81b49b..80e0f23c1c 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-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c index 58b15750db..ff9078ad19 100644 --- a/drivers/hid/hid-nvidia-shield.c +++ b/drivers/hid/hid-nvidia-shield.c @@ -283,7 +283,9 @@ static struct input_dev *shield_haptics_create( return haptics; input_set_capability(haptics, EV_FF, FF_RUMBLE); - input_ff_create_memless(haptics, NULL, play_effect); + ret = input_ff_create_memless(haptics, NULL, play_effect); + if (ret) + goto err; ret = input_register_device(haptics); if (ret) diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index c16d2ba6ea..a593ed62c9 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 cf5992e970..08fb25b845 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/i2c-hid/i2c-hid-of-elan.c b/drivers/hid/i2c-hid/i2c-hid-of-elan.c index 5b91fb106c..091e379332 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-elan.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-elan.c @@ -31,6 +31,7 @@ struct i2c_hid_of_elan { struct regulator *vcc33; struct regulator *vccio; struct gpio_desc *reset_gpio; + bool no_reset_on_power_off; const struct elan_i2c_hid_chip_data *chip_data; }; @@ -40,17 +41,17 @@ static int elan_i2c_hid_power_up(struct i2chid_ops *ops) container_of(ops, struct i2c_hid_of_elan, ops); int ret; + gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1); + if (ihid_elan->vcc33) { ret = regulator_enable(ihid_elan->vcc33); if (ret) - return ret; + goto err_deassert_reset; } ret = regulator_enable(ihid_elan->vccio); - if (ret) { - regulator_disable(ihid_elan->vcc33); - return ret; - } + if (ret) + goto err_disable_vcc33; if (ihid_elan->chip_data->post_power_delay_ms) msleep(ihid_elan->chip_data->post_power_delay_ms); @@ -60,6 +61,15 @@ static int elan_i2c_hid_power_up(struct i2chid_ops *ops) msleep(ihid_elan->chip_data->post_gpio_reset_on_delay_ms); return 0; + +err_disable_vcc33: + if (ihid_elan->vcc33) + regulator_disable(ihid_elan->vcc33); +err_deassert_reset: + if (ihid_elan->no_reset_on_power_off) + gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0); + + return ret; } static void elan_i2c_hid_power_down(struct i2chid_ops *ops) @@ -67,7 +77,14 @@ static void elan_i2c_hid_power_down(struct i2chid_ops *ops) struct i2c_hid_of_elan *ihid_elan = container_of(ops, struct i2c_hid_of_elan, ops); - gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1); + /* + * Do not assert reset when the hardware allows for it to remain + * deasserted regardless of the state of the (shared) power supply to + * avoid wasting power when the supply is left on. + */ + if (!ihid_elan->no_reset_on_power_off) + gpiod_set_value_cansleep(ihid_elan->reset_gpio, 1); + if (ihid_elan->chip_data->post_gpio_reset_off_delay_ms) msleep(ihid_elan->chip_data->post_gpio_reset_off_delay_ms); @@ -79,6 +96,7 @@ static void elan_i2c_hid_power_down(struct i2chid_ops *ops) static int i2c_hid_of_elan_probe(struct i2c_client *client) { struct i2c_hid_of_elan *ihid_elan; + int ret; ihid_elan = devm_kzalloc(&client->dev, sizeof(*ihid_elan), GFP_KERNEL); if (!ihid_elan) @@ -93,21 +111,38 @@ static int i2c_hid_of_elan_probe(struct i2c_client *client) if (IS_ERR(ihid_elan->reset_gpio)) return PTR_ERR(ihid_elan->reset_gpio); + ihid_elan->no_reset_on_power_off = of_property_read_bool(client->dev.of_node, + "no-reset-on-power-off"); + ihid_elan->vccio = devm_regulator_get(&client->dev, "vccio"); - if (IS_ERR(ihid_elan->vccio)) - return PTR_ERR(ihid_elan->vccio); + if (IS_ERR(ihid_elan->vccio)) { + ret = PTR_ERR(ihid_elan->vccio); + goto err_deassert_reset; + } ihid_elan->chip_data = device_get_match_data(&client->dev); if (ihid_elan->chip_data->main_supply_name) { ihid_elan->vcc33 = devm_regulator_get(&client->dev, ihid_elan->chip_data->main_supply_name); - if (IS_ERR(ihid_elan->vcc33)) - return PTR_ERR(ihid_elan->vcc33); + if (IS_ERR(ihid_elan->vcc33)) { + ret = PTR_ERR(ihid_elan->vcc33); + goto err_deassert_reset; + } } - return i2c_hid_core_probe(client, &ihid_elan->ops, - ihid_elan->chip_data->hid_descriptor_address, 0); + ret = i2c_hid_core_probe(client, &ihid_elan->ops, + ihid_elan->chip_data->hid_descriptor_address, 0); + if (ret) + goto err_deassert_reset; + + return 0; + +err_deassert_reset: + if (ihid_elan->no_reset_on_power_off) + gpiod_set_value_cansleep(ihid_elan->reset_gpio, 0); + + return ret; } static const struct elan_i2c_hid_chip_data elan_ekth6915_chip_data = { diff --git a/drivers/hid/intel-ish-hid/ipc/hw-ish.h b/drivers/hid/intel-ish-hid/ipc/hw-ish.h index e99f3a3c65..f89b300417 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 ce5576ef3c..4b8232360c 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 fbe10fbc57..a44367aef6 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 e63b1e806e..6ec499841f 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; |