You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将无效USB控制器事件码1:300映射为有效事件码的技术求助

问题描述
  • 修复旧街机时遇到USB控制器事件解析问题:控制器发送无效事件码 EV_KEY:300(即1:300),街机软件无法识别
  • 需求:拦截该事件并转换为有效事件码 EV_KEY:194(对应KEY_F24)
  • 尝试evsieve工具失败,原因是工具不识别未知事件码300

相关输出

evtest输出

Event: time 1669313468.400824, type 4 (EV_MSC), code 4 (MSC_SCAN), value 9000d
Event: time 1669313468.400824, type 1 (EV_KEY), code 300 (?), value 0

evsieve错误输出

While parsing the arguments "--map key:300 key:up":
    While parsing the key "key:300":
        Invalid argument: unknown event code "300".
解决方案

常规映射工具不支持处理未知事件码,需直接通过evdev接口编写自定义程序实现拦截与转换,以下提供两种可行方案:

方法一:Python脚本(基于python-evdev库)

  1. 安装依赖
sudo apt install python3-evdev
  1. 编写映射脚本(命名为event_remap.py)
from evdev import InputDevice, UInput, ecodes

# 替换为你的控制器实际设备路径(可通过evtest确认)
device_path = '/dev/input/eventX'
dev = InputDevice(device_path)

# 创建虚拟输入设备,复制原设备能力并添加KEY_F24支持
capabilities = dev.capabilities()
if ecodes.EV_KEY in capabilities:
    capabilities[ecodes.EV_KEY].append(ecodes.KEY_F24)
else:
    capabilities[ecodes.EV_KEY] = [ecodes.KEY_F24]

ui = UInput(capabilities, name='Remapped Arcade Controller')

# 循环处理事件
for event in dev.read_loop():
    if event.type == ecodes.EV_KEY and event.code == 300:
        # 将无效码300转换为KEY_F24(194)
        ui.write(ecodes.EV_KEY, ecodes.KEY_F24, event.value)
        ui.syn()
    else:
        # 转发其他正常事件
        ui.write(event.type, event.code, event.value)
        ui.syn()
  1. 运行脚本(需root权限)
sudo python3 event_remap.py

方法二:C语言程序(基于libevdev库,性能更优)

  1. 安装依赖
sudo apt install libevdev-dev
  1. 编写代码(命名为remap_event.c)
#include <libevdev/libevdev.h>
#include <libevdev/libevdev-uinput.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int main() {
    struct libevdev *dev = NULL;
    struct libevdev_uinput *uidev = NULL;
    int fd, rc;

    // 替换为你的控制器实际设备路径
    fd = open("/dev/input/eventX", O_RDONLY);
    rc = libevdev_new_from_fd(fd, &dev);
    if (rc < 0) {
        fprintf(stderr, "初始化libevdev失败: %s\n", strerror(-rc));
        return 1;
    }

    // 创建虚拟输入设备
    rc = libevdev_uinput_create_from_device(dev,
                                            LIBEVDEV_UINPUT_OPEN_MANAGED,
                                            &uidev);
    if (rc < 0) {
        fprintf(stderr, "创建虚拟输入设备失败: %s\n", strerror(-rc));
        libevdev_free(dev);
        close(fd);
        return 1;
    }

    // 处理事件循环
    struct input_event ev;
    while ((rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev)) == 0) {
        if (ev.type == EV_KEY && ev.code == 300) {
            ev.code = KEY_F24;
            libevdev_uinput_write_event(uidev, ev.type, ev.code, ev.value);
        } else {
            libevdev_uinput_write_event(uidev, ev.type, ev.code, ev.value);
        }
        libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
    }

    // 清理资源
    libevdev_uinput_destroy(uidev);
    libevdev_free(dev);
    close(fd);
    return 0;
}
  1. 编译并运行
gcc remap_event.c -o remap_event -levdev
sudo ./remap_event

注意事项

  • 务必将代码中的/dev/input/eventX替换为控制器实际设备路径,可通过evtest或ls /dev/input/命令确认
  • 程序运行需要root权限,因为操作输入设备需特殊系统权限
  • 可将脚本/程序设置为开机自启,确保街机启动时自动加载事件映射

内容的提问来源于stack exchange,提问作者JettDc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:55:17