python/trezorctl: send raw bytes to device (fixes #116)

pull/919/head
matejcik 4 years ago
parent 9a330f3475
commit 2112da7ab5

@ -16,7 +16,7 @@
import click
from .. import debuglink
from .. import debuglink, mapping, messages, protobuf
from ..messages import DebugLinkShowTextStyle as S
@ -71,3 +71,48 @@ def show_text(connect, icon, color, header, body):
return debuglink.show_text(
connect(), header, body_text, icon=icon, icon_color=color
)
@cli.command()
@click.argument("message_name_or_type")
@click.argument("hex_data")
@click.pass_obj
def send_bytes(connect, message_name_or_type, hex_data):
"""Send raw bytes to Trezor.
Message type and message data must be specified separately, due to how message
chunking works on the transport level. Message length is calculated and sent
automatically, and it is currently impossible to explicitly specify invalid length.
MESSAGE_NAME_OR_TYPE can either be a number, or a name from the MessageType enum,
in which case the value of that enum is used.
"""
if message_name_or_type.isdigit():
message_type = int(message_name_or_type)
else:
message_type = getattr(messages.MessageType, message_name_or_type)
if not isinstance(message_type, int):
raise click.ClickException("Invalid message type.")
try:
message_data = bytes.fromhex(hex_data)
except Exception as e:
raise click.ClickException("Invalid hex data.") from e
transport = connect(return_transport=True)
transport.begin_session()
transport.write(message_type, message_data)
response_type, response_data = transport.read()
transport.end_session()
click.echo("Response type: {}".format(response_type))
click.echo("Response data: {}".format(response_data.hex()))
try:
msg = mapping.decode(response_type, response_data)
click.echo("Parsed message:")
click.echo(protobuf.format_message(msg))
except Exception as e:
click.echo("Could not parse response: {}".format(e))

@ -157,19 +157,21 @@ def cli(ctx, path, verbose, is_json, passphrase_on_host, session_id):
except ValueError:
raise click.ClickException("Not a valid session id: {}".format(session_id))
def get_device():
def get_device(return_transport=False):
try:
device = get_transport(path, prefix_search=False)
transport = get_transport(path, prefix_search=False)
except Exception:
try:
device = get_transport(path, prefix_search=True)
transport = get_transport(path, prefix_search=True)
except Exception:
click.echo("Failed to find a Trezor device.")
if path is not None:
click.echo("Using path: {}".format(path))
sys.exit(1)
if return_transport:
return transport
return TrezorClient(
transport=device,
transport=transport,
ui=ui.ClickUI(passphrase_on_host=passphrase_on_host),
session_id=session_id,
)

Loading…
Cancel
Save