diff options
author | Jiri Kosina | 2022-01-10 09:49:13 +0100 |
---|---|---|
committer | Jiri Kosina | 2022-01-10 09:49:13 +0100 |
commit | 8a2094d679d921d104d3296528d4fa419702ce1c (patch) | |
tree | 5feeb2f8b94eb3632109b778276ccd1007486770 /drivers/hid | |
parent | 3809fe479861194e310c23ed48b010c7c0f72d22 (diff) | |
parent | b60d3c803d7603432a08aeaf988aff53b3a5ec64 (diff) |
Merge branch 'for-5.17/core' into for-linus
- support for USI style pens (Tero Kristo, Mika Westerberg)
- quirk for devices that need inverted X/Y axes (Alistair Francis)
- small core code cleanups and deduplication (Benjamin Tissoires)
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/hid-core.c | 93 | ||||
-rw-r--r-- | drivers/hid/hid-debug.c | 35 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 26 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.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/surface-hid/surface_hid_core.c | 25 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 19 |
11 files changed, 180 insertions, 56 deletions
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-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-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/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/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; } |