mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 07:28:10 +00:00
feat(python): add support for unrecognized Trezor models (fixes #3993)
This commit is contained in:
parent
dfdd44becb
commit
008b5df432
1
python/.changelog.d/3993.added
Normal file
1
python/.changelog.d/3993.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Added support for Trezor models not known by the current version of the library.
|
1
python/.changelog.d/3993.deprecated
Normal file
1
python/.changelog.d/3993.deprecated
Normal file
@ -0,0 +1 @@
|
|||||||
|
Calling `models.by_internal_name(None)` is deprecated -- check the presence of `internal_model` explicitly before passing it in.
|
@ -273,19 +273,13 @@ class TrezorClient(Generic[UI]):
|
|||||||
"""Update internal fields based on passed-in Features message."""
|
"""Update internal fields based on passed-in Features message."""
|
||||||
|
|
||||||
if not self.model:
|
if not self.model:
|
||||||
# Trezor Model One bootloader 1.8.0 or older does not send model name
|
if features.internal_model is not None:
|
||||||
model = models.by_internal_name(features.internal_model)
|
self.model = models.by_internal_name(features.internal_model)
|
||||||
if model is None:
|
else:
|
||||||
model = models.by_name(features.model or "1")
|
self.model = models.by_name(features.model)
|
||||||
if model is None:
|
|
||||||
raise RuntimeError(
|
|
||||||
"Unsupported Trezor model"
|
|
||||||
f" (internal_model: {features.internal_model}, model: {features.model})"
|
|
||||||
)
|
|
||||||
self.model = model
|
|
||||||
|
|
||||||
if features.vendor not in self.model.vendors:
|
if features.vendor not in self.model.vendors:
|
||||||
raise RuntimeError("Unsupported device")
|
raise exceptions.TrezorException(f"Unrecognized vendor: {features.vendor}")
|
||||||
|
|
||||||
self.features = features
|
self.features = features
|
||||||
self.version = (
|
self.version = (
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
# You should have received a copy of the License along with this library.
|
# 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>.
|
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import warnings
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Collection, Optional, Tuple
|
from typing import Collection, Tuple
|
||||||
|
|
||||||
from . import mapping
|
from . import mapping
|
||||||
|
|
||||||
@ -36,12 +39,17 @@ class TrezorModel:
|
|||||||
|
|
||||||
# ==== internal names ====
|
# ==== internal names ====
|
||||||
|
|
||||||
|
USBID_TREZOR_ONE = (0x534C, 0x0001)
|
||||||
|
USBID_TREZOR_CORE = (0x1209, 0x53C1)
|
||||||
|
USBID_TREZOR_CORE_BOOTLOADER = (0x1209, 0x53C0)
|
||||||
|
|
||||||
|
|
||||||
T1B1 = TrezorModel(
|
T1B1 = TrezorModel(
|
||||||
name="1",
|
name="1",
|
||||||
internal_name="T1B1",
|
internal_name="T1B1",
|
||||||
minimum_version=(1, 8, 0),
|
minimum_version=(1, 8, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x534C, 0x0001),),
|
usb_ids=(USBID_TREZOR_ONE,),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -50,7 +58,7 @@ T2T1 = TrezorModel(
|
|||||||
internal_name="T2T1",
|
internal_name="T2T1",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,7 +67,7 @@ T2B1 = TrezorModel(
|
|||||||
internal_name="T2B1",
|
internal_name="T2B1",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,7 +76,7 @@ T3T1 = TrezorModel(
|
|||||||
internal_name="T3T1",
|
internal_name="T3T1",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -77,7 +85,7 @@ T3B1 = TrezorModel(
|
|||||||
internal_name="T3B1",
|
internal_name="T3B1",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -86,7 +94,7 @@ T3W1 = TrezorModel(
|
|||||||
internal_name="T3W1",
|
internal_name="T3W1",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -95,7 +103,7 @@ DISC1 = TrezorModel(
|
|||||||
internal_name="D001",
|
internal_name="D001",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -104,10 +112,24 @@ DISC2 = TrezorModel(
|
|||||||
internal_name="D002",
|
internal_name="D002",
|
||||||
minimum_version=(2, 1, 0),
|
minimum_version=(2, 1, 0),
|
||||||
vendors=VENDORS,
|
vendors=VENDORS,
|
||||||
usb_ids=((0x1209, 0x53C1), (0x1209, 0x53C0)),
|
usb_ids=(USBID_TREZOR_CORE, USBID_TREZOR_CORE_BOOTLOADER),
|
||||||
default_mapping=mapping.DEFAULT_MAPPING,
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ==== unknown model ====
|
||||||
|
|
||||||
|
UNKNOWN_MODEL = TrezorModel(
|
||||||
|
name="Unknown Trezor model",
|
||||||
|
internal_name="????",
|
||||||
|
minimum_version=(0, 0, 0),
|
||||||
|
vendors=VENDORS,
|
||||||
|
usb_ids=(),
|
||||||
|
default_mapping=mapping.DEFAULT_MAPPING,
|
||||||
|
)
|
||||||
|
"""Unknown model is a placeholder for detected devices that respond to the Trezor wire
|
||||||
|
protocol, but are not in the list of known models -- presumably models newer than the
|
||||||
|
current library version."""
|
||||||
|
|
||||||
# ==== model based names ====
|
# ==== model based names ====
|
||||||
|
|
||||||
TREZOR_ONE = T1B1
|
TREZOR_ONE = T1B1
|
||||||
@ -121,19 +143,20 @@ TREZOR_DISC2 = DISC2
|
|||||||
TREZORS = frozenset({T1B1, T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
|
TREZORS = frozenset({T1B1, T2T1, T2B1, T3T1, T3B1, T3W1, DISC1, DISC2})
|
||||||
|
|
||||||
|
|
||||||
def by_name(name: Optional[str]) -> Optional[TrezorModel]:
|
def by_name(name: str | None) -> TrezorModel:
|
||||||
if name is None:
|
if name is None:
|
||||||
return T1B1
|
return T1B1
|
||||||
for model in TREZORS:
|
for model in TREZORS:
|
||||||
if model.name == name:
|
if model.name == name:
|
||||||
return model
|
return model
|
||||||
return None
|
return UNKNOWN_MODEL
|
||||||
|
|
||||||
|
|
||||||
def by_internal_name(name: Optional[str]) -> Optional[TrezorModel]:
|
def by_internal_name(name: str) -> TrezorModel:
|
||||||
if name is None:
|
if name is None:
|
||||||
return None
|
warnings.warn("by_internal_name will no longer accept None", stacklevel=2)
|
||||||
|
return None # type: ignore [incompatible with "TrezorModel"]
|
||||||
for model in TREZORS:
|
for model in TREZORS:
|
||||||
if model.internal_name == name:
|
if model.internal_name == name:
|
||||||
return model
|
return model
|
||||||
return None
|
return UNKNOWN_MODEL
|
||||||
|
@ -229,7 +229,9 @@ class ModelsFilter:
|
|||||||
assert isinstance(marker, str)
|
assert isinstance(marker, str)
|
||||||
if marker in cls.MODEL_SHORTCUTS:
|
if marker in cls.MODEL_SHORTCUTS:
|
||||||
selected_models |= cls.MODEL_SHORTCUTS[marker]
|
selected_models |= cls.MODEL_SHORTCUTS[marker]
|
||||||
elif (model := models.by_internal_name(marker.upper())) is not None:
|
elif (
|
||||||
|
model := models.by_internal_name(marker.upper())
|
||||||
|
) is not models.UNKNOWN_MODEL:
|
||||||
selected_models.add(model)
|
selected_models.add(model)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unknown model: {marker}")
|
raise ValueError(f"Unknown model: {marker}")
|
||||||
|
Loading…
Reference in New Issue
Block a user