You are not logged in.

#1 2020-06-07 16:15:27

tomsk
Member
Registered: 2016-12-17
Posts: 224

Get evdev code from specific key

Hello,

I use some python script which will redirect all my keypresses to VM (I use VM with GPU passthrough for gaming) except one key (semicolon).

I use library

evdev.ecodes

from python, and then I use this if statement

mode = "guest" if event.code not in [e.KEY_GRAVE] else "host"

e.KEY_GRAVE is semicolon key, this code works, but now I have new keyboard with dedicated macro keys, so I would like to use another key instead of semicolon key, but my problem is that I don't know how to get evdev code from that new dedicated macro key.

If I use command

xev

I will get this output when I press that dedicated macro key.

KeyPress event, serial 40, synthetic NO, window 0x4400001,
    root 0x135, subw 0x0, time 8267523, (126,124), root:(254,177),
    state 0x10, keycode 191 (keysym 0x1008ff81, XF86Tools), same_screen YES,
    XKeysymToKeycode returns keycode: 179
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

I use several linux distros like: Archlinux, Ubuntu, Fedora, Linux Mint

Offline

#2 2020-06-07 21:29:52

teckk
Member
Registered: 2013-02-21
Posts: 589

Re: Get evdev code from specific key

I can't tell what you are wanting. To get the key?

import curses

def main(a):
    while True:
        b = a.getch()
        a.addstr(str(b) + ' ')

if __name__ == '__main__':
    curses.wrapper(main)
    
#################   
    
import tty, sys

def main():
    tty.setcbreak(sys.stdin)
    while True:
        c = ord(sys.stdin.read(1))
        print(c)
    
main()

https://python-evdev.readthedocs.io/en/ … pidoc.html
https://python-evdev.readthedocs.io/en/ … orial.html

Offline

#3 2020-06-08 09:55:31

tomsk
Member
Registered: 2016-12-17
Posts: 224

Re: Get evdev code from specific key

I want key code in evdev format, for example semicolon has code KEY_GRAVE, but I don't know which code has that new key, if I run your command I get nothing when pressing dedicated macro keys, but when I press standard keys I get numeric code.


I use several linux distros like: Archlinux, Ubuntu, Fedora, Linux Mint

Offline

#4 2020-06-08 12:24:39

teckk
Member
Registered: 2013-02-21
Posts: 589

Re: Get evdev code from specific key

Read the docs for what you want to do. Never used that before so I gave it a little short spin.
https://python-evdev.readthedocs.io/en/ … usage.html

sudo pacman -S python-evdev
>>> import evdev
>>> devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
>>> for device in devices:
...     print(device.path, device.name, device.phys)
... 
<snip>
/dev/input/event4 BTC USB Multimedia Keyboard Consumer Control usb-0000:00:02.0-1/input1
/dev/input/event3 BTC USB Multimedia Keyboard System Control usb-0000:00:02.0-1/input1
/dev/input/event2 BTC USB Multimedia Keyboard usb-0000:00:02.0-1/input0
<snip>
>>> device = evdev.InputDevice('/dev/input/event2')
>>> print(device)
device /dev/input/event2, name "BTC USB Multimedia Keyboard", phys "usb-0000:00:02.0-1/input0"
>>> for event in device.read_loop():
...     if event.type == evdev.ecodes.EV_KEY:
...             print(evdev.categorize(event)
...
key event at 1591618666.932207, 30 (KEY_A), down
akey event at 1591618667.052212, 30 (KEY_A), up
key event at 1591618667.332208, 48 (KEY_B), down
bkey event at 1591618667.460211, 48 (KEY_B), up
key event at 1591618667.780208, 46 (KEY_C), down
ckey event at 1591618667.884213, 46 (KEY_C), up
key event at 1591618668.292212, 32 (KEY_D), down
dkey event at 1591618668.380211, 32 (KEY_D), up

Ok, that works.

Offline

#5 2020-06-08 14:04:46

tomsk
Member
Registered: 2016-12-17
Posts: 224

Re: Get evdev code from specific key

Thank you I tried:

import evdev

#devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
#for device in devices:
    #print(device.path, device.name, device.phys)


device = evdev.InputDevice('/dev/input/event3')
print(device)

for event in device.read_loop():
    if event.type == evdev.ecodes.EV_KEY:
        print(evdev.categorize(event))

and I got:

[tomsk@tomsk-PC ~]$ python test.py
device /dev/input/event3, name "Razer Razer BlackWidow Chroma V2", phys "usb-0000:00:14.0-4.1/input0"

a

a
aaaa

so as you can see I was pressing keys and it didn't show code for it. I have 3 events in /dev/input/ for keyboard, so I tried all 3 and no code.


I use several linux distros like: Archlinux, Ubuntu, Fedora, Linux Mint

Offline

#6 2020-06-19 07:55:56

tomsk
Member
Registered: 2016-12-17
Posts: 224

Re: Get evdev code from specific key

This is my code if someone is interested:

#!/usr/bin/env python3

import asyncio
import evdev
import evdev.ecodes as e
import os
import re
import sys
from subprocess import run, check_output

source_devices = sys.argv[1:]

# Listen to events from the following device.
real_devices = [
    evdev.InputDevice(device)
    for device in source_devices
]

# Then create our own device for our own events.
host_devices = [
    evdev.UInput.from_device(device)
    for device in real_devices
]
guest_devices = [
    evdev.UInput.from_device(device)
    for device in real_devices
]
host_device_paths = [
    os.path.join("/dev/input/by-id", "host-%s" % os.path.basename(path))
    for path in source_devices
]
guest_device_paths = [
    os.path.join("/dev/input/by-id", "guest-%s" % os.path.basename(path))
    for path in source_devices
]

virtual_devices = host_devices + guest_devices
virtual_device_paths = host_device_paths + guest_device_paths

# Unlink all old devices so you don't have any phantom guest-* devices from launching previous VMs.
for devname in os.listdir("/dev/input/by-id"):
    if re.match("^(host|guest)\\-", devname):
        run(["unlink", "--", os.path.join("/dev/input/by-id", devname)])

for (device, path) in zip(virtual_devices, virtual_device_paths):
    if os.path.exists(path):
        run(["unlink", "--", path])
    run(["ln", "-s", device.device, path])

# Now we monopolize the original devices.
for device in real_devices:
    device.grab()

async def replicate(source_device, host_device, guest_device):
    global hooks

    async for event in source_device.async_read_loop():
        if event.type == e.EV_SYN:
            continue

        mode = "guest" if event.code not in [e.KEY_GRAVE] else "host"

        target_device = {
            "host": host_device,
            "guest": guest_device,
        }[mode]

        target_device.write_event(event)
        target_device.syn()


for source_device, host_device, guest_device in zip(real_devices, host_devices, guest_devices):
    asyncio.ensure_future(replicate(source_device, host_device, guest_device))

event_loop = asyncio.get_event_loop()
event_loop.run_forever() 

On line 61 is that if statement where I am checking keypress, e.KEY_GRAVE is code for semicolon key.


I use several linux distros like: Archlinux, Ubuntu, Fedora, Linux Mint

Offline

Board footer

Powered by FluxBB