From: Denis Benato <denis.benato@linux.dev>
To: linux-kernel@vger.kernel.org
Cc: platform-driver-x86@vger.kernel.org, linux-input@vger.kernel.org,
kernel@lists.opengamingcollective.org,
"Benjamin Tissoires" <bentiss@kernel.org>,
"Jiri Kosina" <jikos@kernel.org>,
"Luke D . Jones" <luke@ljones.dev>,
"Mateusz Schwartz" <matthew.schwartz@linux.dev>,
"Denis Benato" <benato.denis96@gmail.com>,
"Jonathan LoBue" <jlobue10@gmail.com>,
"Khamunetri Clark" <khamunetriclark@gmail.com>,
"Derek J. Clark" <derekjohn.clark@gmail.com>,
"Joshua Leivenzon" <hacker1024@users.sourceforge.net>,
"Nathan Chancellor" <nathan@kernel.org>,
"Rebecca Mara Müller" <rebecca.mara@posteo.de>,
"Ivan Levchenko" <me@livan.pro>,
"Corentin Chary" <corentin.chary@gmail.com>,
"Hans de Goede" <hansg@kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
"Denis Benato" <denis.benato@linux.dev>
Subject: [PATCH v15 07/18] HID: asus: add joysticks anti-deadzone configuration
Date: Tue, 10 Nov 2026 02:00:25 +0000 [thread overview]
Message-ID: <20261110020036.112884-8-denis.benato@linux.dev> (raw)
In-Reply-To: <20261110020036.112884-1-denis.benato@linux.dev>
ROG Ally devices allow configuring the anti-deadzone parameter for
the resistive joysticks devices as over time those develops drift,
therefore allow userspace to configure the anti-deadzone by exposing
relevant sysfs attributes.
Signed-off-by: Denis Benato <denis.benato@linux.dev>
Co-developed-by: Luke Jones <luke@ljones.dev>
Signed-off-by: Luke Jones <luke@ljones.dev>
---
drivers/hid/hid-asus.c | 157 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 157 insertions(+)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 5b8b4e2a901e..85641e36c922 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -107,6 +107,9 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define ASUS_ALLY_INNER_THRESHOLD_MIN 0
#define ASUS_ALLY_INNER_THRESHOLD_MAX 50
+#define ASUS_ALLY_ANTI_DEADZONE_MIN 0
+#define ASUS_ALLY_ANTI_DEADZONE_MAX 100
+
#define ASUS_ALLY_TRIGGER_RANGE_LOWER_MIN 0
#define ASUS_ALLY_TRIGGER_RANGE_LOWER_MAX 50
#define ASUS_ALLY_TRIGGER_RANGE_UPPER_MIN 70
@@ -851,6 +854,9 @@ static struct ally_prefs {
u8 left_trigger_max;
u8 right_trigger_min;
u8 right_trigger_max;
+
+ u8 left_anti_deadzone;
+ u8 right_anti_deadzone;
} ally_prefs = {
.lock = __MUTEX_INITIALIZER(ally_prefs.lock),
};
@@ -1334,11 +1340,153 @@ static struct device_attribute dev_attr_right_joystick_outer_threshold =
static struct device_attribute dev_attr_right_joystick_outer_threshold_range =
__ATTR(outer_threshold_range, 0444, right_joystick_outer_threshold_range_show, NULL);
+/**
+ * ally_set_anti_deadzone() - Send the joystick anti-deadzone values to the device
+ * @hdev: HID device the packet is sent on
+ * @left: Anti-deadzone of the left joystick
+ * @right: Anti-deadzone of the right joystick
+ *
+ * Context: Caller must hold ally_prefs.lock.
+ *
+ * Return: 0 on success, -%EOPNOTSUPP if the device does not support
+ * anti-deadzone, -%ENOMEM if the command buffer cannot be allocated, or a
+ * negative error code if sending the packet fails.
+ */
+static int ally_set_anti_deadzone(struct hid_device *hdev, u8 left, u8 right)
+{
+ const u8 payload[] = { left, right };
+ size_t buf_len;
+ int ret;
+
+ if (!ally_prefs.anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ u8 *buf __free(kfree) = ally_alloc_cmd(hdev, CMD_SET_ANTI_DEADZONE,
+ payload, sizeof(payload),
+ &buf_len);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = ally_gamepad_send_packet(hdev, buf, buf_len);
+ if (ret < 0) {
+ hid_err(hdev, "Failed to set anti-deadzone values: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Indices into ally_anti_deadzones[] */
+enum ally_joystick {
+ ALLY_LEFT_JOYSTICK,
+ ALLY_RIGHT_JOYSTICK,
+};
+
+static u8 *const ally_anti_deadzones[] = {
+ [ALLY_LEFT_JOYSTICK] = &ally_prefs.left_anti_deadzone,
+ [ALLY_RIGHT_JOYSTICK] = &ally_prefs.right_anti_deadzone,
+};
+
+static ssize_t ally_anti_deadzone_show(struct device *dev, char *buf,
+ enum ally_joystick which)
+{
+ guard(mutex)(&ally_prefs.lock);
+
+ if (!ally_prefs.anti_deadzone_support) {
+ hid_dbg(to_hid_device(dev), "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ return sysfs_emit(buf, "%u\n", *ally_anti_deadzones[which]);
+}
+
+static ssize_t ally_anti_deadzone_store(struct device *dev, const char *buf,
+ size_t count, enum ally_joystick which,
+ const char *group)
+{
+ u8 value, dz[ARRAY_SIZE(ally_anti_deadzones)];
+ struct hid_device *hdev = to_hid_device(dev);
+ unsigned int i;
+ int ret;
+
+ ret = kstrtou8(buf, 10, &value);
+ if (ret || value > ASUS_ALLY_ANTI_DEADZONE_MAX)
+ return -EINVAL;
+
+ scoped_guard(mutex, &ally_prefs.lock) {
+ if (!ally_prefs.anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dz); i++)
+ dz[i] = *ally_anti_deadzones[i];
+ dz[which] = value;
+
+ ret = ally_set_anti_deadzone(hdev, dz[ALLY_LEFT_JOYSTICK],
+ dz[ALLY_RIGHT_JOYSTICK]);
+ if (ret)
+ return ret;
+
+ *ally_anti_deadzones[which] = value;
+ }
+
+ sysfs_notify(&dev->kobj, group, "anti_deadzone");
+
+ return count;
+}
+
+/* Generates <side>_joystick_anti_deadzone_{show,store,range_show}. */
+#define ALLY_ANTI_DEADZONE_FUNCS(side, SIDE) \
+static ssize_t side##_joystick_anti_deadzone_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return ally_anti_deadzone_show(dev, buf, ALLY_##SIDE##_JOYSTICK); \
+} \
+ \
+static ssize_t side##_joystick_anti_deadzone_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ return ally_anti_deadzone_store(dev, buf, count, ALLY_##SIDE##_JOYSTICK, \
+ #side "_joystick_axis"); \
+} \
+ \
+static ssize_t side##_joystick_anti_deadzone_range_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return sysfs_emit(buf, "%u %u\n", ASUS_ALLY_ANTI_DEADZONE_MIN, \
+ ASUS_ALLY_ANTI_DEADZONE_MAX); \
+}
+
+ALLY_ANTI_DEADZONE_FUNCS(left, LEFT)
+ALLY_ANTI_DEADZONE_FUNCS(right, RIGHT)
+
+static struct device_attribute dev_attr_left_joystick_anti_deadzone =
+ __ATTR(anti_deadzone, 0644, left_joystick_anti_deadzone_show,
+ left_joystick_anti_deadzone_store);
+
+static struct device_attribute dev_attr_left_joystick_anti_deadzone_range =
+ __ATTR(anti_deadzone_range, 0444, left_joystick_anti_deadzone_range_show, NULL);
+
+static struct device_attribute dev_attr_right_joystick_anti_deadzone =
+ __ATTR(anti_deadzone, 0644, right_joystick_anti_deadzone_show,
+ right_joystick_anti_deadzone_store);
+
+static struct device_attribute dev_attr_right_joystick_anti_deadzone_range =
+ __ATTR(anti_deadzone_range, 0444, right_joystick_anti_deadzone_range_show, NULL);
+
static struct attribute *left_joystick_axis_attrs[] = {
&dev_attr_left_joystick_inner_threshold.attr,
&dev_attr_left_joystick_outer_threshold.attr,
&dev_attr_left_joystick_inner_threshold_range.attr,
&dev_attr_left_joystick_outer_threshold_range.attr,
+ &dev_attr_left_joystick_anti_deadzone.attr,
+ &dev_attr_left_joystick_anti_deadzone_range.attr,
NULL
};
@@ -1347,6 +1495,8 @@ static struct attribute *right_joystick_axis_attrs[] = {
&dev_attr_right_joystick_outer_threshold.attr,
&dev_attr_right_joystick_inner_threshold_range.attr,
&dev_attr_right_joystick_outer_threshold_range.attr,
+ &dev_attr_right_joystick_anti_deadzone.attr,
+ &dev_attr_right_joystick_anti_deadzone_range.attr,
NULL
};
@@ -1925,6 +2075,13 @@ static int hid_asus_ally_init(struct hid_device *hdev)
hid_warn(hdev, "Failed to restore trigger ranges: %d\n", ret);
}
+ if (ally_prefs.initialized && ally_prefs.anti_deadzone_support) {
+ ret = ally_set_anti_deadzone(hdev, ally_prefs.left_anti_deadzone,
+ ally_prefs.right_anti_deadzone);
+ if (ret < 0)
+ hid_warn(hdev, "Failed to restore anti-deadzone: %d\n", ret);
+ }
+
return 0;
}
--
2.47.3
next prev parent reply other threads:[~2026-11-10 2:00 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 2:00 [PATCH v15 00/18] HID: asus: add support for ROG Ally handhelds Denis Benato
2026-11-10 2:00 ` [PATCH v15 01/18] HID: asus: size feature reports from the HID report descriptor Denis Benato
2026-11-10 2:24 ` sashiko-bot
2026-11-10 2:00 ` [PATCH v15 02/18] HID: asus: add support for ROG Ally handhelds Denis Benato
2026-11-10 2:26 ` sashiko-bot
2026-11-10 2:00 ` [PATCH v15 03/18] HID: asus: add gamepad configuration Denis Benato
2026-11-10 2:00 ` [PATCH v15 04/18] HID: asus: add vibration strength configuration Denis Benato
2026-11-10 2:00 ` [PATCH v15 05/18] HID: asus: add joysticks inner and outer range configuration Denis Benato
2026-11-10 2:00 ` [PATCH v15 06/18] HID: asus: add triggers " Denis Benato
2026-11-10 2:00 ` Denis Benato [this message]
2026-11-10 2:00 ` [PATCH v15 08/18] HID: asus: add support for response curve Denis Benato
2026-11-10 2:00 ` [PATCH v15 09/18] HID: asus: add support to force feedback Denis Benato
2026-11-10 2:00 ` [PATCH v15 10/18] HID: asus: add support for gamepad mode Denis Benato
2026-11-10 2:00 ` [PATCH v15 11/18] HID: asus: add support for turbo buttons Denis Benato
2026-11-10 2:10 ` sashiko-bot
2026-11-10 2:00 ` [PATCH v15 12/18] HID: asus: add support for btn remapping Denis Benato
2026-11-10 2:17 ` sashiko-bot
2026-11-10 2:00 ` [PATCH v15 13/18] HID: asus: identify XG Mobile stations and bind the LED to the reported model Denis Benato
2026-11-10 2:00 ` [PATCH v15 14/18] HID: asus: expose XG Mobile identity and firmware information Denis Benato
2026-11-10 2:00 ` [PATCH v15 15/18] HID: asus: document ROG XG Mobile sysfs attributes Denis Benato
2026-11-10 2:00 ` [PATCH v15 16/18] HID: asus: document ROG Ally " Denis Benato
2026-11-10 2:00 ` [PATCH v15 17/18] platform/x86: asus-armoury: pick the eGPU activation from the reported GPU Denis Benato
2026-11-10 2:00 ` [PATCH v15 18/18] MAINTAINERS: add maintainer for the ASUS HID driver Denis Benato
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=20261110020036.112884-8-denis.benato@linux.dev \
--to=denis.benato@linux.dev \
--cc=benato.denis96@gmail.com \
--cc=bentiss@kernel.org \
--cc=corentin.chary@gmail.com \
--cc=derekjohn.clark@gmail.com \
--cc=hacker1024@users.sourceforge.net \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=jikos@kernel.org \
--cc=jlobue10@gmail.com \
--cc=kernel@lists.opengamingcollective.org \
--cc=khamunetriclark@gmail.com \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luke@ljones.dev \
--cc=matthew.schwartz@linux.dev \
--cc=me@livan.pro \
--cc=nathan@kernel.org \
--cc=platform-driver-x86@vger.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 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.