In the past days I’ve been studying to find a way to abstract evdev from the input_core subsystem, so we can use it as a userspace interface for the iio drivers.
The problem is that the current evdev implementation is too entangled with the input core subsystem, in particular the input devices initialisation and removal phases will require to rewrite a big part of input_core to realize a truly clean interface.
Some solutions are possible like embedding an iio_dev structure in input_handle and using it to communicate with the iio drivers and some iio specific handler functions, the result of this operations will likely create a giant poorly engineered mess.
After much considerations, studying and a lot of help and tips from Hunyue we have decided that implementing a new, more general subsystem is a better idea.
But how this new system should be organized, and how should it work ?
My idea is that it should only offer an interface to all character devices for kernel/userspace communication handling only the creation and removal of files form the /dev directory, all the actual files operations like read/write/open, ecc will be left to the various subsystems to implement troughtout functions handles registered with the system.
For example let’s say that iio needs a new userspace interface for it’s VCNL 4000 drivers.
What iio will do is to ask nevdev ( == new evdev, this is definitely a temporal name ;)) for a new file in it’s /dev/nevdev directory and pass it’s own file_operations structure. Nevdev will create and register a new file in /dev named (for example) nevdev0 and every time userspace will read or write to it the functions that iio registered will be called.
This means that every subsystem, not only iio or input_core can implement it’s own events and ioctls calls offering a really abstract interface.
Now let’s delve into an overview of the possible api this system will offer .
Like a lot of the other kernel subsystem nevdev will offer the usual register/unregister functions
-int nevdev_register_interface(nevdev_handle * interface, struct device * dev)
-void nevdev_unregister interface(nevdev_handle * interface)
the nevdev_handle is a structure containing some nevdev related thinks like a spinlock a cdev and a device structure, the drivers will have to register two things, a file_operations structure and their device_core device structure.
-struct nevdev_handle* nevdev_allocate_struct(struct file_operations * fops)
this function will allocate nevdev_handle and place fops inside it.
Internally nevdev will have a list of nevdev_handle corresponding to all the registered devices. Every time a new device is registered with int nevdev_register_interface(nevdev_handle * interface) nevdev will:
1:create a new device_core struct device using dev (the second argument in nevdev_register_interface) as a parent and a nevdev global device class as the device class, this way all the newly registered devices will stay in /sys/class/nevdev ready to be exported to /dev/nevdev by udev
2:create a new cdev character device and link it with the fops file_operations struct passed in nevdev_allocate_device.
3:register both with input_core, the hotplug event resulting from this will be intercepted by udev thanks to simple script and new nodes will be created in /dev/nevdev.
I believe nevdev will have is own dinamically allocated major number with the minors corresponding to every newly registered device.
This approach is very similar to the one the current evdev use.
Every time a file_operations syscall arrives it will be intercepted by nevdev first and then sent to the selected device via the registered file_operations struct, this is done in case we need to do some housekeeping (like when we receive an open() or release() call) and because nevdev will offer some global ioctls events for subsystem wide informations.
This is the possible structure of this new subsystem (there may be errors, please notice me if you found some), of course it will reside in a separate kernel module.
One thing I am still thinking about is how to distinguish to wich subsystem a file is registered, it could be as a global ioctls event that asks wich subsystem is the file registered with. This colud be inplemented as a field in nevdev_handle or better as an handle function passed by a subsystem (like iio,input_core, ecc) to nevdev during registration. What do you think ?
With this question solved another ioctls could find all the names of the files registered with a single subsystem and pass them to userspace.
This is the project I would like to present for this year gsoc, what do you think about it ? Do you believe there are problems with this approach ? What can be done better? Should I add some other things (other than the timeline, I’m still thinking about it) for the final application ? I’d love to receive some feedback.
PS for Hunyue: I’ll contact the input_core guys first thing next morning, promise, I just want to wait a while and see if someone think that there is something horribly wrong in this project.
I’ll post a more detailed timeline in the following days, a possible “stretch goal” could be modding the iio core to work with nevdev.
Thanks everyone for reading this loooooooooong post, hope It was at least a bit interesting :).