How to get linux kernel character driver FOPS? - c

# All,
Have got a requirement to replace a character driver ioctl function pointer. Would like to tap into the ioctl implementation of a character driver and replace that function pointer with mine(so that, we could intercept all calls getting into that character device, say X).
Have checked, include/linux/fs.h & fs/char_dev.c. Didn't find any pointers/hints for tapping in character driver IOCTL implementation.
Kernel version used : 4.9.35 (Any kernel version above 3.10 should be also fine).
Can someone point at any possible way if it exists ?
Any help is much appreciated.

Related

Linux kernel replace keys

I have to write a linux kernel module, which change character printed on the screen after pressing a key (let's say - I want 'a' to be printed when I press 'b' on keyboard). What is the best way to do it? I'he thought that good idea is to create module for keyboard. I did some research, i saw few keyloggers (as kernel modules) but all of them where able only to listen what key was pressed, and any change of scancode was imposible (which is pretty obvious in keyloggers). I read 3rd chapter from Linux Device Drivers, and i started to read 6th, but they are talking only about virtual devices, when i want to connect my module with the real device. I saw also this https://stackoverflow.com/questions/33836541/linux-kernel-how-to-capture-a-key-press-and-replace-it-with-another-key, but it wasn't working. My teacher said there is much eaysier way than using interrupts, but I have no idea how to do it (neither using interrupts and any other way).
What should I do? just read next chapters of LDD? Or any other book? Or maybe just lie down and cry?
Here's a very simple example of keyboard driver kernel module: https://github.com/raleighlittles/Olympus-MAJ-1428-Keyboard-Linux-driver/blob/main/hid-olympus-maj1428.c
I had a keyboard that generated weird scancodes for certain non-character keys (read the file, it explains more). Instead of using those scancodes, I wrote code to remap them to the extended function keys (F13, F14, etc.). You could use the code and instead simply switch the scan codes that you want by changing the key_mapping variable.

How i can retrieve data in my linux virtual device driver?

I have to implement virtual device driver, that will calculate sin of specified angle.
I found article how to write hello-world driver, it works nice, when i call cat on it.
But to calculate sin, i need to transfer some data to my driver. Which solution is most painless?
Should i first of all read all input data in separate method, remember it somewhere and then calculate & output?
The most painless solution would probably be to implement a ioctl.
The cat in the linked example uses read(), that is nice when your device generates data, such as a mouse or a video camera, but when a device replies to commands a ioctl is more appropriate: you send a command GET_SIN with an angle as argument and get a reply with the answer.
The alternative would be to write() the angle and then read() the solution: far more complicated, because there may be several processes reading and writing at the same time and it would be a mess!
BTW, beware! AFAIK, the kernel is not allowed to use floating point arithmentic, nor to link to -lm, so you will have to implement the sine as a fix-point integer function, maybe using a table...

Can't get kernel message from module

I'm trying a driver for a custom hardware component, the source code can be found here:
https://github.com/godspeed1989/zedboard/blob/master/led_drv/driver/myled.c
the problem is that when i do:
insmod myled.ko
nothing is shown in the console or in the dmesg log. I'm reading Linux Device Driver 3 and on it is written that you always must do:
module_init(init_function);
module_exit(exit_function);
in the source code there are none of them, instead there is:
module_platform_driver(myled_driver);
But when i load a module with this function nothing is print, instead if I use module_init and module_exit messages appear, what are the difference between this two kind of istructions?
"but why the latter statement doesn't work while the first it's ok? "
The first methond will register the driver to system and bus by module_platform_driver macro.
The latter statement will not register your driver to system and bus. To to this, you need register driver in the init_function() routine by calling platform_device_register().

Using glib to send raw bytes to an FTDI device over USB

I am developing a simple application in C with GTK+2.0 GUI, on Linux of course, this application is designed to control a device which is connected over the USB port and is using FTDI driver to emulate RS232 asynchronious protocol over the USB port.
I am using the function g_io_channel_write_chars() to send data to the device. The problem is the sequence I am sending consist a lot of values that are ASCII but do not match any (visible) character.
For example, when I am sending \x40\x40\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01 it won't work. The program will stop with an error.
GLib:ERROR:/build/buildd/glib2.0-2.34.1/./glib/giochannel.c:2382:g_io_channel_write_chars: code should not be reached
Przerwane (core dumped)
If I use sprintf function to put this sequence in a table only first two values will be copied and this sequence will be send to the device without an error.
Then my question is, how can I send any bytes to the device. Is there an equivalent of g_io_channel_write_chars() for this? I've been studying the documentation of GIOChannel and haven't found anything like this. Thanks very much for your help.
You need to make sure the channel doesn't think it's sending text. The crash you're getting is probably due to GIO trying to validate your data against its idea of the channel's encoding.
Note that the default encoding is UTF-8, and since not all byte sequences are valid UTF-8, this can easily cause validation to fail for random binary data.
Call g_io_channel_set_encoding with the argument NULL, this will make it safe for binary data:
The encoding NULL is safe to use with binary data.

uart buffer is not read

I am trying to read binary data from a serial device in c on linux.
The problem is, that sometimes there are chars in the driver's internal buffer, but polling (with select(2)) returns saying the device is not ready to be read.
I have read and re-read the man of termios and all the related man and searched over the internet. I believe I set all the flags correctly (namely VTIME, VMIN) and unset ICANON.
I tried using the function "tcmakeraw", as well, but it didn't solve the problem.
Do you guys have any ideas about what should I do?
Kind regards & Thanks in advance
Yannay
You should show us the code. I would start with using cfmakeraw on the serial port.
Once you have things working in raw mode, you can make modification and see how it works.
Here is a list of question or things you could check :
after modifying the attribute, using for example cfmakeraw, do you call tcsetattr(...) to
apply your change ?
How do you prove there is still data in the driver receive buffer ?
do you check your system call for errors ?
what is the result of stracing your program ?
Edit based on your comments :
Your protocol "guarantee" .... => check your assumption ! Unchecked, crystal clear guarantee are a good coandidate for "impossible error"
Basically : either select is broken, or your serial driver. Reason for serial driver being broken is a hardware fifo not being full enough to trigger un interrupt, or loosing an interrupt.
What happens when you read directly (not through C) /dev/ttyS0 (or equiv) after you setserial your parameters. Are you able to get the needed data outside of the select()?

Resources