unified-joypad: add option to ignore events

This commit is contained in:
spycat88
2025-08-25 16:17:06 +01:00
parent 0a59335b23
commit e7bbd5c291
2 changed files with 76 additions and 3 deletions

View File

@@ -27,9 +27,34 @@
* expect a standard controller.
*/
virtual-device-name = "ROCKNIX Unified Joypad";
virtual-vendor-id = <0xdead>; // USB Vendor ID in hexadecimal
virtual-product-id = <0xbeef>; // USB Product ID in hexadecimal
virtual-version-id = <0x0100>; // Device version in hexadecimal
virtual-vendor-id = <0x0fff>; // USB Vendor ID in hexadecimal
virtual-product-id = <0x0fff>; // USB Product ID in hexadecimal
virtual-version-id = <0x9001>; // Device version in hexadecimal
/*
* --- Optional: Event Ignore List ---
*
* Use this property to specify input events that should be completely
* blocked from the source devices. This is useful for preventing
* "double inputs" where a single button press generates both a
* button event (EV_KEY) and an axis event (EV_ABS).
*
* The list consists of pairs of u32 values: <TYPE CODE>.
* - The first value is the event type (e.g., EV_ABS).
* - The second value is the event code (e.g., ABS_BRAKE).
*
* The total number of elements must be even. You can find the numerical
* values for types and codes in the kernel's 'linux/input-event-codes.h'
* or use the macros defined in 'dt-bindings/input/input.h'.
*
* Example: Block the analog axis events from the L2/R2 triggers that
* also send digital button events.
*/
ignore-events = <
/* Type Code */
EV_ABS ABS_BRAKE, // Block the L2 trigger's analog axis (ABS_BRAKE)
EV_ABS ABS_GAS // Block the R2 trigger's analog axis (ABS_GAS)
>;
/*
* --- Optional: Button Remapping Rules ---

View File

@@ -29,6 +29,11 @@ struct key_remap {
u32 to;
};
struct event_filter {
u32 type;
u32 code;
};
struct device_remap_config {
const char *name;
const char *phys;
@@ -59,6 +64,9 @@ static u16 vdev_version;
static struct device_remap_config *remap_configs;
static int num_remap_configs;
static struct event_filter *ignored_events;
static int num_ignored_events;
static struct delayed_work rebuild_work;
static struct mutex dev_mutex;
@@ -154,6 +162,11 @@ static void joypad_event(struct input_handle *handle, unsigned int type,
struct device_remap_config *remap_cfg = handle->private;
int i;
for (i = 0; i < num_ignored_events; i++) {
if (type == ignored_events[i].type && code == ignored_events[i].code)
return; /* This is an ignored event, do nothing. */
}
if (vdev) {
if (type == EV_KEY && remap_cfg) {
for (i = 0; i < remap_cfg->num_remaps; i++) {
@@ -294,6 +307,37 @@ static void rebuild_virtual_device_work(struct work_struct *work)
mutex_unlock(&dev_mutex);
}
static int parse_ignore_list(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int n_vals;
n_vals = of_property_count_u32_elems(np, "ignore-events");
if (n_vals <= 0)
return 0; /* No property found, which is fine */
if (n_vals % 2 != 0) {
dev_warn(&pdev->dev, "Property 'ignore-events' must have an even number of elements (type/code pairs).\n");
return -EINVAL;
}
num_ignored_events = n_vals / 2;
ignored_events = devm_kcalloc(&pdev->dev, num_ignored_events, sizeof(*ignored_events), GFP_KERNEL);
if (!ignored_events) {
num_ignored_events = 0;
return -ENOMEM;
}
if (of_property_read_u32_array(np, "ignore-events", (u32 *)ignored_events, n_vals)) {
dev_err(&pdev->dev, "Failed to read 'ignore-events' property.\n");
num_ignored_events = 0;
return -EINVAL;
}
pr_info(DRV_NAME ": Will ignore %d event types.\n", num_ignored_events);
return 0;
}
static int parse_remaps(struct platform_device *pdev)
{
struct device_node *remaps_np, *child;
@@ -382,6 +426,10 @@ static int unified_joypad_probe(struct platform_device *pdev)
if (of_property_read_u32(np, "virtual-version-id", &temp_val) == 0)
vdev_version = (u16)temp_val;
ret = parse_ignore_list(pdev);
if (ret)
return ret;
ret = parse_remaps(pdev);
if (ret)
return ret;