【问题标题】:How can I capture raw HID input on Linux?如何在 Linux 上捕获原始 HID 输入?
【发布时间】:2009-05-17 05:46:20
【问题描述】:

我想要完成的简短版本:我有一个作为通用 HID 设备实现的脚踏板(INFINITY-IN-USB-1,如果有兴趣的话),我希望它在 Linux 上表现为 CtrlAlt 键。我正在寻找 X 级别的东西,即不仅仅是单个程序。

加长版:我在 Windows XP 中通过调用 DLL 函数 RegisterRawInputDevicesGetRawInputData 并在隐藏的情况下侦听输入来使此设置工作窗户。一切都是通过一个相当简单的AutoHotkey 脚本完成的(如果有人感兴趣,我可以在这里发布)。关键是,不需要任何额外的驱动程序等;只需要本机 Windows DLL 文件。

我希望这个设置可以在 Linux 上运行(更具体地说是 Ubuntu 下的 GNOME,但我偶尔会使用其他发行版/窗口管理器,因此很感谢 X 级别的解决方案)。此脚踏板不会将自己注册为键盘甚至操纵杆,而是使用 UsagePage 12, Usage 3 注册为 HID 设备。

我注意到最新的 Ubuntu 可以检测和使用Microsoft Natural Keyboard 上的收藏键,这些键也注册为 HID 设备*。我使用与使用脚踏板相同的方法在 Windows 上使用这些键(即,没有捆绑软件)。所以我假设这个踏板的东西也可以在 Linux 上运行,但问题是如何?

(我不熟悉 Linux 上的低级内容,因此请在适用时提供介绍或教程的链接。)

* 对于那些不知情的人,Microsoft Natural Keyboard 注册为常规键盘和通用 HID 设备。如果某些应用程序(例如捆绑的应用程序)不知道如何解释 HID 输入,则常规键将起作用,但收藏夹键和特殊功能键无用。


澄清一下,Linux 将踏板按下视为输入。它确实可以识别 USB 设备,但xev 没有为踏板按下提供任何输出。我已经看到有人成功使用Wine 下的踏板用于转录软件的报告,但这必须以 Windows 方式工作,并且不能提供我想要的(这使得踏板看起来像所有本机 Linux 应用程序的键盘)。是否需要一些低级 Linux 键盘驱动程序?


这里有更多信息:如果我在终端发出这个

cat /dev/usb/hiddev0

dev/usb/hiddev0 是我的踏板),我得到了与我的踏板压力相对应的原始代码。这是一个开始。我知道这些原始代码是什么意思:在二进制中,0001、0010、0100 分别对应于每个踏板,踏板按下的组合发送这些二进制数的组合,并释放仍然按下的任何踏板的踏板触发输入(如果全部踏板抬起,发送 0000)。

我怎样才能让 X 收听 dev/usb/hiddev0 并将原始代码转换为特殊的键码,以便我可以使用 xmodmap 或其他东西映射它们?

【问题讨论】:

    标签: linux hid hid-device


    【解决方案1】:

    你会想要uinput。您将在 /dev/usb/hiddev0 上收听,然后创建新事件,您将在 /dev/input/uinput 上发送。

    这解释了它并提供了一个小教程: Using uinput driver in Linux- 2.6.x to send user input {这是 this 存档页面上提到的 EInfochips 的“仪表板”出版物 2007 年 1 月“本月提示”文章}。

    【讨论】:

    • 你能详细说明一下吗?如何以编程方式收听 /dev/usb/hiddev0 (您链接的文章仅讨论 uinput)?我认为生成的程序(监听 hiddev 并通过 uinput 发送键盘/鼠标事件)必须作为守护进程运行?
    • 是的,我从您的问题中假设您已经知道如何阅读 hiddev0。您可能正在编写一个守护进程。首先编写一个程序,该程序不断读取 hiddev0 并打印出印刷机。然后您可以修改它以通过 uinput 发出新事件。这基本上会将这些事件重新注入内核,但作为键盘或鼠标事件(您选择)。无需对 X 进行任何更改。
    【解决方案2】:

    我在我的博客上写过如何让我的 Infinity IN-USB-1(又名“VEC USB 脚踏板”)在 X 下发送任意键符:

    Use VEC/Infinity USB Foot Pedal as a Keyboard Under Linux

    (它也应该适用于 IN-USB-2 以及可能由 VEC 和 P.I. Engineering 及其克隆销售的其他一些 USB 脚踏控制器型号。)

    这是较短的版本:

    让 X 识别踏板

    踏板是符合 HID 的 USB 设备,内核可以毫无问题地发现它并通过 /dev/input/eventX 节点将其事件提供给用户空间。要查看您可以运行 evtest 程序(在 Debian 上:sudo apt install evtest)。因此,您无需进入 HID 级别即可使用脚踏板。

    问题在于 udev 没有将其标记为键盘或鼠标,因此 X 忽略了它。这可以通过一行 udev 规则文件来解决(感谢 Parlatype 开发人员 Gabor Karsay 在 Parlatype Issue 28 中提供此解决方案):

    ACTION=="add|change", KERNEL=="event[0-9]*", ATTRS{idVendor}=="05f3", ATTRS{idProduct}=="00ff", ENV{ID_INPUT_KEYBOARD}="1"
    

    将该行放入名为/etc/udev/rules.d/10-vec-usb-footpedal.rules 的文件中。无需重启任何东西,udev 应该会自动检测文件。

    现在,当您拔下并重新插入 USB 踏板时,X 应该能够识别它(并发送鼠标按钮事件)。要验证,请运行 xev

    使用 udev hwdb 重新映射键符

    拥有只发送鼠标点击的踏板可能不是您想要的。踏板开关发送的这个键码可以用udev hwdb文件重新映射。

    /etc/udev/hwdb.d/(我把我的放在/etc/udev/hwdb.d/60-usb-footpedal.hwdb)下创建一个包含这些行的文件: /etc/udev/hwdb.d/60-usb-footpedal.hwdb

    evdev:input:b*v05F3p00FF*
     KEYBOARD_KEY_90001=f14
     KEYBOARD_KEY_90002=f15
     KEYBOARD_KEY_90003=f16
    

    这次我们确实需要通知系统更新二进制 hwdb 文件:

    $ sudo systemd-hwdb update
    

    然后拔下并重新插入设备。

    hwdb 文件的第一行匹配我们的设备(供应商05F3,产品00FF),随后的行将扫描码(十六进制)映射到键码。我选择了 F14、F15 和 F16 功能键,但在/usr/include/linux/input-event-codes.h 中定义了可用键码列表;要使用该文件中的名称#defined 作为 hwdb 键码,只需将它们转换为小写并删除 key_ 前缀。

    我计算机上的默认 (pc+us) xkb 键盘布局分别将F14F15F16 映射到XF86Launch5XF86Launch6XF86Launch7 键符。如果您现在打开xev 并踩下踏板,您应该会看到这些键符发出。使用这些键符,每个踏板开关都可以映射为桌面或窗口管理器中的热键。

    您还可以使用 xmodmap 之类的东西将 XF86* 键符号重新映射到其他键。有关更多详细信息,包括在 vim 中映射键、更多文档链接、指向直接读取 HID 设备的指针(如果需要)以及 Mac OS X 的解决方案,请参阅我的weblog post

    脚踏控制器

    我要提到的最后一件事是一个名为 footcontroller 的 python 程序,它从 evdev 设备 (/dev/input/eventX) 读取事件,并且可以配置为发出击键(通过 xdotool)或运行脚本以响应踩着踏板。它可以用来代替 xmodmap 让您的踏板发送您想要的任何击键。

    【讨论】:

      【解决方案3】:

      如果设备显示在 /dev/input 中,请使用“evdev”X 驱动程序将其连接起来,就像使用键盘或鼠标一样。

      【讨论】:

      • evdev 不适用于 TinyCore 有什么想法吗?
      【解决方案4】:

      您应该调查LIRC。它解释来自遥控器的输入。一些受支持的遥控器显然将自己显示为通用 HID 设备,因此您可以让您的设备与 LIRC 对话。

      【讨论】:

        【解决方案5】:

        这里有同样的问题,但无线键盘上有特殊键。我感觉到你的痛苦。

        无论如何,试图让它工作,这是我的方法:

        1. sleep 10; killall cat 然后在另一个终端中快速:cat /dev/usb/hiddevice0 > key1.usbdump 并按下/使用该设备。这将转储该密钥的 hiddevice 的二进制输出。
        2. 我迅速编写了一个 Python 脚本来读取 hiddevice 输入和触发事件。到目前为止,它在第一次击键时起作用。这与 Adam 的建议类似,但我认为 uinput 更难编程/使用,尽管可能更优雅,而且 Python 很容易获得。

        所以这是一项正在进行的工作(仅适用于第一次按下),但也许这样的东西可能对你有用:

        sf1 = open("test.usbdump").read() # Read the earlier USB dump from hiddevice
        kb = open("/dev/usb/hiddev0")
        while 1:
            # Prints true if the specific key has been read.
            print (kb.read(len(sf1)) == sf1)
            # Basically all that has to be done is if ^ is true, then fire off the event you want.
        

        如果有人可以帮助我完成我的程序,或者我做错了,请告诉我。 ;)

        我意识到 hiddevice 的初始转储中包含一些标头。使用一些 bless 十六进制编辑和位差分,您可以找到哪些值是重要的,并在 Python 中检查它们。 (例如,十六进制数字“B0”表示我的键盘上按下了一个特殊功能键,稍后会有更多关于按下哪个键的信息等)

        我的最终结果是:hiddevice0 似乎挂起并在一段时间后停止提供数据,不知道为什么,但是我使用 /dev/input/event* (它也可能对你有用),这似乎工作得更好。再次,相同的十六进制编辑和低级解析导致成功。在此过程中,我发现sudo cat /dev/input/event3 | hexdump 非常有助于确定哪些字节对您很重要。

        所以,如果你有一个SK-8812 IBM keyboard,并且想使用特殊键,你可以和我谈谈以获得我使用的脚本。

        【讨论】:

        • 在同一个终端,你可以输入 ( sleep 10 ; killall cat ) & cat /usb/dev/hiddev0 > key1.usbdump
        【解决方案6】:

        对于我的绑定/快捷方式,我使用Compiz、easystroke 和 xmacro 的组合。

        根据您的需要,我认为缺少的部分是 xbindkeys。我为您找到了这个链接,它可能会帮助您进行设置:

        http://linux-trackball.dreamhosters.com/

        我想知道是否有办法区分几种鼠标设备。

        【讨论】:

        • 我已经知道 xbindkeys 等,但问题是 X 无法识别我的踏板,所以 xbindkeys 到目前为止是没用的。即使您提供的链接的作者在他的轨迹球上也有一些仍然无法使用的按钮。我的问题是关于如何让那些不工作的密钥工作,而不是关于如何使用已经工作的密钥。很抱歉造成混乱。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多