# This file is part of the Trezor project. # # Copyright (C) 2012-2019 SatoshiLabs and contributors # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License version 3 # as published by the Free Software Foundation. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the License along with this library. # If not, see . import click from .. import device, messages from . import ChoiceType PASSPHRASE_SOURCE = { "ask": messages.PassphraseSourceType.ASK, "device": messages.PassphraseSourceType.DEVICE, "host": messages.PassphraseSourceType.HOST, } ROTATION = {"north": 0, "east": 90, "south": 180, "west": 270} @click.group(name="set") def cli(): """Device settings.""" @cli.command() @click.option("-r", "--remove", is_flag=True) @click.pass_obj def pin(connect, remove): """Set, change or remove PIN.""" return device.change_pin(connect(), remove) @cli.command() # keep the deprecated -l/--label option, make it do nothing @click.option("-l", "--label", "_ignore", is_flag=True, hidden=True, expose_value=False) @click.argument("label") @click.pass_obj def label(connect, label): """Set new device label.""" return device.apply_settings(connect(), label=label) @cli.command() @click.argument("rotation", type=ChoiceType(ROTATION)) @click.pass_obj def display_rotation(connect, rotation): """Set display rotation. Configure display rotation for Trezor Model T. The options are north, east, south or west. """ return device.apply_settings(connect(), display_rotation=rotation) @cli.command() @click.argument("delay", type=str) @click.pass_obj def auto_lock_delay(connect, delay): """Set auto-lock delay (in seconds).""" value, unit = delay[:-1], delay[-1:] units = {"s": 1, "m": 60, "h": 3600} if unit in units: seconds = float(value) * units[unit] else: seconds = float(delay) # assume seconds if no unit is specified return device.apply_settings(connect(), auto_lock_delay_ms=int(seconds * 1000)) @cli.command() @click.argument("flags") @click.pass_obj def flags(connect, flags): """Set device flags.""" flags = flags.lower() if flags.startswith("0b"): flags = int(flags, 2) elif flags.startswith("0x"): flags = int(flags, 16) else: flags = int(flags) return device.apply_flags(connect(), flags=flags) @cli.command() @click.option("-f", "--filename", default=None) @click.pass_obj def homescreen(connect, filename): """Set new homescreen.""" if filename is None: img = b"\x00" elif filename.endswith(".toif"): img = open(filename, "rb").read() if img[:8] != b"TOIf\x90\x00\x90\x00": raise click.ClickException("File is not a TOIF file with size of 144x144") else: from PIL import Image im = Image.open(filename) if im.size != (128, 64): raise click.ClickException("Wrong size of the image") im = im.convert("1") pix = im.load() img = bytearray(1024) for j in range(64): for i in range(128): if pix[i, j]: o = i + j * 128 img[o // 8] |= 1 << (7 - o % 8) img = bytes(img) return device.apply_settings(connect(), homescreen=img) # # passphrase operations # @cli.group() def passphrase(): """Enable, disable or configure passphrase protection.""" @passphrase.command(name="enabled") @click.pass_obj def passphrase_enable(connect): """Enable passphrase.""" return device.apply_settings(connect(), use_passphrase=True) @passphrase.command(name="disabled") @click.pass_obj def passphrase_disable(connect): """Disable passphrase.""" return device.apply_settings(connect(), use_passphrase=False) @passphrase.command(name="source") @click.argument("source", type=ChoiceType(PASSPHRASE_SOURCE)) @click.pass_obj def passphrase_source(connect, source): """Set passphrase source. Configure how to enter passphrase on Trezor Model T. The options are: \b ask - always ask where to enter passphrase device - always enter passphrase on device host - always enter passphrase on host """ return device.apply_settings(connect(), passphrase_source=source)