[PATCH v2 07/12] HID: asus: add joysticks anti-deadzone configuration
From: Denis Benato
Date: Wed Aug 19 2026 - 16:04:39 EST
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.
Assisted-by: opencode:glm-5.2
Signed-off-by: Denis Benato <denis.benato@xxxxxxxxx>
Signed-off-by: Luke Jones <luke@xxxxxxxxxx>
---
drivers/hid/hid-asus.c | 189 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 189 insertions(+)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 23a0cec2de15..050d979f4315 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -1247,6 +1247,191 @@ 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() - Set anti-deadzone values for joysticks
+ * @hdev: HID device
+ * @cfg: ally config
+ * @left_adz: left joystick anti-deadzone value (0-100)
+ * @right_adz: right joystick anti-deadzone value (0-100)
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int ally_set_anti_deadzone(struct hid_device *hdev, struct ally_config *cfg,
+ u8 left_adz, u8 right_adz)
+{
+ const u8 payload[] = { left_adz, right_adz };
+ int ret;
+
+ if (!cfg->anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ u8 *buf __free(kfree) = ally_alloc_cmd(CMD_SET_ANTI_DEADZONE, payload, sizeof(payload));
+ if (!buf)
+ return -ENOMEM;
+
+ ret = ally_dev_set_report(hdev, buf, ROG_ALLY_REPORT_SIZE);
+ if (ret < 0) {
+ hid_err(hdev, "Failed to set anti-deadzone values: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static ssize_t left_joystick_anti_deadzone_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ struct ally_handheld *const ally = drvdata->rog_ally;
+ struct ally_config *cfg;
+
+ if (!ally)
+ return -ENODEV;
+
+ cfg = ally_get_config(ally);
+ if (!cfg)
+ return -ENODEV;
+
+ scoped_guard(mutex, &cfg->config_mutex) {
+ if (!cfg->anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ return sysfs_emit(buf, "%u\n", cfg->left_anti_deadzone);
+ }
+}
+
+static ssize_t left_joystick_anti_deadzone_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ struct ally_handheld *const ally = drvdata->rog_ally;
+ struct ally_config *cfg;
+ u8 value;
+ int ret;
+
+ if (!ally)
+ return -ENODEV;
+
+ cfg = ally_get_config(ally);
+ if (!cfg)
+ return -ENODEV;
+
+ ret = kstrtou8(buf, 10, &value);
+ if (ret || value > 100)
+ return -EINVAL;
+
+ scoped_guard(mutex, &cfg->config_mutex) {
+ if (!cfg->anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ ret = ally_set_anti_deadzone(hdev, cfg, value, cfg->right_anti_deadzone);
+ if (ret)
+ return ret;
+
+ cfg->left_anti_deadzone = value;
+ }
+
+ return count;
+}
+
+static ssize_t left_joystick_anti_deadzone_range_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "0 100\n");
+}
+
+static ssize_t right_joystick_anti_deadzone_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ struct ally_handheld *const ally = drvdata->rog_ally;
+ struct ally_config *cfg;
+
+ if (!ally)
+ return -ENODEV;
+
+ cfg = ally_get_config(ally);
+ if (!cfg)
+ return -ENODEV;
+
+ scoped_guard(mutex, &cfg->config_mutex) {
+ if (!cfg->anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ return sysfs_emit(buf, "%u\n", cfg->right_anti_deadzone);
+ }
+}
+
+static ssize_t right_joystick_anti_deadzone_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hid_device *hdev = to_hid_device(dev);
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ struct ally_handheld *const ally = drvdata->rog_ally;
+ struct ally_config *cfg;
+ u8 value;
+ int ret;
+
+ if (!ally)
+ return -ENODEV;
+
+ cfg = ally_get_config(ally);
+ if (!cfg)
+ return -ENODEV;
+
+ ret = kstrtou8(buf, 10, &value);
+ if (ret || value > 100)
+ return -EINVAL;
+
+ scoped_guard(mutex, &cfg->config_mutex) {
+ if (!cfg->anti_deadzone_support) {
+ hid_dbg(hdev, "Anti-deadzone not supported on this device\n");
+ return -EOPNOTSUPP;
+ }
+
+ ret = ally_set_anti_deadzone(hdev, cfg, cfg->left_anti_deadzone, value);
+ if (ret)
+ return ret;
+
+ cfg->right_anti_deadzone = value;
+ }
+
+ return count;
+}
+
+static ssize_t right_joystick_anti_deadzone_range_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sysfs_emit(buf, "0 100\n");
+}
+
+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);
+
/**
* ally_set_trigger_ranges() - Generic function to set triggers ranges
* @hdev: HID device
@@ -1586,6 +1771,8 @@ static struct attribute *left_joystick_axis_attrs[] = {
&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
};
@@ -1594,6 +1781,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
};
--
2.47.3