通过 UART 在 Open WRT 上镜像 USB HID 信号

通过 UART 在 Open WRT 上镜像 USB HID 信号

设置:运行 OpenWRT 的 Linkit 板(Smart 7688 Duo)和连接到 USB 主机的通用键盘。

目标:转储从 /dev/input/event0 获得的信号,并通过开发板的本机 UART 将其发送到 Atmega32u4。所以这个 Atmega 对于它所连接的机器来说就像一个键盘。

到目前为止我得到的是:在 OpenWRT 上从键盘获取信号并通过串行将其发送到 atmega 并不困难。但真正的问题是让 Atmega 像真正的键盘一样工作。

我使用基于此的Python脚本回答为了简化数据的可视化,我可以轻松地通过串行将其发送到 Arduino IDE 控制台。所以用一个简单的键盘.press()在 arduino 草图上的声明我重现了机器中的按键,ATmega 的作用就像 HID。

看起来非常简单,而且您只需要模仿简单的击键即可。但事实证明,重现实际键盘的所有特性非常棘手,例如同时按键、修改键、大写锁定等。

有人尝试过类似的事情吗?

PS.:我的想法是修改Arduino键盘类以便能够发送主要报告我想要的方式处理从 OpenWRT 收到的原始数据,但正如我所说,结果非常复杂。我只是不想让如果声明对于收到的每种数据,并告诉 Atmega 执行匹配密钥。我认为有一种方法可以简单地镜像信号。

编辑:

非常感谢@dirkt 付出了如此多的努力和时间的帮助。这是一次非常富有成效的讨论,我学到了很多东西。当被告知我们从 /dev/hidraw0 获得的报告将在另一侧实现所有特殊键时,您已经接近我需要的答案了。

因此,用收集到的信息重新提出问题: 如何从键盘获取格式为:[修饰符,保留,键,键,键,键,键,键]的报告

/dev/hidraw0 返回键和事件(1:按下 0:释放 2:按住),但我不知道如何获取修饰符字节。 (暂时忘记保留的)

答案1

部分答案:

我们先来整理一些东西。

如果我理解正确的话,OpenWRT 正在 MPU (MT7688) 上运行。 MPU 看到 UART 后面的 MCU (ATmega),并且 MPU 有一个 USB 控制器,通用 USB HID 键盘连接到该控制器。

在内核中,按键会经过以下层:

keyboard -> USB -> HID -> input

因此键盘将 USB 数据包作为“中断”发送,其中包含 HID 报告数据。 HID 数据在 HID 描述符中进行描述,对于键盘,通常有一个修饰符字节和最多六个同时按键。但其他格式也是可能的。您可以从 读取原始 hid 报告/dev/hidrawX。 HID 报告被转换为内核输入层事件,其中包含单个按键/释放,这些是您从/dev/input/event0.

这与 UART 或其背后的 ATmega 无关。

现在有多种方法可以通过其他总线(而不是通过 USB)将 HID 设备连接到内核层。例如通过 I2C 或通过 UART。

那是你要的吗?这又与 上 USB 键盘事件的存在无关/dev/input/event0

另一种选择是发明您自己的私有协议,无论您喜欢什么,在 ATmega 的一侧运行,并运行一个小 C 程序,通过以下方式注册新的输入层设备输入法,读取UART,然后发送输入层事件。

那是你要的吗?同样,它与 USB 键盘事件的存在无关/dev/input/event0,也与将这些事件转发到 UART 无关。

或者您想从 MPU 获取键盘事件,将它们发送到 ATmega,在那里处理它们,然后将它们发送回来并让它们充当真正的输入事件?这当然是可能的,但您必须问自己为什么不在 MPU 上进行此处理。

所以,请描述你的实际目标。目前,有点不清楚。你可以摆弄 Linux 输入层,你可以摆弄 Linux HID 层,你可以将事件注入到这两个层,并做你想做的一切。格式并不是特别困难。你必须具体说明什么你要。

修改 Arduino 键盘类,以便能够按照我想要的方式使用从 OpenWRT 接收的原始数据发送 KeyReports

没有多大意义。内核层没有“Arduino键盘类”。如果您使用“Arduino 键盘类”作为您的开发系统的一部分,请关联到它。它可能不会对您有太大帮助,您还需要了解其他格式(HID 报告、输入层事件)。

编辑

因此,回顾一下(下次您提出问题时,请以类似的方式描述它。另请参阅问题XY问题):

您希望在 USB 键盘和其他计算机之间有一个中间设备,其中其他计算机应该只看到一个普通键盘,并且在该设备上您可以进行键盘记录、触发其他事件等。(您还没有指定是否可以该中间设备必须是实际的硬件,或者是否也可以在 PC 上安装有助于完成任务或对键盘事件进行额外处理的东西。)

为此,您想使用 Linkit 板。 Linkit 板上的 MPU 充当键盘的 USB 主机。它通过 UART 连接到 MCU(ATmega),MCU 本身可以充当 USB HID 设备,而 USB HID 设备又可以连接到另一台 PC。

要充当 USB HID 设备,MCU 需要做三件事:它必须有一个描述报告的 HID 描述符,它需要发送 HID 键盘按下报告,并且它需要对来自 PC 的 HID 报告做出反应设置键盘 LED 等。我假设您有一个 ATmega 库可以为您处理所有这些事情。

最简单的方法是从真正的 USB 键盘复制 HID 描述符。您可以在 中找到人类可读形式的 HID 描述符/sys/kernel/debug/hid/DEVICE_ID/rdesc,其中 DEVICE_ID 标识您的键盘。要么解析它开头的十六进制,要么查明是否有 ioctl 可以直接获取此信息。

然后,您需要 MPU 上的小程序,它使用 ad-hoc 协议与 ATmega 进行通信。它必须执行以下操作: (1) 如果连接了 USB hid 设备,则读取并解析 HID 描述符,将 HID 描述符发送到 ATmega。 (2) 现在进入循环并转发来自 的 HID 报告/dev/hidrawN,其中N是通过 UART 的键盘编号,并将从 UART 接收到的 HID 报告写入/dev/hidrawN。 (3) 如果 USB 键盘断开连接,则发送“退出”消息。

在 ATmega 上,您需要一个小程序来使用可用的 HID 库来实现另一端。

您可以选择在哪一侧实施按键记录等。

同时按键、大写锁定等均通过转发 HID 报告自动处理。

相关内容