LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-29-2013, 10:21 AM   #1
theosys
LQ Newbie
 
Registered: May 2009
Location: Austria
Distribution: Debian, openSUSE, (K)Ubuntu
Posts: 11

Rep: Reputation: 0
Question Injecting key strokes to simulate a keyboard


I've here an embedded device, where the Linux on it was updated to kernel 3.2. With older versions of the kernel I could open the "keyboard" in /dev/input/eventX and send key strokes to the main application running on it (keyboard based on an IR receiver). This allowed me, to control the device over network without having a keyboard attached to it, simply by "telnet" to the box and send keystrokes over a simple command line tool.

But with the newer kernel something changed. The /dev/input/eventX devices are still there and I can send my keystrokes, but now it doesn't work any more. The keys don't arrive at the main program. The main difference I realized was, that the USB keyboard driver is not loaded any more by default, except if I plug in a real keyboard to the USB port. If I do that, it partially work, but the special keys (RED, BLUE, ...) don't work any more. I assume this is, because this buttons are not present on a normal keyboard.

I tried a lot. Adding the key-codes to the function keys and other keys and manipulate the "keymap" table. The only way to bring the functionality partially back was to manipulate the keyboard tables of the main program, that is written in Python. But every time an update is made, this key-tables are overwritten and I have to change it back.

What I need is a way in user space (the kernel is in a protected area of the memory) to simulate a keyboard. I'm able to compile and add a kernel module to the system, because the kernel modules are on normal writable memory. But I'm not a kernel programmer and don't know how to write a functional kernel module.

Is there somewhere some code or examples that show how to implement a virtual keyboard that doesn't need some hardware like USB? I would prefer this solution, because it promises to work also with future kernels.
Or maybe somebody knows a way to add the missing special keys to some unused keyboard keys? I would prefer the function keys. I tried this already, but had no luck.

The embedded device uses a MIPS32 processor. The operating system is a normal Linux and there are all command line commands available, one have on a normal Linux machine. It has an IR receiver working over /dev/input/eventX. Beside this I have a complete developer environment for this device, containing the full source code. And I'm familiar with c and c++.
 
Old 07-29-2013, 12:49 PM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
You question is quite compelling, but I have trouble understanding where all of the elements of your system fit together. What is the nature of the 'main application' on the embedded device? Is it an X application? What does the application use for it's X server? Normally, an X server includes the keyboard/pointer/display combination. Does your application have some facility to use an alternate input stream, which you describe as a 'telnet' connection? What do you mean exactly by 'open the "keyboard" in /dev/input/eventX and send key strokes to the main application'?

I get the sense that you're doing something unconventional that has resulted in breaking your application, and that using a more conventional means will solve it.

--- rod.
 
Old 07-30-2013, 01:49 AM   #3
theosys
LQ Newbie
 
Registered: May 2009
Location: Austria
Distribution: Debian, openSUSE, (K)Ubuntu
Posts: 11

Original Poster
Rep: Reputation: 0
Arrow

The main program controls a player able to play videos and audio files. It has a WEB interface and there is a big hard disk included. But the hdd is optional so the operating system is on a fixed memory. There is no X installed. Instead there is a proprietary hardware controlled by the main program, where the drivers for it are in the kernel (source for drivers is available but under a non free license). The main program is written in Python and is also under a non free license.
There is a network card included. This allows me to access the box over ethernet. On the box is a simple telnet server running, allows me to login to the system. Then I'm on a normal command line of a bash-shell. The Linux distribution is for embedded devices, but because there is enough free memory, I can install whatever I want. It is not a main stream distribution and has a proprietary packet management system. It works basically like the Debian "deb"-format but is a lot simpler.

The WEB interface lets me control the box mostly but I've to simulate the complete IR remote control. And here the problem starts. The WEB-interface allows me to install or remove several components of the player (video codecs, audio codecs, third party modules to list an index and the like). Beside this it's possible to individually set the functions of the buttons of the remote control to call and control some of the third party modules. Because a customer can do that, I've to send the key strokes of the remote control to the main program. I don't know whether the customer has changed the functionality of some buttons or not. Beside this the remote control distinguishes between short and long key presses for most of the buttons. The WEB-interface has no function to send the buttons of the remote control, only ways to call each of the possible functions and modules.

This is the reason why I have to find a way to inject key strokes in a way the main program will receive and take action. The box will be controlled by a controller from AMX over ethernet. At least the customer has a touch panel from AMX or an application on his/her smart phone providing the same functionality as the touch panel. On the touch panel the user finds all the buttons of the remote control.

Because the box is in a rack in the cellar, it's not possible to use the IR remote control. Of course the touch panel allows to control several other things like TVs, light and a lot more. This simplifies the control of a whole house. With only one remote control the customer can control it's whole house and the described player is a part of it.

How does it basically work?
There is a driver for the IR receiver in the kernel. It uses the "udev" system to declare itself as a kind of keyboard. As a result the "udev" creates some special devices in the directory "/dev/input/" called "event0", "event1", and so on. It was possible to open the special device and send keystrokes to it and this keystrokes where treated as if it was a real keyboard. Allthough I can still do that, the keystrokes now never reach the main program.
If I connect a real keyboard to the USB connector, it behaves as it would on a normal PC. The keyboard is able to control the main program but only partially, because several keys, like the color buttons or "play", "pause", etc. are not present on a normal keyboard. My method to inject keys works only with the special device for the real keyboard and I can only send keystrokes for buttons present on a normal keyboard. If you like, I can show the source of what at least partially works.

Now I'm searching for a different method to inject keystrokes. Is there a possibility?
 
Old 07-30-2013, 09:17 AM   #4
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Okay, I think I get it now. Using the device nodes for a device which is principally an output device, and sending data to it seems like functionality that is unintended, or at least not uniformly supported across other similar drivers. This is the unconventional nature that I speculated about.
You have a driver which supports an IR remote control receiver, but your data source is actually all software; either your shell based utilities, or some web server CGI application, or whatever else. Do you need the system to retain the functionality of the IR remote receiver at all? As I see it, one possible course is to install the original, working driver into the new kernel. Are you able to identify the driver module for the IR receiver? Is the driver in the new kernel a different driver, or an updated version of the older driver? If the latter, it might be as simple as copying the old sources over the new ones, and making the old module in the new kernel source tree. If the former, perhaps try reverting to the original driver, if it still exists in the new kernel.
Does the application read directly from the driver nodes, or is the input device part of a pseudo-console which the application sees as it's standard input device? If you have source code for the application, it should be easy enough to make it read it's input from multiple sources, such as the existing device node(s) and a socket. The socket interface would allow you to make a clean and robust interface to all of your other tools and utilities. Overall, I would see this as the definitive solution.
Conceptually, this is similar to something know generically as a software wedge, or keyboard wedge. I don't know how much this kind of thing gets done under Linux, but its a common way for things like barcode scanners to be supported in Windows. Might give you an avenue for further research.

--- rod.

Last edited by theNbomr; 07-30-2013 at 09:27 AM.
 
Old 07-30-2013, 10:08 AM   #5
theosys
LQ Newbie
 
Registered: May 2009
Location: Austria
Distribution: Debian, openSUSE, (K)Ubuntu
Posts: 11

Original Poster
Rep: Reputation: 0
Sorry, but I think you misunderstood what I need. I've never changed the kernel nor one of the modules for it. There is still the original driver working and it works well. I can still control the box with the IR remote control.
All I've done is to compile a small program and use it as a key injection. To clarify this, here is the main part of the source. The program is running in the user space and uses only the official API. In the following code, only the parameter parsing is removed:

Code:
[...]
struct input_event ev;
const char *device;

[...]

fd = open(device, O_RDWR);

if (fd == -1) {
        perror(device);
        return EXIT_FAILURE;
}

ev.type = EV_KEY;
ev.code = code;
ev.value = 1;     // 0 = released, 1 = pressed

ret = write(fd, &ev, sizeof(struct input_event));
if (ret < 0) {
        perror("write");
        close(fd);
        return EXIT_FAILURE;
}

if (single_event == false) {
        ev.value ^= 1;
        ret = write(fd, &ev, sizeof(struct input_event));
        if (ret < 0) {
               perror("write");
               close(fd);
               return EXIT_FAILURE;
        }
}

close(fd);
return EXIT_SUCCESS;
This simple program is able to inject a key stroke into the keyboard special device (one of /dev/input/eventX). This works with (most) regular keyboards connected over USB. But it is limited to the keys the connected keyboard supports. The original IR driver declares itself also as a keyboard. It is detected from "udev" the same way as a real keyboard, but injecting keystrokes to the IR-keyboard is ignored. This worked with older kernels but does not with kernel 3.2 and newer.

However. Currently I'm experimenting with the keyboard-tools. I got the Debian sources and compiled the tools for the MIPS32 environment. The tools are working but lacking keywords needed for the special keys. Now I'm implementing an extra symbol table containing the missing keywords. I'll try to map the key-codes to the function keys or maybe some other keys. On success, the above code will still work.

In every case I would need a hint or a different idea on how to manage this. A virtual keyboard listening on a network would be ideal. But I haven't found any source implementing this. Does anybody know about such a keyboard for Linux?

BTW: I've no idea about this Windblows. I don't use it since years. Even for my work I use Linux only. However this so called operating system deals with keyboards, it doesn't matter for me.
 
Old 07-30-2013, 11:12 AM   #6
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Okay, now I'm really confused, because on one hand you say "I've never changed the kernel nor one of the modules for it", but then you go on to say "This worked with older kernels but does not with kernel 3.2".
At any rate, writing to a keyboard or keyboard-like driver will always be a hit and miss affair, as those devices are principally output devices. If your code needs to take input from multiple sources, you should write it in a way that does so.
I wasn't suggesting that you should use Windows, only that there is a conceptual solution used in Windows that may exist in some form for Linux. There is the uinput driver, which sounds like it addresses your problem in some form, although I don't think it will accommodate direct support for the IR remote. It may work as a sort of shim with userspace code acquiring actual IR remote events and then stuffing them into the uinput device.

--- rod.
 
Old 07-30-2013, 11:57 AM   #7
theosys
LQ Newbie
 
Registered: May 2009
Location: Austria
Distribution: Debian, openSUSE, (K)Ubuntu
Posts: 11

Original Poster
Rep: Reputation: 0
The kernel changed with an update of the vendor of the player. All I did was installing the latest release as required by the vendor. I can't install the older release, because I would loose support. I don't want to change anything of the distribution if not absolutely necessary. This is why I'm searching for a solution that only adds something preferentially in the user space or makes the add of a kernel module necessary without changing anything already installed by the vendor.
 
Old 08-02-2013, 07:05 AM   #8
theosys
LQ Newbie
 
Registered: May 2009
Location: Austria
Distribution: Debian, openSUSE, (K)Ubuntu
Posts: 11

Original Poster
Rep: Reputation: 0
Cool

Here I've to comment my own question.

I've solved the problem. I learned, that there is a kernel module called "uinput". Because there didn't exist a special device for it and the module was not present in the kernel tree I thought it does not exist on my player. But this module is compiled directly into the kernel and all I had to do was creating the special device. Then, after playing around with this kernel module, I found the solution. With a little code I can write a daemon that represents a virtual keyboard listening on a network device. That's exactly what I need. Now the box is controllable over the network
 
Old 11-03-2016, 04:13 AM   #9
dig the code
LQ Newbie
 
Registered: Oct 2016
Location: Sri Lanka
Distribution: Ubuntu, CentOS, OpenSuse and many
Posts: 1

Rep: Reputation: Disabled
I am trying the something similer

Hi,
I am also trying to do something similer to this, Is it able to have sample code. ?
 
Old 11-03-2016, 01:17 PM   #10
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=14, FreeBSD_12{.0|.1}
Posts: 5,583
Blog Entries: 11

Rep: Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606Reputation: 3606
Welcome to LQ dig_the_code!

You have posted a reply to a thread that has been inactive for some time.

You should open your own thread with a more complete description of your own requirements in order to get better exposure and responses specific to your needs.

Please review the LQ Site FAQs for guidance in posting your questions and interacting with members here on LQ!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] How can I simulate key strokes events in other processes in linux? RonBigman Programming 2 02-06-2011 01:42 PM
[SOLVED] How to programatically feed top with key strokes babaqga Linux - Software 4 09-02-2010 02:54 AM
USB keyboard - Capture key strokes/input v333k Linux - Software 2 10-19-2009 01:44 PM
problem recognising key strokes himateja Programming 3 05-27-2005 05:54 AM
Repeating key strokes toxic53 Linux - General 1 12-11-2002 09:06 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:44 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration