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.
trezor-firmware/python/src/trezorlib/cli/settings.py

162 lines
4.5 KiB

# 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
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)