Browse Source

simplify main and make pynput/evdev api consistent

master
evan 3 years ago
parent
commit
392c502c56
  1. 2
      README.md
  2. 322
      remarkable_mouse/evdev.py
  3. 23
      remarkable_mouse/pynput.py
  4. 154
      remarkable_mouse/remarkable_mouse.py

2
README.md

@ -15,7 +15,7 @@ pip install remarkable-mouse
remouse remouse
``` ```
By default, `10.11.99.1` is used as the address. Seems to work pretty well wirelessly, too. By default ssh-agent is used to authenticate if it is available, otherwise you are asked for your password. By default, `10.11.99.1` is used as the address. Seems to work pretty well wirelessly, too. By default ssh-agent is used to authenticate if it is available, otherwise you are asked for your password. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh).
# Examples # Examples

322
remarkable_mouse/evdev.py

@ -3,9 +3,11 @@ import struct
import subprocess import subprocess
from screeninfo import get_monitors from screeninfo import get_monitors
import time import time
from itertools import cycle
from socket import timeout as TimeoutError
logging.basicConfig(format='%(message)s') logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__) log = logging.getLogger('remouse')
# Maximum value that can be reported by the Wacom driver for the X axis # Maximum value that can be reported by the Wacom driver for the X axis
MAX_ABS_X = 20967 MAX_ABS_X = 20967
@ -13,6 +15,11 @@ MAX_ABS_X = 20967
# Maximum value that can be reported by the Wacom driver for the Y axis # Maximum value that can be reported by the Wacom driver for the Y axis
MAX_ABS_Y = 15725 MAX_ABS_Y = 15725
# Maximum value that can be reported by the cyttsp5_mt driver for the X axis
MT_MAX_ABS_X = 767
# Maximum value that can be reported by the cyttsp5_mt driver for the Y axis
MT_MAX_ABS_Y = 1023
def create_local_device(): def create_local_device():
""" """
@ -26,23 +33,70 @@ def create_local_device():
device = libevdev.Device() device = libevdev.Device()
# Set device properties to emulate those of Wacom tablets # Set device properties to emulate those of Wacom tablets
device.name = 'reMarkable tablet' device.name = 'reMarkable pen'
device.id = { device.id = {
'bustype': 0x18, # i2c 'bustype': 0x03, # usb
'vendor': 0x056a, # wacom 'vendor': 0x056a, # wacom
'product': 0, 'product': 0,
'version': 54 'version': 54
} }
# ----- Buttons -----
# Enable buttons supported by the digitizer # Enable buttons supported by the digitizer
device.enable(libevdev.EV_KEY.BTN_TOOL_PEN) device.enable(libevdev.EV_KEY.BTN_TOOL_PEN)
device.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER) device.enable(libevdev.EV_KEY.BTN_TOOL_RUBBER)
device.enable(libevdev.EV_KEY.BTN_TOUCH) device.enable(libevdev.EV_KEY.BTN_TOUCH)
device.enable(libevdev.EV_KEY.BTN_STYLUS) device.enable(libevdev.EV_KEY.BTN_STYLUS)
device.enable(libevdev.EV_KEY.BTN_STYLUS2) 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)
# Enable position, tilt, distance and pressure change events # ----- 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( device.enable(
libevdev.EV_ABS.ABS_X, libevdev.EV_ABS.ABS_X,
libevdev.InputAbsInfo( libevdev.InputAbsInfo(
@ -61,38 +115,26 @@ def create_local_device():
) )
device.enable( device.enable(
libevdev.EV_ABS.ABS_PRESSURE, libevdev.EV_ABS.ABS_PRESSURE,
libevdev.InputAbsInfo( libevdev.InputAbsInfo(minimum=0, maximum=4095)
minimum=0,
maximum=4095
)
) )
device.enable( device.enable(
libevdev.EV_ABS.ABS_DISTANCE, libevdev.EV_ABS.ABS_DISTANCE,
libevdev.InputAbsInfo( libevdev.InputAbsInfo(minimum=0, maximum=255)
minimum=0,
maximum=255
)
) )
device.enable( device.enable(
libevdev.EV_ABS.ABS_TILT_X, libevdev.EV_ABS.ABS_TILT_X,
libevdev.InputAbsInfo( libevdev.InputAbsInfo(minimum=-9000, maximum=9000)
minimum=-9000,
maximum=9000
)
) )
device.enable( device.enable(
libevdev.EV_ABS.ABS_TILT_Y, libevdev.EV_ABS.ABS_TILT_Y,
libevdev.InputAbsInfo( libevdev.InputAbsInfo(minimum=-9000, maximum=9000)
minimum=-9000,
maximum=9000
)
) )
return device.create_uinput_device() return device.create_uinput_device()
# remap screen coordinates to wacom coordinates # map computer screen coordinates to rM pen coordinates
def remap(x, y, wacom_width, wacom_height, monitor_width, def map_comp2pen(x, y, wacom_width, wacom_height, monitor_width,
monitor_height, mode, orientation=None): monitor_height, mode, orientation=None):
if orientation in ('bottom', 'top'): if orientation in ('bottom', 'top'):
@ -113,86 +155,175 @@ def remap(x, y, wacom_width, wacom_height, monitor_width,
scaling * (y - (monitor_height - wacom_height / scaling) / 2) scaling * (y - (monitor_height - wacom_height / scaling) / 2)
) )
def pipe_device(args, remote_device, local_device): # map computer screen coordinates to rM touch coordinates
def map_comp2touch(x, y, touch_width, touch_height, monitor_width,
monitor_height, mode, orientation=None):
if orientation in ('left', 'right'):
x, y = y, x
monitor_width, monitor_height = monitor_height, monitor_width
ratio_width, ratio_height = touch_width / monitor_width, touch_height / monitor_height
if mode == 'fit':
scaling = max(ratio_width, ratio_height)
elif mode == 'fill':
scaling = min(ratio_width, ratio_height)
else:
raise NotImplementedError
return (
scaling * (x - (monitor_width - touch_width / scaling) / 2),
scaling * (y - (monitor_height - touch_height / scaling) / 2)
)
def configure_xinput(*, orientation, monitor, threshold, mode):
""" """
Pipe events from a remote device to a local device. Configure screen mapping settings from rM to local machine
Args: Args:
args: argparse arguments orientation (str): location of charging port relative to screen
remote_device (paramiko.ChannelFile): read-only stream of input events monitor (int): monitor number to use
local_device: local virtual input device to write events to threshold (int): pressure threshold for detecting pen
mode (str): scaling mode when mapping reMarkable pen coordinates to screen
""" """
# give time for virtual device creation before running xinput commands # give time for virtual device creation before running xinput commands
time.sleep(1) time.sleep(1)
# ----- Pen -----
# set orientation with xinput # set orientation with xinput
orientation = {'left': 0, 'bottom': 1, 'top': 2, 'right': 3}[args.orientation] orientation = {'left': 0, 'bottom': 1, 'top': 2, 'right': 3}[orientation]
result = subprocess.run( result = subprocess.run(
'xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" {}'.format(orientation), 'xinput --set-prop "reMarkable pen stylus" "Wacom Rotation" {}'.format(orientation),
capture_output=True, capture_output=True,
shell=True shell=True
) )
if result.returncode != 0: if result.returncode != 0:
log.warning("Error setting orientation: %s", result.stderr) log.warning("Error setting orientation: %s", result.stderr.decode('utf8'))
# set monitor to use # set monitor to use
monitor = get_monitors()[args.monitor] monitor = get_monitors()[monitor]
log.debug('Chose monitor: {}'.format(monitor)) log.debug('Chose monitor: {}'.format(monitor))
result = subprocess.run( result = subprocess.run(
'xinput --map-to-output "reMarkable tablet stylus" {}'.format(monitor.name), 'xinput --map-to-output "reMarkable pen stylus" {}'.format(monitor.name),
capture_output=True, capture_output=True,
shell=True shell=True
) )
if result.returncode != 0: if result.returncode != 0:
log.warning("Error setting monitor: %s", result.stderr) log.warning("Error setting monitor: %s", result.stderr.decode('utf8'))
# set stylus pressure # set stylus pressure
result = subprocess.run( result = subprocess.run(
'xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" {}'.format(args.threshold), 'xinput --set-prop "reMarkable pen stylus" "Wacom Pressure Threshold" {}'.format(threshold),
capture_output=True, capture_output=True,
shell=True shell=True
) )
if result.returncode != 0: if result.returncode != 0:
log.warning("Error setting pressure threshold: %s", result.stderr) log.warning("Error setting pressure threshold: %s", result.stderr.decode('utf8'))
# set fitting mode # set fitting mode
min_x, min_y = remap( min_x, min_y = map_comp2pen(
0, 0, 0, 0,
MAX_ABS_X, MAX_ABS_Y, monitor.width, monitor.height, MAX_ABS_X, MAX_ABS_Y, monitor.width, monitor.height,
args.mode, mode,
args.orientation orientation
) )
max_x, max_y = remap( max_x, max_y = map_comp2pen(
monitor.width, monitor.height, monitor.width, monitor.height,
MAX_ABS_X, MAX_ABS_Y, monitor.width, monitor.height, MAX_ABS_X, MAX_ABS_Y, monitor.width, monitor.height,
args.mode, mode,
args.orientation orientation
) )
log.debug("Wacom tablet area: {} {} {} {}".format(min_x, min_y, max_x, max_y)) log.debug("Wacom tablet area: {} {} {} {}".format(min_x, min_y, max_x, max_y))
result = subprocess.run( result = subprocess.run(
'xinput --set-prop "reMarkable tablet stylus" "Wacom Tablet Area" \ 'xinput --set-prop "reMarkable pen stylus" "Wacom Tablet Area" \
{} {} {} {}'.format(min_x, min_y, max_x, max_y), {} {} {} {}'.format(min_x, min_y, max_x, max_y),
capture_output=True, capture_output=True,
shell=True shell=True
) )
if result.returncode != 0: if result.returncode != 0:
log.warning("Error setting fit: %s", result.stderr) log.warning("Error setting fit: %s", result.stderr.decode('utf8'))
# ----- Touch -----
# Set touch fitting mode
mt_min_x, mt_min_y = map_comp2touch(
0, 0,
MT_MAX_ABS_X, MT_MAX_ABS_Y, monitor.width, monitor.height,
mode,
orientation
)
mt_max_x, mt_max_y = map_comp2touch(
monitor.width, monitor.height,
MT_MAX_ABS_X, MT_MAX_ABS_Y, monitor.width, monitor.height,
mode,
orientation
)
log.debug("Multi-touch area: {} {} {} {}".format(mt_min_x, mt_min_y, mt_max_x * 2, mt_max_y * 2))
result = subprocess.run(
'xinput --set-prop "reMarkable pen touch" "Wacom Tablet Area" \
{} {} {} {}'.format(mt_min_x, mt_min_y, mt_max_x, mt_max_y),
capture_output=True,
shell=True
)
if result.returncode != 0:
log.warning("Error setting fit: %s", result.stderr.decode('utf8'))
result = subprocess.run( # Just need to rotate the touchscreen -90 so that it matches the wacom sensor.
'xinput --set-prop "reMarkable pen touch" "Coordinate Transformation Matrix" 0 1 0 -1 0 1 0 0 1',
capture_output=True,
shell=True
)
if result.returncode != 0:
log.warning("Error setting orientation: %s", result.stderr.decode('utf8'))
def read_tablet(rm_inputs, *, orientation, monitor, 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 (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))
configure_xinput(
orientation=orientation,
monitor=monitor,
threshold=threshold,
mode=mode,
)
import libevdev import libevdev
# While debug mode is active, we log events grouped together between
# SYN_REPORT events. Pending events for the next log are stored here
pending_events = [] pending_events = []
# loop inputs forever
# for input_name, stream in cycle(rm_inputs.items()):
stream = rm_inputs['pen']
while True: while True:
e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', remote_device.read(16)) try:
data = stream.read(16)
except TimeoutError:
continue
e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data)
e_bit = libevdev.evbit(e_type, e_code) e_bit = libevdev.evbit(e_type, e_code)
event = libevdev.InputEvent(e_bit, value=e_value) event = libevdev.InputEvent(e_bit, value=e_value)
local_device.send_events([event]) local_device.send_events([event])
if args.debug: # While debug mode is active, we log events grouped together between
# SYN_REPORT events. Pending events for the next log are stored here
if log.level == logging.DEBUG:
if e_bit == libevdev.EV_SYN.SYN_REPORT: if e_bit == libevdev.EV_SYN.SYN_REPORT:
event_repr = ', '.join( event_repr = ', '.join(
'{} = {}'.format( '{} = {}'.format(
@ -203,4 +334,99 @@ def pipe_device(args, remote_device, local_device):
log.debug('{}.{:0>6} - {}'.format(e_time, e_millis, event_repr)) log.debug('{}.{:0>6} - {}'.format(e_time, e_millis, event_repr))
pending_events = [] pending_events = []
else: else:
pending_events += [event] pending_events.append(event)
def create_handler(*, orientation, monitor, threshold, mode):
import libevdev
try:
local_device = create_local_device()
log.info("Created virtual input device '{}'".format(local_device.devnode))
except PermissionError:
log.error('Insufficient permissions for creating a virtual input device')
log.error('Make sure you run this program as root')
sys.exit(1)
configure_xinput(
orientation=orientation,
monitor=monitor,
threshold=threshold,
mode=mode,
)
pending_events = []
def handler(e_time, e_millis, e_type, e_code, e_value):
e_bit = libevdev.evbit(e_type, e_code)
event = libevdev.InputEvent(e_bit, value=e_value)
local_device.send_events([event])
# While debug mode is active, we log events grouped together between
# SYN_REPORT events. Pending events for the next log are stored here
# if log.level == logging.DEBUG:
# if e_bit == libevdev.EV_SYN.SYN_REPORT:
# event_repr = ', '.join(
# '{} = {}'.format(
# event.code.name,
# event.value
# ) for event in pending_events
# )
# log.debug('{}.{:0>6} - {}'.format(e_time, e_millis, event_repr))
# pending_events = []
# else:
# pending_events.append(event)
return handler
# pen_down = 0
# while True:
# for device in rm_inputs:
# try:
# e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', ev.read(16))
# e_bit = libevdev.evbit(e_type, e_code)
# except timeout:
# continue
# if e_bit == libevdev.EV_KEY.KEY_LEFT:
# e_bit = libevdev.EV_KEY.BTN_0
# if e_bit == libevdev.EV_KEY.KEY_HOME:
# e_bit = libevdev.EV_KEY.BTN_1
# if e_bit == libevdev.EV_KEY.KEY_RIGHT:
# e_bit = libevdev.EV_KEY.BTN_2
# event = libevdev.InputEvent(e_bit, value=e_value)
# if e_bit == libevdev.EV_KEY.BTN_TOOL_PEN:
# pen_down = e_value
# if pen_down and 'ABS_MT' in event.code.name: # Palm rejection
# pass
# else:
# local_device.send_events([event])
# if args.debug:
# if e_bit == libevdev.EV_SYN.SYN_REPORT:
# event_repr = ', '.join(
# '{} = {}'.format(
# event.code.name,
# event.value
# ) for event in pending_events
# )
# log.debug('{}.{:0>6} - {}'.format(e_time, e_millis, event_repr))
# pending_events = []
# else:
# pending_events += [event]

23
remarkable_mouse/pynput.py

@ -3,7 +3,7 @@ import struct
from screeninfo import get_monitors from screeninfo import get_monitors
logging.basicConfig(format='%(message)s') logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__) log = logging.getLogger('remouse')
# evtype_sync = 0 # evtype_sync = 0
# evtype_key = 1 # evtype_key = 1
@ -57,8 +57,17 @@ def remap(x, y, wacom_width, wacom_height, monitor_width,
) )
def read_tablet(args, remote_device): def read_tablet(rm_inputs, *, orientation, monitor, threshold, mode):
"""Loop forever and map evdev events to mouse""" """Loop forever and map evdev events to mouse
Args:
rm_inputs (dictionary of paramiko.ChannelFile): dict of pen, button
and touch input streams
orientation (str): tablet orientation
monitor (int): monitor number to map to
threshold (int): pressure threshold
mode (str): mapping mode
"""
from pynput.mouse import Button, Controller from pynput.mouse import Button, Controller
@ -67,11 +76,11 @@ def read_tablet(args, remote_device):
mouse = Controller() mouse = Controller()
monitor = get_monitors()[args.monitor] monitor = get_monitors()[monitor]
log.debug('Chose monitor: {}'.format(monitor)) log.debug('Chose monitor: {}'.format(monitor))
while True: while True:
_, _, e_type, e_code, e_value = struct.unpack('2IHHi', remote_device.read(16)) _, _, e_type, e_code, e_value = struct.unpack('2IHHi', rm_inputs['pen'].read(16))
if e_type == e_type_abs: if e_type == e_type_abs:
@ -90,7 +99,7 @@ def read_tablet(args, remote_device):
# handle draw # handle draw
if e_code == e_code_stylus_pressure: if e_code == e_code_stylus_pressure:
log.debug('\t\t{}'.format(e_value)) log.debug('\t\t{}'.format(e_value))
if e_value > args.threshold: if e_value > threshold:
if lifted: if lifted:
log.debug('PRESS') log.debug('PRESS')
lifted = False lifted = False
@ -108,7 +117,7 @@ def read_tablet(args, remote_device):
x, y, x, y,
wacom_width, wacom_height, wacom_width, wacom_height,
monitor.width, monitor.height, monitor.width, monitor.height,
args.mode, args.orientation mode, orientation
) )
mouse.move( mouse.move(
monitor.x + mapped_x - mouse.position[0], monitor.x + mapped_x - mouse.position[0],

154
remarkable_mouse/remarkable_mouse.py

@ -7,25 +7,31 @@ import os
import sys import sys
import struct import struct
from getpass import getpass from getpass import getpass
from itertools import cycle
import paramiko import paramiko
import paramiko.agent import paramiko.agent
logging.basicConfig(format='%(message)s') logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__) log = logging.getLogger('remouse')
default_key = os.path.expanduser('~/.ssh/remarkable')
def open_remote_device(args, file='/dev/input/event0'):
def open_rm_inputs(*, address, key, password):
""" """
Open a remote input device via SSH. Open a remote input device via SSH.
Args: Args:
args: argparse arguments address (str): address to reMarkable
file (str): path to the input device on the device key (str, optional): path to reMarkable ssh key
password (str, optional): reMarkable ssh password
Returns: Returns:
(paramiko.ChannelFile): read-only stream of input events (paramiko.ChannelFile): read-only stream of pen events
(paramiko.ChannelFile): read-only stream of touch events
(paramiko.ChannelFile): read-only stream of button events
""" """
log.info("Connecting to input '{}' on '{}'".format(file, args.address)) log.debug("Connecting to input '{}'".format(address))
client = paramiko.SSHClient() client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
@ -35,29 +41,35 @@ def open_remote_device(args, file='/dev/input/event0'):
agent = paramiko.agent.Agent() agent = paramiko.agent.Agent()
if args.key is not None: def use_key(key):
password = None
try: try:
pkey = paramiko.RSAKey.from_private_key_file(os.path.expanduser(args.key)) pkey = paramiko.RSAKey.from_private_key_file(os.path.expanduser(key))
except paramiko.ssh_exception.PasswordRequiredException: except paramiko.ssh_exception.PasswordRequiredException:
passphrase = getpass( passphrase = getpass(
"Enter passphrase for key '{}': ".format(os.path.expanduser(args.key)) "Enter passphrase for key '{}': ".format(os.path.expanduser(key))
) )
pkey = paramiko.RSAKey.from_private_key_file( pkey = paramiko.RSAKey.from_private_key_file(
os.path.expanduser(args.key), os.path.expanduser(key),
password=passphrase password=passphrase
) )
elif args.password: return pkey
password = args.password
if key is not None:
password = None
pkey = use_key(key)
elif os.path.exists(default_key):
password = None
pkey = use_key(default_key)
elif password:
pkey = None pkey = None
elif not agent.get_keys(): elif not agent.get_keys():
password = getpass( password = getpass(
"Password for '{}': ".format(args.address) "Password for '{}': ".format(address)
) )
pkey = None pkey = None
client.connect( client.connect(
args.address, address,
username='root', username='root',
password=password, password=password,
pkey=pkey, pkey=pkey,
@ -68,12 +80,33 @@ def open_remote_device(args, file='/dev/input/event0'):
paramiko.agent.AgentRequestHandler(session) paramiko.agent.AgentRequestHandler(session)
# Start reading events pen_file = client.exec_command(
_, stdout, _ = client.exec_command('cat ' + file) 'readlink -f /dev/input/touchscreen0'
)[1].read().decode('utf8').rstrip('\n')
# handle both reMarkable versions
# https://github.com/Eeems/oxide/issues/48#issuecomment-690830572
if pen_file == '/dev/input/event0':
# rM 1
touch_file = '/dev/input/event1'
button_file = '/dev/input/event2'
else:
# rM 2
touch_file = '/dev/input/event2'
button_file = '/dev/input/event0'
print("connected to", args.address) log.debug('Pen:{}\nTouch:{}\nButton:{}'.format(pen_file, touch_file, button_file))
return stdout # Start reading events
pen = client.exec_command('cat ' + pen_file)[1]
touch = client.exec_command('cat ' + touch_file)[1]
button = client.exec_command('cat ' + button_file)[1]
# Skip to next input if no data available
# pen.channel.setblocking(0)
# touch.channel.setblocking(0)
# button.channel.setblocking(0)
return {'pen': pen, 'touch': touch, 'button': button}
def main(): def main():
@ -84,39 +117,90 @@ def main():
parser.add_argument('--password', default=None, type=str, help="ssh password") parser.add_argument('--password', default=None, type=str, help="ssh password")
parser.add_argument('--address', default='10.11.99.1', type=str, help="device address") parser.add_argument('--address', default='10.11.99.1', type=str, help="device address")
parser.add_argument('--mode', default='fill', choices=['fit', 'fill'], help="scale setting") parser.add_argument('--mode', default='fill', choices=['fit', 'fill'], help="scale setting")
parser.add_argument('--orientation', default='right', choices=['top', 'left', 'right', 'bottom'], help="position of tablet buttons") parser.add_argument('--orientation', default='right', choices=['top', 'left', 'right', 'bottom'], help="position of charging port")
parser.add_argument('--monitor', default=0, type=int, metavar='NUM', help="monitor to output to") parser.add_argument('--monitor', default=0, type=int, metavar='NUM', help="monitor to output to")
parser.add_argument('--threshold', metavar='THRESH', default=600, type=int, help="stylus pressure threshold (default 600)") parser.add_argument('--threshold', metavar='THRESH', default=600, type=int, help="stylus pressure threshold (default 600)")
parser.add_argument('--evdev', action='store_true', default=False, help="use evdev to support pen pressure (requires root, Linux only)") parser.add_argument('--evdev', action='store_true', default=False, help="use evdev to support pen pressure (requires root, Linux only)")
args = parser.parse_args() args = parser.parse_args()
remote_device = open_remote_device(args)
if args.debug: if args.debug:
logging.getLogger('').setLevel(logging.DEBUG)
log.setLevel(logging.DEBUG) log.setLevel(logging.DEBUG)
log.info('Debugging enabled...') print('Debugging enabled...')
else: else:
log.setLevel(logging.INFO) log.setLevel(logging.INFO)
if args.evdev: # ----- Connect to device -----
from remarkable_mouse.evdev import create_local_device, pipe_device
try: rm_inputs = open_rm_inputs(
local_device = create_local_device() address=args.address,
log.info("Created virtual input device '{}'".format(local_device.devnode)) key=args.key,
except PermissionError: password=args.password,
log.error('Insufficient permissions for creating a virtual input device') )
log.error('Make sure you run this program as root') print("Connected to", args.address)
sys.exit(1)
pipe_device(args, remote_device, local_device) # ----- Setup event handlers -----
if args.evdev:
# from remarkable_mouse.evdev import create_local_device, configure_xinput, read_tablet
# try:
# local_device = create_local_device()
# log.info("Created virtual input device '{}'".format(local_device.devnode))
# except PermissionError:
# log.error('Insufficient permissions for creating a virtual input device')
# log.error('Make sure you run this program as root')
# sys.exit(1)
# configure_xinput(
# orientation=args.orientation,
# monitor=args.monitor,
# threshold=args.threshold,
# mode=args.mode,
# )
# read_tablet(rm_inputs, local_device)
#
# from remarkable_mouse.evdev import create_handler
from remarkable_mouse.evdev import read_tablet
else: else:
from remarkable_mouse.pynput import read_tablet from remarkable_mouse.pynput import read_tablet
read_tablet(args, remote_device)
read_tablet(
rm_inputs,
orientation=args.orientation,
monitor=args.monitor,
threshold=args.threshold,
mode=args.mode,
)
# from remarkable_mouse.pynput import create_handler
# event_handler = create_handler(
# orientation=args.orientation,
# monitor=args.monitor,
# threshold=args.threshold,
# mode=args.mode,
# )
# ----- Handle events -----
# loop inputs forever
# import socket
# for name, stream in cycle(rm_inputs.items()):
# try:
# data = stream.read(16)
# except socket.timeout:
# continue
# e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data)
# event_handler(e_time, e_millis, e_type, e_code, e_value)
except PermissionError:
log.error('Insufficient permissions for creating a virtual input device')
log.error('Make sure you run this program as root')
sys.exit(1)
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass
except EOFError: except EOFError:

Loading…
Cancel
Save