I have created a virtual mouse by writing data in /dev/uinput.
However it seems that the data are not the same in /dev/input/eventX (where my mouse is) and /dev/input/mice.
I don't use another mouse.
How is this thing possible?
/dev/input/mice provides data in the PS/2 mouse protocol.
/dev/input/event* use the Linux input event interface (struct input_event structures as described in /usr/include/linux/input.h).
Related
I am using the XInput2 interface in C++ to get raw input events for keyboard and mouse on my X11 application to linux. That works fine.
I have a joystick and a bluetooth connected game controller (xbox controller like)
I don't see any events from either of those using XInput2
Should I expect to be able to get events from those as well as keyboard & mouse or is there a different method I should use for them?
A brief look seems to indicate that I can use read events from /dev/input/event* for them. Is this the correct way to interface with them in low level linux. That seems a pity as I'll need two entirely different input event systems, one for keyboard & mouse, and one for controller and joystick so wanted to make sure before going that way.
When I connect a gamepad on my Linux kernel v5.14 there are two new devices that show up:
/dev/input/event23
/dev/input/js1
If I cat <file> | xxd both device files provide gamepad event information. But event23 is much more verbose than js1.
Also, evtest gives error Invalid Argument on js1 but works fine on event23. The same happens when I use libevdev both device files.
It looks like with every event, js1 dumps the contents of an input_event struct (defined in linux/input.h)
What is the difference between the device files? Why do they have different information and what more information does event23 provide over js1?
/dev/input/js* devices are created by the joydev legacy joystick driver. It only supports joysticks and joystick-like devices.
https://www.kernel.org/doc/html/latest/input/joydev/joystick.html
/dev/input/event* devices are created by the evdev input event interface. It supports all types of input devices, not just joysticks.
https://linux.die.net/man/4/evdev
The joydev interface exposes a subset of the information exposed through evdev, specifically it will only expose an input if it looks like a joystick button or axis. New applications should prefer to use evdev, but joydev is usually still available.
The "looks like a joystick button or axis" heuristic can sometimes be a problem for joydev. When a HID gamepad is connected, evdev and joydev use information in the device's HID report descriptor to detect the number of button and axis inputs. joydev only considers buttons from the HID Button usage page, but newer gamepads sometimes define special buttons with different usages. This is especially common for Android gamepads, which have non-Button usages for the Home and Back buttons. These buttons don't get picked up by joydev.
Another big difference: joydev is purely for input. evdev supports gamepad rumble and force feedback effects.
In Linux, how do you create an input event interface with a user specified event number and map that to a specific device event?
I'm using the gpio-keys driver to translate key presses from a keypad. I define the keys to be used in my board configuration source file as shown below
static struct gpio_keys_button ev_keys[] = {
[0] = {
.type = EV_KEY,
.active_low = 1,
.wakeup = 0,
.debounce_interval = KEYS_DEBOUNCE_MS,
.code = KEY_MUTE,
.desc = "mute",
.gpio = PUSHBUTTON_MUTE,
}
};
and register this with the kernel.
And I enable the event interface and GPIO buttons when building the kernel.
Device Drivers ---> Input device support --> Event interface
Device Drivers ---> Input device support --> Keyboards --> GPIO buttons
This creates a node to the event at /dev/input/event0 to which the GPIO button events are mapped. In a system that uses only one event interface I can call poll() on the fd to /dev/input/event0 and everything works as expected.
Now, I have second peripheral on my system that uses /dev/input/event0 by default and I need to map the events from the gpio-keys driver to another event. Any suggestions on how I go about creating an event with a number/id I can specify and then map this to the gpio-keys events?
Thanks.
If you mean by "mapping" specifying the name of the /dev/input/eventX 'file', you should use Udev. The kernel assigns the number of the event device, it is a bad idea and probably impossible to try and force this number since you never know which other device may have gotten this number first.
My recommendation would be to let Udev create a symlink that points to your device; you can choose your own name and use that in your program (i.e. /dev/my_first_keypad). For example, my Wacom tablet is assigned /dev/wacom with the following udev rule:
KERNEL=="event*", SUBSYSTEM=="input", SUBSYSTEMS=="input", ATTRS{name}=="Wacom Volito", SYMLINK+="wacom"
The trick is to find the proper set of variables to exactly specify your keypad. If it is USB based, the vender/product ID are a good start. Otherwise, use udevadm info --export-db to get a full dump of the Udev database. Udev rules go in files in /etc/udev/rules.d/ or /lib/udev.d, depending on the Linux distribution you are using.
You can check System.map file for functions that register event interface. The one that comes first, usually gets lowest eventX number and later functions gets eventX number increased by one. IMO, its ok to rely on static device node file for embedded device where device configuration is static and is not going to change during operation, but generally you should use udev for you purposes.
What is the best way to capture HID input on linux for games? I don't need anything special. Just mouse and keyboard. Right now I'm using Xlib. I have a separate input thread, which has its own connection to the X Server (Display instance) and it handles events for main render window. It is working just fine, but it is a bit limited. For example, I'm missing mouse raw input.
Have you tried opening and reading device files in /dev/input?
I have a Linux USB HID device (a Hama MCE), and I can read its events manually by reading cat /dev/input/event7 and cat /dev/input/event8. Whenever I press a key on the device, a few bytes become available for reading with one of the cat commands above. I have a default installation of Ubuntu Jaunty 64-bit desktop on the machine.
I think I can write a parser to interpret the bytes emitted by the device, or I'll use libhid if it's more convenient.
My questions are:
How do I prevent the text-mode virtual consoles from receiving some of the key presses on the device as normal keypresses? As of now, some device keys result an Enter, a BackSpace, a PageUp or numeric keypad numbers.
Similarly, how do I prevent the X server from receiving keyboard and mouse events from this device? I have several USB keyboards and mice connected to the computer. I want the X server receive events from all of them, except for this device.
How do I set up that whenever the device gets connected to the computer, the command /usr/local/bin/keydumper /dev/input/event7 /dev/input/event8 (or one command for each /dev/ path) would get run, with the proper /dev/ paths substituted in the command line?
Answering my own question based on answers from the Linux USB HID driver developers:
Question 1. and 2.: Do
ioctl(open("/dev/input/event7", O_RDONLY), EVIOCGRAB, 1);
As long as this filehandle is open, the events generated would go only
to this filehandle (not to other open()s of the same device or to the
system keyboard or mouse event pool). At most one process can hold a
successful EVIOCGRAB at a HID device at a time. Lirc can be configured
to do an EVIOCGRAB.
Question 3.: Configure udev to start the program once the device is connected.
I do not have enough points to comment sadly.
If you are looking for the definition of EVIOCGRAB try
#include <linux/input.h>
I think solution for all questions can be writing own filter device driver, or custom driver for your device. I know such a thing (filter device driver) is available on windows so something similar can be on Linux. In that filter device driver you could block all unwanted events from the target device that you wish to block, I don't really get 3 question so I don't know how to answer for that.