Linux Input/HID development
 help / color / mirror / Atom feed
From: Paolo Pisati <p.pisati@gmail.com>
To: Jiri Kosina <jikos@kernel.org>, Benjamin Tissoires <bentiss@kernel.org>
Cc: "Joshua Leivenzon" <hacker1024@users.sourceforge.net>,
	linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Denis Benato" <denis.benato@linux.dev>,
	"Rebecca Mara Müller" <rebecca.mara@posteo.de>,
	"Luke Jones" <luke@ljones.dev>, "Ivan Levchenko" <me@livan.pro>,
	"Nathan Chancellor" <nathan@kernel.org>,
	"Paolo Pisati" <p.pisati@gmail.com>
Subject: [PATCH v4 4/7] HID: asus: Cycle the platform profile from the Zenbook Duo profile key
Date: Tue, 20 Oct 2026 11:24:14 +0200	[thread overview]
Message-ID: <20261020092423.36380-5-p.pisati@gmail.com> (raw)
In-Reply-To: <20261020092423.36380-1-p.pisati@gmail.com>

From: Joshua Leivenzon <hacker1024@users.sourceforge.net>

The Zenbook Duo keyboard reports Fn+F, the performance mode key, as
vendor usage 0x9d. On the built-in keyboards of other ASUS laptops the
same key arrives through asus-wmi, which cycles the platform profile
in response. Do the same here so the key works on the detachable
keyboard too. Other ASUS devices may use the same usage for something
else, so only handle it on the Zenbook Duo keyboards.

asus_event() runs from the HID input path, which for USB is the URB
completion handler, while platform_profile_cycle() takes a mutex, so run
it from the driver's worker like the Fn-lock toggle, and consume the
event. Queue at most one cycle at a time, so that a device repeating the
key cannot grow the worker's list. Only call it when the platform
profile class is reachable: it is not built on architectures without
ACPI, where HID_ASUS still is, and it may be a module while HID_ASUS is
built in.

Signed-off-by: Joshua Leivenzon <hacker1024@users.sourceforge.net>
[pisati: defer platform_profile_cycle() to the worker and queue at
 most one cycle, only handle the usage on Zenbook Duo keyboards, return
 1 from asus_event() instead of propagating its return value, and
 guard the call with IS_REACHABLE(CONFIG_ACPI_PLATFORM_PROFILE)]
Signed-off-by: Paolo Pisati <p.pisati@gmail.com>
---
 drivers/hid/hid-asus.c | 54 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 68211ebe1290..739637f1964a 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -29,6 +29,7 @@
 #include <linux/input/mt.h>
 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
 #include <linux/power_supply.h>
+#include <linux/platform_profile.h>
 #include <linux/leds.h>
 
 #include "hid-ids.h"
@@ -117,6 +118,7 @@ enum asus_work_action_type {
 	FN_LOCK_SYNC,
 	BRIGHTNESS_SET,
 	WMI_FAN,
+	PLATFORM_PROFILE_CYCLE,
 };
 
 struct hid_raw_event_data {
@@ -431,6 +433,36 @@ static int asus_kbd_fn_lock_set(struct asus_drvdata *drvdata, bool enabled)
 	return 0;
 }
 
+static int asus_platform_profile_cycle(struct asus_drvdata *drvdata)
+{
+	struct asus_worker *worker = drvdata->worker;
+	struct asus_work_action *action, *pending;
+
+	if (!IS_REACHABLE(CONFIG_ACPI_PLATFORM_PROFILE))
+		return 0;
+
+	guard(spinlock_irqsave)(&worker->lock);
+
+	/*
+	 * One pending cycle is enough: a key press cannot outrun the
+	 * worker, and a device repeating the key must not grow the list.
+	 */
+	list_for_each_entry(pending, &worker->actions, node) {
+		if (pending->type == PLATFORM_PROFILE_CYCLE)
+			return 0;
+	}
+
+	action = kzalloc_obj(struct asus_work_action, GFP_ATOMIC);
+	if (!action)
+		return -ENOMEM;
+
+	action->type = PLATFORM_PROFILE_CYCLE;
+	INIT_LIST_HEAD(&action->node);
+	asus_worker_schedule(worker, action);
+
+	return 0;
+}
+
 static int asus_kbd_wmi_fan_send(struct asus_drvdata *drvdata, u8 *report_data,
 				 size_t report_size)
 {
@@ -467,6 +499,20 @@ static int asus_event(struct hid_device *hdev, struct hid_field *field,
 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_ASUSVENDOR &&
 	    (usage->hid & HID_USAGE) != 0x00 &&
 	    (usage->hid & HID_USAGE) != 0xff && !usage->type) {
+		/* Zenbook Duo Fn+F: cycle the platform profile */
+		if ((drvdata->quirks & QUIRK_ZENBOOK_DUO_KEYBOARD) &&
+		    (usage->hid & HID_USAGE) == 0x9d) {
+			if (value) {
+				ret = asus_platform_profile_cycle(drvdata);
+				if (ret) {
+					hid_err(hdev, "Failed to cycle the platform profile: %d\n",
+						ret);
+					return ret;
+				}
+			}
+			return 1;
+		}
+
 		hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
 			 usage->hid & HID_USAGE);
 	}
@@ -773,6 +819,7 @@ static void asus_work(struct work_struct *work)
 	struct asus_worker *worker = container_of(work, struct asus_worker, work);
 	struct asus_work_action *action = NULL;
 	unsigned long flags;
+	int ret;
 
 	/*
 	 * Dequeue the next action, if any. Once teardown has begun .removed
@@ -801,6 +848,13 @@ static void asus_work(struct work_struct *work)
 	case WMI_FAN:
 		asus_kbd_wmi_fan(worker->hdev, &action->data.fan_hid_data);
 		break;
+	case PLATFORM_PROFILE_CYCLE:
+		if (!IS_REACHABLE(CONFIG_ACPI_PLATFORM_PROFILE))
+			break;
+		ret = platform_profile_cycle();
+		if (ret)
+			hid_dbg(worker->hdev, "Failed to cycle the platform profile: %d\n", ret);
+		break;
 	default:
 		hid_err(worker->hdev, "Invalid action type: %d\n", action->type);
 		break;
-- 
2.43.0


  parent reply	other threads:[~2026-10-20  9:24 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-20  9:24 [PATCH v4 0/7] HID: asus: ASUS Zenbook Duo keyboard support Paolo Pisati
2026-10-20  9:24 ` [PATCH v4 1/7] HID: asus: Fix up Zenbook Duo report descriptors Paolo Pisati
2026-10-20  9:24 ` [PATCH v4 2/7] HID: asus: Add missing Zenbook Duo hotkeys Paolo Pisati
2026-10-20  9:24 ` [PATCH v4 3/7] HID: asus: Force hid-input to bind to the Zenbook Duo hotkey interface Paolo Pisati
2026-10-20  9:24 ` Paolo Pisati [this message]
2026-10-20  9:24 ` [PATCH v4 5/7] HID: asus: Do not send feature reports larger than declared Paolo Pisati
2026-10-20  9:24 ` [PATCH v4 6/7] HID: asus: add prod-id, quirk for Zenbook Duo keyboard Paolo Pisati
2026-10-20  9:24 ` [PATCH v4 7/7] HID: asus: Keep the Zenbook Duo input device names Paolo Pisati

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=20261020092423.36380-5-p.pisati@gmail.com \
    --to=p.pisati@gmail.com \
    --cc=bentiss@kernel.org \
    --cc=denis.benato@linux.dev \
    --cc=hacker1024@users.sourceforge.net \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luke@ljones.dev \
    --cc=me@livan.pro \
    --cc=nathan@kernel.org \
    --cc=rebecca.mara@posteo.de \
    /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