Using libiio trigger to propagate IRQ to userspace - linux

I browsed most of that litterature already and the kernel side of it is very much covered, understood and assimilated.
However my question is basically: How can I be alerted, for example through a callback function, when an interruption occurs in the kernel space and my daemon
lives in userspace.
IRQ Occuring -------> Upper half of the interrupt(put the timestamp in the buffer) ---------> Lower half of the interrupt handler (read data and adds the
timestamp in the buffer) -----------> ???? userspace daemon (async callback of some description) that will write a log on the HD.
I have everything up to the daemon part written and working, I seem to understand that through libiio you can assign a trigger to a particular channel or
attribute but that is where I get stuck.
Litterature on the libiio (most notably its wiki) has a chapter on triggers that is 4 lines long ... not very helpful to say the least.
iioinfo lists the devices present in the LSM6DSLTR (18 devices including two triggers) and I have been unable to assign the triggers to any device that they are
not assigned to already (No such file or directory) which I gather refer to the absence of the trigger directory in the sysfs for that particular device.
I also gather that the sysfs directory is, of course, slave to the kernel device tree and that the creation of that part of the device tree is made as the
driver is loaded.
So there must be a way to alter that part of the sysfs filesystem by asking the kernel driver to provision a device in the context to implement the trigger
directory so we can assign a trigger to it
second part will be to slave that trigger to an actual IRQ (42 in my case - as listed in /proc/interrupts) and be alerted in the userspace daemon when a
thresold has been reached in terms of either acceleration or vibration ...
Well, this is the nuts and bolts of what I am trying to achieve. the last part will be to write a few registers on the chip to configure how and when IRQ will
occur for any given integrated devices.

Related

Wait until driver instance has probed

I have written a Linux driver that is contained in a module. The probe() function sets up the hardware and creates a device file for userspace usage with device_create(). The device_create() is the last thing in the probe function.
I load the kernel module through the init_module syscall. It seems to me that the probe function is run as a callee of the syscall, i.e. that the probe function is done once the syscall returns to userspace. However I am not sure about this.
Sometimes, right after module insertion, the device file that is created through device_create is not there yet.
What is the correct way to wait for the driver has probed and all the effects of the probe such as created device files are visible?
A possible solution is waiting for node creation events in /dev by "inotify" API, provided that you can foresee the name. Here the official description and an example: https://man7.org/linux/man-pages/man7/inotify.7.html

Best Way to copy data from Kernel Driver to user space driver

I am having a kernel driver which is currently reading data from a sensor.
Now I have to write a user space application which will call kernel's sensor_read() API and send data to cloud.
How can I expose kernel's sensor_read() call to user space and read this data from user space? Data is about 10 bytes.
How can I expose kernel's sensor_read() call to user space and read this data from user space?
Most likely you should use IIO kernel framework, as it's specifically designed for writing sensor drivers. IIO exposes necessary files for your driver (in /sys/bus/iio/ and /dev/iio*). You can read() those files, or poll() them (to handle interrupts).
Official documentation is available here. You can also use some existing drivers as a reference, look here: drivers/iio/ .
Before IIO framework was introduced, it was common to provide sysfs files for drivers manually. So if you use old enough kernel, that should be the way to write the driver: handle your bus (like I2C) and sysfs files manually. But still, the best way is to use new kernel and IIO.
I am working on a Gyro + accel sensor. Linux driver will be sending events of type EV_MSC for both of them
It's not unusual for chip to have more than one sensor on it. In that case you should create two different drivers: one for accelerometer, and one for gyro. This way you will have two different files, one file per sensor.
For example, look how it's done for LSM330DLC chip (accelerometer + gyro):
accel driver: drivers/iio/accel/st_accel_core.c
gyro driver: drivers/iio/gyro/st_gyro_core.c
Both drivers are calling iio_device_register() function from driver's probe function, which creates corresponding files (which you can read/poll). Refer to documentation for further details.
As per my understanding I will open both the input devices from user space and add then to list of FD's which we want to poll. So when there is a new event how I can determine whether this event is from Gyro or aceel?
If you are curious about how to handle two /dev/input/event* files in user space, you basically have two choices:
using blocking I/O: you can read/poll them in different threads
using non-blocking I/O: you can open those files as O_NONBLOCK and just read() them in the same one thread; if new data is not available yet -- it will return -1 and errno will be set to EAGAIN; you can do those reads in infinite loop, for instance
This answer contains example of how to handle input file in C. And here you can read about blocking/non-blocking I/O.
There are many ways to access sensors data from kernel space to userspace
Check for relevant driver of the sensor you used. Check whether it supports/provides sysfs support.
you can read the data from /sys/class/ interfaces. You need to ensure that the relevant parameters exported to sysfs.
For eg: Temperature sensors should have exported temperature values(equivalent factors) in sysfs entry.
Examples(Below examples are fictions only)
cat /sys/class/hwmon/tempsensor/value
cat /sys/class/hwmon/tempsensor/min_value
cat /sys/class/hwmon/tempsensor/max_value
In some drivers, you can read them through ioctl / read / write api's to read/write sensor data.
You can use IOCTL (ioctl/read) calls to access the kernel functions from User space.
Refer below link for sample:
http://www.tldp.org/LDP/lkmpg/2.4/html/x856.html

IRQ Handling from User Space Linux

I'm writting a driver for a synthesized device in an FPGA. The device has several IRQs and have requested them on my driver:
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
rc = request_irq(irq, &Custom_driver_handler,IRQF_TRIGGER_RISING , DRIVER_NAME, base_addr);
My problem is that i want that the irq_handler calls a function of an user space application. Is there any way to call my user space application from the irq_handler of the driver on kernel space??
I know i could save a flag from the driver and mmap its direction from the user application to polling it, but what i want to know is if there is any faster/more correct way.
Thank you in advance
There are several ways of invoking user-space functions from kernel, usually named upcalls: http://lkml.iu.edu/hypermail/linux/kernel/9809.3/0922.html; check also https://lwn.net/Articles/127698/ "Handling interrupts in user space" and the http://wiki.tldp.org/kernel_user_space_howto overview from 2008, part "Sending Signals from the Kernel to the User Space".
To make writing drivers easier, there is UIO framework in the kernel now: https://unix.stackexchange.com/questions/136274/can-i-achieve-functionality-similar-to-interrupts-in-linux-userspace https://lwn.net/Articles/232575/ https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt/ https://www.osadl.org/fileadmin/dam/rtlws/12/Koch.pdf http://www.hep.by/gnu/kernel/uio-howto/
With UIO you can block or poll special file descriptor to wait for interrupt (block by using read() syscall; poll with poll syscall): https://lwn.net/Articles/232575/
On the user space side, the first UIO-handled device will show up as /dev/uio0 (assuming a normal udev setup). The user-space driver will open the device. Reading the device returns an int value which is the event count (number of interrupts) seen by the device; if no interrupts have come in since the last read, the operation will block until an interrupt happens (though non-blocking operation is supported in the usual way as well). The file descriptor can be passed to poll().
include/linux/uio_driver.h is available in linux kernel for many years, it is here for 3. and 4. versions of kernel.

sysfs_create_group(): Where to call?

currently i write an driver module which offers some entries in the sysfs. I read a lot through the driver source tree and the internet. I found two approches where the sysfs_create_group() is called:
a) most commonly: In the probe() function of the Driver. Like adviced here
How to attach file operations to sysfs attribute in platform driver?
Random Thing i looked at:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/rtc/rtc-ds1307.c#n1580
b) In the driver struct.
http://kroah.com/log/blog/2013/06/26/how-to-create-a-sysfs-file-correctly/
I know, Greg KH is a very well known developer. So i tried to follow his advice. In the bla_show()/bla_store() functions i tried to get my Driver private data, but my printk()'s showed much different addresses than i printed in the probe() function. My private data is (null). Which is ofc wrong.
When i use approch a) it works as expected, but as Greg KH suggests it is wrong too. I see it a lot in the stable tree in different drivers. Greg writes, the userspace already got the notification that there is a new device, but the LDD3 book states, that the probe function is there to determine if the device is present.
To sum my question up:
Why get the userspace notified about it, even when the kernel doesnt know if it can handle it?
Where is the right place to call sysfs_create_group()? Is it a) or b) ?
LDD3: https://static.lwn.net/images/pdf/LDD3/ch14.pdf
PDF page 24
probe is a function called to query the existence of a specific device
(and whether this driver can work with it), remove is called when the
device is removed from the system,and shutdown is called at shutdown
time to quiesce the device.
I am more confused than before .....
Best Regards
Georg
A device driver is a program that controls a particular type of device that is attached to your computer.
Platform devices are inherently not discoverable, i.e. the hardware cannot say "Hey! I'm present!" to the software. So for these kind of device we need a driver which call as Platform drivers. Drivers provide probe() and remove() methods.
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
.
.
struct device_driver driver;// this file has 2 parameter name or owner.
};
probe() should in general verify that the specified device hardware
actually exists. First we register our driver. Once it found device then it'll call driver probe. It is using name for searching a device.
Ans : your device is available then you need sysfs entry for communication (To the user space). so conceptually you need to define you sysfs entry in probe.
sys_notify function on your attribute and it will cause your userspace code to wake up. It will trigger when sysfs is available for userspace. It just avoiding a blocking call. When kernel does not have sysfs then it'll not notify userspace.
sysfs is a virtual file system provided by the Linux kernel that exports information about various kernel subsystems, hardware devices, and associated device drivers from the kernel's device model to user space through virtual files. When your device is available then you need this entry to export your information.

how did the kernel find the right process to send hardware interrupt

At first, this two things might exist:
A system has a table to response hardware interrupt
A process has a table to response interrupt send/set by the kernel
If I hit a key on the keyboard, the keyboard will send a interrupt to the CPU/kernel, and the kernel will process this interrupt. But, maybe the current running process is not the foreground one in front of our eyes, it could be a daemon process or something else. So, how the kernel knows which process should read/response our key stroke?
Thanks!
Hardware interrupts are only handled by the kernel. The device-specific event is processed and if there is event/data to share with user space then the driver makes that available. In your example of a keyboard, the device driver services the interrupt, extracting any data and clearing the condition. The input event representing the data which is pulled from the hardware is then sent to the input subsystem. A user space process must have the exposed input device handle open and blocked on a read. The input subsystem within the kernel is managing this. It's very common to see the same in other drivers: expose a device handle (e.g. /dev/misc/mydevice) which responds to open/close/read/write/ioctl. When a process performs a "read" and there is no data, the kernel code blocks the calling process causing it to wait until there is data to satisfy the read condition. I recommend reading up on kernel device drivers. "Linux Device Drivers" is a great start.

Resources