mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 17:38:39 +00:00
trezorlib: workaround for a problem with Trezor One webusb
when webusb version of T1 is wiped, the usb device changes serial immediately (unlike TT, which changes it after reconnect). That confuses libusb on linux, and next time the device is reset, it will insist on re-enumeration. To solve this, we leave some explanatory comments, and trigger the device reset through opening the device right after a wipe. The client instance is unusable after that, but not much we can do about it, and on next run trezorctl will behave as if nothing bad happened.
This commit is contained in:
parent
18eab21932
commit
0a8b5a08c2
@ -374,7 +374,8 @@ def wipe_device(connect, bootloader):
|
||||
click.echo("Wiping user data!")
|
||||
|
||||
try:
|
||||
return device.wipe(connect())
|
||||
device.wipe(client)
|
||||
click.echo("Device wiped")
|
||||
except tools.CallException as e:
|
||||
click.echo("Action failed: {} {}".format(*e.args))
|
||||
sys.exit(3)
|
||||
|
@ -45,6 +45,7 @@ class TrezorDevice:
|
||||
|
||||
|
||||
@expect(proto.Success, field="message")
|
||||
@session
|
||||
def apply_settings(
|
||||
client,
|
||||
label=None,
|
||||
@ -74,6 +75,7 @@ def apply_settings(
|
||||
|
||||
|
||||
@expect(proto.Success, field="message")
|
||||
@session
|
||||
def apply_flags(client, flags):
|
||||
out = client.call(proto.ApplyFlags(flags=flags))
|
||||
client.init_device() # Reload Features
|
||||
@ -81,6 +83,7 @@ def apply_flags(client, flags):
|
||||
|
||||
|
||||
@expect(proto.Success, field="message")
|
||||
@session
|
||||
def change_pin(client, remove=False):
|
||||
ret = client.call(proto.ChangePin(remove=remove))
|
||||
client.init_device() # Re-read features
|
||||
@ -93,14 +96,26 @@ def set_u2f_counter(client, u2f_counter):
|
||||
return ret
|
||||
|
||||
|
||||
@expect(proto.Success, field="message")
|
||||
def wipe(client):
|
||||
ret = client.call(proto.WipeDevice())
|
||||
def wipe(client) -> bool:
|
||||
"""Initiate device wipe.
|
||||
|
||||
Returns whether it's safe to continue using the client instance.
|
||||
(see comment in `WebUsbHandle.open`)
|
||||
"""
|
||||
# This is not marked @session by design: the subsequent init_device should run
|
||||
# in a separate session, so that when it triggers a USB error, a subsequent
|
||||
# re-enumeration fixes it. See comment in WebUsbHandle.open
|
||||
# XXX this should actually call the USB reset explicitly
|
||||
client.call(proto.WipeDevice())
|
||||
try:
|
||||
client.init_device()
|
||||
return ret
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
@expect(proto.Success, field="message")
|
||||
@session
|
||||
def recover(
|
||||
client,
|
||||
word_count=24,
|
||||
|
@ -53,7 +53,16 @@ class WebUsbHandle:
|
||||
else:
|
||||
args = ()
|
||||
raise IOError("Cannot open device", *args)
|
||||
|
||||
self.handle.resetDevice()
|
||||
# XXX this may fail with LIBUSB_ERROR_NOT_FOUND
|
||||
# This will usually happen after device wipe, because USB serial has changed,
|
||||
# and requires re-enumeration and reacquiring of the device.
|
||||
# I haven't found a reasonable way of handling it here, or in the enumeration
|
||||
# step. (In particular, it seems impossible to force libusb to re-enumerate
|
||||
# explicitly, without calling device reset.)
|
||||
# So now I'm just leaving it here to crash in some cases.
|
||||
|
||||
self.handle.claimInterface(self.interface)
|
||||
|
||||
def close(self) -> None:
|
||||
|
Loading…
Reference in New Issue
Block a user