forked from https://github.com/Evidlo/remarkable_mouse | patches include cool mapping mode that actually does proper aspect ratio conversion and fixing it for smartcard ssh setups
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

149 lines
5.1 KiB

import logging
import struct
import subprocess
from screeninfo import get_monitors
import time
from itertools import cycle
from socket import timeout as TimeoutError
import libevdev
from .codes import codes, types
from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, the_cooler_remap, cool_monitor_mapping
logging.basicConfig(format='%(message)s')
log = logging.getLogger('remouse')
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 read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode):
"""Pipe rM evdev events to local device
Args:
rm_inputs (dictionary of paramiko.ChannelFile): dict of pen, button
and touch input streams
orientation (str): tablet orientation
monitor_num (int): monitor number to map to
threshold (int): pressure threshold
mode (str): mapping mode
"""
local_device = create_local_device()
log.debug("Created virtual input device '{}'".format(local_device.devnode))
monitor, (tot_width, tot_height) = get_monitor(region, monitor_num, orientation)
pending_events = []
x = y = 0
# loop inputs forever
# for input_name, stream in cycle(rm_inputs.items()):
stream = rm_inputs['pen']
while True:
try:
data = stream.read(16)
except TimeoutError:
continue
e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data)
# intercept EV_ABS events and modify coordinates
if types[e_type] == 'EV_ABS':
# handle x direction
if codes[e_type][e_code] == 'ABS_X':
x = e_value
# handle y direction
if codes[e_type][e_code] == 'ABS_Y':
y = e_value
if mode == 'cool':
mapx, mapy = the_cooler_remap(x, y, monitor)
mapped_x, mapped_y = cool_monitor_mapping(mapx, mapy, monitor, tot_width, tot_height)
else:
mapped_x, mapped_y = remap(
x, y,
wacom_max_x, wacom_max_y,
# 20k something | presumably 3840 | 7680 15k something,
# -> 10k something presumably 15k something
wacom_max_x * (monitor.width / tot_width), wacom_max_y * (monitor.height / tot_height),
mode, orientation
)
mapped_x += wacom_max_x * (monitor.x / tot_width)
mapped_y += wacom_max_y * (monitor.y / tot_height)
# reinsert modified values into evdev event
if codes[e_type][e_code] == 'ABS_X':
e_value = int(mapped_x)
if codes[e_type][e_code] == 'ABS_Y':
e_value = int(mapped_y)
# pass events directly to libevdev
e_bit = libevdev.evbit(e_type, e_code)
e = libevdev.InputEvent(e_bit, value=e_value)
local_device.send_events([e])
if log.level == logging.DEBUG:
log_event(e_time, e_millis, e_type, e_code, e_value)