mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 12:28:09 +00:00
parent
aaa224a4f7
commit
8049282bdb
1
python/.changelog.d/1026.added
Normal file
1
python/.changelog.d/1026.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
New exception type `DeviceIsBusy` indicates that the device is in use by another process.
|
1
python/.changelog.d/1026.fixed
Normal file
1
python/.changelog.d/1026.fixed
Normal file
@ -0,0 +1 @@
|
|||||||
|
trezorctl will correctly report that device is in use.
|
@ -21,9 +21,8 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, Optional
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from .. import exceptions
|
from .. import exceptions, transport
|
||||||
from ..client import TrezorClient
|
from ..client import TrezorClient
|
||||||
from ..transport import get_transport
|
|
||||||
from ..ui import ClickUI, ScriptUI
|
from ..ui import ClickUI, ScriptUI
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -67,14 +66,14 @@ class TrezorConnection:
|
|||||||
def get_transport(self) -> "Transport":
|
def get_transport(self) -> "Transport":
|
||||||
try:
|
try:
|
||||||
# look for transport without prefix search
|
# look for transport without prefix search
|
||||||
return get_transport(self.path, prefix_search=False)
|
return transport.get_transport(self.path, prefix_search=False)
|
||||||
except Exception:
|
except Exception:
|
||||||
# most likely not found. try again below.
|
# most likely not found. try again below.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# look for transport with prefix search
|
# look for transport with prefix search
|
||||||
# if this fails, we want the exception to bubble up to the caller
|
# if this fails, we want the exception to bubble up to the caller
|
||||||
return get_transport(self.path, prefix_search=True)
|
return transport.get_transport(self.path, prefix_search=True)
|
||||||
|
|
||||||
def get_ui(self) -> "TrezorClientUI":
|
def get_ui(self) -> "TrezorClientUI":
|
||||||
if self.script:
|
if self.script:
|
||||||
@ -101,6 +100,9 @@ class TrezorConnection:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
client = self.get_client()
|
client = self.get_client()
|
||||||
|
except transport.DeviceIsBusy:
|
||||||
|
click.echo("Device is in use by another process.")
|
||||||
|
sys.exit(1)
|
||||||
except Exception:
|
except Exception:
|
||||||
click.echo("Failed to find a Trezor device.")
|
click.echo("Failed to find a Trezor device.")
|
||||||
if self.path is not None:
|
if self.path is not None:
|
||||||
|
@ -26,7 +26,7 @@ import click
|
|||||||
|
|
||||||
from .. import log, messages, protobuf, ui
|
from .. import log, messages, protobuf, ui
|
||||||
from ..client import TrezorClient
|
from ..client import TrezorClient
|
||||||
from ..transport import enumerate_devices
|
from ..transport import DeviceIsBusy, enumerate_devices
|
||||||
from ..transport.udp import UdpTransport
|
from ..transport.udp import UdpTransport
|
||||||
from . import (
|
from . import (
|
||||||
AliasedGroup,
|
AliasedGroup,
|
||||||
@ -247,9 +247,15 @@ def list_devices(no_resolve: bool) -> Optional[Iterable["Transport"]]:
|
|||||||
return enumerate_devices()
|
return enumerate_devices()
|
||||||
|
|
||||||
for transport in enumerate_devices():
|
for transport in enumerate_devices():
|
||||||
client = TrezorClient(transport, ui=ui.ClickUI())
|
try:
|
||||||
click.echo(f"{transport} - {format_device_name(client.features)}")
|
client = TrezorClient(transport, ui=ui.ClickUI())
|
||||||
client.end_session()
|
description = format_device_name(client.features)
|
||||||
|
client.end_session()
|
||||||
|
except DeviceIsBusy:
|
||||||
|
description = "Device is in use by another process"
|
||||||
|
except Exception:
|
||||||
|
description = "Failed to read details"
|
||||||
|
click.echo(f"{transport} - {description}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +48,10 @@ class TransportException(TrezorException):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceIsBusy(TransportException):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Transport:
|
class Transport:
|
||||||
"""Raw connection to a Trezor device.
|
"""Raw connection to a Trezor device.
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional
|
|||||||
import requests
|
import requests
|
||||||
|
|
||||||
from ..log import DUMP_PACKETS
|
from ..log import DUMP_PACKETS
|
||||||
from . import MessagePayload, Transport, TransportException
|
from . import DeviceIsBusy, MessagePayload, Transport, TransportException
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..models import TrezorModel
|
from ..models import TrezorModel
|
||||||
@ -37,14 +37,19 @@ CONNECTION = requests.Session()
|
|||||||
CONNECTION.headers.update(TREZORD_ORIGIN_HEADER)
|
CONNECTION.headers.update(TREZORD_ORIGIN_HEADER)
|
||||||
|
|
||||||
|
|
||||||
def call_bridge(uri: str, data: Optional[str] = None) -> requests.Response:
|
class BridgeException(TransportException):
|
||||||
url = TREZORD_HOST + "/" + uri
|
def __init__(self, path: str, status: int, message: str) -> None:
|
||||||
|
self.path = path
|
||||||
|
self.status = status
|
||||||
|
self.message = message
|
||||||
|
super().__init__(f"trezord: {path} failed with code {status}: {message}")
|
||||||
|
|
||||||
|
|
||||||
|
def call_bridge(path: str, data: Optional[str] = None) -> requests.Response:
|
||||||
|
url = TREZORD_HOST + "/" + path
|
||||||
r = CONNECTION.post(url, data=data)
|
r = CONNECTION.post(url, data=data)
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
error_str = (
|
raise BridgeException(path, r.status_code, r.json()["error"])
|
||||||
f"trezord: {uri} failed with code {r.status_code}: {r.json()['error']}"
|
|
||||||
)
|
|
||||||
raise TransportException(error_str)
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
@ -150,7 +155,12 @@ class BridgeTransport(Transport):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def begin_session(self) -> None:
|
def begin_session(self) -> None:
|
||||||
data = self._call("acquire/" + self.device["path"])
|
try:
|
||||||
|
data = self._call("acquire/" + self.device["path"])
|
||||||
|
except BridgeException as e:
|
||||||
|
if e.message == "wrong previous session":
|
||||||
|
raise DeviceIsBusy(self.device["path"]) from e
|
||||||
|
raise
|
||||||
self.session = data.json()["session"]
|
self.session = data.json()["session"]
|
||||||
|
|
||||||
def end_session(self) -> None:
|
def end_session(self) -> None:
|
||||||
|
@ -22,7 +22,7 @@ from typing import Iterable, List, Optional
|
|||||||
|
|
||||||
from ..log import DUMP_PACKETS
|
from ..log import DUMP_PACKETS
|
||||||
from ..models import TREZORS, TrezorModel
|
from ..models import TREZORS, TrezorModel
|
||||||
from . import UDEV_RULES_STR, TransportException
|
from . import UDEV_RULES_STR, DeviceIsBusy, TransportException
|
||||||
from .protocol import ProtocolBasedTransport, ProtocolV1
|
from .protocol import ProtocolBasedTransport, ProtocolV1
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -57,7 +57,10 @@ class WebUsbHandle:
|
|||||||
else:
|
else:
|
||||||
args = ()
|
args = ()
|
||||||
raise IOError("Cannot open device", *args)
|
raise IOError("Cannot open device", *args)
|
||||||
self.handle.claimInterface(self.interface)
|
try:
|
||||||
|
self.handle.claimInterface(self.interface)
|
||||||
|
except usb1.USBErrorAccess as e:
|
||||||
|
raise DeviceIsBusy(self.device) from e
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
if self.handle is not None:
|
if self.handle is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user