From nobody Sat Feb 7 05:44:08 2026 Received: from relay12.grserver.gr (relay12.grserver.gr [88.99.38.195]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34E29480329; Thu, 22 Jan 2026 07:51:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=88.99.38.195 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769068291; cv=none; b=Y6wTRFNDxv9iydD/hpsDfTM8nk0Vmr7NHWTLorYyW9PlsM81yyUhwGZisgGyULuIUaxdVINGK7vii6mAcBTrwm4i8MUGX9ZbcJH5j1rkkhtO1kQSd7pSCnLvwlnM3/L1N6mG1b60Wfso6uRCo/JUYM8xhcauPxeubQ83dVPbBaA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769068291; c=relaxed/simple; bh=OkE7yuMFIli9rYIIEQaBAW2fbkV8rZD5uHxGzl3gm84=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=r1H8cFJRM91XqRj4oJgWRKWi+oOUGS/WHgDsgb7xHOle0DaQuNlSrRPNFGigR1+H2iUqf1PjH1HKJwx+XuzxuZpvd7BAoiNTV8JJ3JpyzxS4VECkfw3qHagcsj1PThxMZjHoYjGJrwDKNWUx7mqUXy83TGHCx2RpIRymE0zV46c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev; spf=pass smtp.mailfrom=antheas.dev; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b=Hrz3mfLJ; arc=none smtp.client-ip=88.99.38.195 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=antheas.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=antheas.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=antheas.dev header.i=@antheas.dev header.b="Hrz3mfLJ" Received: from relay12 (localhost [127.0.0.1]) by relay12.grserver.gr (Proxmox) with ESMTP id 90652BC1E4; Thu, 22 Jan 2026 09:51:18 +0200 (EET) Received: from linux3247.grserver.gr (linux3247.grserver.gr [213.158.90.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by relay12.grserver.gr (Proxmox) with ESMTPS id BB5B2BC22F; Thu, 22 Jan 2026 09:51:17 +0200 (EET) Received: from antheas-z13 (unknown [IPv6:2a05:f6c3:fefd:0:42c:a43d:2848:c282]) by linux3247.grserver.gr (Postfix) with ESMTPSA id A49FB1FDF38; Thu, 22 Jan 2026 09:51:16 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=antheas.dev; s=default; t=1769068277; bh=yKVLTSVKQ9etXKDdGfFKUrCcbd0y4L9UosWTbg87APU=; h=From:To:Subject; b=Hrz3mfLJU5oqc6BylYFf86xPeg5N2WC2gO2sLxOW8mhlJffUmZbwD2BXhKUZxMNwX vh5+u6fMAaUWPSM7ade4g7Xtsfzj7QXYMSaqROOOYIg0WaGCdMFM8b/2//oTE+1kiF KVeH/67uW3NNb/rS1ReKzZ7PWB88rkLBR3TUgzHCQLKovWSPf0s7l+wL4qM1BemhxO a0sVw+95HEEDusQpUEfDT9x0rCUgEfAJFy99DYXxQNnmLC6CuYA7krY/PknO3mRWPd Hkba085PmpISMzOBHlIULlQFHNhZoI0xLUIVQDgOuvfmP57WSUk/fkR+9SRYcrzkNY 0FP361EqvWwQQ== Authentication-Results: linux3247.grserver.gr; spf=pass (sender IP is 2a05:f6c3:fefd:0:42c:a43d:2848:c282) smtp.mailfrom=lkml@antheas.dev smtp.helo=antheas-z13 Received-SPF: pass (linux3247.grserver.gr: connection is authenticated) From: Antheas Kapenekakis To: platform-driver-x86@vger.kernel.org, linux-input@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Jiri Kosina , Benjamin Tissoires , Corentin Chary , "Luke D . Jones" , Hans de Goede , =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= , Denis Benato , Antheas Kapenekakis , Denis Benato Subject: [PATCH v12 10/11] platform/x86: asus-wmi: add keyboard brightness event handler Date: Thu, 22 Jan 2026 08:50:43 +0100 Message-ID: <20260122075044.5070-11-lkml@antheas.dev> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260122075044.5070-1-lkml@antheas.dev> References: <20260122075044.5070-1-lkml@antheas.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-PPP-Message-ID: <176906827730.715496.3788144599916749879@linux3247.grserver.gr> X-PPP-Vhost: antheas.dev X-Virus-Scanned: clamav-milter 1.4.3 at linux3247.grserver.gr X-Virus-Status: Clean Content-Type: text/plain; charset="utf-8" The keyboard brightness control of Asus WMI keyboards is handled in kernel, which leads to the shortcut going from brightness 0, to 1, to 2, and 3. However, for HID keyboards it is exposed as a key and handled by the user's desktop environment. For the toggle button, this means that brightness control becomes on/off. In addition, in the absence of a DE, the keyboard brightness does not work. Therefore, expose an event handler for the keyboard brightness control which can then be used by hid-asus. Since this handler is called from an interrupt context, defer the actual work to a workqueue. In the process, introduce ASUS_EV_MAX_BRIGHTNESS to hold the constant for maximum brightness since it is shared between hid-asus/asus-wmi. Reviewed-by: Luke D. Jones Tested-by: Luke D. Jones Acked-by: Benjamin Tissoires Reviewed-by: Denis Benato Signed-off-by: Antheas Kapenekakis --- drivers/platform/x86/asus-wmi.c | 46 +++++++++++++++++++--- include/linux/platform_data/x86/asus-wmi.h | 13 ++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wm= i.c index c45846be3f99..4cbd7b9806dc 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1719,6 +1719,44 @@ static void kbd_led_update_all(struct work_struct *w= ork) } } =20 +/* + * This function is called from hid-asus to inform asus-wmi of brightness + * changes initiated by the keyboard backlight keys. + */ +int asus_hid_event(enum asus_hid_event event) +{ + struct asus_wmi *asus; + int brightness; + + guard(spinlock_irqsave)(&asus_ref.lock); + asus =3D asus_ref.asus; + if (!asus || !asus->kbd_led_registered) + return -EBUSY; + + brightness =3D asus->kbd_led_wk; + + switch (event) { + case ASUS_EV_BRTUP: + brightness +=3D 1; + break; + case ASUS_EV_BRTDOWN: + brightness -=3D 1; + break; + case ASUS_EV_BRTTOGGLE: + if (brightness >=3D ASUS_EV_MAX_BRIGHTNESS) + brightness =3D 0; + else + brightness +=3D 1; + break; + } + + asus->kbd_led_wk =3D clamp_val(brightness, 0, ASUS_EV_MAX_BRIGHTNESS); + asus->kbd_led_notify =3D true; + queue_work(asus->led_workqueue, &asus->kbd_led_work); + return 0; +} +EXPORT_SYMBOL_GPL(asus_hid_event); + /* * These functions actually update the LED's, and are called from a * workqueue. By doing this as separate work rather than when the LED @@ -1801,13 +1839,11 @@ static void do_kbd_led_set(struct led_classdev *led= _cdev, int value) { struct asus_hid_listener *listener; struct asus_wmi *asus; - int max_level; =20 asus =3D container_of(led_cdev, struct asus_wmi, kbd_led); - max_level =3D asus->kbd_led.max_brightness; =20 scoped_guard(spinlock_irqsave, &asus_ref.lock) - asus->kbd_led_wk =3D clamp_val(value, 0, max_level); + asus->kbd_led_wk =3D clamp_val(value, 0, ASUS_EV_MAX_BRIGHTNESS); =20 if (asus->kbd_led_avail) kbd_led_update(asus); @@ -2011,7 +2047,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) asus->kbd_led.flags =3D LED_BRIGHT_HW_CHANGED; asus->kbd_led.brightness_set_blocking =3D kbd_led_set; asus->kbd_led.brightness_get =3D kbd_led_get; - asus->kbd_led.max_brightness =3D 3; + asus->kbd_led.max_brightness =3D ASUS_EV_MAX_BRIGHTNESS; asus->kbd_led_avail =3D !kbd_led_read(asus, &led_val, NULL); INIT_WORK(&asus->kbd_led_work, kbd_led_update_all); =20 @@ -4530,7 +4566,7 @@ static void asus_wmi_handle_event_code(int code, stru= ct asus_wmi *asus) return; } if (code =3D=3D NOTIFY_KBD_BRTTOGGLE) { - if (led_value >=3D asus->kbd_led.max_brightness) + if (led_value >=3D ASUS_EV_MAX_BRIGHTNESS) kbd_led_set_by_kbd(asus, 0); else kbd_led_set_by_kbd(asus, led_value + 1); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/pla= tform_data/x86/asus-wmi.h index d347cffd05d5..7b872b5d0960 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -178,6 +178,14 @@ struct asus_hid_listener { void (*brightness_set)(struct asus_hid_listener *listener, int brightness= ); }; =20 +enum asus_hid_event { + ASUS_EV_BRTUP, + ASUS_EV_BRTDOWN, + ASUS_EV_BRTTOGGLE, +}; + +#define ASUS_EV_MAX_BRIGHTNESS 3 + #if IS_REACHABLE(CONFIG_ASUS_WMI) void set_ally_mcu_hack(enum asus_ally_mcu_hack status); void set_ally_mcu_powersave(bool enabled); @@ -186,6 +194,7 @@ int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u= 32 *retval); int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retva= l); int asus_hid_register_listener(struct asus_hid_listener *cdev); void asus_hid_unregister_listener(struct asus_hid_listener *cdev); +int asus_hid_event(enum asus_hid_event event); #else static inline void set_ally_mcu_hack(enum asus_ally_mcu_hack status) { @@ -213,6 +222,10 @@ static inline int asus_hid_register_listener(struct as= us_hid_listener *bdev) static inline void asus_hid_unregister_listener(struct asus_hid_listener *= bdev) { } +static inline int asus_hid_event(enum asus_hid_event event) +{ + return -ENODEV; +} #endif =20 #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */ --=20 2.52.0