I’m starting to dig into the evdev api on linux for the purpose of playing around with uinput emulation. I noticed that between a joystick and a touch pad, there are different button/key event codes to distinguish between joypad button presses and mouse clicks. But both devices have event codes for ABS_X and ABS_Y axis.
joystick dump: # Event type 3 (EV_ABS) # Event code 0 (ABS_X) # Value 128 # Min 0 # Max 255 # Fuzz 0 # Flat 15 # Resolution 0 # Event code 1 (ABS_Y) # Value 103 # Min 0 # Max 255 # Fuzz 0 # Flat 15 # Resolution 0 touchpad dump: # Event type 3 (EV_ABS) # Event code 0 (ABS_X) # Value 3909 # Min 1270 # Max 5670 # Fuzz 0 # Flat 0 # Resolution 44 # Event code 1 (ABS_Y) # Value 3835 # Min 1240 # Max 4746 # Fuzz 0 # Flat 0 # Resolution 66
So how does x11 know whether to treat the ‘/dev/input/eventX’ node as a joystick or a mouse for the purpose of moving the on screen cursor? Is there some ioctl I can use to set whether or not the device gets loaded by x11? Something else that the driver needs to do to indicate this?
I looked around at some bug reports and found that there have been cases in old releases where the joypad did move the mouse when connected but I could not find any patches that would indicate what they changed to indicate that distinction to x11.
Before someone says it, I know that using libevdev if preferred over direct calls to uinput in practice, but this is for educational purposes only. And even there, I have the same question.
Advertisement
Answer
So I went through the uinput module documentation and sample code. I noticed that in their example code for simulating a mouse, they added an event for the left mouse button (BTN_LEFT
) via the ioctl calls
ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_KEYBIT, BTN_LEFT);
I found it odd that they included this event type since they are only moving(and not clicking) the mouse in the example code, and sure enough removing those ioctls caused the axis events not to effect the x11 pointer.
Now in their example code they use relative axis events (REL_X
, REL_Y
) for the mouse move rather than the absolute events that I was referring to (ABS_X
, ABS_Y
). This is because they are simulating an actual mouse rather than a touch pad. But that did give me a hint that x11 looks for certain event types to be listed in the device bits to determine what kind of device it is.
As further confirmation of this theory, I found this note in the detection section of gamepad devices in same documentation. All gamepads that follow the protocol described here map BTN_GAMEPAD. This is an alias for BTN_SOUTH/BTN_A. It can be used to identify a gamepad as such.
While this doesn’t say anything about mice or touchpads explicitly it does support the idea that certain event bits set on input devices are used to determine how x11 treats the input from these devices. I did find that creating a gamepad device that sets the BTN_GAMEPAD
bit will still function as a mouse if you also set the BTN_LEFT
bit and the REL_X
REL_Y
bits so it seems like what x11 is doing is just looking for a few key bits to be set to treat something as a mouse.
Okay so back to the touchpad/joystick problem, I have not yet figured out how to simulate a touch pad to test exactly which bits need to be set for x11 to recognize a device as a touch pad, though I suspect that the BTN_TOUCH
event plays a role in it. Whatever combination of event bits that causes x11 to recognize the device as a touchpad and move the pointer, it stands to reason that this combination is not typically found on a gamepad and that is what indicates to x11 that the joypad should not move the cursor despite it having the ABS_X
and ABS_Y
axes just like the touch pad. If I have time later I will try to figure out exactly what the combination is and update this solution.