Re: [PATCH v2] platform/x86: thinkpad_acpi: Handle keyboard cover attach/detach events

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

 



Hi


2021. február 10., szerda 18:54 keltezéssel, Alexander Kobel írta:

> ThinkPad X1 Tablets emit HKEY 0x4012 and 0x4013 events when a keyboard
> cover is attached/detached or folded to the back of the device. They are
> used to switch from normal to tablet mode in userspace; e.g., to offer
> touch keyboard choices when focus goes to a text box and no keyboard is
> attached, or to enable autorotation of the display according to the
> built-in orientation sensor.
>
> This patch handles the two events by issuing corresponding
> SW_TABLET_MODE notifications to the ACPI userspace.
>
> Tested as working on a ThinkPad X1 Tablet Gen 2, 20JCS00C00, and as
> non-interfering with a ThinkPad X1 Carbon 7th, 20QESABM02 (normal
> clamshell, so it does not have a keyboard cover).
>
> Signed-off-by: Alexander Kobel <a-kobel@xxxxxxxxxx>
> ---
>  drivers/platform/x86/thinkpad_acpi.c | 91 +++++++++++++++++++++++++++-
>  1 file changed, 90 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
> index c404706379d9..8c1ff555f10b 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -174,6 +174,11 @@ enum tpacpi_hkey_event_t {
>  						     or port replicator */
>  	TP_HKEY_EV_HOTPLUG_UNDOCK	= 0x4011, /* undocked from hotplug
>  						     dock or port replicator */
> +	/* Thinkpad X1 Tablet series (and probably other GTOP type 4) emit 0x4012 and 0x4013

The preferred style of multi-line comments is

/* <note the empty line here>
 * Lorem ipsum ...
 */


> +	 * when keyboard cover is attached, detached or folded onto the back
> +	 */
> +	TP_HKEY_EV_KBD_COVER_ATTACH	= 0x4012, /* keyboard cover attached */
> +	TP_HKEY_EV_KBD_COVER_DETACH	= 0x4013, /* keyboard cover detached or folded back */
>
>  	/* User-interface events */
>  	TP_HKEY_EV_LID_CLOSE		= 0x5001, /* laptop lid closed */
> @@ -308,6 +313,8 @@ static struct {
>  		TP_HOTKEY_TABLET_NONE = 0,
>  		TP_HOTKEY_TABLET_USES_MHKG,
>  		TP_HOTKEY_TABLET_USES_GMMS,
> +		TP_HOTKEY_TABLET_USES_GTOP_ANY_TYPE,
> +		TP_HOTKEY_TABLET_USES_GTOP_X1_TABLET_TYPE,
>  	} hotkey_tablet;
>  	u32 kbdlight:1;
>  	u32 light:1;
> @@ -2166,11 +2173,32 @@ static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
>  	return !!(mode & TP_ACPI_MULTI_MODE_TABLET_LIKE);
>  }
>
> +static int hotkey_gtop_any_type_get_tablet_mode(int s)
> +{
> +	return !(s & 0x1);
> +}

I believe it would be preferable to do something like

  #define TP_GTOP_TYPE_ANY_ATTACH_STATE BIT(0)
  /* or possibly use an enum */
  ...
  return !(s & TP_GTOP_TYPE_ANY_ATTACH_STATE);

or let `s` be `unsigned long`, and then

  #define TP_GTOP_TYPE_ANY_ATTACH_STATE_BIT 0
  ...
  return !test_bit(TP_GTOP_TYPE_ANY_ATTACH_STATE_BIT, &s);

or something along these lines, and I also think the return type could be `bool`.


> +
> +static int hotkey_gtop_x1_tablet_type_get_tablet_mode(int s)
> +{
> +	return (!(s & 0x1) /* keyboard NOT attached */
> +		|| ((s >> 16) & 0x1) /* or folded onto the back */);
> +}

Same here, I suggest using the `BIT()` macro or `test_bit()` and preferably
name the constants.


> +
>  static int hotkey_get_tablet_mode(int *status)
>  {
>  	int s;
>
>  	switch (tp_features.hotkey_tablet) {
> +	case TP_HOTKEY_TABLET_USES_GTOP_ANY_TYPE:
> +		if (!acpi_evalf(hkey_handle, &s, "GTOP", "dd", 0x0200))
> +			return -EIO;
> +		*status = hotkey_gtop_any_type_get_tablet_mode(s);
> +		break;
> +	case TP_HOTKEY_TABLET_USES_GTOP_X1_TABLET_TYPE:
> +		if (!acpi_evalf(hkey_handle, &s, "GTOP", "dd", 0x0200))
> +			return -EIO;
> +		*status = hotkey_gtop_x1_tablet_type_get_tablet_mode(s);
> +		break;
>  	case TP_HOTKEY_TABLET_USES_MHKG:
>  		if (!acpi_evalf(hkey_handle, &s, "MHKG", "d"))
>  			return -EIO;
> @@ -3213,7 +3241,62 @@ static int hotkey_init_tablet_mode(void)
>  	int in_tablet_mode = 0, res;
>  	char *type = NULL;
>
> -	if (acpi_evalf(hkey_handle, &res, "GMMS", "qdd", 0)) {
> +	if (acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x0000)
> +	    && res >= 0x0103
> +	    && acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x0100)) {

Minor thing, but checkpatch prefers `&&` at the end of the line. And the rest of
the code places them at the end, too.


> +		/*
> +		 * GTOP ("Get Tablet OPtion") state ASL method definition:
> +		 * - Input: 0x0000: Query version
> +		 *   Output: 0x0103 (version 1.03)
> +		 * - Input: 0x0100: Query interface type
> +		 *   Output: DWORD But 31-0 Interface type
                                    ^
Shouldn't that be "Bit"?


> +		 *     0: Reserved
> +		 *     1: Any type
> +		 *     2: ThinkPad Helix series
> +		 *     3: ThinkPad 10 series
> +		 *     4: ThinkPad X1 Tablet series
> +		 * - Input: 0x0200: Get attach option
> +		 *   Output: Option attach state
> +		 *     (0: detached, 1: attached)
> +		 *     version >= 1.03 and interface type 1:
> +		 *       Bit 0: Any option attach state
> +		 *       Bit 31-1: Reserved(0)
> +		 *     version >= 1.03 and interface type 4:
> +		 *       Bit 0: Thin-KBD attach state
> +		 *       Bit 1: Pro-Cartridge attach state
> +		 *       Bit 3-2: Pico-Cartridge attach state
> +		 *         00: detached
> +		 *         01: attached
> +		 *         10: attached with battery error
> +		 *         11: Reserved
> +		 *       Bit 4: 3D Cartridge attach state
> +		 *       Bit 5: Reserve 1 attach state
> +		 *       Bit 6: Reserve 2 attach state
> +		 *       Bit 15-7: Reserved(0)
> +		 *       Bit 16: Folio keyboard location
> +		 *         (valid if folio attached)
> +		 *         0: keyboard is NOT folded onto the back
> +		 *         1: keyboard is folded onto the back of the system
> +		 *       Bit 31-17: Reserved(0)
> +		 */
> +		switch (res) {
> +		case 1:
> +			tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GTOP_ANY_TYPE;
> +			if (acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x200))

Please name that `0x200` something like TP_GTOP_CMD_GET_ATTACH_STATE or something
you like. (Same for the rest of the GTOP calls.) I know it's just above in the comment,
but I still think it'd be better to have concrete, more or less self-explanatory names
in the actual command.


> +				in_tablet_mode = hotkey_gtop_any_type_get_tablet_mode(res);
> +			type = "GTOP";
> +			break;
> +		case 4:
> +			tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GTOP_X1_TABLET_TYPE;
> +			if (acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x200))
> +				in_tablet_mode = hotkey_gtop_x1_tablet_type_get_tablet_mode(res);
> +			type = "GTOP";
> +			break;
> +		default:
> +			pr_err("unsupported GTOP type, please report this to %s\n", TPACPI_MAIL);
> +			break;
> +		}
> +	} else if (acpi_evalf(hkey_handle, &res, "GMMS", "qdd", 0)) {
>  		int has_tablet_mode;
> [...]


Regards,
Barnabás Pőcze




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

  Powered by Linux