From: Alexander Egorov <begeebe@gmail.com>
To: platform-driver-x86@vger.kernel.org
Cc: hansg@kernel.org, ilpo.jarvinen@linux.intel.com,
lkml@antheas.dev, derekjohn.clark@gmail.com, samsagax@gmail.com,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 2/2] platform/x86: oxpec: Report tablet mode on OneXPlayer detachables
Date: Tue, 28 Jul 2026 11:35:29 +0300 [thread overview]
Message-ID: <20260728083529.329772-3-begeebe@gmail.com> (raw)
In-Reply-To: <20260728083529.329772-1-begeebe@gmail.com>
The OneXPlayer X1 family and Super X have detachable pogo-pin
keyboards. The firmware does not expose a tablet-mode input switch.
The Super X keyboard enumerates as 1a86:1305. The X1 family folio
keyboard enumerates as 258a:001e.
Register an input device on these boards and report SW_TABLET_MODE from
the model-specific pogo keyboard USB hotplug state. Other USB and
Bluetooth keyboards do not affect the switch.
A complete dump of the 256-byte Super X EC register map was compared
with the keyboard attached, detached, and reattached. No register
changed predictably with the attachment state.
Tested on a OneXPlayer Super X. Mutter enables accelerometer-driven
display rotation only while the pogo keyboard is absent.
Assisted-by: Codex:gpt-5.6
Signed-off-by: Alexander Egorov <begeebe@gmail.com>
---
drivers/platform/x86/Kconfig | 2 +
drivers/platform/x86/oxpec.c | 103 +++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b54b521..3bcbd49 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1055,6 +1055,8 @@ config OXP_EC
depends on ACPI_EC
depends on ACPI_BATTERY
depends on HWMON
+ depends on INPUT
+ depends on USB
depends on X86
help
Enables support for the platform EC of OneXPlayer and AOKZOE
diff --git a/drivers/platform/x86/oxpec.c b/drivers/platform/x86/oxpec.c
index df29e41..5c07a35 100644
--- a/drivers/platform/x86/oxpec.c
+++ b/drivers/platform/x86/oxpec.c
@@ -18,10 +18,12 @@
#include <linux/dmi.h>
#include <linux/hwmon.h>
#include <linux/init.h>
+#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/processor.h>
+#include <linux/usb.h>
#include <acpi/battery.h>
/* Handle ACPI lock mechanism */
@@ -55,6 +57,8 @@ enum oxp_board {
static enum oxp_board board;
static struct device *oxp_dev;
+static struct input_dev *oxp_tablet_mode_input;
+static struct notifier_block oxp_usb_notifier;
/* Fan reading and PWM */
#define OXP_SENSOR_FAN_REG 0x76 /* Fan reading is 2 registers long */
@@ -293,6 +297,74 @@ static const struct dmi_system_id dmi_table[] = {
{},
};
+#define OXP_KEYBOARD_VID_QINHENG 0x1a86
+#define OXP_KEYBOARD_PID_K2445 0x1305
+#define OXP_KEYBOARD_VID_HAILUCK 0x258a
+#define OXP_KEYBOARD_PID_HAILUCK 0x001e
+
+static int oxp_find_keyboard(struct usb_device *udev, void *data)
+{
+ bool *keyboard_attached = data;
+ u16 vid = le16_to_cpu(udev->descriptor.idVendor);
+ u16 pid = le16_to_cpu(udev->descriptor.idProduct);
+
+ switch (board) {
+ case oxp_x1:
+ if (vid == OXP_KEYBOARD_VID_HAILUCK &&
+ pid == OXP_KEYBOARD_PID_HAILUCK)
+ *keyboard_attached = true;
+ break;
+ case oxp_super_x:
+ if (vid == OXP_KEYBOARD_VID_QINHENG &&
+ pid == OXP_KEYBOARD_PID_K2445)
+ *keyboard_attached = true;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int oxp_usb_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct usb_device *udev = data;
+ u16 vid = le16_to_cpu(udev->descriptor.idVendor);
+ u16 pid = le16_to_cpu(udev->descriptor.idProduct);
+ bool keyboard = false;
+
+ switch (board) {
+ case oxp_x1:
+ keyboard = vid == OXP_KEYBOARD_VID_HAILUCK &&
+ pid == OXP_KEYBOARD_PID_HAILUCK;
+ break;
+ case oxp_super_x:
+ keyboard = vid == OXP_KEYBOARD_VID_QINHENG &&
+ pid == OXP_KEYBOARD_PID_K2445;
+ break;
+ default:
+ break;
+ }
+
+ if (!keyboard)
+ return NOTIFY_DONE;
+
+ switch (action) {
+ case USB_DEVICE_ADD:
+ input_report_switch(oxp_tablet_mode_input, SW_TABLET_MODE, false);
+ break;
+ case USB_DEVICE_REMOVE:
+ input_report_switch(oxp_tablet_mode_input, SW_TABLET_MODE, true);
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+
+ input_sync(oxp_tablet_mode_input);
+ return NOTIFY_OK;
+}
+
/* Helper functions to handle EC read/write */
static int read_from_ec(u8 reg, int size, long *val)
{
@@ -948,6 +1020,7 @@ static const struct hwmon_chip_info oxp_ec_chip_info = {
/* Initialization logic */
static int oxp_platform_probe(struct platform_device *pdev)
{
+ bool keyboard_attached = false;
struct device *dev = &pdev->dev;
struct device *hwdev;
int ret;
@@ -965,6 +1038,33 @@ static int oxp_platform_probe(struct platform_device *pdev)
return ret;
}
+ switch (board) {
+ case oxp_x1:
+ case oxp_super_x:
+ oxp_tablet_mode_input = devm_input_allocate_device(dev);
+ if (!oxp_tablet_mode_input)
+ return -ENOMEM;
+
+ oxp_tablet_mode_input->name = "OneXPlayer Tablet Mode Switch";
+ oxp_tablet_mode_input->phys = "oxp-platform/input0";
+ oxp_tablet_mode_input->id.bustype = BUS_HOST;
+ input_set_capability(oxp_tablet_mode_input, EV_SW, SW_TABLET_MODE);
+
+ ret = input_register_device(oxp_tablet_mode_input);
+ if (ret)
+ return ret;
+
+ oxp_usb_notifier.notifier_call = oxp_usb_notify;
+ usb_register_notify(&oxp_usb_notifier);
+ usb_for_each_dev(&keyboard_attached, oxp_find_keyboard);
+ input_report_switch(oxp_tablet_mode_input, SW_TABLET_MODE,
+ !keyboard_attached);
+ input_sync(oxp_tablet_mode_input);
+ break;
+ default:
+ break;
+ }
+
return 0;
}
@@ -1005,6 +1105,9 @@ static int __init oxp_platform_init(void)
static void __exit oxp_platform_exit(void)
{
+ if (board == oxp_x1 || board == oxp_super_x)
+ usb_unregister_notify(&oxp_usb_notifier);
+
platform_device_unregister(oxp_platform_device);
platform_driver_unregister(&oxp_platform_driver);
}
--
2.55.0
prev parent reply other threads:[~2026-07-28 8:35 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-27 21:59 [PATCH] platform/x86: oxpec: Report tablet mode on OneXPlayer Super X Alexander Egorov
2026-07-28 7:14 ` Antheas Kapenekakis
2026-07-28 8:35 ` [PATCH v2 0/2] platform/x86: oxpec: Report tablet mode on OneXPlayer detachables Alexander Egorov
2026-07-28 8:35 ` [PATCH v2 1/2] platform/x86: oxpec: Distinguish OneXPlayer Super X board Alexander Egorov
2026-07-28 8:35 ` Alexander Egorov [this message]
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=20260728083529.329772-3-begeebe@gmail.com \
--to=begeebe@gmail.com \
--cc=derekjohn.clark@gmail.com \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lkml@antheas.dev \
--cc=platform-driver-x86@vger.kernel.org \
--cc=samsagax@gmail.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.