packages: remove unified-joypad driver

This commit is contained in:
spycat88
2025-11-15 19:22:46 +00:00
parent 5e4a997f87
commit a3ea87e99e
11 changed files with 2 additions and 704 deletions

View File

@@ -1,2 +1 @@
SUBSYSTEM=="input", ATTRS{name}=="AYN Odin2 Gamepad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1"
SUBSYSTEM=="input", ATTRS{name}=="ROCKNIX Unified Joypad", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1"

View File

@@ -61,7 +61,7 @@
# for a list of additional drivers see packages/linux-drivers
# Space separated list is supported,
# e.g. ADDITIONAL_DRIVERS="DRIVER1 DRIVER2"
ADDITIONAL_DRIVERS="unified-joypad"
ADDITIONAL_DRIVERS=""
# Additional Firmware to use ( )
# Space separated list is supported,

View File

@@ -3,7 +3,7 @@ new file mode 100644
index 000000000000..845a7cf600e2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs8550-ayaneo-pocketdmg.dts
@@ -0,0 +1,150 @@
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025, ROCKNIX (https://github.com/ROCKNIX)
@@ -19,45 +19,6 @@ index 000000000000..845a7cf600e2
+ qcom,msm-id = <0x258 0x20000>, <0x259 0x20000>;
+ compatible = "ayaneo,pocketdmg", "qcom,qcs8550", "qcom,sm8550";
+ rocknix-u-boot-dt-id = "u-boot-pocket-dmg";
+
+ rocknix_unified_joypad {
+ compatible = "rocknix,unified-joypad";
+
+ target-device-names = "AYANEO DEVICE",
+ "AYANEO DEVICE",
+ "AYANEO Controller";
+
+ virtual-device-name = "ROCKNIX Unified Joypad";
+ virtual-vendor-id = <0x0fff>;
+ virtual-product-id = <0x0fff>;
+ virtual-version-id = <0x9001>;
+
+ ignore-events = <EV_ABS ABS_BRAKE // Ignore L2 axis
+ EV_ABS ABS_GAS>; // Ignore R2 axis
+
+ remaps {
+ remap_1 {
+ target-device-name = "AYANEO Controller";
+ target-device-phys = "usb-0001:01:00.0-2/input0";
+
+ key-remaps = <
+ 304 0x131 // BTN_SOUTH -> BTN_EAST
+ 305 0x130 // KEY_EAST -> BTN_SOUTH
+ >;
+ };
+
+ remap_2 {
+ target-device-name = "AYANEO DEVICE";
+ target-device-phys = "usb-0001:01:00.0-1/input1";
+
+ key-remaps = <
+ 183 115 // KEY_F13 -> KEY_VOLUMEUP
+ 184 114 // KEY_F14 -> KEY_VOLUMEDOWN
+ 194 0x13c // KEY_F24 -> BTN_MODE
+ >;
+ };
+ };
+ };
+};
+
+&tlmm {

View File

@@ -20,5 +20,4 @@
1900f6a24b480000df14000000010000,H700 Gamepad,platform:Linux,x:b3,a:b1,b:b0,y:b2,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,
0300b605202000000130000001000000,AYN Odin2 Gamepad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b6,guide:b8,start:b7,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
1900365541594e204f64696e20476100,AYN Odin Gamepad,platform:Linux,x:b2,a:b1,b:b0,y:b3,back:b8,guide:b10,start:b9,dpleft:b15,dpdown:b14,dpright:b16,dpup:b13,leftshoulder:b4,lefttrigger:a5,rightshoulder:b5,righttrigger:a4,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,
060003bdff0f0000ff0f000001900000,ROCKNIX Unified Joypad,platform:Linux,x:b3,a:b1,b:b0,y:b4,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,righttrigger:b9,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,
030081b85e0400008e02000000020000,Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,

View File

@@ -1,2 +0,0 @@
input_driver = "udev"
input_device = "AYANEO Controller"

View File

@@ -1,42 +0,0 @@
input_driver = "udev"
input_device = "ROCKNIX Unified Joypad"
input_b_btn = "0"
input_y_btn = "3"
input_select_btn = "4"
input_start_btn = "6"
input_up_btn = "11"
input_down_btn = "12"
input_left_btn = "13"
input_right_btn = "14"
input_a_btn = "1"
input_x_btn = "2"
input_l_btn = "9"
input_r_btn = "10"
input_l2_axis = "+4"
input_r2_axis = "+5"
input_l3_btn = "7"
input_r3_btn = "8"
input_l_x_plus_axis = "+0"
input_l_x_minus_axis = "-0"
input_l_y_plus_axis = "+1"
input_l_y_minus_axis = "-1"
input_r_x_plus_axis = "+2"
input_r_x_minus_axis = "-2"
input_r_y_plus_axis = "+3"
input_r_y_minus_axis = "-3"
# Hotkeys
input_enable_hotkey_btn = "5"
input_exit_emulator_btn = "6"
input_menu_toggle_btn = "2"
input_fps_toggle_btn = "3"
input_screenshot_btn = "1"
input_reset_btn = "0"
input_load_state_btn = "9"
input_save_state_btn = "10"
input_rewind_axis = "+4"
input_toggle_fast_forward_axis = "+5"

View File

@@ -1,20 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2024-present ROCKNIX (https://github.com/ROCKNIX)
PKG_NAME="unified-joypad"
PKG_VERSION="1.0"
PKG_LICENSE="GPL"
PKG_SITE="https://github.com/ROCKNIX"
PKG_URL=""
PKG_LONGDESC="unified-joypad: ROCKNIX unified joypad driver"
PKG_TOOLCHAIN="manual"
PKG_IS_KERNEL_PKG="yes"
make_target() {
kernel_make -C $(kernel_path) M=${PKG_BUILD}
}
makeinstall_target() {
mkdir -p ${INSTALL}/$(get_full_module_dir)/${PKG_NAME}
cp *.ko ${INSTALL}/$(get_full_module_dir)/${PKG_NAME}
}

View File

@@ -1 +0,0 @@
obj-m += unified-joypad.o

View File

@@ -1,96 +0,0 @@
/ {
/*
* This node configures the unified_joypad driver. It should be added
* to your target device's main .dts file.
*/
rocknix_unified_joypad {
/*
* This 'compatible' string is mandatory. It's the key that the Linux
* kernel uses to find and load the correct driver for this node.
* It must not be changed.
*/
compatible = "rocknix,unified-joypad";
/*
* A list of all physical device names the driver should manage.
* A "slot" is reserved for each entry. If you have two physical
* devices with the same name, you MUST list the name twice.
*/
target-device-names = "AYANEO DEVICE", // Slot for the first device
"AYANEO DEVICE", // Slot for the second device
"AYANEO Controller";
/*
* --- Optional: Virtual Device Properties ---
* These properties override the appearance of the final virtual device.
* This is useful for ensuring compatibility with applications that
* expect a standard controller.
*/
virtual-device-name = "ROCKNIX Unified Joypad";
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 ---
* This sub-node contains specific remapping configurations.
*/
remaps {
/*
* Remap rule for the "AYANEO Controller".
* Since its name is unique, using 'target-device-phys' is optional
* but recommended for a more robust configuration.
*/
remap_1 {
target-device-name = "AYANEO Controller";
target-device-phys = "usb-0001:01:00.0-2/input0";
key-remaps = <
/* from to */
304 0x131 // BTN_SOUTH -> BTN_EAST
305 0x130 // BTN_EAST -> BTN_SOUTH
>;
};
/*
* Remap rule for a specific "AYANEO DEVICE". We use the unique
* 'target-device-phys' property to distinguish it from the other
* device that shares the same name.
*/
remap_2 {
target-device-name = "AYANEO DEVICE";
target-device-phys = "usb-0001:01:00.0-1/input1";
key-remaps = <
/* from to (decimal) */
183 115 // KEY_F13 -> KEY_VOLUMEUP
184 114 // KEY_F14 -> KEY_VOLUMEDOWN
194 0x13c // KEY_F24 -> BTN_MODE
>;
};
};
};
};

View File

@@ -1,473 +0,0 @@
/*
* unified_joypad.c - A kernel module to merge multiple input devices.
*
* This module creates a single virtual input device that combines events from
* multiple physical input devices. It is configured via a Device Tree node,
* including optional button remapping by device name or unique physical path.
*
* It will also grab the source devices to prevent them from reporting events
* independently to the system.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/jiffies.h>
#define DRV_NAME "unified_joypad"
/* --- Data Structures --- */
struct key_remap {
u32 from;
u32 to;
};
struct event_filter {
u32 type;
u32 code;
};
struct device_remap_config {
const char *name;
const char *phys;
int num_remaps;
struct key_remap *remaps;
};
/* --- Module Information --- */
MODULE_AUTHOR("ROCKNIX");
MODULE_DESCRIPTION("Merges multiple input devices into one unified input device");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");
MODULE_INFO(intree, "Y");
/* --- Global Variables --- */
static struct input_dev *vdev;
static struct input_dev **source_devs;
static int num_target_devices;
static char **target_device_names;
static const char *vdev_name;
static u16 vdev_vendor;
static u16 vdev_product;
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;
/* --- Forward Declarations --- */
static void rebuild_virtual_device_work(struct work_struct *work);
/* --- Functions --- */
static void copy_attributes(struct input_dev *dev, struct input_dev *vdev)
{
int i;
for (i = 0; i < BITS_TO_LONGS(EV_MAX); i++)
vdev->evbit[i] |= dev->evbit[i];
for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++)
vdev->keybit[i] |= dev->keybit[i];
for (i = 0; i < BITS_TO_LONGS(REL_MAX); i++)
vdev->relbit[i] |= dev->relbit[i];
for (i = 0; i < BITS_TO_LONGS(ABS_MAX); i++)
vdev->absbit[i] |= dev->absbit[i];
for (i = 0; i < ABS_MAX; i++) {
if (test_bit(i, dev->absbit)) {
input_set_abs_params(vdev, i,
dev->absinfo[i].minimum,
dev->absinfo[i].maximum,
dev->absinfo[i].fuzz,
dev->absinfo[i].flat);
}
}
}
static void rebuild_virtual_device(void)
{
int error;
int i, j;
bool has_devices = false;
if (vdev) {
pr_info(DRV_NAME ": Destroying virtual device.\n");
input_unregister_device(vdev);
vdev = NULL;
}
for (i = 0; i < num_target_devices; i++) {
if (source_devs[i]) {
has_devices = true;
break;
}
}
if (!has_devices)
return;
pr_info(DRV_NAME ": Rebuilding virtual device...\n");
vdev = input_allocate_device();
if (!vdev) {
pr_err(DRV_NAME ": Failed to allocate virtual device\n");
return;
}
vdev->name = vdev_name;
vdev->id.bustype = BUS_VIRTUAL;
vdev->id.vendor = vdev_vendor;
vdev->id.product = vdev_product;
vdev->id.version = vdev_version;
for (i = 0; i < num_target_devices; i++) {
if (source_devs[i])
copy_attributes(source_devs[i], vdev);
}
__set_bit(EV_KEY, vdev->evbit);
for (i = 0; i < num_remap_configs; i++) {
for (j = 0; j < remap_configs[i].num_remaps; j++)
__set_bit(remap_configs[i].remaps[j].to, vdev->keybit);
}
error = input_register_device(vdev);
if (error) {
pr_err(DRV_NAME ": Failed to register virtual device, error %d\n", error);
input_free_device(vdev);
vdev = NULL;
} else {
pr_info(DRV_NAME ": Virtual device '%s' created/rebuilt successfully.\n", vdev->name);
}
}
static void joypad_event(struct input_handle *handle, unsigned int type,
unsigned int code, int value)
{
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++) {
if (code == remap_cfg->remaps[i].from) {
code = remap_cfg->remaps[i].to;
break;
}
}
}
input_event(vdev, type, code, value);
}
}
static int joypad_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
struct input_handle *handle;
struct device_remap_config *name_match = NULL;
struct device_remap_config *phys_match = NULL;
int error, i, slot = -1;
bool is_target = false;
for (i = 0; i < num_target_devices; i++) {
if (strcmp(dev->name, target_device_names[i]) == 0) {
is_target = true;
break;
}
}
if (!is_target)
return -ENODEV;
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
if (!handle)
return -ENOMEM;
handle->dev = dev;
handle->handler = handler;
handle->name = "joypad_handle";
for (i = 0; i < num_remap_configs; i++) {
if (remap_configs[i].phys && dev->phys &&
strcmp(remap_configs[i].phys, dev->phys) == 0) {
phys_match = &remap_configs[i];
break;
}
if (!name_match && remap_configs[i].name &&
strcmp(remap_configs[i].name, dev->name) == 0) {
name_match = &remap_configs[i];
}
}
if (phys_match)
handle->private = phys_match;
else if (name_match)
handle->private = name_match;
error = input_register_handle(handle);
if (error) {
kfree(handle);
return error;
}
error = input_open_device(handle);
if (error) {
input_unregister_handle(handle);
kfree(handle);
return error;
}
input_grab_device(handle);
mutex_lock(&dev_mutex);
for (i = 0; i < num_target_devices; i++) {
if (strcmp(dev->name, target_device_names[i]) == 0 && !source_devs[i]) {
source_devs[i] = dev;
slot = i;
break;
}
}
mutex_unlock(&dev_mutex);
if (slot != -1) {
pr_info(DRV_NAME ": Successfully connected to and grabbed '%s'\n", dev->name);
/* Schedule a rebuild in 200ms. If another device connects, this will reset the timer. */
schedule_delayed_work(&rebuild_work, msecs_to_jiffies(200));
} else {
pr_warn(DRV_NAME ": No free slot for '%s'\n", dev->name);
input_release_device(handle);
input_close_device(handle);
input_unregister_handle(handle);
kfree(handle);
return -EBUSY;
}
return 0;
}
static void joypad_disconnect(struct input_handle *handle)
{
int i;
pr_info(DRV_NAME ": Disconnecting from '%s'\n", handle->dev->name);
mutex_lock(&dev_mutex);
for (i = 0; i < num_target_devices; i++) {
if (source_devs[i] == handle->dev) {
source_devs[i] = NULL;
break;
}
}
mutex_unlock(&dev_mutex);
/* Also schedule a rebuild on disconnect */
schedule_delayed_work(&rebuild_work, msecs_to_jiffies(200));
input_release_device(handle);
input_close_device(handle);
input_unregister_handle(handle);
kfree(handle);
}
static const struct input_device_id joypad_ids[] = {
{ .driver_info = 1 },
{ }
};
static struct input_handler joypad_handler = {
.event = joypad_event,
.connect = joypad_connect,
.disconnect = joypad_disconnect,
.name = "unified_joypad_handler",
.id_table = joypad_ids,
};
static void rebuild_virtual_device_work(struct work_struct *work)
{
mutex_lock(&dev_mutex);
rebuild_virtual_device();
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;
int count = 0;
int valid_configs = 0;
remaps_np = of_get_child_by_name(pdev->dev.of_node, "remaps");
if (!remaps_np)
return 0;
count = of_get_child_count(remaps_np);
if (count == 0) {
of_node_put(remaps_np);
return 0;
}
remap_configs = devm_kcalloc(&pdev->dev, count, sizeof(*remap_configs), GFP_KERNEL);
if (!remap_configs) {
of_node_put(remaps_np);
return -ENOMEM;
}
for_each_child_of_node(remaps_np, child) {
struct device_remap_config *cfg = &remap_configs[valid_configs];
int n_vals;
of_property_read_string(child, "target-device-name", &cfg->name);
of_property_read_string(child, "target-device-phys", &cfg->phys);
if (!cfg->name && !cfg->phys)
continue;
n_vals = of_property_count_u32_elems(child, "key-remaps");
if (n_vals <= 0 || n_vals % 2 != 0)
continue;
cfg->num_remaps = n_vals / 2;
cfg->remaps = devm_kcalloc(&pdev->dev, cfg->num_remaps, sizeof(*cfg->remaps), GFP_KERNEL);
if (!cfg->remaps) {
of_node_put(remaps_np);
return -ENOMEM;
}
if (of_property_read_u32_array(child, "key-remaps", (u32 *)cfg->remaps, n_vals)) {
cfg->num_remaps = 0;
continue;
}
valid_configs++;
}
num_remap_configs = valid_configs;
of_node_put(remaps_np);
return 0;
}
static int unified_joypad_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int i, count, ret;
u32 temp_val;
pr_info(DRV_NAME ": Loading module...\n");
count = of_property_count_strings(np, "target-device-names");
if (count <= 0)
return count == 0 ? -ENODEV : count;
num_target_devices = count;
source_devs = devm_kcalloc(&pdev->dev, num_target_devices, sizeof(struct input_dev *), GFP_KERNEL);
target_device_names = devm_kcalloc(&pdev->dev, num_target_devices, sizeof(char *), GFP_KERNEL);
if (!source_devs || !target_device_names)
return -ENOMEM;
for (i = 0; i < num_target_devices; i++) {
if (of_property_read_string_index(np, "target-device-names", i, (const char **)&target_device_names[i]))
return -EINVAL;
}
if (of_property_read_string(np, "virtual-device-name", &vdev_name))
vdev_name = "ROCKNIX Unified Joypad";
if (of_property_read_u32(np, "virtual-vendor-id", &temp_val) == 0)
vdev_vendor = (u16)temp_val;
if (of_property_read_u32(np, "virtual-product-id", &temp_val) == 0)
vdev_product = (u16)temp_val;
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;
mutex_init(&dev_mutex);
INIT_DELAYED_WORK(&rebuild_work, rebuild_virtual_device_work);
return input_register_handler(&joypad_handler);
}
static void unified_joypad_remove(struct platform_device *pdev)
{
input_unregister_handler(&joypad_handler);
/* Cancel any pending work before cleaning up */
cancel_delayed_work_sync(&rebuild_work);
mutex_lock(&dev_mutex);
if (vdev)
input_unregister_device(vdev);
mutex_unlock(&dev_mutex);
pr_info(DRV_NAME ": Module unloaded.\n");
}
static const struct of_device_id unified_joypad_of_match[] = {
{ .compatible = "rocknix,unified-joypad" },
{ }
};
MODULE_DEVICE_TABLE(of, unified_joypad_of_match);
static struct platform_driver unified_joypad_platform_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = unified_joypad_of_match,
},
.probe = unified_joypad_probe,
.remove = unified_joypad_remove,
};
module_platform_driver(unified_joypad_platform_driver);

View File

@@ -1758,31 +1758,4 @@
<input name="x" type="button" id="2" value="1" />
<input name="y" type="button" id="3" value="1" />
</inputConfig>
<inputConfig type="joystick" deviceName="ROCKNIX Unified Joypad" deviceGUID="0600516fff0f0000ff0f000001900000">
<input name="a" type="button" id="1" value="1" />
<input name="b" type="button" id="0" value="1" />
<input name="down" type="hat" id="0" value="4" />
<input name="hotkeyenable" type="button" id="12" value="1" />
<input name="left" type="hat" id="0" value="8" />
<input name="leftanalogdown" type="axis" id="1" value="1" />
<input name="leftanalogleft" type="axis" id="0" value="-1" />
<input name="leftanalogright" type="axis" id="0" value="1" />
<input name="leftanalogup" type="axis" id="1" value="-1" />
<input name="leftshoulder" type="button" id="6" value="1" />
<input name="leftthumb" type="button" id="13" value="1" />
<input name="lefttrigger" type="axis" id="5" value="1" />
<input name="right" type="hat" id="0" value="2" />
<input name="rightanalogdown" type="axis" id="3" value="1" />
<input name="rightanalogleft" type="axis" id="2" value="-1" />
<input name="rightanalogright" type="axis" id="2" value="1" />
<input name="rightanalogup" type="axis" id="3" value="-1" />
<input name="rightshoulder" type="button" id="7" value="1" />
<input name="rightthumb" type="button" id="14" value="1" />
<input name="righttrigger" type="axis" id="4" value="1" />
<input name="select" type="button" id="10" value="1" />
<input name="start" type="button" id="11" value="1" />
<input name="up" type="hat" id="0" value="1" />
<input name="x" type="button" id="3" value="1" />
<input name="y" type="button" id="4" value="1" />
</inputConfig>
</inputList>