Re: [PATCH] platform/x86: asus-wmi: Fix SW_TABLET_MODE always reporting 1 on the Asus UX360CA

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 9/16/20 4:00 PM, Samuel Čavoj wrote:
Hello,

On 16.09.2020 15:13, Hans de Goede wrote:
Hi,

On 9/16/20 3:04 PM, Hans de Goede wrote:
Hi,

On 9/11/20 3:26 PM, Hans de Goede wrote:
On the Asus UX360CA the ASUS_WMI_DEVID_KBD_DOCK devstate always reports 0,
which we translate to SW_TABLET_MODE=1. Which causes libinput to disable
the keyboard and touchpad even if the 360 degree hinges style 2-in-1 is
in laptop mode.

Samuel found out that this model has another WMI "object" with an devid of
0x00060062 which correctly reports laptop vs tablet-mode on the
Asus UX360CA.

All the models on which the SW_TABLET_MODE code was previously tested do
not have this new devid 0x00060062 object.

This commit adds support for the new devid 0x00060062 object and prefers it
over the older 0x00120063 object when present, fixing SW_TABLET_MODE always
being reported as 1 on these models.

Reported-and-tested-by: Samuel Čavoj <samuel@xxxxxxxxx>
Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>

Self NACK, preferring the newer ASUS WMI device-id for the switch when present
does not fix this everywhere.

Recently there have been more bug-reports about this and at least the Asus E200HA
laptop does not have the newer ASUS WMI device-id in its DSDT:

    https://bugzilla.redhat.com/show_bug.cgi?id=1875339
    https://bugzilla.redhat.com/show_bug.cgi?id=1875828
    https://bugzilla.redhat.com/show_bug.cgi?id=1876997

So I'm preparing a new patch which uses a DMI based whitelist for the SW_TABLET_MODE
functionality, Using the existing DMI quirks mechanism in asus-nb-wmi.c .

p.s.

Note the new ASUS-WMI device-id did actually give a working SW_TABLET_MODE
on the Asus Zenbook Flip UX360CA.

Samuel Čavoj, perhaps you can do a follow-up patch to my fix (once I've
posted it) enabling the new dev-id on devices with "Zenbook Flip*" as
DMI product-name ?

I would be happy to.


At least I hope the DMI product-name starts with a prefix which has Flip in it?  See:
at /sys/class/dmi/id/product_name

Unfortunately, this is not the case. product_name is just "UX360CAK" and
none of the other values contain anything useful either. (e.g.
product_family is just "UX")

It seems all the UX360 models are flip models (I guess the 360 refers
to 360 degree hinges), so you could do a non-exact (the default) DMI_MATCH
on product-name containing UX360.

Two solutions come to my mind:
  1. Manually build up a whitelist of devices with DEVID_FLIP_TABLET_MODE.
  2. Keep the logic of first checking the DEVID_FLIP_TABLET_MODE. If
     present use it, if not present then fall back to your DMI whitelist
     for the DEVID_KDB_DOCK.

The first solution sounds like an uphill battle and I don't know how I
would even start collecting devices. The second one is risky, but as we
haven't yet seen a device which misreports DEVID_FLIP_TABLET_MODE, I
think it should be fine. Unless ASUS does it yet again, of course.

I fully expect Asus to have done this again.

What do you think?

One advantage of the DEVID_FLIP_TABLET_MODE is that it directly
returns SW_TABLET_MODE, where as ASUS_WMI_DEVID_KBD_DOCK returns 1
when a Transformer model is attached to its kbd-dock, so we need
to invert the value to get SW_TABLET_MODE and it seems that on
all non transformers ASUS_WMI_DEVID_KBD_DOCK simply always returns 0
which we invert to 1, causing the issue at hand.

So assuming that on non flips DEVID_FLIP_TABLET_MODE defaults
to returning 0, we should avoid the alwasy reporting 1 problem.

But the mere presence of a SW_TABLET_MODE switch hints to userspace
that it is dealing with a 2-in-1 which might make userspace change
some behavior even if currently not in tablet-mode.

Hans, you have a collection of DSTS's, is that right? Could you try
searching it for DEVID_FLIP_TABLET_MODE and seeing if the devices which
have it actually also have a 360 degree hinge? This could shed some
light on the situation. I have indirect access to a UX434FLC as well (it
does not have the hinge) so I can check it myself.

Most of my Asus DSDTs are from various Transformer models. Of the
non transform DSDTs which I have both the FX503VD and the GL503VD
have the DEVID_FLIP_TABLET_MODE even though they are not 2-in-1s
so I believe that it would be best to support DEVID_FLIP_TABLET_MODE
through an allow-list too, just like I'm doing for the
ASUS_WMI_DEVID_KBD_DOCK in my upcoming fix.

Regards,

Hans


---
   drivers/platform/x86/asus-wmi.c            | 32 ++++++++++++++++++----
   include/linux/platform_data/x86/asus-wmi.h |  1 +
   2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 8f4acdc06b13..c8689da0323b 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -63,6 +63,7 @@ MODULE_LICENSE("GPL");
   #define NOTIFY_KBD_BRTTOGGLE        0xc7
   #define NOTIFY_KBD_FBM            0x99
   #define NOTIFY_KBD_TTP            0xae
+#define NOTIFY_FLIP_TABLET_MODE_CHANGE    0xfa
   #define ASUS_WMI_FNLOCK_BIOS_DISABLED    BIT(0)
@@ -173,6 +174,7 @@ struct asus_wmi {
       int spec;
       int sfun;
       bool wmi_event_queue;
+    bool use_flip_tablet_mode;
       struct input_dev *inputdev;
       struct backlight_device *backlight_device;
@@ -365,12 +367,22 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
       if (err)
           goto err_free_dev;
-    result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK);
+    result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_FLIP_TABLET_MODE);
       if (result >= 0) {
+        asus->use_flip_tablet_mode = true;
           input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
-        input_report_switch(asus->inputdev, SW_TABLET_MODE, !result);
-    } else if (result != -ENODEV) {
-        pr_err("Error checking for keyboard-dock: %d\n", result);
+        input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
+    } else {
+        if (result != -ENODEV)
+            pr_err("Error checking for flip-tablet-mode: %d\n", result);
+
+        result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK);
+        if (result >= 0) {
+            input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE);
+            input_report_switch(asus->inputdev, SW_TABLET_MODE, !result);
+        } else if (result != -ENODEV) {
+            pr_err("Error checking for keyboard-dock: %d\n", result);
+        }
       }
       err = input_register_device(asus->inputdev);
@@ -2114,7 +2126,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
           return;
       }
-    if (code == NOTIFY_KBD_DOCK_CHANGE) {
+    if (!asus->use_flip_tablet_mode && code == NOTIFY_KBD_DOCK_CHANGE) {
           result = asus_wmi_get_devstate_simple(asus,
                                 ASUS_WMI_DEVID_KBD_DOCK);
           if (result >= 0) {
@@ -2125,6 +2137,16 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
           return;
       }
+    if (asus->use_flip_tablet_mode && code == NOTIFY_FLIP_TABLET_MODE_CHANGE) {
+        result = asus_wmi_get_devstate_simple(asus,
+                              ASUS_WMI_DEVID_FLIP_TABLET_MODE);
+        if (result >= 0) {
+            input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
+            input_sync(asus->inputdev);
+        }
+        return;
+    }
+
       if (asus->fan_boost_mode_available && code == NOTIFY_KBD_FBM) {
           fan_boost_mode_switch_next(asus);
           return;
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index 897b8332a39f..1897b4683562 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -62,6 +62,7 @@
   /* Misc */
   #define ASUS_WMI_DEVID_CAMERA        0x00060013
+#define ASUS_WMI_DEVID_FLIP_TABLET_MODE    0x00060062
   /* Storage */
   #define ASUS_WMI_DEVID_CARDREADER    0x00080013







[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux