Capture and interpret XI2 RawKeyPress event with python

前端 未结 1 1327
天命终不由人
天命终不由人 2021-01-14 19:41

Self resolved

It\'s posted below as an answer.

Trying to get what xinput test-xi2 --root prints with python xlib.
Using version 1.9 from g

1条回答
  •  傲寒
    傲寒 (楼主)
    2021-01-14 20:16

    Managed to hack some portion of the binary data in RawKeyPress event.
    The precess was rather... inelegant though, I wonder how real hackers do this.

    from Xlib import X, XK, display, error
    from Xlib.ext import xinput
    import time
    
    
    class Test:
        def __init__(self):
            self.dpy_input = display.Display(None)
            #try setting events to capture
            root = self.dpy_input.screen().root
            root.xinput_select_events([(xinput.AllMasterDevices, xinput.RawKeyPressMask)])
            extension_info = self.dpy_input.query_extension('XInputExtension')
            self.xinput_major = extension_info.major_opcode
            self.version_info = self.dpy_input.xinput_query_version()
            print('Found XInput version %u.%u' %(
                self.version_info.major_version,
                self.version_info.major_version,) )
    
        def run(self):
            while True:
                event = self.dpy_input.next_event()
                if event is None:
                    break
                if event.type != self.dpy_input.extension_event.GenericEvent:
                    break
                if event.evtype != xinput.RawKeyPress:
                    break
    
                # print (event.__class__)
                # print(event.__dict__)
                print(event)
                b = event._data["data"]
    
                device = b[0:1]
                print("device:%d" % ( int.from_bytes(device,"little")))
                # value at b[1] seems like padding, always 0.
    
                # 7th byte contains x11 keycode
                keycode = b[6]
                print("keycode:"+str(keycode))
    
    
                # Not certain as to what this really is.
                timestamp = b[2:6] # four bytes int
                print('timestamp:'+str(int.from_bytes(timestamp,"little")))
    
                # Not certain as to what this really is.
                valuators = b[7:9] # 2 bytes, short int
                print("valuators:" + str(int.from_bytes(valuators,"little")))
    
                device_id = b[10:11] # 2 bytes, short int
                print("device id:" + str(int.from_bytes(device_id,"little")))
    
    
    if __name__ == "__main__":
        t = Test()
        t.run()
    

    I compared the python script output with the output from xinput test-xi2 --root for a A keypress.

    Python:

    b'\x03\x00H\x8a\xd9\x1c&\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    

    xinput:

    EVENT type 14 (RawKeyRelease)
        device: 3 (12)
        detail: 38
        valuators:
    

    Now the scripts prints:

    Found XInput version 2.2
    (evtype = 13, data = b'\x03\x004=A\x1d&\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', type = 35, length = 2, extension = 131, sequence_number = 15)
    device:3
    keycode:38
    timestamp:490814772
    valuators:0
    device id:12
    

    Although it's rather incomplete still, I have to leave off here as now I know RawKeyPress event does not provide what I want: hid usage id or linux kernel scancode.

    0 讨论(0)
提交回复
热议问题