diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-apple.c | 146 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 93 | ||||
-rw-r--r-- | drivers/hid/hid-debug.c | 35 | ||||
-rw-r--r-- | drivers/hid/hid-holtek-mouse.c | 15 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 2 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 26 | ||||
-rw-r--r-- | drivers/hid/hid-magicmouse.c | 20 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.c | 3 | ||||
-rw-r--r-- | drivers/hid/hid-quirks.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-uclogic-params.c | 31 | ||||
-rw-r--r-- | drivers/hid/hid-vivaldi.c | 3 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid-acpi.c | 2 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid-core.c | 19 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid-of-goodix.c | 2 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid-of.c | 10 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.h | 2 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ipc/ipc.c | 6 | ||||
-rw-r--r-- | drivers/hid/intel-ish-hid/ishtp-fw-loader.c | 3 | ||||
-rw-r--r-- | drivers/hid/surface-hid/surface_hid_core.c | 25 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 19 |
20 files changed, 380 insertions, 83 deletions
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 2c9c5faa74a9..24802a4a636e 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -16,24 +16,28 @@ #include <linux/device.h> #include <linux/hid.h> +#include <linux/jiffies.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/timer.h> #include "hid-ids.h" -#define APPLE_RDESC_JIS 0x0001 -#define APPLE_IGNORE_MOUSE 0x0002 -#define APPLE_HAS_FN 0x0004 -/* 0x0008 reserved, was: APPLE_HIDDEV */ -#define APPLE_ISO_TILDE_QUIRK 0x0010 -#define APPLE_MIGHTYMOUSE 0x0020 -#define APPLE_INVERT_HWHEEL 0x0040 -/* 0x0080 reserved, was: APPLE_IGNORE_HIDINPUT */ -#define APPLE_NUMLOCK_EMULATION 0x0100 +#define APPLE_RDESC_JIS BIT(0) +#define APPLE_IGNORE_MOUSE BIT(1) +#define APPLE_HAS_FN BIT(2) +/* BIT(3) reserved, was: APPLE_HIDDEV */ +#define APPLE_ISO_TILDE_QUIRK BIT(4) +#define APPLE_MIGHTYMOUSE BIT(5) +#define APPLE_INVERT_HWHEEL BIT(6) +/* BIT(7) reserved, was: APPLE_IGNORE_HIDINPUT */ +#define APPLE_NUMLOCK_EMULATION BIT(8) +#define APPLE_RDESC_BATTERY BIT(9) #define APPLE_FLAG_FKEY 0x01 #define HID_COUNTRY_INTERNATIONAL_ISO 13 +#define APPLE_BATTERY_TIMEOUT_MS 60000 static unsigned int fnmode = 1; module_param(fnmode, uint, 0644); @@ -58,10 +62,12 @@ MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. " "[0] = as-is, Mac layout, 1 = swapped, PC layout)"); struct apple_sc { + struct hid_device *hdev; unsigned long quirks; unsigned int fn_on; unsigned int fn_found; DECLARE_BITMAP(pressed_numlock, KEY_CNT); + struct timer_list battery_timer; }; struct apple_key_translation { @@ -70,6 +76,28 @@ struct apple_key_translation { u8 flags; }; +static const struct apple_key_translation apple2021_fn_keys[] = { + { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, + { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, + { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, + { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, + { KEY_F4, KEY_SEARCH, APPLE_FLAG_FKEY }, + { KEY_F5, KEY_MICMUTE, APPLE_FLAG_FKEY }, + { KEY_F6, KEY_SLEEP, APPLE_FLAG_FKEY }, + { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, + { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY }, + { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY }, + { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY }, + { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY }, + { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY }, + { KEY_UP, KEY_PAGEUP }, + { KEY_DOWN, KEY_PAGEDOWN }, + { KEY_LEFT, KEY_HOME }, + { KEY_RIGHT, KEY_END }, + { } +}; + static const struct apple_key_translation macbookair_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, { KEY_ENTER, KEY_INSERT }, @@ -214,7 +242,11 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } if (fnmode) { - if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && + if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 || + hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 || + hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021) + table = apple2021_fn_keys; + else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) table = macbookair_fn_keys; else if (hid->product < 0x21d || hid->product >= 0x300) @@ -333,6 +365,43 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field, return 0; } +static int apple_fetch_battery(struct hid_device *hdev) +{ +#ifdef CONFIG_HID_BATTERY_STRENGTH + struct apple_sc *asc = hid_get_drvdata(hdev); + struct hid_report_enum *report_enum; + struct hid_report *report; + + if (!(asc->quirks & APPLE_RDESC_BATTERY) || !hdev->battery) + return -1; + + report_enum = &hdev->report_enum[hdev->battery_report_type]; + report = report_enum->report_id_hash[hdev->battery_report_id]; + + if (!report || report->maxfield < 1) + return -1; + + if (hdev->battery_capacity == hdev->battery_max) + return -1; + + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); + return 0; +#else + return -1; +#endif +} + +static void apple_battery_timer_tick(struct timer_list *t) +{ + struct apple_sc *asc = from_timer(asc, t, battery_timer); + struct hid_device *hdev = asc->hdev; + + if (apple_fetch_battery(hdev) == 0) { + mod_timer(&asc->battery_timer, + jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS)); + } +} + /* * MacBook JIS keyboard has wrong logical maximum * Magic Keyboard JIS has wrong logical maximum @@ -354,6 +423,30 @@ static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, "fixing up MacBook JIS keyboard report descriptor\n"); rdesc[53] = rdesc[59] = 0xe7; } + + /* + * Change the usage from: + * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0 + * 0x09, 0x0b, // Usage (Vendor Usage 0x0b) 3 + * To: + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 + * 0x09, 0x06, // Usage (Keyboard) 2 + */ + if ((asc->quirks & APPLE_RDESC_BATTERY) && *rsize == 83 && + rdesc[46] == 0x84 && rdesc[58] == 0x85) { + hid_info(hdev, + "fixing up Magic Keyboard battery report descriptor\n"); + *rsize = *rsize - 1; + rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL); + if (!rdesc) + return NULL; + + rdesc[0] = 0x05; + rdesc[1] = 0x01; + rdesc[2] = 0x09; + rdesc[3] = 0x06; + } + return rdesc; } @@ -376,6 +469,9 @@ static void apple_setup_input(struct input_dev *input) for (trans = apple_iso_keyboard; trans->from; trans++) set_bit(trans->to, input->keybit); + for (trans = apple2021_fn_keys; trans->from; trans++) + set_bit(trans->to, input->keybit); + if (swap_fn_leftctrl) { for (trans = swapped_fn_leftctrl_keys; trans->from; trans++) set_bit(trans->to, input->keybit); @@ -428,7 +524,7 @@ static int apple_input_configured(struct hid_device *hdev, if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) { hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n"); - asc->quirks = 0; + asc->quirks &= ~APPLE_HAS_FN; } return 0; @@ -447,6 +543,7 @@ static int apple_probe(struct hid_device *hdev, return -ENOMEM; } + asc->hdev = hdev; asc->quirks = quirks; hid_set_drvdata(hdev, asc); @@ -463,9 +560,23 @@ static int apple_probe(struct hid_device *hdev, return ret; } + timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0); + mod_timer(&asc->battery_timer, + jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS)); + apple_fetch_battery(hdev); + return 0; } +static void apple_remove(struct hid_device *hdev) +{ + struct apple_sc *asc = hid_get_drvdata(hdev); + + del_timer_sync(&asc->battery_timer); + + hid_hw_stop(hdev); +} + static const struct hid_device_id apple_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE), .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL }, @@ -540,11 +651,11 @@ static const struct hid_device_id apple_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015), - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015), .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015), - .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY }, { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015), .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), @@ -640,6 +751,14 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, + { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), + .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK }, { } }; @@ -650,6 +769,7 @@ static struct hid_driver apple_driver = { .id_table = apple_devices, .report_fixup = apple_report_fixup, .probe = apple_probe, + .remove = apple_remove, .event = apple_event, .input_mapping = apple_input_mapping, .input_mapped = apple_input_mapped, diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index dbed2524fd47..f1aed5bbd000 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2126,6 +2126,99 @@ void hid_hw_close(struct hid_device *hdev) } EXPORT_SYMBOL_GPL(hid_hw_close); +/** + * hid_hw_request - send report request to device + * + * @hdev: hid device + * @report: report to send + * @reqtype: hid request type + */ +void hid_hw_request(struct hid_device *hdev, + struct hid_report *report, int reqtype) +{ + if (hdev->ll_driver->request) + return hdev->ll_driver->request(hdev, report, reqtype); + + __hid_request(hdev, report, reqtype); +} +EXPORT_SYMBOL_GPL(hid_hw_request); + +/** + * hid_hw_raw_request - send report request to device + * + * @hdev: hid device + * @reportnum: report ID + * @buf: in/out data to transfer + * @len: length of buf + * @rtype: HID report type + * @reqtype: HID_REQ_GET_REPORT or HID_REQ_SET_REPORT + * + * Return: count of data transferred, negative if error + * + * Same behavior as hid_hw_request, but with raw buffers instead. + */ +int hid_hw_raw_request(struct hid_device *hdev, + unsigned char reportnum, __u8 *buf, + size_t len, unsigned char rtype, int reqtype) +{ + if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) + return -EINVAL; + + return hdev->ll_driver->raw_request(hdev, reportnum, buf, len, + rtype, reqtype); +} +EXPORT_SYMBOL_GPL(hid_hw_raw_request); + +/** + * hid_hw_output_report - send output report to device + * + * @hdev: hid device + * @buf: raw data to transfer + * @len: length of buf + * + * Return: count of data transferred, negative if error + */ +int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len) +{ + if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) + return -EINVAL; + + if (hdev->ll_driver->output_report) + return hdev->ll_driver->output_report(hdev, buf, len); + + return -ENOSYS; +} +EXPORT_SYMBOL_GPL(hid_hw_output_report); + +#ifdef CONFIG_PM +int hid_driver_suspend(struct hid_device *hdev, pm_message_t state) +{ + if (hdev->driver && hdev->driver->suspend) + return hdev->driver->suspend(hdev, state); + + return 0; +} +EXPORT_SYMBOL_GPL(hid_driver_suspend); + +int hid_driver_reset_resume(struct hid_device *hdev) +{ + if (hdev->driver && hdev->driver->reset_resume) + return hdev->driver->reset_resume(hdev); + + return 0; +} +EXPORT_SYMBOL_GPL(hid_driver_reset_resume); + +int hid_driver_resume(struct hid_device *hdev) +{ + if (hdev->driver && hdev->driver->resume) + return hdev->driver->resume(hdev); + + return 0; +} +EXPORT_SYMBOL_GPL(hid_driver_resume); +#endif /* CONFIG_PM */ + struct hid_dynid { struct list_head list; struct hid_device_id id; diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 7a92e2a04a09..26c31d759914 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -141,8 +141,10 @@ static const struct hid_usage_entry hid_usage_table[] = { {0, 0x33, "Touch"}, {0, 0x34, "UnTouch"}, {0, 0x35, "Tap"}, + {0, 0x38, "Transducer Index"}, {0, 0x39, "TabletFunctionKey"}, {0, 0x3a, "ProgramChangeKey"}, + {0, 0x3B, "Battery Strength"}, {0, 0x3c, "Invert"}, {0, 0x42, "TipSwitch"}, {0, 0x43, "SecondaryTipSwitch"}, @@ -160,7 +162,40 @@ static const struct hid_usage_entry hid_usage_table[] = { {0, 0x59, "ButtonType"}, {0, 0x5A, "SecondaryBarrelSwitch"}, {0, 0x5B, "TransducerSerialNumber"}, + {0, 0x5C, "Preferred Color"}, + {0, 0x5D, "Preferred Color is Locked"}, + {0, 0x5E, "Preferred Line Width"}, + {0, 0x5F, "Preferred Line Width is Locked"}, {0, 0x6e, "TransducerSerialNumber2"}, + {0, 0x70, "Preferred Line Style"}, + {0, 0x71, "Preferred Line Style is Locked"}, + {0, 0x72, "Ink"}, + {0, 0x73, "Pencil"}, + {0, 0x74, "Highlighter"}, + {0, 0x75, "Chisel Marker"}, + {0, 0x76, "Brush"}, + {0, 0x77, "No Preference"}, + {0, 0x80, "Digitizer Diagnostic"}, + {0, 0x81, "Digitizer Error"}, + {0, 0x82, "Err Normal Status"}, + {0, 0x83, "Err Transducers Exceeded"}, + {0, 0x84, "Err Full Trans Features Unavailable"}, + {0, 0x85, "Err Charge Low"}, + {0, 0x90, "Transducer Software Info"}, + {0, 0x91, "Transducer Vendor Id"}, + {0, 0x92, "Transducer Product Id"}, + {0, 0x93, "Device Supported Protocols"}, + {0, 0x94, "Transducer Supported Protocols"}, + {0, 0x95, "No Protocol"}, + {0, 0x96, "Wacom AES Protocol"}, + {0, 0x97, "USI Protocol"}, + {0, 0x98, "Microsoft Pen Protocol"}, + {0, 0xA0, "Supported Report Rates"}, + {0, 0xA1, "Report Rate"}, + {0, 0xA2, "Transducer Connected"}, + {0, 0xA3, "Switch Disabled"}, + {0, 0xA4, "Switch Unimplemented"}, + {0, 0xA5, "Transducer Switches"}, { 15, 0, "PhysicalInterfaceDevice" }, {0, 0x00, "Undefined"}, {0, 0x01, "Physical_Interface_Device"}, diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c index b7172c48ef9f..7c907939bfae 100644 --- a/drivers/hid/hid-holtek-mouse.c +++ b/drivers/hid/hid-holtek-mouse.c @@ -65,8 +65,23 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, static int holtek_mouse_probe(struct hid_device *hdev, const struct hid_device_id *id) { + int ret; + if (!hid_is_usb(hdev)) return -EINVAL; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "hid parse failed: %d\n", ret); + return ret; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed: %d\n", ret); + return ret; + } + return 0; } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 19da07777d62..df7bbdf81aa5 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -175,6 +175,8 @@ #define USB_DEVICE_ID_APPLE_IRCONTROL4 0x8242 #define USB_DEVICE_ID_APPLE_IRCONTROL5 0x8243 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f #define USB_VENDOR_ID_ASUS 0x0486 #define USB_DEVICE_ID_ASUS_T91MT 0x0185 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 03f994541981..1ce75e8b49d5 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -52,6 +52,7 @@ static const struct { #define map_rel(c) hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c)) #define map_key(c) hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c)) #define map_led(c) hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c)) +#define map_msc(c) hid_map_usage(hidinput, usage, &bit, &max, EV_MSC, (c)) #define map_abs_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ &max, EV_ABS, (c)) @@ -876,10 +877,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x5b: /* TransducerSerialNumber */ case 0x6e: /* TransducerSerialNumber2 */ - usage->type = EV_MSC; - usage->code = MSC_SERIAL; - bit = input->mscbit; - max = MSC_MAX; + map_msc(MSC_SERIAL); break; default: goto unknown; @@ -1333,6 +1331,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct input = field->hidinput->input; + if (usage->type == EV_ABS && + (((*quirks & HID_QUIRK_X_INVERT) && usage->code == ABS_X) || + ((*quirks & HID_QUIRK_Y_INVERT) && usage->code == ABS_Y))) { + value = field->logical_maximum - value; + } + if (usage->hat_min < usage->hat_max || usage->hat_dir) { int hat_dir = usage->hat_dir; if (!hat_dir) @@ -1465,7 +1469,8 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report) } EXPORT_SYMBOL_GPL(hidinput_report_event); -int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field) +static int hidinput_find_field(struct hid_device *hid, unsigned int type, + unsigned int code, struct hid_field **field) { struct hid_report *report; int i, j; @@ -1480,7 +1485,6 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int } return -1; } -EXPORT_SYMBOL_GPL(hidinput_find_field); struct hid_field *hidinput_get_led_field(struct hid_device *hid) { @@ -1743,6 +1747,16 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid, case HID_GD_MOUSE: suffix = "Mouse"; break; + case HID_DG_PEN: + /* + * yes, there is an issue here: + * DG_PEN -> "Stylus" + * DG_STYLUS -> "Pen" + * But changing this now means users with config snippets + * will have to change it and the test suite will not be happy. + */ + suffix = "Stylus"; + break; case HID_DG_STYLUS: suffix = "Pen"; break; diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index d7687ce70614..2ccded36dafd 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -51,6 +51,8 @@ static bool report_undeciphered; module_param(report_undeciphered, bool, 0644); MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); +#define TRACKPAD2_2021_BT_VERSION 0x110 + #define TRACKPAD_REPORT_ID 0x28 #define TRACKPAD2_USB_REPORT_ID 0x02 #define TRACKPAD2_BT_REPORT_ID 0x31 @@ -538,10 +540,22 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd __set_bit(REL_HWHEEL_HI_RES, input->relbit); } } else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) { - /* setting the device name to ensure the same driver settings - * get loaded, whether connected through bluetooth or USB + /* If the trackpad has been connected to a Mac, the name is + * automatically personalized, e.g., "José Expósito's Trackpad". + * When connected through Bluetooth, the personalized name is + * reported, however, when connected through USB the generic + * name is reported. + * Set the device name to ensure the same driver settings get + * loaded, whether connected through bluetooth or USB. */ - input->name = "Apple Inc. Magic Trackpad 2"; + if (hdev->vendor == BT_VENDOR_ID_APPLE) { + if (input->id.version == TRACKPAD2_2021_BT_VERSION) + input->name = "Apple Inc. Magic Trackpad"; + else + input->name = "Apple Inc. Magic Trackpad 2"; + } else { /* USB_VENDOR_ID_APPLE */ + input->name = hdev->name; + } __clear_bit(EV_MSC, input->evbit); __clear_bit(BTN_0, input->keybit); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 082376a6cb3d..99eabfb4145b 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1606,9 +1606,6 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) case HID_DG_STYLUS: /* force BTN_STYLUS to allow tablet matching in udev */ __set_bit(BTN_STYLUS, hi->input->keybit); - fallthrough; - case HID_DG_PEN: - suffix = "Stylus"; break; default: suffix = "UNKNOWN"; diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index ee7e504e7279..9af1dc8ae3a2 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -304,6 +304,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) }, #endif #if IS_ENABLED(CONFIG_HID_APPLEIR) { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) }, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index adff1bd68d9f..3e70f969fb84 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -66,7 +66,7 @@ static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev, __u8 idx, size_t len) { int rc; - struct usb_device *udev = hid_to_usb_dev(hdev); + struct usb_device *udev; __u8 *buf = NULL; /* Check arguments */ @@ -75,6 +75,8 @@ static int uclogic_params_get_str_desc(__u8 **pbuf, struct hid_device *hdev, goto cleanup; } + udev = hid_to_usb_dev(hdev); + buf = kmalloc(len, GFP_KERNEL); if (buf == NULL) { rc = -ENOMEM; @@ -450,7 +452,7 @@ static int uclogic_params_frame_init_v1_buttonpad( { int rc; bool found = false; - struct usb_device *usb_dev = hid_to_usb_dev(hdev); + struct usb_device *usb_dev; char *str_buf = NULL; const size_t str_len = 16; @@ -460,6 +462,8 @@ static int uclogic_params_frame_init_v1_buttonpad( goto cleanup; } + usb_dev = hid_to_usb_dev(hdev); + /* * Enable generic button mode */ @@ -707,9 +711,9 @@ static int uclogic_params_huion_init(struct uclogic_params *params, struct hid_device *hdev) { int rc; - struct usb_device *udev = hid_to_usb_dev(hdev); - struct usb_interface *iface = to_usb_interface(hdev->dev.parent); - __u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + struct usb_device *udev; + struct usb_interface *iface; + __u8 bInterfaceNumber; bool found; /* The resulting parameters (noop) */ struct uclogic_params p = {0, }; @@ -723,6 +727,10 @@ static int uclogic_params_huion_init(struct uclogic_params *params, goto cleanup; } + udev = hid_to_usb_dev(hdev); + iface = to_usb_interface(hdev->dev.parent); + bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + /* If it's not a pen interface */ if (bInterfaceNumber != 0) { /* TODO: Consider marking the interface invalid */ @@ -834,10 +842,10 @@ int uclogic_params_init(struct uclogic_params *params, struct hid_device *hdev) { int rc; - struct usb_device *udev = hid_to_usb_dev(hdev); - __u8 bNumInterfaces = udev->config->desc.bNumInterfaces; - struct usb_interface *iface = to_usb_interface(hdev->dev.parent); - __u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + struct usb_device *udev; + __u8 bNumInterfaces; + struct usb_interface *iface; + __u8 bInterfaceNumber; bool found; /* The resulting parameters (noop) */ struct uclogic_params p = {0, }; @@ -848,6 +856,11 @@ int uclogic_params_init(struct uclogic_params *params, goto cleanup; } + udev = hid_to_usb_dev(hdev); + bNumInterfaces = udev->config->desc.bNumInterfaces; + iface = to_usb_interface(hdev->dev.parent); + bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + /* * Set replacement report descriptor if the original matches the * specified size. Otherwise keep interface unchanged. diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c index cd7ada48b1d9..72957a9f7117 100644 --- a/drivers/hid/hid-vivaldi.c +++ b/drivers/hid/hid-vivaldi.c @@ -57,6 +57,9 @@ static int vivaldi_probe(struct hid_device *hdev, int ret; drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + hid_set_drvdata(hdev, drvdata); ret = hid_parse(hdev); diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c index a6f0257a26de..b96ae15e0ad9 100644 --- a/drivers/hid/i2c-hid/i2c-hid-acpi.c +++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c @@ -111,7 +111,7 @@ static int i2c_hid_acpi_probe(struct i2c_client *client) } return i2c_hid_core_probe(client, &ihid_acpi->ops, - hid_descriptor_address); + hid_descriptor_address, 0); } static const struct acpi_device_id i2c_hid_acpi_match[] = { diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 517141138b00..be00e07df06c 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -912,7 +912,7 @@ static void i2c_hid_core_shutdown_tail(struct i2c_hid *ihid) } int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, - u16 hid_descriptor_address) + u16 hid_descriptor_address, u32 quirks) { int ret; struct i2c_hid *ihid; @@ -1009,6 +1009,8 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, goto err_mem_free; } + hid->quirks |= quirks; + return 0; err_mem_free: @@ -1063,11 +1065,9 @@ static int i2c_hid_core_suspend(struct device *dev) int ret; int wake_status; - if (hid->driver && hid->driver->suspend) { - ret = hid->driver->suspend(hid, PMSG_SUSPEND); - if (ret < 0) - return ret; - } + ret = hid_driver_suspend(hid, PMSG_SUSPEND); + if (ret < 0) + return ret; /* Save some power */ i2c_hid_set_power(client, I2C_HID_PWR_SLEEP); @@ -1125,12 +1125,7 @@ static int i2c_hid_core_resume(struct device *dev) if (ret) return ret; - if (hid->driver && hid->driver->reset_resume) { - ret = hid->driver->reset_resume(hid); - return ret; - } - - return 0; + return hid_driver_reset_resume(hid); } #endif diff --git a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c index 52674149a275..b4dad66fa954 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c @@ -150,7 +150,7 @@ static int i2c_hid_of_goodix_probe(struct i2c_client *client, goodix_i2c_hid_deassert_reset(ihid_goodix, true); mutex_unlock(&ihid_goodix->regulator_mutex); - return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001); + return i2c_hid_core_probe(client, &ihid_goodix->ops, 0x0001, 0); } static const struct goodix_i2c_hid_timing_data goodix_gt7375p_timing_data = { diff --git a/drivers/hid/i2c-hid/i2c-hid-of.c b/drivers/hid/i2c-hid/i2c-hid-of.c index 4bf7cea92637..97a27a803f58 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of.c +++ b/drivers/hid/i2c-hid/i2c-hid-of.c @@ -21,6 +21,7 @@ #include <linux/delay.h> #include <linux/device.h> +#include <linux/hid.h> #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> @@ -71,6 +72,7 @@ static int i2c_hid_of_probe(struct i2c_client *client, struct device *dev = &client->dev; struct i2c_hid_of *ihid_of; u16 hid_descriptor_address; + u32 quirks = 0; int ret; u32 val; @@ -105,8 +107,14 @@ static int i2c_hid_of_probe(struct i2c_client *client, if (ret) return ret; + if (device_property_read_bool(dev, "touchscreen-inverted-x")) + quirks |= HID_QUIRK_X_INVERT; + + if (device_property_read_bool(dev, "touchscreen-inverted-y")) + quirks |= HID_QUIRK_Y_INVERT; + return i2c_hid_core_probe(client, &ihid_of->ops, - hid_descriptor_address); + hid_descriptor_address, quirks); } static const struct of_device_id i2c_hid_of_match[] = { diff --git a/drivers/hid/i2c-hid/i2c-hid.h b/drivers/hid/i2c-hid/i2c-hid.h index 05a7827d211a..236cc062d5ef 100644 --- a/drivers/hid/i2c-hid/i2c-hid.h +++ b/drivers/hid/i2c-hid/i2c-hid.h @@ -32,7 +32,7 @@ struct i2chid_ops { }; int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, - u16 hid_descriptor_address); + u16 hid_descriptor_address, u32 quirks); int i2c_hid_core_remove(struct i2c_client *client); void i2c_hid_core_shutdown(struct i2c_client *client); diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index 45e0c7b1c9ec..8ccb246b0114 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -909,7 +909,11 @@ static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length, */ static bool _dma_no_cache_snooping(struct ishtp_device *dev) { - return dev->pdev->device == EHL_Ax_DEVICE_ID; + return (dev->pdev->device == EHL_Ax_DEVICE_ID || + dev->pdev->device == TGL_LP_DEVICE_ID || + dev->pdev->device == TGL_H_DEVICE_ID || + dev->pdev->device == ADL_S_DEVICE_ID || + dev->pdev->device == ADL_P_DEVICE_ID); } static const struct ishtp_hw_ops ish_hw_ops = { diff --git a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c index 0e1183e96147..e24988586710 100644 --- a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c +++ b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c @@ -268,7 +268,8 @@ static int get_firmware_variant(struct ishtp_cl_data *client_data, } /** - * loader_cl_send() Send message from host to firmware + * loader_cl_send() - Send message from host to firmware + * * @client_data: Client data instance * @out_msg: Message buffer to be sent to firmware * @out_size: Size of out going message diff --git a/drivers/hid/surface-hid/surface_hid_core.c b/drivers/hid/surface-hid/surface_hid_core.c index 5571e74abe91..e46330b2e561 100644 --- a/drivers/hid/surface-hid/surface_hid_core.c +++ b/drivers/hid/surface-hid/surface_hid_core.c @@ -204,50 +204,35 @@ static int surface_hid_suspend(struct device *dev) { struct surface_hid_device *d = dev_get_drvdata(dev); - if (d->hid->driver && d->hid->driver->suspend) - return d->hid->driver->suspend(d->hid, PMSG_SUSPEND); - - return 0; + return hid_driver_suspend(d->hid, PMSG_SUSPEND); } static int surface_hid_resume(struct device *dev) { struct surface_hid_device *d = dev_get_drvdata(dev); - if (d->hid->driver && d->hid->driver->resume) - return d->hid->driver->resume(d->hid); - - return 0; + return hid_driver_resume(d->hid); } static int surface_hid_freeze(struct device *dev) { struct surface_hid_device *d = dev_get_drvdata(dev); - if (d->hid->driver && d->hid->driver->suspend) - return d->hid->driver->suspend(d->hid, PMSG_FREEZE); - - return 0; + return hid_driver_suspend(d->hid, PMSG_FREEZE); } static int surface_hid_poweroff(struct device *dev) { struct surface_hid_device *d = dev_get_drvdata(dev); - if (d->hid->driver && d->hid->driver->suspend) - return d->hid->driver->suspend(d->hid, PMSG_HIBERNATE); - - return 0; + return hid_driver_suspend(d->hid, PMSG_HIBERNATE); } static int surface_hid_restore(struct device *dev) { struct surface_hid_device *d = dev_get_drvdata(dev); - if (d->hid->driver && d->hid->driver->reset_resume) - return d->hid->driver->reset_resume(d->hid); - - return 0; + return hid_driver_reset_resume(d->hid); } const struct dev_pm_ops surface_hid_pm_ops = { diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 2dcaf31eb9cd..54752c85604b 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1563,8 +1563,8 @@ static int hid_resume_common(struct hid_device *hid, bool driver_suspended) int status = 0; hid_restart_io(hid); - if (driver_suspended && hid->driver && hid->driver->resume) - status = hid->driver->resume(hid); + if (driver_suspended) + status = hid_driver_resume(hid); return status; } @@ -1588,11 +1588,9 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) { set_bit(HID_SUSPENDED, &usbhid->iofl); spin_unlock_irq(&usbhid->lock); - if (hid->driver && hid->driver->suspend) { - status = hid->driver->suspend(hid, message); - if (status < 0) - goto failed; - } + status = hid_driver_suspend(hid, message); + if (status < 0) + goto failed; driver_suspended = true; } else { usbhid_mark_busy(usbhid); @@ -1602,8 +1600,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) } else { /* TODO: resume() might need to handle suspend failure */ - if (hid->driver && hid->driver->suspend) - status = hid->driver->suspend(hid, message); + status = hid_driver_suspend(hid, message); driver_suspended = true; spin_lock_irq(&usbhid->lock); set_bit(HID_SUSPENDED, &usbhid->iofl); @@ -1644,8 +1641,8 @@ static int hid_reset_resume(struct usb_interface *intf) int status; status = hid_post_reset(intf); - if (status >= 0 && hid->driver && hid->driver->reset_resume) { - int ret = hid->driver->reset_resume(hid); + if (status >= 0) { + int ret = hid_driver_reset_resume(hid); if (ret < 0) status = ret; } |