From: marcoshalano@gmail.com
To: Angela Czubak <acz@semihalf.com>,
linux-input@vger.kernel.org, upstream@semihalf.com,
benjamin.tissoires@redhat.com, jikos@kernel.org,
dmitry.torokhov@gmail.com, Angela Czubak <acz@semihalf.com>
Subject: Re: [PATCH v3 17/17] HID: multitouch: Add lid handler for touchpad on Redrix chromebook
Date: Sat, 14 May 2022 21:07:39 -0300 [thread overview]
Message-ID: <eaa15224-50d9-e3b4-f5df-a29ef6a9043b@gmail.com> (raw)
In-Reply-To: <20220513093927.1632262-18-acz@semihalf.com>
On 13/05/2022 06:39, Angela Czubak <acz@semihalf.com> wrote:
> If user closes the lid the touchscreen gets close to the touchpad surface,
> which causes interference and makes the touchpad enter noise mode.
> Right after opening the lid the cursor is unresponsive because of the mode
> mentioned.
> To fix this issue we switch the surface off and on so that Elan's FW
> performs recalibration once the lid has been opened.
>
A non related question: this hid-haptic module is made just for newer touchpads which have a haptic response instead of regular clicks, or the haptic logic could be extended for other haptic devices, like Sony's DualSense controller triggers?
> Signed-off-by: Angela Czubak <acz@semihalf.com>
> ---
> drivers/hid/hid-multitouch.c | 220 ++++++++++++++++++++++++++++++++++-
> 1 file changed, 219 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index 2d1b8c400c2f..73e47fe7d773 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -32,11 +32,14 @@
> */
>
> #include <linux/device.h>
> +#include <linux/delay.h>
> +#include <linux/dmi.h>
> #include <linux/hid.h>
> #include <linux/module.h>
> #include <linux/slab.h>
> #include <linux/input/mt.h>
> #include <linux/jiffies.h>
> +#include <linux/sched.h>
> #include <linux/string.h>
> #include <linux/timer.h>
>
> @@ -159,6 +162,7 @@ struct mt_report_data {
> };
>
> struct mt_device {
> + struct list_head list; /* for list of devices needing input handler */
> struct mt_class mtclass; /* our mt device class */
> struct timer_list release_timer; /* to release sticky fingers */
> struct hid_haptic_device *haptic; /* haptic related configuration */
> @@ -173,8 +177,15 @@ struct mt_device {
>
> struct list_head applications;
> struct list_head reports;
> +
> + struct work_struct lid_work;
> + struct mutex mode_mutex;
> + bool lid_switch;
> };
>
> +static struct workqueue_struct *mt_mode_wq;
> +static LIST_HEAD(mt_devices_with_lid_handler);
> +
> static void mt_post_parse_default_settings(struct mt_device *td,
> struct mt_application *app);
> static void mt_post_parse(struct mt_device *td, struct mt_application *app);
> @@ -394,6 +405,91 @@ static const struct mt_class mt_classes[] = {
> { }
> };
>
> +static void mt_input_lid_event(struct input_handle *handle, unsigned int type,
> + unsigned int code, int value)
> +{
> + struct mt_device *td, *n;
> +
> + if (type == EV_SW && code == SW_LID && !value) {
> + list_for_each_entry_safe(td, n, &mt_devices_with_lid_handler, list)
> + queue_work(mt_mode_wq, &td->lid_work);
> + }
> +}
> +
> +struct mt_input_lid {
> + struct input_handle handle;
> +};
> +
> +static int mt_input_lid_connect(struct input_handler *handler,
> + struct input_dev *dev,
> + const struct input_device_id *id)
> +{
> + struct mt_input_lid *lid;
> + char *name;
> + int error;
> +
> + lid = kzalloc(sizeof(*lid), GFP_KERNEL);
> + if (!lid)
> + return -ENOMEM;
> +
> + name = kasprintf(GFP_KERNEL, "hid-mt-lid-%s", dev_name(&dev->dev));
> + if (!name) {
> + error = -ENOMEM;
> + goto err_free_lid;
> + }
> +
> + lid->handle.dev = dev;
> + lid->handle.handler = handler;
> + lid->handle.name = name;
> + lid->handle.private = lid;
> +
> + error = input_register_handle(&lid->handle);
> + if (error)
> + goto err_free_name;
> +
> + error = input_open_device(&lid->handle);
> + if (error)
> + goto err_unregister_handle;
> +
> + return 0;
> +
> +err_unregister_handle:
> + input_unregister_handle(&lid->handle);
> +err_free_name:
> + kfree(name);
> +err_free_lid:
> + kfree(lid);
> + return error;
> +}
> +
> +static void mt_input_lid_disconnect(struct input_handle *handle)
> +{
> + struct mt_input_lid *lid = handle->private;
> +
> + input_close_device(handle);
> + input_unregister_handle(handle);
> +
> + kfree(handle->name);
> + kfree(lid);
> +}
> +
> +static const struct input_device_id mt_input_lid_ids[] = {
> + {
> + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT,
> + .evbit = { BIT_MASK(EV_SW) },
> + .swbit = { [BIT_WORD(SW_LID)] = BIT_MASK(SW_LID) },
> + },
> + { },
> +};
> +
> +static struct input_handler mt_input_lid_handler = {
> + .event = mt_input_lid_event,
> + .connect = mt_input_lid_connect,
> + .disconnect = mt_input_lid_disconnect,
> + .name = "hid-mt-lid",
> + .id_table = mt_input_lid_ids,
> +};
> +
> static ssize_t mt_show_quirks(struct device *dev,
> struct device_attribute *attr,
> char *buf)
> @@ -548,6 +644,83 @@ static struct mt_usages *mt_allocate_usage(struct hid_device *hdev,
> return usage;
> }
>
> +static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency,
> + bool surface_switch, bool button_switch);
> +
> +static void lid_work_handler(struct work_struct *work)
> +{
> +
> + struct mt_device *td = container_of(work, struct mt_device,
> + lid_work);
> + struct hid_device *hdev = td->hdev;
> +
> + mutex_lock(&td->mode_mutex);
> + mt_set_modes(hdev, HID_LATENCY_NORMAL, false, false);
> + /* Elan's touchpad VID 323B needs this delay to handle both switch
> + * surface off and switch surface on and trigger recalibration
> + * properly.
> + */
> + msleep(50);
> + mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
> + mutex_unlock(&td->mode_mutex);
> +}
> +
> +static const struct dmi_system_id mt_lid_handler_dmi_table[] = {
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Google"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "Redrix"),
> + },
> + },
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "Google"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "Redrix4ES"),
> + },
> + },
> + {}
> +};
> +
> +static int mt_create_lid_handler(void)
> +{
> + int error = 0;
> +
> + if (!dmi_check_system(mt_lid_handler_dmi_table))
> + return 0;
> +
> + mt_mode_wq = alloc_ordered_workqueue("hid-mt-lid", WQ_FREEZABLE);
> + if (mt_mode_wq == NULL)
> + return -ENOMEM;
> +
> + error = input_register_handler(&mt_input_lid_handler);
> + if (error)
> + goto remove_wq;
> +
> + return 0;
> +
> +remove_wq:
> + destroy_workqueue(mt_mode_wq);
> + mt_mode_wq = NULL;
> + return error;
> +}
> +
> +static void mt_configure_lid_handler(struct mt_device *td)
> +{
> + struct hid_device *hdev = td->hdev;
> +
> + if (hdev->bus != BUS_I2C)
> + return;
> +
> + td->lid_switch = true;
> + list_add_tail(&td->list, &mt_devices_with_lid_handler);
> +}
> +
> +static void mt_destroy_lid_handler(void)
> +{
> + input_unregister_handler(&mt_input_lid_handler);
> + destroy_workqueue(mt_mode_wq);
> +}
> +
> static struct mt_application *mt_allocate_application(struct mt_device *td,
> struct hid_report *report)
> {
> @@ -571,6 +744,8 @@ static struct mt_application *mt_allocate_application(struct mt_device *td,
> if (application == HID_DG_TOUCHPAD) {
> mt_application->mt_flags |= INPUT_MT_POINTER;
> td->inputmode_value = MT_INPUTMODE_TOUCHPAD;
> + if (mt_mode_wq)
> + mt_configure_lid_handler(td);
> }
>
> mt_application->scantime = DEFAULT_ZERO;
> @@ -1767,6 +1942,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
> INIT_LIST_HEAD(&td->applications);
> INIT_LIST_HEAD(&td->reports);
>
> + INIT_LIST_HEAD(&td->list);
> + INIT_WORK(&td->lid_work, lid_work_handler);
> + mutex_init(&td->mode_mutex);
> +
> if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
> td->serial_maybe = true;
>
> @@ -1830,12 +2009,18 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state)
> struct mt_device *td = hid_get_drvdata(hdev);
> struct hid_haptic_device *haptic = td->haptic;
>
> + /* Wait for switch on completion */
> + if (td->lid_switch)
> + flush_workqueue(mt_mode_wq);
> +
> + mutex_lock(&td->mode_mutex);
> /* High latency is desirable for power savings during S3/S0ix */
> if ((td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP) ||
> !hid_hw_may_wakeup(hdev))
> mt_set_modes(hdev, HID_LATENCY_HIGH, false, false);
> else
> mt_set_modes(hdev, HID_LATENCY_HIGH, true, true);
> + mutex_unlock(&td->mode_mutex);
>
> if (td->is_haptic_touchpad)
> hid_haptic_suspend(hdev, haptic);
> @@ -1849,7 +2034,10 @@ static int mt_reset_resume(struct hid_device *hdev)
> struct hid_haptic_device *haptic = td->haptic;
>
> mt_release_contacts(hdev);
> +
> + mutex_lock(&td->mode_mutex);
> mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
> + mutex_unlock(&td->mode_mutex);
>
> if (td->is_haptic_touchpad)
> hid_haptic_resume(hdev, haptic);
> @@ -1868,7 +2056,9 @@ static int mt_resume(struct hid_device *hdev)
>
> hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
>
> + mutex_lock(&td->mode_mutex);
> mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
> + mutex_unlock(&td->mode_mutex);
>
> if (td->is_haptic_touchpad)
> hid_haptic_resume(hdev, haptic);
> @@ -1883,7 +2073,9 @@ static int mt_reset(struct hid_device *hdev)
> struct hid_haptic_device *haptic = td->haptic;
>
> mt_release_contacts(hdev);
> + mutex_lock(&td->mode_mutex);
> mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
> + mutex_unlock(&td->mode_mutex);
>
> if (td->is_haptic_touchpad)
> hid_haptic_reset(hdev, haptic);
> @@ -1899,6 +2091,8 @@ static void mt_remove(struct hid_device *hdev)
>
> sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
> hid_hw_stop(hdev);
> +
> + list_del(&td->list);
> }
>
> /*
> @@ -2302,4 +2496,28 @@ static struct hid_driver mt_driver = {
> .resume = mt_resume,
> #endif
> };
> -module_hid_driver(mt_driver);
> +
> +static int __init mt_init(void)
> +{
> + int ret;
> +
> + ret = hid_register_driver(&mt_driver);
> + if (ret)
> + return ret;
> +
> + ret = mt_create_lid_handler();
> + if (ret)
> + hid_unregister_driver(&mt_driver);
> +
> + return ret;
> +}
> +module_init(mt_init);
> +
> +static void __exit mt_exit(void)
> +{
> + if (mt_mode_wq)
> + mt_destroy_lid_handler();
> +
> + hid_unregister_driver(&mt_driver);
> +}
> +module_exit(mt_exit);
>
next prev parent reply other threads:[~2022-05-15 0:07 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-13 9:39 [PATCH v3 00/17] *** Implement simple haptic HID support *** Angela Czubak
2022-05-13 9:39 ` [PATCH v3 01/17] HID: add haptics page defines Angela Czubak
2022-05-13 9:39 ` [PATCH v3 02/17] Input: add FF_HID effect type Angela Czubak
2022-05-13 9:39 ` [PATCH v3 03/17] HID: haptic: introduce hid_haptic_device Angela Czubak
2022-05-13 9:39 ` [PATCH v3 04/17] HID: input: allow mapping of haptic output Angela Czubak
2022-05-13 9:39 ` [PATCH v3 05/17] HID: haptic: initialize haptic device Angela Czubak
2022-05-13 9:39 ` [PATCH v3 06/17] Input: add shared effects Angela Czubak
2022-05-13 9:39 ` [PATCH v3 07/17] HID: haptic: implement release and press effects Angela Czubak
2022-05-13 9:39 ` [PATCH v3 08/17] HID: input: calculate resolution for pressure Angela Czubak
2022-05-13 9:39 ` [PATCH v3 09/17] HID: haptic: add functions handling events Angela Czubak
2022-05-13 9:39 ` [PATCH v3 10/17] Input: MT - add INPUT_MT_MAX_FORCE flags Angela Czubak
2022-05-13 9:39 ` [PATCH v3 11/17] HID: haptic: add hid_haptic_switch_mode Angela Czubak
2022-05-13 9:39 ` [PATCH v3 12/17] HID: multitouch: add haptic multitouch support Angela Czubak
2022-05-13 9:39 ` [PATCH v3 13/17] Input: introduce EVIOCFF(TAKE|RELEASE)CONTROL Angela Czubak
2022-05-13 9:39 ` [PATCH v3 14/17] HID: haptic: add hid_haptic_change_control Angela Czubak
2022-05-13 9:39 ` [PATCH v3 15/17] HID: add HID device reset callback Angela Czubak
2022-05-13 9:39 ` [PATCH v3 16/17] HID: haptic: implement HID haptic " Angela Czubak
2022-05-13 9:39 ` [PATCH v3 17/17] HID: multitouch: Add lid handler for touchpad on Redrix chromebook Angela Czubak
2022-05-15 0:07 ` marcoshalano [this message]
2022-05-22 17:55 ` [PATCH v3 00/17] *** Implement simple haptic HID support *** Angela Czubak
2022-05-23 6:57 ` Jiri Kosina
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=eaa15224-50d9-e3b4-f5df-a29ef6a9043b@gmail.com \
--to=marcoshalano@gmail.com \
--cc=acz@semihalf.com \
--cc=benjamin.tissoires@redhat.com \
--cc=dmitry.torokhov@gmail.com \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=upstream@semihalf.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).