diff --git a/setup.py b/setup.py
index 0639e902a..4d5f99247 100755
--- a/setup.py
+++ b/setup.py
@@ -33,6 +33,7 @@ setup(
url='https://github.com/trezor/python-trezor',
packages=[
'trezorlib',
+ 'trezorlib.transport',
'trezorlib.messages',
'trezorlib.qt',
'trezorlib.tests.device_tests',
diff --git a/tools/encfs_aes_getpass.py b/tools/encfs_aes_getpass.py
index ef67b5529..64ba603f8 100755
--- a/tools/encfs_aes_getpass.py
+++ b/tools/encfs_aes_getpass.py
@@ -16,21 +16,15 @@ import hashlib
import binascii
from trezorlib.client import TrezorClient
-from trezorlib.device import TrezorDevice
-
-# Python2 vs Python3
-try:
- input = raw_input
-except NameError:
- pass
+from trezorlib.transport import enumerate_devices
def wait_for_devices():
- devices = TrezorDevice.enumerate()
+ devices = enumerate_devices()
while not len(devices):
sys.stderr.write("Please connect TREZOR to computer and press Enter...")
input()
- devices = TrezorDevice.enumerate()
+ devices = enumerate_devices()
return devices
diff --git a/tools/helloworld.py b/tools/helloworld.py
index 9712a2b26..c91e5d392 100755
--- a/tools/helloworld.py
+++ b/tools/helloworld.py
@@ -1,21 +1,11 @@
#!/usr/bin/env python3
-from __future__ import print_function
-
from trezorlib.client import TrezorClient
-from trezorlib.device import TrezorDevice
+from trezorlib.transport import get_transport
def main():
- # List all connected TREZORs on USB/UDP
- devices = TrezorDevice.enumerate()
-
- # Check whether we found any
- if len(devices) == 0:
- print('No TREZOR found')
- return
-
# Use first connected device
- transport = devices[0]
+ transport = get_transport()
# Creates object for manipulating TREZOR
client = TrezorClient(transport)
diff --git a/tools/mem_flashblock.py b/tools/mem_flashblock.py
index af8b15c50..6de4f7a8a 100755
--- a/tools/mem_flashblock.py
+++ b/tools/mem_flashblock.py
@@ -1,9 +1,7 @@
#!/usr/bin/env python3
-from __future__ import print_function
-
from trezorlib.debuglink import DebugLink
from trezorlib.client import TrezorClient
-from trezorlib.transport_hid import HidTransport
+from trezorlib.transport import enumerate_devices
import binascii
import sys
@@ -16,8 +14,8 @@ sectorlens = [0x4000, 0x4000, 0x4000, 0x4000,
def main():
- # List all connected TREZORs on USB
- devices = HidTransport.enumerate()
+ # List all debuggable TREZORs
+ devices = [device for device in enumerate_devices() if hasattr(device, 'find_debug')]
# Check whether we found any
if len(devices) == 0:
diff --git a/tools/mem_read.py b/tools/mem_read.py
index eafa20571..c6a4a3a16 100755
--- a/tools/mem_read.py
+++ b/tools/mem_read.py
@@ -1,9 +1,7 @@
#!/usr/bin/env python3
-from __future__ import print_function
-
from trezorlib.debuglink import DebugLink
from trezorlib.client import TrezorClient
-from trezorlib.transport_hid import HidTransport
+from trezorlib.transport import enumerate_devices
import sys
# usage examples
@@ -16,8 +14,8 @@ import sys
def main():
- # List all connected TREZORs on USB
- devices = HidTransport.enumerate()
+ # List all debuggable TREZORs
+ devices = [device for device in enumerate_devices() if hasattr(device, 'find_debug')]
# Check whether we found any
if len(devices) == 0:
diff --git a/tools/mem_write.py b/tools/mem_write.py
index ae94a8bf5..f3f11cece 100755
--- a/tools/mem_write.py
+++ b/tools/mem_write.py
@@ -1,16 +1,14 @@
#!/usr/bin/env python3
-from __future__ import print_function
-
from trezorlib.debuglink import DebugLink
from trezorlib.client import TrezorClient
-from trezorlib.transport_hid import HidTransport
+from trezorlib.transport import enumerate_devices
import binascii
import sys
def main():
- # List all connected TREZORs on USB
- devices = HidTransport.enumerate()
+ # List all debuggable TREZORs
+ devices = [device for device in enumerate_devices() if hasattr(device, 'find_debug')]
# Check whether we found any
if len(devices) == 0:
diff --git a/tools/mnemonic_check.py b/tools/mnemonic_check.py
index 6c5c1fc55..1dce3feb6 100755
--- a/tools/mnemonic_check.py
+++ b/tools/mnemonic_check.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
-from __future__ import print_function
import binascii
import hashlib
import mnemonic
@@ -16,12 +15,6 @@ __doc__ = '''
without an internet connection).
'''
-# Python2 vs Python3
-try:
- input = raw_input
-except NameError:
- pass
-
def generate_entropy(strength, internal_entropy, external_entropy):
'''
diff --git a/tools/pwd_reader.py b/tools/pwd_reader.py
index 7fdea73fa..a979bd527 100755
--- a/tools/pwd_reader.py
+++ b/tools/pwd_reader.py
@@ -1,7 +1,4 @@
#!/usr/bin/env python3
-
-from __future__ import print_function
-
from binascii import hexlify, unhexlify
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
@@ -9,14 +6,10 @@ import hmac
import hashlib
import json
import os
-try:
- from urllib.parse import urlparse
-except:
- from urlparse import urlparse
- input = raw_input
+from urllib.parse import urlparse
from trezorlib.client import TrezorClient
-from trezorlib.transport_hid import HidTransport
+from trezorlib.transport import get_transport
# Return path by BIP-32
@@ -132,12 +125,13 @@ def printEntries(entries):
def main():
- devices = HidTransport.enumerate()
- if not devices:
- print('TREZOR is not plugged in. Please, connect TREZOR and retry.')
+ try:
+ transport = get_transport()
+ except Exception as e:
+ print(e)
return
- client = TrezorClient(devices[0])
+ client = TrezorClient(transport)
print()
print('Confirm operation on TREZOR')
diff --git a/tools/rng_entropy_collector.py b/tools/rng_entropy_collector.py
index 2ae738a32..1f4dcbcde 100755
--- a/tools/rng_entropy_collector.py
+++ b/tools/rng_entropy_collector.py
@@ -8,21 +8,14 @@ from __future__ import print_function
import io
import sys
from trezorlib.client import TrezorClient
-from trezorlib.device import TrezorDevice
-
-
-def get_client():
- devices = TrezorDevice.enumerate() # list all connected TREZORs on USB
- if len(devices) == 0: # check whether we found any
- return None
- transport = devices[0] # use first connected device
- return TrezorClient(transport) # creates object for communicating with TREZOR
+from trezorlib.transport import get_transport
def main():
- client = get_client()
- if not client:
- print('No TREZOR connected')
+ try:
+ client = TrezorClient(get_transport())
+ except Exception as e:
+ print(e)
return
arg1 = sys.argv[1] # output file
diff --git a/tools/signtest.py b/tools/signtest.py
index 4cc6bdefa..7ec2f4f5c 100755
--- a/tools/signtest.py
+++ b/tools/signtest.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-from __future__ import print_function
import binascii
import os
import random
@@ -12,8 +11,7 @@ import hashlib
from trezorlib.client import TrezorClient
from trezorlib.tx_api import TxApiTestnet
from trezorlib.tx_api import TxApiBitcoin
-from trezorlib.transport_hid import HidTransport
-from trezorlib.transport_bridge import BridgeTransport
+from trezorlib.transport import get_transport
def hash160(x):
@@ -152,16 +150,13 @@ def main():
numinputs = 100
sizeinputtx = 10
- # List all connected TREZORs on USB
- devices = HidTransport.enumerate()
-
- # Check whether we found any
- if len(devices) == 0:
- print('No TREZOR found')
+ # Use first connected device
+ try:
+ transport = get_transport()
+ except Exception as e:
+ print(e)
return
- # Use first connected device
- transport = devices[0]
print(transport)
txstore = MyTxApiBitcoin()
diff --git a/trezorctl b/trezorctl
index fb9d04867..aeea36d62 100755
--- a/trezorctl
+++ b/trezorctl
@@ -29,7 +29,7 @@ import os
import sys
from trezorlib.client import TrezorClient, TrezorClientVerbose, CallException, format_protobuf
-from trezorlib.device import TrezorDevice
+from trezorlib.transport import get_transport, enumerate_devices, TransportException
from trezorlib import messages as proto
from trezorlib import protobuf
from trezorlib.coins import coins_txapi
@@ -72,9 +72,24 @@ CHOICE_OUTPUT_SCRIPT_TYPE = ChoiceType({
def cli(ctx, path, verbose, is_json):
if ctx.invoked_subcommand != 'list':
if verbose:
- ctx.obj = lambda: TrezorClientVerbose(TrezorDevice.find_by_path(path))
+ cls = TrezorClientVerbose
else:
- ctx.obj = lambda: TrezorClient(TrezorDevice.find_by_path(path))
+ cls = TrezorClient
+
+ def get_device():
+ try:
+ device = get_transport(path, prefix_search=False)
+ except:
+ try:
+ device = get_transport(path, prefix_search=True)
+ except:
+ click.echo("Failed to find a TREZOR device.")
+ if path is not None:
+ click.echo("Using path: {}".format(path))
+ sys.exit(1)
+ return cls(device)
+
+ ctx.obj = get_device
@cli.resultcallback()
@@ -108,7 +123,7 @@ def print_result(res, path, verbose, is_json):
@cli.command(name='list', help='List connected TREZOR devices.')
def ls():
- return TrezorDevice.enumerate()
+ return enumerate_devices()
@cli.command(help='Show version of trezorctl/trezorlib.')
diff --git a/trezorlib/device.py b/trezorlib/device.py
index 2e3b42b90..7d62b142c 100644
--- a/trezorlib/device.py
+++ b/trezorlib/device.py
@@ -16,53 +16,24 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see .
+import warnings
-from .transport_bridge import BridgeTransport
-from .transport_hid import HidTransport
-from .transport_udp import UdpTransport
-from .transport_webusb import WebUsbTransport
+from .transport import enumerate_devices, get_transport
-class TrezorDevice(object):
+class TrezorDevice:
+ '''
+ This class is deprecated. (There is no reason for it to exist in the first
+ place, it is nothing but a collection of two functions.)
+ Instead, please use functions from the ``trezorlib.transport`` module.
+ '''
@classmethod
def enumerate(cls):
- devices = []
-
- for d in BridgeTransport.enumerate():
- devices.append(d)
-
- for d in UdpTransport.enumerate():
- devices.append(d)
-
- for d in HidTransport.enumerate():
- devices.append(d)
-
- for d in WebUsbTransport.enumerate():
- devices.append(d)
-
- return devices
+ warnings.warn('TrezorDevice is deprecated.', DeprecationWarning)
+ return enumerate_devices()
@classmethod
def find_by_path(cls, path):
- if path is None:
- try:
- return cls.enumerate()[0]
- except IndexError:
- raise Exception("No TREZOR device found")
-
- prefix = path.split(':')[0]
-
- if prefix == BridgeTransport.PATH_PREFIX:
- return BridgeTransport.find_by_path(path)
-
- if prefix == UdpTransport.PATH_PREFIX:
- return UdpTransport.find_by_path(path)
-
- if prefix == WebUsbTransport.PATH_PREFIX:
- return WebUsbTransport.find_by_path(path)
-
- if prefix == HidTransport.PATH_PREFIX:
- return HidTransport.find_by_path(path)
-
- raise Exception("Unknown path prefix '%s'" % prefix)
+ warnings.warn('TrezorDevice is deprecated.', DeprecationWarning)
+ return get_transport(path, prefix_search=False)
diff --git a/trezorlib/tests/device_tests/common.py b/trezorlib/tests/device_tests/common.py
index e702fdd99..0fffb7ae9 100644
--- a/trezorlib/tests/device_tests/common.py
+++ b/trezorlib/tests/device_tests/common.py
@@ -23,86 +23,23 @@ import pytest
import os
from trezorlib.client import TrezorClient, TrezorClientDebugLink
+from trezorlib.transport import get_transport
from trezorlib import tx_api
tests_dir = os.path.dirname(os.path.abspath(__file__))
tx_api.cache_dir = os.path.join(tests_dir, '../txcache')
-try:
- from trezorlib.transport_hid import HidTransport
- HID_ENABLED = True
-except ImportError as e:
- print('HID transport disabled:', e)
- HID_ENABLED = False
-
-try:
- from trezorlib.transport_webusb import WebUsbTransport
- WEBUSB_ENABLED = True
-except ImportError as e:
- print('WebUSB transport disabled:', e)
- WEBUSB_ENABLED = False
-
-try:
- from trezorlib.transport_pipe import PipeTransport
- PIPE_ENABLED = True
-except ImportError as e:
- print('PIPE transport disabled:', e)
- PIPE_ENABLED = False
-
-try:
- from trezorlib.transport_udp import UdpTransport
- UDP_ENABLED = True
-except ImportError as e:
- print('UDP transport disabled:', e)
- UDP_ENABLED = False
+def get_device():
+ path = os.environ.get('TREZOR_PATH')
+ return get_transport(path)
-def pipe_exists(path):
- import os
- import stat
- try:
- return stat.S_ISFIFO(os.stat(path).st_mode)
- except:
- return False
-
-
-def get_transport():
- if HID_ENABLED and HidTransport.enumerate():
- devices = HidTransport.enumerate()
- wirelink = devices[0]
- debuglink = devices[0].find_debug()
-
- elif WEBUSB_ENABLED and WebUsbTransport.enumerate():
- devices = WebUsbTransport.enumerate()
- wirelink = devices[0]
- debuglink = devices[0].find_debug()
-
- elif PIPE_ENABLED and pipe_exists('/tmp/pipe.trezor.to'):
- wirelink = PipeTransport('/tmp/pipe.trezor', False)
- debuglink = PipeTransport('/tmp/pipe.trezor_debug', False)
-
- elif UDP_ENABLED:
- wirelink = UdpTransport('127.0.0.1:21324')
- debuglink = UdpTransport('127.0.0.1:21325')
-
- return wirelink, debuglink
-
-
-if HID_ENABLED and HidTransport.enumerate():
- print('Using TREZOR')
-elif WEBUSB_ENABLED and WebUsbTransport.enumerate():
- print('Using TREZOR via WebUSB')
-elif PIPE_ENABLED and pipe_exists('/tmp/pipe.trezor.to'):
- print('Using Emulator (v1=pipe)')
-elif UDP_ENABLED:
- print('Using Emulator (v2=udp)')
-
-
-class TrezorTest(object):
+class TrezorTest:
def setup_method(self, method):
- wirelink, debuglink = get_transport()
+ wirelink = get_device()
+ debuglink = wirelink.find_debug()
self.client = TrezorClientDebugLink(wirelink)
self.client.set_debuglink(debuglink)
self.client.set_tx_api(tx_api.TxApiBitcoin)
diff --git a/trezorlib/transport.py b/trezorlib/transport.py
deleted file mode 100644
index 9d747c570..000000000
--- a/trezorlib/transport.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# This file is part of the TREZOR project.
-#
-# Copyright (C) 2012-2016 Marek Palatinus
-# Copyright (C) 2012-2016 Pavol Rusnak
-# Copyright (C) 2016 Jochen Hoenicke
-#
-# This library is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# 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 GNU Lesser General Public License
-# along with this library. If not, see .
-
-from __future__ import absolute_import
-
-
-class TransportException(Exception):
- pass
-
-
-class Transport(object):
-
- def __init__(self):
- self.session_counter = 0
-
- def session_begin(self):
- if self.session_counter == 0:
- self.open()
- self.session_counter += 1
-
- def session_end(self):
- self.session_counter = max(self.session_counter - 1, 0)
- if self.session_counter == 0:
- self.close()
-
- def open(self):
- raise NotImplementedError
-
- def close(self):
- raise NotImplementedError
diff --git a/trezorlib/transport/__init__.py b/trezorlib/transport/__init__.py
new file mode 100644
index 000000000..fb6d4aa32
--- /dev/null
+++ b/trezorlib/transport/__init__.py
@@ -0,0 +1,97 @@
+# This file is part of the TREZOR project.
+#
+# Copyright (C) 2012-2016 Marek Palatinus
+# Copyright (C) 2012-2016 Pavol Rusnak
+# Copyright (C) 2016 Jochen Hoenicke
+#
+# This library is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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 GNU Lesser General Public License
+# along with this library. If not, see .
+
+
+class TransportException(Exception):
+ pass
+
+
+class Transport(object):
+
+ def __init__(self):
+ self.session_counter = 0
+
+ def __str__(self):
+ return self.get_path()
+
+ def get_path(self):
+ return '{}:{}'.format(self.PATH_PREFIX, self.device)
+
+ def session_begin(self):
+ if self.session_counter == 0:
+ self.open()
+ self.session_counter += 1
+
+ def session_end(self):
+ self.session_counter = max(self.session_counter - 1, 0)
+ if self.session_counter == 0:
+ self.close()
+
+ def open(self):
+ raise NotImplementedError
+
+ def close(self):
+ raise NotImplementedError
+
+ @classmethod
+ def enumerate(cls):
+ raise NotImplementedError
+
+ @classmethod
+ def find_by_path(cls, path, prefix_search=False):
+ for device in cls.enumerate():
+ if path is None or device.get_path() == path \
+ or (prefix_search and device.get_path().startswith(path)):
+ return device
+
+ raise TransportException('{} device not found: {}'.format(cls.PATH_PREFIX, path))
+
+
+def all_transports():
+ from .bridge import BridgeTransport
+ from .hid import HidTransport
+ from .udp import UdpTransport
+ from .webusb import WebUsbTransport
+ return (BridgeTransport, HidTransport, UdpTransport, WebUsbTransport)
+
+
+def enumerate_devices():
+ return [device
+ for transport in all_transports()
+ for device in transport.enumerate()]
+
+
+def get_transport(path=None, prefix_search=False):
+ if path is None:
+ try:
+ return enumerate_devices()[0]
+ except IndexError:
+ raise Exception("No TREZOR device found") from None
+
+ # Find whether B is prefix of A (transport name is part of the path)
+ # or A is prefix of B (path is a prefix, or a name, of transport).
+ # This naively expects that no two transports have a common prefix.
+ def match_prefix(a, b):
+ return a.startswith(b) or b.startswith(a)
+
+ transports = [t for t in all_transports() if match_prefix(path, t.PATH_PREFIX)]
+ if transports:
+ return transports[0].find_by_path(path, prefix_search=prefix_search)
+
+ raise Exception("Unknown path prefix '%s'" % prefix)
diff --git a/trezorlib/transport_bridge.py b/trezorlib/transport/bridge.py
similarity index 84%
rename from trezorlib/transport_bridge.py
rename to trezorlib/transport/bridge.py
index 599f3556e..cb38ec64f 100644
--- a/trezorlib/transport_bridge.py
+++ b/trezorlib/transport/bridge.py
@@ -17,17 +17,15 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see .
-from __future__ import absolute_import
-
import requests
import binascii
from io import BytesIO
import struct
-from . import mapping
-from . import messages
-from . import protobuf
-from .transport import Transport, TransportException
+from .. import mapping
+from .. import messages
+from .. import protobuf
+from . import Transport, TransportException
TREZORD_HOST = 'http://127.0.0.1:21325'
@@ -45,16 +43,13 @@ class BridgeTransport(Transport):
HEADERS = {'Origin': 'https://python.trezor.io'}
def __init__(self, device):
- super(BridgeTransport, self).__init__()
+ super().__init__()
self.device = device
self.conn = requests.Session()
self.session = None
self.response = None
- def __str__(self):
- return self.get_path()
-
def get_path(self):
return '%s:%s' % (self.PATH_PREFIX, self.device['path'])
@@ -68,17 +63,6 @@ class BridgeTransport(Transport):
except:
return []
- @classmethod
- def find_by_path(cls, path):
- if isinstance(path, bytes):
- path = path.decode()
- path = path.replace('%s:' % cls.PATH_PREFIX, '')
-
- for transport in BridgeTransport.enumerate():
- if path is None or transport.device['path'] == path:
- return transport
- raise TransportException('Bridge device not found')
-
def open(self):
r = self.conn.post(TREZORD_HOST + '/acquire/%s/null' % self.device['path'], headers=self.HEADERS)
if r.status_code != 200:
diff --git a/trezorlib/transport_hid.py b/trezorlib/transport/hid.py
similarity index 89%
rename from trezorlib/transport_hid.py
rename to trezorlib/transport/hid.py
index 91f19b2f1..3a6884ca2 100644
--- a/trezorlib/transport_hid.py
+++ b/trezorlib/transport/hid.py
@@ -16,22 +16,20 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see .
-from __future__ import absolute_import
-
import time
import hid
import os
-from .protocol_v1 import ProtocolV1
-from .protocol_v2 import ProtocolV2
-from .transport import Transport, TransportException
+from ..protocol_v1 import ProtocolV1
+from ..protocol_v2 import ProtocolV2
+from . import Transport, TransportException
DEV_TREZOR1 = (0x534c, 0x0001)
DEV_TREZOR2 = (0x1209, 0x53c1)
DEV_TREZOR2_BL = (0x1209, 0x53c0)
-class HidHandle(object):
+class HidHandle:
def __init__(self, path):
self.path = path
@@ -79,9 +77,6 @@ class HidTransport(Transport):
self.hid = hid_handle
self.hid_version = None
- def __str__(self):
- return self.get_path()
-
def get_path(self):
return "%s:%s" % (self.PATH_PREFIX, self.device['path'].decode())
@@ -100,17 +95,6 @@ class HidTransport(Transport):
devices.append(HidTransport(dev))
return devices
- @classmethod
- def find_by_path(cls, path):
- if isinstance(path, str):
- path = path.encode()
- path = path.replace(b'%s:' % cls.PATH_PREFIX.encode(), b'')
-
- for transport in HidTransport.enumerate():
- if path is None or transport.device['path'] == path:
- return transport
- raise TransportException('HID device not found')
-
def find_debug(self):
if isinstance(self.protocol, ProtocolV2):
# For v2 protocol, lets use the same HID interface, but with a different session
diff --git a/trezorlib/transport_udp.py b/trezorlib/transport/udp.py
similarity index 73%
rename from trezorlib/transport_udp.py
rename to trezorlib/transport/udp.py
index ad520f8d5..7bbad169c 100644
--- a/trezorlib/transport_udp.py
+++ b/trezorlib/transport/udp.py
@@ -16,14 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see .
-from __future__ import absolute_import
-
import os
import socket
-from .protocol_v1 import ProtocolV1
-from .protocol_v2 import ProtocolV2
-from .transport import Transport, TransportException
+from ..protocol_v1 import ProtocolV1
+from ..protocol_v2 import ProtocolV2
+from . import Transport, TransportException
class UdpTransport(Transport):
@@ -48,26 +46,41 @@ class UdpTransport(Transport):
self.protocol = protocol
self.socket = None
- def __str__(self):
- return self.get_path()
-
def get_path(self):
return "%s:%s:%s" % ((self.PATH_PREFIX,) + self.device)
- @staticmethod
- def enumerate():
- devices = []
- d = UdpTransport("%s:%d" % (UdpTransport.DEFAULT_HOST, UdpTransport.DEFAULT_PORT))
- d.open()
- if d._ping():
- devices.append(d)
- d.close()
- return devices
+ def find_debug(self):
+ host, port = self.device
+ return UdpTransport('{}:{}'.format(host, port + 1), self.protocol)
@classmethod
- def find_by_path(cls, path):
- path = path.replace('%s:' % cls.PATH_PREFIX, '')
- return UdpTransport(path)
+ def _try_path(cls, path):
+ d = cls(path)
+ try:
+ d.open()
+ if d._ping():
+ return d
+ else:
+ raise TransportException('No TREZOR device found at address {}'.format(path))
+ finally:
+ d.close()
+
+ @classmethod
+ def enumerate(cls):
+ devices = []
+ default_path = '{}:{}'.format(cls.DEFAULT_HOST, cls.DEFAULT_PORT)
+ try:
+ return [cls._try_path(default_path)]
+ except TransportException:
+ return []
+
+ @classmethod
+ def find_by_path(cls, path, prefix_search=False):
+ if prefix_search:
+ return super().find_by_path(path, prefix_search)
+ else:
+ path = path.replace('{}:'.format(cls.PATH_PREFIX), '')
+ return cls._try_path(path)
def open(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
diff --git a/trezorlib/transport_webusb.py b/trezorlib/transport/webusb.py
similarity index 89%
rename from trezorlib/transport_webusb.py
rename to trezorlib/transport/webusb.py
index 1e8d0b433..44b5dafb5 100644
--- a/trezorlib/transport_webusb.py
+++ b/trezorlib/transport/webusb.py
@@ -16,16 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this library. If not, see .
-from __future__ import absolute_import
-
import time
import os
import atexit
import usb1
-from .protocol_v1 import ProtocolV1
-from .protocol_v2 import ProtocolV2
-from .transport import Transport, TransportException
+from ..protocol_v1 import ProtocolV1
+from ..protocol_v2 import ProtocolV2
+from . import Transport, TransportException
DEV_TREZOR1 = (0x534c, 0x0001)
DEV_TREZOR2 = (0x1209, 0x53c1)
@@ -37,7 +35,7 @@ DEBUG_INTERFACE = 1
DEBUG_ENDPOINT = 2
-class WebUsbHandle(object):
+class WebUsbHandle:
def __init__(self, device):
self.device = device
@@ -88,9 +86,6 @@ class WebUsbTransport(Transport):
self.handle = handle
self.debug = debug
- def __str__(self):
- return self.get_path()
-
def get_path(self):
return "%s:%s" % (self.PATH_PREFIX, dev_to_str(self.device))
@@ -106,17 +101,18 @@ class WebUsbTransport(Transport):
continue
if not is_vendor_class(dev):
continue
- devices.append(WebUsbTransport(dev))
+ try:
+ # workaround for issue #223:
+ # on certain combinations of Windows USB drivers and libusb versions,
+ # Trezor is returned twice (possibly because Windows know it as both
+ # a HID and a WebUSB device), and one of the returned devices is
+ # non-functional.
+ dev.getProduct()
+ devices.append(WebUsbTransport(dev))
+ except usb1.USBErrorNotSupported:
+ pass
return devices
- @classmethod
- def find_by_path(cls, path):
- path = path.replace('%s:' % cls.PATH_PREFIX, '') # Remove prefix from __str__()
- for transport in WebUsbTransport.enumerate():
- if path is None or dev_to_str(transport.device) == path:
- return transport
- raise TransportException('WebUSB device not found')
-
def find_debug(self):
if isinstance(self.protocol, ProtocolV2):
# TODO test this