Event injection does not work
mqnc opened this issue · 3 comments
I am running in python3.8 on KUbuntu 20.04. I have the same issue when using your nemesis, the python-uinput library.
Here is my code:
from evdev import UInput, ecodes as e
import time
ui = UInput.from_device(
"/dev/input/by-path/pci-0000:02:00.0-usb-0:1:1.0-event-joystick", name='fake')
ui.capabilities(verbose=True).keys()
ui.write(e.EV_KEY, e.BTN_0, 1)
ui.syn()
while True:
ui.write(e.EV_ABS, e.ABS_X, 20)
ui.syn()
ui.write(e.EV_ABS, e.ABS_X, 40)
ui.syn()
time.sleep(0.1)
The device I am copying is a real x-box 360 gamepad. I run the code as root.
I am testing with this page: https://gamepad-tester.com/
The fake gamepad appears and does one single update (which I can see in the timestamp).
If I do this:
cat /dev/input/js0
I can see garbage being printed out whenever I touch my real gamepad. If I do the same for the fake gamepad, it also shows a bit of garbage which looks fairly plausible, given the events I send:
me@pc:~$ cat /dev/input/js1
K�� K�� K�� K�� K�� K�� K�� K�� K� K�� K��
K�� K�$� K��� K� K�K�� K��� K�� K��^C
me@pc:~$ cat /dev/input/js1
\a��\a��\a��\a��\a��\a��\a��\a��\a�\a�� \a��
\a��\a�$�\a���\a�\a�K��\a���\a��\a��^C
me@pc:~$ cat /dev/input/js1
8o��8o��8o��8o��8o��8o��8o��8o��8o�8o�� 8o��
8o��8o�$�8o���8o�8o�K��8o���8o��8o��^C
me@pc:~$ cat /dev/input/js1
d|��d|��d|��d|��d|��d|��d|��d|��d|�d|�� d|��
d|��d|�$�d|���d|�d|�K��d|���d|��d|��^C
The curious thing however is, that it does not continue printing. It prints around 2 lines when I run cat but that's it. But the lines are always different for every run (my python script runs continuously in another terminal).
However,
me@pc:~$ cat /dev/input/event21
this keeps printing stuff.
The fake gamepad also doesn't show up in /dev/input/by-id/ or in /dev/input/by-path/
But I can see it here:
cat /proc/bus/input/devices
I: Bus=0003 Vendor=045e Product=028e Version=0114
N: Name="Microsoft X-Box 360 pad"
P: Phys=usb-0000:02:00.0-1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/usb3/3-1/3-1:1.0/input/input85
U: Uniq=
H: Handlers=event20 js0
B: PROP=0
B: EV=20000b
B: KEY=7cdb000000000000 0 0 0 0
B: ABS=3003f
B: FF=107030000 0
I: Bus=0003 Vendor=0001 Product=0001 Version=0001
N: Name="fake"
P: Phys=py-evdev-uinput
S: Sysfs=/devices/virtual/input/input94
U: Uniq=
H: Handlers=event21 js1
B: PROP=0
B: EV=20000b
B: KEY=7cdb000000000000 0 0 0 0
B: ABS=3003f
B: FF=0
I was thinking maybe it's just a problem with browsers but the KDE Gamepad Controller program shows the same behavior.
This thing works however:
https://github.com/GrantEdwards/uinput-joystick-demo
but I'd prefer to work in python.
Any help appreciated!
Try using the evtest
utility instead of looking at the garbage. :-)
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x1 product 0x1 version 0x1
Input device name: "fake"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 304 (BTN_SOUTH)
Event code 305 (BTN_EAST)
Event code 307 (BTN_NORTH)
Event code 308 (BTN_WEST)
Event code 310 (BTN_TL)
Event code 311 (BTN_TR)
Event code 314 (BTN_SELECT)
Event code 315 (BTN_START)
Event code 316 (BTN_MODE)
Event code 317 (BTN_THUMBL)
Event code 318 (BTN_THUMBR)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 30
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 1 (ABS_Y)
Value 495
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 2 (ABS_Z)
Value 0
Min 0
Max 255
Event code 3 (ABS_RX)
Value -5130
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 4 (ABS_RY)
Value -164
Min -32768
Max 32767
Fuzz 16
Flat 128
Event code 5 (ABS_RZ)
Value 0
Min 0
Max 255
Event code 16 (ABS_HAT0X)
Value 0
Min -1
Max 1
Event code 17 (ABS_HAT0Y)
Value 0
Min -1
Max 1
Event type 21 (EV_FF)
Properties:
Testing ... (interrupt to exit)
Event: time 1640600002.895447, type 3 (EV_ABS), code 0 (ABS_X), value 27
Event: time 1640600002.895447, -------------- SYN_REPORT ------------
Event: time 1640600002.895456, type 3 (EV_ABS), code 0 (ABS_X), value 30
Event: time 1640600002.895456, -------------- SYN_REPORT ------------
Event: time 1640600002.995596, type 3 (EV_ABS), code 0 (ABS_X), value 27
Event: time 1640600002.995596, -------------- SYN_REPORT ------------
Event: time 1640600002.995605, type 3 (EV_ABS), code 0 (ABS_X), value 30
Event: time 1640600002.995605, -------------- SYN_REPORT ------------
Event: time 1640600003.095732, type 3 (EV_ABS), code 0 (ABS_X), value 27
Event: time 1640600003.095732, -------------- SYN_REPORT ------------
Event: time 1640600003.095757, type 3 (EV_ABS), code 0 (ABS_X), value 30
Event: time 1640600003.095757, -------------- SYN_REPORT ------------
Event: time 1640600003.195824, type 3 (EV_ABS), code 0 (ABS_X), value 27
Event: time 1640600003.195824, -------------- SYN_REPORT ------------
Event: time 1640600003.195830, type 3 (EV_ABS), code 0 (ABS_X), value 30
This looks good! Although the value doesn't match but that is probably due to some scaling.
I was wondering what other tools I'm unaware of and typed "ev " and discovered
evdev-joystick, evemu-device, evemu-play, evtest, evemu-describe, evemu-event, evemu-record
Those might also be useful. But I'd still prefer to work with a python library :p
But thanks for the hint so far!
I also checked if I can somehow read the output of the older input streams /dev/input/js1 and found that jstest can do it (I thought I tried that yesterday but it just threw an error).
$ jstest /dev/input/js1
Driver version is 2.1.0.
Joystick (fake) has 8 axes (X, Y, Z, Rx, Ry, Rz, Hat0X, Hat0Y)
and 11 buttons (BtnA, BtnB, BtnX, BtnY, BtnTL, BtnTR, BtnSelect, BtnStart, BtnMode, BtnThumbL, BtnThumbR).
Testing ... (interrupt to exit)
Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2: 0 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2:-32767 3: 0 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2:-32767 3: -5042 4: 0 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2:-32767 3: -5042 4: -37 5: 0 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2:-32767 3: -5042 4: -37 5:-32767 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2:-32767 3: -5042 4: -37 5:-32767 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off Axes: 0: 0 1: 369 2:-32767 3: -5042 4: -37 5:-32767 6: 0 7: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off 9:off 10:off ^C
If I run this for my real gamepad, it prints stuff when I touch it. The fake one immediately prints what I pasted above and nothing more. So I guess that something is wrong with the old interface and browsers connect to that. The behavior in the browser pretty much matches with what I can see in the output here.
Ok I think I got it.
BTN_0 does not work but BTN_A does. The capabilities() of the gamepad lists ['BTN_A', 'BTN_GAMEPAD', 'BTN_SOUTH']. Furthermore, the axis values that I sent were so miniscule (compared to 32767) that they probably got filtered out by the api as noise to the point that they don't even generate an event. Using BTN_A and higher test values for the axes works fine.
So I guess I got terribly unlucky with my tests :/