From nobody Mon Jun 8 19:47:26 2026 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1795C35674E for ; Tue, 26 May 2026 21:45:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779831918; cv=none; b=rHNIhomBuVkO4v4GgrhrLVqwILGVQmuO5EOGPk4Xo0aRRUWfSoBCcDUoLCRk9YL74LFx3vs/NYI0OCmPGMdbaZwvFjycE8+Uq7/+5d9KeZW+3kdJsmFsjwFsW/CPGyY2Q2UkefknF0kaT/cMUsqTOlVqveZkycf38VrFN9abi6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779831918; c=relaxed/simple; bh=zATfa1rbHrlVnG5dOUsmtrQQCN0dtUgSHK+vSITKnR0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=RGppmbGk4s3rk1dO8t0MBR7vWL9UTJ8PP4ACBCMKQf3zrUMQoOPCj9MCnqtwt566o4SEbEAI2DVH2ph1raqbakuYvgmln3LqoJukNZcB0wPd2rYIS9xotXMKARBD+DuPSq+zh/mGBfHCSi1PzyOJD0Yo7NYuBMpL7DFt4CkkUmY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=i/Tec4ZL; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="i/Tec4ZL" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-4903d730b1fso45991945e9.2 for ; Tue, 26 May 2026 14:45:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779831915; x=1780436715; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=kcCRAWkFYQNapDu/EJtVwj7lasodmrVBt/SVzCwAIkE=; b=i/Tec4ZLhas7+GgHjqQAd+1CPjhTIeWFFilgiU6r2IMSKwPEQ32CjvY5fiuNLAzAVy DpsyTFPDLgCr312JdhRyEEtr7J7QsVXNcK4Lbu2HzbVo4LAruMmldjXeIzKflM/JCcdT yZztpA+xnM2IGL5i4tZY0DqLRc4wIHpvxC5h9o/L/JiSsPWW2gh4lrnYQlMfZgPZ4A9+ pRU6zJNeW7EE1R/MGhtkPvERLJ/+eKFwhO8YalATZ4wlb+DasIPj4WJoeajqMjYROAoC 6Yhxq4/j9LtXDeb16gJ6FncK03qtsLJ9bVLaDgFSgbCYiAmFdaK9tw0H/njJIj2eT7uK cU8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779831915; x=1780436715; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=kcCRAWkFYQNapDu/EJtVwj7lasodmrVBt/SVzCwAIkE=; b=Z1N2Y93V+ByYTiW3SQwc3x72Qm0ES4qjg2VxJIqdadPlH+57tJfwpXLfJCG/UHvYnN z5b4wK7F9awIiXYYW4T1FTiCuyl+8iaX4uhrxzhNDE3+bUvIqOJKwyUUYovAOq3OBlTV Q85MFZ7MURM4zAewX0Rf4W1nUZx4QT7Ar6iqSP3vXLNcNkIG9eWP9WC4dGhJFgZlCxVe nt6goc+V3+i6Qvk2x9p6LWdlxXzy8ie/5TKWlWg2SJmBTPhuaYDkN1sVCSZMbllcYb/c zGsAmHdHZ0tm3+TgN2CbqrlAHM3bu/eW69sSLoWZ1oIcUPaImeWn63hV9AcNzYYBAdDH T3Vw== X-Forwarded-Encrypted: i=1; AFNElJ9lSWlqV8R9/a08YzxCpDj+uCrNwjX72aJXVcOHdPl//xYO8v3gqj5945PMApvsClhyEIYqff/dBG9eXCk=@vger.kernel.org X-Gm-Message-State: AOJu0Ywt0omzCW2ZF8nhACy0pNosd5qHKgH/wbxaKS84URznxrECyLiK Gfr7oKW4RTemQNXO8XiPcty33Yop8/QMQHopwrsyc2sCH1Dc99VABHVe X-Gm-Gg: Acq92OHwYbZj7EfAb4ydvw4J2hlLPv4Bdovg5fVteNR36Ci0TLSwrq9xpL6l4S/Fmvp xHn0UjXL150TLHpH11GX8cGWLgjiU/an7YRiTb5rFBPah4C7uHo+kL6fngLjsxV5jUrm9wRDTJ1 omosv69omX2H2hXfUGSoArTMsJAIY+551F8Ft1KB3JqFdbIdYI/VdzgBOBWZ5HNatjgozWL5IyG YGnhQ7j8rXbnJTj3GFKdtaV/l0Pv4Hz2fHY+wCFJgbcbBwqT8GRA+I006C4MpJeHunx7PnaYP9r lcHA06095cBqCMu/c6PJIugyjjQs25clCExj1iy/5pqHuCaM2cJCgx7c6RAJoFMx2oLXNN5szU0 FcYnJaoOKzyOvQ2B7Dt/zTigB51/RvGHwj8xs/r4rck4T7eB7t4w3lqODdHaglJNoHcTGMu6BO/ PxtzMNI1M6zQPi2oGsNStEppJA5KUvdlrM+Pj6F8xPql+uJRBBSMsTSAZl/wdDXLeGzT8zhg== X-Received: by 2002:a05:600c:a213:b0:48e:8741:fd42 with SMTP id 5b1f17b1804b1-490424ada3bmr221028465e9.12.1779831915273; Tue, 26 May 2026 14:45:15 -0700 (PDT) Received: from shiro (79.191.45.28.ipv4.supernova.orange.pl. [79.191.45.28]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45edb5a2908sm1085607f8f.18.2026.05.26.14.45.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 May 2026 14:45:14 -0700 (PDT) From: =?UTF-8?q?Dariusz=20Figza=C5=82?= To: platform-driver-x86@vger.kernel.org Cc: corentin.chary@gmail.com, luke@ljones.dev, denis.benato@linux.dev, hansg@kernel.org, ilpo.jarvinen@linux.intel.com, linux-kernel@vger.kernel.org, =?UTF-8?q?Dariusz=20Figza=C5=82?= Subject: [PATCH] platform/x86: asus-wmi: add keystone dongle support Date: Tue, 26 May 2026 23:44:39 +0200 Message-ID: <20260526214439.70142-1-dariuszfigzal@gmail.com> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The ASUS Keystone is a physical NFC-like dongle that slots into supported ASUS laptops. The EC fires WMI notify code 0xB4 on insert/remove events. Expose the current insert state via a sysfs attribute by querying WMI device ID 0x00120091 (DSTS). This devid does not follow the standard DSTS convention: PRESENCE_BIT (0x00010000) encodes the insert state rather than feature presence, and STATUS_BIT is never set. Presence of a keystone slot is detected by a successful DSTS call (any result other than -ENODEV). Signed-off-by: Dariusz Figza=C5=82 Reviewed-by: Denis Benato --- drivers/platform/x86/asus-wmi.c | 75 ++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 7 ++ 2 files changed, 82 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wm= i.c index 80144c412b90..a3fa3921aef3 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -70,6 +70,7 @@ module_param(fnlock_default, bool, 0444); #define NOTIFY_KBD_TTP 0xae #define NOTIFY_LID_FLIP 0xfa #define NOTIFY_LID_FLIP_ROG 0xbd +#define NOTIFY_KEYSTONE 0xb4 =20 #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0) =20 @@ -279,6 +280,8 @@ struct asus_wmi { u32 tablet_switch_dev_id; bool tablet_switch_inverted; =20 + bool keystone_detected; + enum fan_type fan_type; enum fan_type gpu_fan_type; enum fan_type mid_fan_type; @@ -646,6 +649,66 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *a= sus, u32 dev_id) return status =3D=3D 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); } =20 +/* Keystone **************************************************************= *****/ + +static ssize_t keystone_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus =3D dev_get_drvdata(dev); + u32 retval; + int err; + + err =3D asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_KEYSTONE, &retval); + if (err) + return err; + + return sysfs_emit(buf, "%d\n", !!(retval & ASUS_WMI_DSTS_PRESENCE_BIT)); +} + +static DEVICE_ATTR_RO(keystone); + +static void asus_wmi_keystone_notify(struct asus_wmi *asus) +{ + sysfs_notify(&asus->platform_device->dev.kobj, NULL, "keystone"); +} + +static int asus_wmi_keystone_init(struct asus_wmi *asus) +{ + u32 retval; + int err; + + /* + * Use a raw devstate call rather than asus_wmi_dev_is_present(). + * For this devid, PRESENCE_BIT encodes current insert state, not + * feature presence, so asus_wmi_dev_is_present() would return false + * whenever the dongle is absent at boot, even on machines that have + * a keystone slot. + * -ENODEV means the firmware doesn't know this devid at all. + * retval is not examined here, only the return code matters. + */ + err =3D asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_KEYSTONE, &retval); + if (err =3D=3D -ENODEV) + return 0; + if (err) + return err; + + err =3D device_create_file(&asus->platform_device->dev, &dev_attr_keyston= e); + if (err) + return err; + + asus->keystone_detected =3D true; + return 0; +} + +static void asus_wmi_keystone_exit(struct asus_wmi *asus) +{ + if (!asus->keystone_detected) + return; + + device_remove_file(&asus->platform_device->dev, &dev_attr_keystone); + asus->keystone_detected =3D false; +} + /* Input *****************************************************************= *****/ static void asus_wmi_tablet_sw_report(struct asus_wmi *asus, bool value) { @@ -4575,6 +4638,12 @@ static void asus_wmi_handle_event_code(int code, str= uct asus_wmi *asus) return; } =20 + if (code =3D=3D NOTIFY_KEYSTONE) { + if (asus->keystone_detected) + asus_wmi_keystone_notify(asus); + return; + } + if (code =3D=3D NOTIFY_KBD_FBM || code =3D=3D NOTIFY_KBD_TTP) { if (asus->fan_boost_mode_available) fan_boost_mode_switch_next(asus); @@ -5085,6 +5154,10 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_sysfs; =20 + err =3D asus_wmi_keystone_init(asus); + if (err) + dev_warn(&pdev->dev, "Keystone initialization failed: %d\n", err); + err =3D asus_wmi_input_init(asus); if (err) goto fail_input; @@ -5170,6 +5243,7 @@ static int asus_wmi_add(struct platform_device *pdev) fail_hwmon: asus_wmi_input_exit(asus); fail_input: + asus_wmi_keystone_exit(asus); asus_wmi_sysfs_exit(asus->platform_device); fail_sysfs: fail_custom_fan_curve: @@ -5191,6 +5265,7 @@ static void asus_wmi_remove(struct platform_device *d= evice) asus_wmi_backlight_exit(asus); asus_screenpad_exit(asus); asus_wmi_input_exit(asus); + asus_wmi_keystone_exit(asus); asus_wmi_led_exit(asus); asus_wmi_rfkill_exit(asus); asus_wmi_debugfs_exit(asus); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/pla= tform_data/x86/asus-wmi.h index 554f41b827e1..c29962d5baac 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -147,6 +147,13 @@ #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 #define ASUS_WMI_DEVID_GPU_MUX_VIVO 0x00090026 =20 +/* Keystone dongle insert/remove state. + * PRESENCE_BIT (0x00010000) encodes insert state: + * 0x00010000 =3D inserted, 0x00000000 =3D absent. STATUS_BIT is never set. + * 0xFFFFFFFE means no keystone slot on this machine. + */ +#define ASUS_WMI_DEVID_KEYSTONE 0x00120091 + /* TUF laptop RGB modes/colours */ #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 #define ASUS_WMI_DEVID_TUF_RGB_MODE2 0x0010005A --=20 2.54.0