6

我正在尝试为嵌入式 Linux 系统构建自定义操纵杆/游戏手柄设备。我正在寻找允许我从用户空间代码在 /dev/input 中创建节点的库或系统 API。

我想要这个,因为:

  • 定制硬件可以使用现有的 SPI 或 I2C 驱动程序与系统通信(这是我的硬件设计,所以我可以做任何最有技术意义的事情)

  • 内核模块不能使用其他驱动程序,只能从其他模块导出符号

我知道制作内核模块的唯一方法是使用内核代码并将其编译为内核模块。我不是想用用户空间代码来实现内核模块。

我正在寻找一个允许我创建文件的 API,当读取或写入该文件时,函数会被调用。这是字符驱动程序的一般概念。我不需要内核提供或强加的特权或限制。

必须有某种方法来模拟不涉及编写全新内核模块的文件 I/O。

谢谢!

4

6 回答 6

5

您可以使用用户空间输入子系统来做您想做的事情,请参阅:

http://thiemonge.org/getting-started-with-uinput

并举个例子:

https://xboxdrv.gitlab.io/

于 2013-01-07T03:44:17.343 回答
5

老问题,但我想我会添加一个花絮,这样看这个的人就不会得到错误的想法。大约在过去的 3-4 年里,有一个小框架,它被添加来扩展 FUSE 文件系统边缘,它提供了一个沙盒解决方案来精确地完成提问者的要求。

它被称为 CUSE,它允许字符驱动程序由属于 FUSE 组的人在内核中打开了 FUSE 和 CUSE 的系统上实例化。所需要的只是一个适当的应用程序(您的发行版上的 OSS 适配守护进程只是一个这样的应用程序,FWIW ...)

那时的“你不能”之类的答案根本没有帮助,没有真正考虑过这个问题,而且……呵呵……总体上是错误的……即使在那时。

CUSE 并没有像 FUSE 那样被广泛采用,因此以漂亮的易于使用的绑定形式在那里做事的帮助较少,但它仍然存在。把我带到这个话题的是我在寻找一个“更好”的答案,如果有关于这个主题的答案的话。答案是“是的,如果你能做 Python……”(pycuse)——如果你不能在那里做 Python,你只能靠自己了。嗯...我从来没有接受过这种事情...所以我要向 pycuse 学习并制作 C++/Go/etc。当我接触到它们时绑定,并且在我需要的时候需要一个新的用于我正在使用的语言的语言。

至于其余的……呵呵……下次你的鸭子多一排。你肯定没有上这个。

于 2016-04-22T17:52:00.687 回答
1

尝试创建自己的 char 设备,然后编写一个与驱动程序通信的用户空间应用程序(我建议在这种情况下使用 netlink,因为它可能在其他驱动程序不导出符号时用作后门,但它们确实打开了用户空间的功能,在这种情况下,具有 netlink 帮助的用户空间可以用作网关)。

在您的自定义字符设备中,您可以让用户告诉您要创建的设备的路径是什么。即 char 设备创建具有固定名称的初始 char 设备,然后用户应用程序可以使用 netlink(或 ioctl)告诉该 char 设备创建另一个具有自定义名称的 char 设备。

希望这可以帮助

于 2012-12-28T02:30:14.210 回答
1

您正在准确描述viewos虚拟机

http://wiki.virtualsquare.org/wiki/index.php/Main_Page

http://wiki.virtualsquare.org/wiki/index.php/UMview#Modules

这个虚拟机可以劫持每个指向你的内核的系统调用到你的用户空间模块(它被认为使 linux 不那么单一)

$umview xterm你用命令启动一个 umview 实例

所以在新生成的 xterm 中运行的每个程序都会被跟踪

现在你可以简单地做(在​​ umview 实例中)

$um_add_service umdev
$mount -t umdevJoystick none <your file, for example /dev/virtualJoystick>

所以你可以编写一个模块来拦截每个读/写/...到你的/dev/virtualJoystick文件并做你想做的事

(模块语法很简单)

static int joystick_read(char type, dev_t device, struct dev_info *di){
    /*my operation...probably a XTestEvent() or something like that*/
}
static int joystick_write(char type, dev_t device, struct dev_info *di){
    /*my operation...probably a XTestEvent() or something like that*/
}
/*...*/
struct umdev_operations umdev_ops={
    /*hijacking table*/
    .read=joystick_read,
    .write=joystick_write,
};

umdev_testmodulesumview 源代码中的目录作为一个小教程非常有用!;))

于 2013-03-01T12:31:02.857 回答
1

有一些限制,您可以考虑可以使用 LD_PRELOAD 和库覆盖对设备的常见调用的应用程序。

看这里了解更多详情

于 2013-08-11T04:28:23.120 回答
-3

你不能。

“字符设备”是指内核中面向字符的接口。

您可以按照 LIUB 的建议创建一个类似熔断器的接口,将类似内核的 API 编组回用户空间,如果您绝对需要/dev/input.

然而,如果您实际上并不需要 HID 设备并且因为它仅用于您的硬件,并且您“不需要内核访问”,因为您实际上可以从用户空间与低级硬件进行通信,您可能会考虑其他一些选项:

于 2012-12-29T09:51:16.280 回答