Linux keyboard delay - linux

So I want to build a kernel module (I suppose) which would insert little delay after a keyboard key is pressed (let's say 500ms). I managed to do this in Windows through hooks, but it seems to be different in Linux. Note that I do not wish to use x11 methods, as I want it to also work from the linux console (even if there is no X server running). From what I was able to understand, it would require to build a kernel module and insert it dynamically into the kernel with insmod. I managed to build a key logger which would dump each pressed key to the kernel log, but inserting a delay would require sending the thread that handles the keyboard interrupt handler to sleep, which is a very bad idea, and also to rewrite the entire USB_KBD driver, because the current script calls the request_irq function with the IRQF_SHARED flag set, so I guess the original driver still does its job before executing my function.
I am currently requesting an interrupt handler like this
request_irq (1, (irq_handler_t) irq_handler, IRQF_SHARED, "keyboard_stats_irq", (void *)(irq_handler));
Any suggestions on how to handle this (any other way) ?

You can write a user space daemon that reads the input events from /dev/input/input* (whatever the keyboard device is), while grabbing the device to block the events to go through the rest of the system (ioctl(fd, EVIOCGRAB, 1)).
Then, the daemon can create a virtual input device, using /dev/uinput and write the input events there after some delay. Since the delay will be implemented in user-space, that will be quite easy.
Starting your daemon will be equivalent to hot-plugging a virtual keyboard, and modern X servers (less than 10 years?) are able to cope with hot-plugged input devices. And the vconsole driver works fine too with those.

Related

Last command during poweroff

I am writing some software to shutdown some external hardware wired into my control board. The catch is that I need to wait for the VERY end of the poweroff operation to send the signal (through a gpio output). I am weighing some options right now, but I am curious as to where I can see what the kernel actually does right before poweroff.
Is there a file somewhere that I can look into?
Start at the function kernel_power_off in kernel/reboot.c and follow the code. The final power-off operations are very platform specific, so if you want to follow down to the bitter end, you'd need to figure out exactly which bits of arch-specific code you're using.
One simpler possibility for sending your signals is to register a kmsg_dump handler. The last thing kernel_power_off does before invoking the platform-specific power-off code is to execute kmsg_dump(KMSG_DUMP_POWEROFF);. (Just ignore any kmsg_dump calls other than that one.)

Restoring Keyboard IRQ

I'm very new to the Linux Kernel Module development and trying to write a simple kernel module which can later be extended as the keyboard driver.
I tried following two approaches:
Interrupt Based Approach
I started writing the code after following the guide given here. But the only problem is that the machine freezes when I run rmmod because it is not able to restore the IRQ to the original keyboard driver.
Is there any way to save the device name & device id of the original keyboard driver before requesting the IRQ in init() and then restore everything back to normal once the exit() i.e. cleanup_module() is fired?
void cleanup_module() {
/* Something to restore everything back to normal */
free_irq(1, NULL);
}
Polling Approach
In this approach, I am continuously polling for the Key Pressed & Released by using a while loop and then copying the input back to the user.
while(!(inb(0x64) & 0x1) || (input = inb(0x60)) & 0x80);
The problem I'm facing here is that it never comes out of the while loop. I'm assuming that is because the original keyboard driver serves the request.
Is there any way to get the request forwarded from the original keyboard driver?
I appreciate any help/pointers on this.
Thanks!
I'm afraid that I do not see how this can work as long as the normal kernel keyboard driver is also controlling the keyboard, since both drivers will be attempting to control the device. The kernel i8042 driver (I assume that is the relevant one for you) registers its interrupt as shared, and if your driver managed to register for the same interrupt then it will also have registered its handler as shared, so that both got notified on interrupts and would race to access the device.
If you registered a shared handler, this might also explain the crash when you unload it: unregistering a shared interrupt handler only works when the second parameter contains a valid dev_id; so unregistering would fail when called with NULL as you did, but the handler code would still be unloaded from memory. This would leading to a crash on a future interrupt.
Regarding your polling approach, yes, since the normal driver is notified on interrupts it is rather likely to beat you to reading the keyboard.

Linux Kernel - stoping a running kernel timer from user space

I am trying to blink an LED in my embedded device while Linux is booting. Basically the LED blink shows that Linux is in the process of booting.
To blinks the LED, I am doing the following things
Created a global timer (LED blink timer) in init/main.c
static struct timer_list pwr_led_timer;
Started the timer as soon as init_timers() function is finished in start_kernel()
setup_timer and mod_timer functions used.
When timer fires, in the timer handler, LED is toggled. And timer restarted.
When kernel finishes the whole boot process, I am switching off the LED and deleting the timer.
del_timer_sync(&pwr_led_timer);
Question:
I would like to stop the timer and switch of the LED from user space from my application instead of stopping at the kernel (that is point number 4). Is there a standard way to stop the kernel running timer from user space ?
since pwr_led_timer is global struct, can any IOCTL call be used to stop the timer from user space ? My Idea is do some IOCTL and get access to kernel. Since the pwr_led_timer is global, in IOCTL I can call the del_timer_sync() with pwr_led_timer. But not sure which device I should open to IOCTL (?)
Sorry, I am new to kernel/driver programming. I tried to search the net but could not get any clue.
Kindly let me know if anyone has any inputs. Thanks in advance.
Regards,
Emerson
Have you considered trying netlink? It's a powerful method for user-to-kernel (or process-to-process) communication which both simple and lightweight.

Posix Serial Connection with Callbacks

I am trying to communicate with an arduino using the code from,
http://todbot.com/blog/2006/12/06/arduino-serial-c-code-to-talk-to-arduino/
which uses termios to open and talk to an arduino in a non blocking way which works fine. What I was wondering is when on Java using rxtx I can register a callback function that is called when ever there is data on the line so that I don't have to manually check. I googled but could not find any info on how to register a callback function?
I am on Linux/OS X and I am trying to avoid launching a new thread just to watch/read data on the line.
Posix itself does not define a way to assign a callback function to be called when serial data arrives. The standard way to do this type of processing if you don't want to use a seperate thread is to use the select library function. This allows you program to define a set of file descriptors your program is interested in and then go to sleep. Select will automatically wake up your process if something interesting happens to one of the file descriptors you've declared interest in (such as new data becoming available for reading). This avoids having to busy-wait and poll multiple descriptors for activity.
Another option would be to use a library like libevent which sits on top of the Posix layer and provides the callback infrastructure. http://monkey.org/~provos/libevent/
Boost.Asio can provide callback functionality when using serial ports. It runs on Linux and Mac OS X.

Simulating file descriptor in user space

I would like to implement a socket-like object in user space. There's an important requirement that it should be pollable (i.e. it's state should be queryable via select or poll call).
Is there a platform neutral way of implementing such an object?
I'm aware that on Linux there's eventfd which kind of suits the needs except that there's no way to force it to signalize neither POLLIN nor POLLOUT.
You can use socketpair() to create a pair of connected AF_UNIX sockets. This is better than pipe() as it allows for bidirectional communication. If this isn't good enough for your needs, another option (which requires root for a daemon) would be to use the as-yet-not-in-mainline-Linux CUSE patches to create a device driver in userspace to do whatever you like. Or you can just hook into whatever event loop your user will be using...
The new linux eventfd can also emulate POLLIN/POLLOUT, although not both at once - set its value to 0xfffffffffffffffe for POLLIN but not POLLOUT, 0 for POLLOUT but not POLLIN, or anything else for both.
Other than these options, there's no platform-neutral way to do this, no. The usual pattern is to use a FIFO just to wake up the event loop, and have it poll using some other API once it's awake.
You want to build an user space object, that will be accessible through system call ?
ie open, read, write etc ... are redirected to your userspace object ?
You need either kernel support or libc support, otherwise I don't see how you can redirect your system call.
eventfd is not what you are asking for, it is implemented in kernel space. Did you describe your real problem ? Could fifo or unix domain socket fit your need ?
What about pseudo tty ? I don't know if you can block writing from the master side by faking the hardware flow control.
It's really not clear what you're trying to do; if you want a socket-like device, why not use sockets? You don't say ... And what's the deal with POLLIN and POLLOUT?
I kinda suspect you might be interested in using pseudo-terminal devices, see man 7 pty.
Use pipe(). It gives you two fd's, one to write, one to read.
Use the fd[1] to do your select/poll on.
Use the fd[0] to signal your select/poll for activity.

Resources