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.

174 lines
5.9 KiB

5 years ago
# Evan Widloski - 2019-02-23
# Use reMarkable as mouse input
import argparse
import logging
import os
import sys
import struct
from getpass import getpass
from itertools import cycle
Send events to a virtual input device Instead of sending mouse move and click events to the system’s main device, create a separate virtual input device that registers itself as a Wacom tablet. Most importantly, this enables pressure and tilt sensitivity which is picked up by programs such as GIMP or Krita. Because this uses the `libevdev` library that is only supported on Linux, this commit breaks compatibility with Windows and (probably) macOS. Furthermore, because creating virtual input devices is restricted to root, the script must now be run with `sudo`. Failing to do so will most likely trigger a permission error. CLI changes ----------- * Drop the `--orientation` flag. Orientation of the device can now be configured just like any other Wacom device using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" <orientation> ``` where `<orientation>` is one of 0 (for “right” orientation), 1 (for “portrait” orientation), 2 (for “left” orientation) or 3 (for “reversed portrait” orientation). * Drop the `--monitor` flag. This can also be configured using `xinput` instead: ``` xinput --map-to-output "reMarkable tablet stylus" <output> ``` where `<output>` is the name of an output currently connected to the device, as listed by `xrandr` (e.g. LVDS1). * Drop the `--offset` flag. This didn’t seem to be used anywhere in the code. * Drop the `--threshold` flag. The pressure threshold required to trigger a click event can be configured using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" 1000 ``` where `1000` can be replaced by an arbitrary pressure threshold. On my machine, the default seems to be 26. The pressure profile (mapping the actual pressure put on the stylus to the pressure actually received by the drawing programs) can also be adjusted using the following prop: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressurecurve" 50 0 100 50 ``` Dependencies changes -------------------- Replaced dependency pynput with libevdev (which requires that libevdev is present on the system). Dropped dependency `screeninfo` because assigning the input to a monitor is no longer done through this program.
5 years ago
5 years ago
import paramiko
import paramiko.agent
Send events to a virtual input device Instead of sending mouse move and click events to the system’s main device, create a separate virtual input device that registers itself as a Wacom tablet. Most importantly, this enables pressure and tilt sensitivity which is picked up by programs such as GIMP or Krita. Because this uses the `libevdev` library that is only supported on Linux, this commit breaks compatibility with Windows and (probably) macOS. Furthermore, because creating virtual input devices is restricted to root, the script must now be run with `sudo`. Failing to do so will most likely trigger a permission error. CLI changes ----------- * Drop the `--orientation` flag. Orientation of the device can now be configured just like any other Wacom device using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" <orientation> ``` where `<orientation>` is one of 0 (for “right” orientation), 1 (for “portrait” orientation), 2 (for “left” orientation) or 3 (for “reversed portrait” orientation). * Drop the `--monitor` flag. This can also be configured using `xinput` instead: ``` xinput --map-to-output "reMarkable tablet stylus" <output> ``` where `<output>` is the name of an output currently connected to the device, as listed by `xrandr` (e.g. LVDS1). * Drop the `--offset` flag. This didn’t seem to be used anywhere in the code. * Drop the `--threshold` flag. The pressure threshold required to trigger a click event can be configured using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" 1000 ``` where `1000` can be replaced by an arbitrary pressure threshold. On my machine, the default seems to be 26. The pressure profile (mapping the actual pressure put on the stylus to the pressure actually received by the drawing programs) can also be adjusted using the following prop: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressurecurve" 50 0 100 50 ``` Dependencies changes -------------------- Replaced dependency pynput with libevdev (which requires that libevdev is present on the system). Dropped dependency `screeninfo` because assigning the input to a monitor is no longer done through this program.
5 years ago
5 years ago
logging.basicConfig(format='%(message)s')
log = logging.getLogger('remouse')
5 years ago
default_key = os.path.expanduser('~/.ssh/remarkable')
5 years ago
def open_rm_inputs(*, address, key, password):
Send events to a virtual input device Instead of sending mouse move and click events to the system’s main device, create a separate virtual input device that registers itself as a Wacom tablet. Most importantly, this enables pressure and tilt sensitivity which is picked up by programs such as GIMP or Krita. Because this uses the `libevdev` library that is only supported on Linux, this commit breaks compatibility with Windows and (probably) macOS. Furthermore, because creating virtual input devices is restricted to root, the script must now be run with `sudo`. Failing to do so will most likely trigger a permission error. CLI changes ----------- * Drop the `--orientation` flag. Orientation of the device can now be configured just like any other Wacom device using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" <orientation> ``` where `<orientation>` is one of 0 (for “right” orientation), 1 (for “portrait” orientation), 2 (for “left” orientation) or 3 (for “reversed portrait” orientation). * Drop the `--monitor` flag. This can also be configured using `xinput` instead: ``` xinput --map-to-output "reMarkable tablet stylus" <output> ``` where `<output>` is the name of an output currently connected to the device, as listed by `xrandr` (e.g. LVDS1). * Drop the `--offset` flag. This didn’t seem to be used anywhere in the code. * Drop the `--threshold` flag. The pressure threshold required to trigger a click event can be configured using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" 1000 ``` where `1000` can be replaced by an arbitrary pressure threshold. On my machine, the default seems to be 26. The pressure profile (mapping the actual pressure put on the stylus to the pressure actually received by the drawing programs) can also be adjusted using the following prop: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressurecurve" 50 0 100 50 ``` Dependencies changes -------------------- Replaced dependency pynput with libevdev (which requires that libevdev is present on the system). Dropped dependency `screeninfo` because assigning the input to a monitor is no longer done through this program.
5 years ago
"""
Open a remote input device via SSH.
Args:
address (str): address to reMarkable
key (str, optional): path to reMarkable ssh key
password (str, optional): reMarkable ssh password
Returns:
(paramiko.ChannelFile): read-only stream of pen events
(paramiko.ChannelFile): read-only stream of touch events
(paramiko.ChannelFile): read-only stream of button events
Send events to a virtual input device Instead of sending mouse move and click events to the system’s main device, create a separate virtual input device that registers itself as a Wacom tablet. Most importantly, this enables pressure and tilt sensitivity which is picked up by programs such as GIMP or Krita. Because this uses the `libevdev` library that is only supported on Linux, this commit breaks compatibility with Windows and (probably) macOS. Furthermore, because creating virtual input devices is restricted to root, the script must now be run with `sudo`. Failing to do so will most likely trigger a permission error. CLI changes ----------- * Drop the `--orientation` flag. Orientation of the device can now be configured just like any other Wacom device using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" <orientation> ``` where `<orientation>` is one of 0 (for “right” orientation), 1 (for “portrait” orientation), 2 (for “left” orientation) or 3 (for “reversed portrait” orientation). * Drop the `--monitor` flag. This can also be configured using `xinput` instead: ``` xinput --map-to-output "reMarkable tablet stylus" <output> ``` where `<output>` is the name of an output currently connected to the device, as listed by `xrandr` (e.g. LVDS1). * Drop the `--offset` flag. This didn’t seem to be used anywhere in the code. * Drop the `--threshold` flag. The pressure threshold required to trigger a click event can be configured using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" 1000 ``` where `1000` can be replaced by an arbitrary pressure threshold. On my machine, the default seems to be 26. The pressure profile (mapping the actual pressure put on the stylus to the pressure actually received by the drawing programs) can also be adjusted using the following prop: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressurecurve" 50 0 100 50 ``` Dependencies changes -------------------- Replaced dependency pynput with libevdev (which requires that libevdev is present on the system). Dropped dependency `screeninfo` because assigning the input to a monitor is no longer done through this program.
5 years ago
"""
log.debug("Connecting to input '{}'".format(address))
5 years ago
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pkey = None
agent = paramiko.agent.Agent()
def use_key(key):
for key_type in [paramiko.RSAKey, paramiko.Ed25519Key, paramiko.ECDSAKey]:
try:
pkey = key_type.from_private_key_file(os.path.expanduser(key))
except paramiko.ssh_exception.SSHException:
continue
except paramiko.ssh_exception.PasswordRequiredException:
passphrase = getpass(
"Enter passphrase for key '{}': ".format(os.path.expanduser(key))
)
pkey = paramiko.RSAKey.from_private_key_file(
os.path.expanduser(key), password=passphrase
)
break
return pkey
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 is not None:
5 years ago
pkey = None
elif not agent.get_keys():
5 years ago
password = getpass(
"Password for '{}': ".format(address)
5 years ago
)
pkey = None
client.connect(
address,
5 years ago
username='root',
password=password,
pkey=pkey,
look_for_keys=True,
disabled_algorithms=dict(pubkeys=["rsa-sha2-512", "rsa-sha2-256"])
5 years ago
)
session = client.get_transport().open_session()
paramiko.agent.AgentRequestHandler(session)
pen_file = client.exec_command(
'readlink -f /dev/input/touchscreen0'
)[1].read().decode('utf8').rstrip('\n')
5 years ago
# 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'
log.debug('Pen:{}\nTouch:{}\nButton:{}'.format(pen_file, touch_file, button_file))
5 years ago
# 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]
5 years ago
return {'pen': pen, 'touch': touch, 'button': button}
5 years ago
5 years ago
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='fill', choices=['fit', 'fill', 'stretch', 'cool'], help="""Scale setting.
Fit (default): take up the entire tablet, but not necessarily the entire monitor.
Fill: take up the entire monitor, but not necessarily the entire tablet.
Stretch: take up both the entire tablet and monitor, but don't maintain aspect ratio.
Cool: fit the entire monitor on the tablet, ensure 1:1 aspect ratio on both.""")
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('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor")
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()
if args.debug:
log.setLevel(logging.DEBUG)
print('Debugging enabled...')
Send events to a virtual input device Instead of sending mouse move and click events to the system’s main device, create a separate virtual input device that registers itself as a Wacom tablet. Most importantly, this enables pressure and tilt sensitivity which is picked up by programs such as GIMP or Krita. Because this uses the `libevdev` library that is only supported on Linux, this commit breaks compatibility with Windows and (probably) macOS. Furthermore, because creating virtual input devices is restricted to root, the script must now be run with `sudo`. Failing to do so will most likely trigger a permission error. CLI changes ----------- * Drop the `--orientation` flag. Orientation of the device can now be configured just like any other Wacom device using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" <orientation> ``` where `<orientation>` is one of 0 (for “right” orientation), 1 (for “portrait” orientation), 2 (for “left” orientation) or 3 (for “reversed portrait” orientation). * Drop the `--monitor` flag. This can also be configured using `xinput` instead: ``` xinput --map-to-output "reMarkable tablet stylus" <output> ``` where `<output>` is the name of an output currently connected to the device, as listed by `xrandr` (e.g. LVDS1). * Drop the `--offset` flag. This didn’t seem to be used anywhere in the code. * Drop the `--threshold` flag. The pressure threshold required to trigger a click event can be configured using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" 1000 ``` where `1000` can be replaced by an arbitrary pressure threshold. On my machine, the default seems to be 26. The pressure profile (mapping the actual pressure put on the stylus to the pressure actually received by the drawing programs) can also be adjusted using the following prop: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressurecurve" 50 0 100 50 ``` Dependencies changes -------------------- Replaced dependency pynput with libevdev (which requires that libevdev is present on the system). Dropped dependency `screeninfo` because assigning the input to a monitor is no longer done through this program.
5 years ago
else:
log.setLevel(logging.INFO)
# ----- Connect to device -----
rm_inputs = open_rm_inputs(
address=args.address,
key=args.key,
password=args.password,
)
print("Connected to", args.address)
3 years ago
# ----- Handle events -----
if args.evdev:
from remarkable_mouse.evdev import read_tablet
else:
from remarkable_mouse.pynput import read_tablet
read_tablet(
rm_inputs,
orientation=args.orientation,
monitor_num=args.monitor,
region=args.region,
threshold=args.threshold,
mode=args.mode,
)
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)
5 years ago
except KeyboardInterrupt:
pass
Send events to a virtual input device Instead of sending mouse move and click events to the system’s main device, create a separate virtual input device that registers itself as a Wacom tablet. Most importantly, this enables pressure and tilt sensitivity which is picked up by programs such as GIMP or Krita. Because this uses the `libevdev` library that is only supported on Linux, this commit breaks compatibility with Windows and (probably) macOS. Furthermore, because creating virtual input devices is restricted to root, the script must now be run with `sudo`. Failing to do so will most likely trigger a permission error. CLI changes ----------- * Drop the `--orientation` flag. Orientation of the device can now be configured just like any other Wacom device using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" <orientation> ``` where `<orientation>` is one of 0 (for “right” orientation), 1 (for “portrait” orientation), 2 (for “left” orientation) or 3 (for “reversed portrait” orientation). * Drop the `--monitor` flag. This can also be configured using `xinput` instead: ``` xinput --map-to-output "reMarkable tablet stylus" <output> ``` where `<output>` is the name of an output currently connected to the device, as listed by `xrandr` (e.g. LVDS1). * Drop the `--offset` flag. This didn’t seem to be used anywhere in the code. * Drop the `--threshold` flag. The pressure threshold required to trigger a click event can be configured using `xinput`: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" 1000 ``` where `1000` can be replaced by an arbitrary pressure threshold. On my machine, the default seems to be 26. The pressure profile (mapping the actual pressure put on the stylus to the pressure actually received by the drawing programs) can also be adjusted using the following prop: ``` xinput --set-prop "reMarkable tablet stylus" "Wacom Pressurecurve" 50 0 100 50 ``` Dependencies changes -------------------- Replaced dependency pynput with libevdev (which requires that libevdev is present on the system). Dropped dependency `screeninfo` because assigning the input to a monitor is no longer done through this program.
5 years ago
except EOFError:
pass
if __name__ == '__main__':
main()