def __init__(self, uuid): self._events_state = { "ABS_X": None, "ABS_Y": None, "ABS_RX": None, "ABS_RY": None, "BTN_NORTH": None, "BTN_SOUTH": None, "BTN_EAST": None, "BTN_WEST": None } self._axis_min = -32768 self._axis_max = 32767 self.device = evd.Device() self.device.name = f"gamepad-{uuid}" for ev in list(self._events_state.keys())[:4]: self.device.enable( evd.evbit(ev), evd.InputAbsInfo(minimum=self._axis_min, maximum=self._axis_max)) for ev in list(self._events_state.keys())[4:]: self.device.enable(evd.evbit(ev)) self.uinput_node = self.device.create_uinput_device() print("New device at {} ({})".format(self.uinput_node.devnode, self.uinput_node.syspath)) time.sleep( 1) # Give everything time to register that the device exists
def create_local_device(): """ Create a virtual input device on this host that has the same characteristics as a Wacom tablet. Returns: virtual input device """ import libevdev device = libevdev.Device() # Set device properties to emulate those of Wacom tablets device.name = 'reMarkable pen' device.id = { 'bustype': 0x03, # usb 'vendor': 0x056a, # wacom 'product': 0, 'version': 54 } # Enable buttons supported by the digitizer device.enable(libevdev.EV_KEY.BTN_TOOL_PEN) device.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER) device.enable(libevdev.EV_KEY.BTN_TOUCH) device.enable(libevdev.EV_KEY.BTN_STYLUS) device.enable(libevdev.EV_KEY.BTN_STYLUS2) device.enable(libevdev.EV_KEY.BTN_0) device.enable(libevdev.EV_KEY.BTN_1) device.enable(libevdev.EV_KEY.BTN_2) inputs = ( # touch inputs (libevdev.EV_ABS.ABS_MT_POSITION_X, 0, 767, 2531), (libevdev.EV_ABS.ABS_MT_POSITION_Y, 0, 1023, 2531), (libevdev.EV_ABS.ABS_MT_PRESSURE, 0, 255, None), (libevdev.EV_ABS.ABS_MT_TOUCH_MAJOR, 0, 255, None), (libevdev.EV_ABS.ABS_MT_TOUCH_MINOR, 0, 255, None), (libevdev.EV_ABS.ABS_MT_ORIENTATION, -127, 127, None), (libevdev.EV_ABS.ABS_MT_SLOT, 0, 31, None), (libevdev.EV_ABS.ABS_MT_TOOL_TYPE, 0, 1, None), (libevdev.EV_ABS.ABS_MT_TRACKING_ID, 0, 65535, None), # pen inputs (libevdev.EV_ABS.ABS_X, 0, 20967, 2531), # cyttps5_mt driver (libevdev.EV_ABS.ABS_Y, 0, 15725, 2531), # cyttsp5_mt (libevdev.EV_ABS.ABS_PRESSURE, 0, 4095, None), (libevdev.EV_ABS.ABS_DISTANCE, 0, 255, None), (libevdev.EV_ABS.ABS_TILT_X, -9000, 9000, None), (libevdev.EV_ABS.ABS_TILT_Y, -9000, 9000, None)) for code, minimum, maximum, resolution in inputs: device.enable( code, libevdev.InputAbsInfo(minimum=minimum, maximum=maximum, resolution=resolution)) return device.create_uinput_device()
def __enter__(self): self.dev = libevdev.Device() self.dev.name = "Tablet alone" ### NB: all the following information needs to be enabled ### in order to recognize the device as a tablet. # Say that the device will send "absolute" values self.dev.enable(libevdev.INPUT_PROP_DIRECT) # Say that we are using the pen (not the erasor), and should be set to 1 when we are at proximity to the device. # See http://www.infradead.org/~mchehab/kernel_docs_pdf/linux-input.pdf page 9 (=13) and guidelines page 12 (=16), or the https://github.com/linuxwacom/input-wacom/blob/master/4.5/wacom_w8001.c (rdy=proximity) self.dev.enable(libevdev.EV_KEY.BTN_TOOL_PEN) self.dev.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER) # Click self.dev.enable(libevdev.EV_KEY.BTN_TOUCH) # Press button 1 on pen self.dev.enable(libevdev.EV_KEY.BTN_STYLUS) # Press button 2 on pen, see great doc self.dev.enable(libevdev.EV_KEY.BTN_STYLUS2) # Send absolute X coordinate self.dev.enable( libevdev.EV_ABS.ABS_X, libevdev.InputAbsInfo(minimum=0, maximum=32767, resolution=100)) # Send absolute Y coordinate self.dev.enable( libevdev.EV_ABS.ABS_Y, libevdev.InputAbsInfo(minimum=0, maximum=32767, resolution=100)) # Send absolute pressure self.dev.enable(libevdev.EV_ABS.ABS_PRESSURE, libevdev.InputAbsInfo(minimum=0, maximum=8191)) # Use to confirm that we finished to send the informations # (to be sent after every burst of information, otherwise # the kernel does not proceed the information) self.dev.enable(libevdev.EV_SYN.SYN_REPORT) # Report buffer overflow self.dev.enable(libevdev.EV_SYN.SYN_DROPPED) self.uinput = self.dev.create_uinput_device() print("New device at {} ({})".format(self.uinput.devnode, self.uinput.syspath)) # Sleep for a bit so udev, libinput, Xorg, Wayland, ... # all have had a chance to see the device and initialize # it. Otherwise the event will be sent by the kernel but # nothing is ready to listen to the device yet. And it # will never be detected in the futur ;-) time.sleep(1) # self.simulate_first_click() self.reset_state() return self
def create(device): evdev = fetch(device, "evdev") d = libevdev.Device() d.name = fetch(evdev, "name") ids = fetch(evdev, "id") if len(ids) != 4: raise YamlException("Invalid ID format: {}".format(ids)) d.id = dict(zip(["bustype", "vendor", "product", "version"], ids)) codes = fetch(evdev, "codes") for evtype, evcodes in codes.items(): for code in evcodes: data = None if evtype == libevdev.EV_ABS.value: values = fetch(evdev, "absinfo")[code] absinfo = libevdev.InputAbsInfo( minimum=values[0], maximum=values[1], fuzz=values[2], flat=values[3], resolution=values[4], ) data = absinfo elif evtype == libevdev.EV_REP.value: if code == libevdev.EV_REP.REP_DELAY.value: data = 500 elif code == libevdev.EV_REP.REP_PERIOD.value: data = 20 d.enable(libevdev.evbit(evtype, code), data=data) properties = fetch(evdev, "properties") for prop in properties: d.enable(libevdev.propbit(prop)) uinput = d.create_uinput_device() check_udev_properties(device, uinput) return uinput
def from_name(cls, name: str, type: str) -> "Device": """ Create a Device from the given name with the given type (pen, pad, finger). This method iterates through the test/devices/*.yml files and finds the file for the device with the given name, then loads the matching event node for that type. """ type = type.lower() assert type.lower() in ("pen", "pad", "finger") for ymlfile in Path("test/devices").glob("*.yml"): with open(ymlfile) as fd: yml = yaml.safe_load(fd) logger.debug(f"Found device: {yml['name']}") if yml["name"].upper() != name.upper(): continue for d in yml["devices"]: if d["type"] != type: continue name = d["name"] id = InputId.from_list([int(i, 16) for i in d["id"]]) bits = [libevdev.evbit(b) for b in d["bits"]] abs = { libevdev.evbit(n): libevdev.InputAbsInfo(*v) for n, v in d["abs"].items() } props = [libevdev.propbit(p) for p in d["props"]] return Device(name=name, id=id, bits=bits, absinfo=abs, props=props) raise ValueError( f"Device '{name}' does not have type '{type}'") raise ValueError(f"Device '{name}' does not exist")
def create_local_device(): """ Create a virtual input device on this host that has the same characteristics as a Wacom tablet. Returns: virtual input device """ import libevdev device = libevdev.Device() # Set device properties to emulate those of Wacom tablets device.name = 'reMarkable tablet' device.id = { 'bustype': 0x18, # i2c 'vendor': 0x056a, # wacom 'product': 0, 'version': 54 } # Enable buttons supported by the digitizer device.enable(libevdev.EV_KEY.BTN_TOOL_PEN) device.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER) device.enable(libevdev.EV_KEY.BTN_TOUCH) device.enable(libevdev.EV_KEY.BTN_STYLUS) device.enable(libevdev.EV_KEY.BTN_STYLUS2) # Enable position, tilt, distance and pressure change events device.enable( libevdev.EV_ABS.ABS_X, libevdev.InputAbsInfo(minimum=0, maximum=MAX_ABS_X, resolution=2531)) device.enable( libevdev.EV_ABS.ABS_Y, libevdev.InputAbsInfo(minimum=0, maximum=MAX_ABS_Y, resolution=2531)) device.enable(libevdev.EV_ABS.ABS_PRESSURE, libevdev.InputAbsInfo(minimum=0, maximum=4095)) device.enable(libevdev.EV_ABS.ABS_DISTANCE, libevdev.InputAbsInfo(minimum=0, maximum=255)) device.enable(libevdev.EV_ABS.ABS_TILT_X, libevdev.InputAbsInfo(minimum=-9000, maximum=9000)) device.enable(libevdev.EV_ABS.ABS_TILT_Y, libevdev.InputAbsInfo(minimum=-9000, maximum=9000)) return device.create_uinput_device()
print( "fatal got garbage back from max coordinate query. TODO deal with graphire" ) sys.exit() dev.enable(libevdev.EV_REL.REL_X) dev.enable(libevdev.EV_REL.REL_Y) dev.enable(libevdev.INPUT_PROP_DIRECT) dev.enable(libevdev.INPUT_PROP_POINTER) dev.enable(libevdev.EV_KEY.BTN_TOOL_PEN) dev.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER) dev.enable(libevdev.EV_KEY.BTN_STYLUS) dev.enable(libevdev.EV_KEY.BTN_STYLUS2) dev.enable( libevdev.EV_ABS.ABS_X, libevdev.InputAbsInfo(minimum=0, maximum=Xmax * 10, resolution=1270)) dev.enable( libevdev.EV_ABS.ABS_Y, libevdev.InputAbsInfo(minimum=0, maximum=Ymax * 10, resolution=1270)) dev.enable(libevdev.EV_ABS.ABS_PRESSURE, libevdev.InputAbsInfo(0, 254)) dev.enable(libevdev.EV_ABS.ABS_TILT_X, libevdev.InputAbsInfo(minimum=-64, maximum=64)) dev.enable(libevdev.EV_ABS.ABS_TILT_Y, libevdev.InputAbsInfo(minimum=-64, maximum=64)) dev.enable(libevdev.EV_KEY.BTN_LEFT) dev.enable(libevdev.EV_KEY.BTN_RIGHT) dev.enable(libevdev.EV_KEY.BTN_MIDDLE) devr.enable(libevdev.EV_REL.REL_X) devr.enable(libevdev.EV_REL.REL_Y) devr.enable(libevdev.INPUT_PROP_DIRECT)
def create_local_device(): """ Create a virtual input device on this host that has the same characteristics as a Wacom tablet. Returns: virtual input device """ import libevdev device = libevdev.Device() # Set device properties to emulate those of Wacom tablets device.name = 'reMarkable pen' device.id = { 'bustype': 0x03, # usb 'vendor': 0x056a, # wacom 'product': 0, 'version': 54 } # ----- Buttons ----- # Enable buttons supported by the digitizer device.enable(libevdev.EV_KEY.BTN_TOOL_PEN) device.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER) device.enable(libevdev.EV_KEY.BTN_TOUCH) device.enable(libevdev.EV_KEY.BTN_STYLUS) device.enable(libevdev.EV_KEY.BTN_STYLUS2) device.enable(libevdev.EV_KEY.BTN_0) device.enable(libevdev.EV_KEY.BTN_1) device.enable(libevdev.EV_KEY.BTN_2) # ----- Touch ----- # Enable Touch input device.enable( libevdev.EV_ABS.ABS_MT_POSITION_X, libevdev.InputAbsInfo(minimum=0, maximum=MT_MAX_ABS_X, resolution=2531) # resolution correct? ) device.enable( libevdev.EV_ABS.ABS_MT_POSITION_Y, libevdev.InputAbsInfo(minimum=0, maximum=MT_MAX_ABS_Y, resolution=2531) # resolution correct? ) device.enable(libevdev.EV_ABS.ABS_MT_PRESSURE, libevdev.InputAbsInfo(minimum=0, maximum=255)) device.enable(libevdev.EV_ABS.ABS_MT_TOUCH_MAJOR, libevdev.InputAbsInfo(minimum=0, maximum=255)) device.enable(libevdev.EV_ABS.ABS_MT_TOUCH_MINOR, libevdev.InputAbsInfo(minimum=0, maximum=255)) device.enable(libevdev.EV_ABS.ABS_MT_ORIENTATION, libevdev.InputAbsInfo(minimum=-127, maximum=127)) device.enable(libevdev.EV_ABS.ABS_MT_SLOT, libevdev.InputAbsInfo(minimum=0, maximum=31)) device.enable(libevdev.EV_ABS.ABS_MT_TOOL_TYPE, libevdev.InputAbsInfo(minimum=0, maximum=1)) device.enable(libevdev.EV_ABS.ABS_MT_TRACKING_ID, libevdev.InputAbsInfo(minimum=0, maximum=65535)) # ----- Pen ----- # Enable pen input, tilt and pressure device.enable( libevdev.EV_ABS.ABS_X, libevdev.InputAbsInfo(minimum=0, maximum=MAX_ABS_X, resolution=2531)) device.enable( libevdev.EV_ABS.ABS_Y, libevdev.InputAbsInfo(minimum=0, maximum=MAX_ABS_Y, resolution=2531)) device.enable(libevdev.EV_ABS.ABS_PRESSURE, libevdev.InputAbsInfo(minimum=0, maximum=4095)) device.enable(libevdev.EV_ABS.ABS_DISTANCE, libevdev.InputAbsInfo(minimum=0, maximum=255)) device.enable(libevdev.EV_ABS.ABS_TILT_X, libevdev.InputAbsInfo(minimum=-9000, maximum=9000)) device.enable(libevdev.EV_ABS.ABS_TILT_Y, libevdev.InputAbsInfo(minimum=-9000, maximum=9000)) return device.create_uinput_device()