You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
4.1 KiB
Python
128 lines
4.1 KiB
Python
#!/bin/env python
|
|
# Evan Widloski - 2019-02-23
|
|
# Use reMarkable as mouse input
|
|
|
|
import argparse
|
|
import logging
|
|
import os
|
|
import sys
|
|
import struct
|
|
from getpass import getpass
|
|
|
|
import paramiko
|
|
import paramiko.agent
|
|
|
|
logging.basicConfig(format='%(message)s')
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
def open_remote_device(args, file='/dev/input/event0'):
|
|
"""
|
|
Open a remote input device via SSH.
|
|
|
|
Args:
|
|
args: argparse arguments
|
|
file (str): path to the input device on the device
|
|
Returns:
|
|
(paramiko.ChannelFile): read-only stream of input events
|
|
"""
|
|
log.info("Connecting to input '{}' on '{}'".format(file, args.address))
|
|
|
|
client = paramiko.SSHClient()
|
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
pkey = None
|
|
password = None
|
|
|
|
agent = paramiko.agent.Agent()
|
|
|
|
if args.key is not None:
|
|
password = None
|
|
try:
|
|
pkey = paramiko.RSAKey.from_private_key_file(os.path.expanduser(args.key))
|
|
except paramiko.ssh_exception.PasswordRequiredException:
|
|
passphrase = getpass(
|
|
"Enter passphrase for key '{}': ".format(os.path.expanduser(args.key))
|
|
)
|
|
pkey = paramiko.RSAKey.from_private_key_file(
|
|
os.path.expanduser(args.key),
|
|
password=passphrase
|
|
)
|
|
elif args.password:
|
|
password = args.password
|
|
pkey = None
|
|
elif not agent.get_keys():
|
|
password = getpass(
|
|
"Password for '{}': ".format(args.address)
|
|
)
|
|
pkey = None
|
|
|
|
client.connect(
|
|
args.address,
|
|
username='root',
|
|
password=password,
|
|
pkey=pkey,
|
|
look_for_keys=False
|
|
)
|
|
|
|
session = client.get_transport().open_session()
|
|
|
|
paramiko.agent.AgentRequestHandler(session)
|
|
|
|
# Start reading events
|
|
_, stdout, _ = client.exec_command('cat ' + file)
|
|
|
|
print("connected to", args.address)
|
|
|
|
return stdout
|
|
|
|
|
|
def main():
|
|
try:
|
|
parser = argparse.ArgumentParser(description="use reMarkable tablet as a mouse input")
|
|
parser.add_argument('--debug', action='store_true', default=False, help="enable debug messages")
|
|
parser.add_argument('--key', type=str, metavar='PATH', help="ssh private key")
|
|
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('--mode', default='fit', 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('--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('--evdev', action='store_true', default=False, help="use evdev to support pen pressure (requires root, Linux only)")
|
|
|
|
args = parser.parse_args()
|
|
|
|
remote_device = open_remote_device(args)
|
|
|
|
if args.debug:
|
|
logging.getLogger('').setLevel(logging.DEBUG)
|
|
log.setLevel(logging.DEBUG)
|
|
log.info('Debugging enabled...')
|
|
else:
|
|
log.setLevel(logging.INFO)
|
|
|
|
if args.evdev:
|
|
from remarkable_mouse.evdev import create_local_device, pipe_device
|
|
|
|
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)
|
|
|
|
pipe_device(args, remote_device, local_device)
|
|
|
|
else:
|
|
from remarkable_mouse.pynput import read_tablet
|
|
read_tablet(args, remote_device)
|
|
|
|
except KeyboardInterrupt:
|
|
pass
|
|
except EOFError:
|
|
pass
|
|
|
|
if __name__ == '__main__':
|
|
main()
|