Search code examples
linuxinputkerneldrivers

Implementing a Linux Character Driver in User-space


I am trying to build a custom joystick/gamepad device for an embedded Linux system. I am looking for a library or system API that will allow me to create a node in /dev/input from userspace code.

I would like this because:

  • The custom hardware can communicate with the system using the existing SPI or I2C drivers (it's my hardware design so I can do whatever makes the most technical sense)

  • Kernel modules can't utilize other drivers, only exported symbols from other modules

I understand the only way to make a kernel module is with kernel code and compiling that as a kernel module. I am not trying to achieve a kernel module with userspace code.

I am looking for an API that allows me to create a file, and when that file is read from or written to, functions get called. That's the general concept of a character driver. I don't need the privileges or restrictions that the kernel provides or imposes.

There must be some way to emulate file I/O that doesn't involve writing a brand new kernel module.

Thanks!


Solution

  • You can't.

    A "character device" refers to an in-kernel character-oriented interface.

    You could do what LIUB suggests and create a fuse-like interface that marshalls the kernel-like API back into userspace, and you will need to do something like this if you absolutely need HID-style devices produced in /dev/input.

    Yet if you don't actually need HID devices and since it is just for your hardware, and you "don't need kernel access" as you can actually communicate with the low-level hardware from userspace, you might consider some other options:

    • You could use XSendEvent or the XTEST protocol to synthesise local events.
    • You could build a network server (or one that uses multicast unix-domain socket to efficiently distribute data) that allows clients to connect.
    • If it's really just read() you want clients to do, you could use a fifo. When your program write()s packets that are evenly divisible into a PIPE_BUF (512 bytes) you can be guaranteed they cannot be accidentally interleaved in another packet.