diff --git a/hwilib/devices/bitbox02.py b/hwilib/devices/bitbox02.py index 04e7036f9..2a7fbab1a 100644 --- a/hwilib/devices/bitbox02.py +++ b/hwilib/devices/bitbox02.py @@ -176,6 +176,10 @@ def enumerate(password: str = "") -> List[Dict[str, object]]: path = device_info["path"].decode() client = Bitbox02Client(path) client.set_noise_config(SilentNoiseConfig()) + d_data: Dict[str, object] = {} + bb02 = None + with handle_errors(common_err_msgs["enumerate"], d_data): + bb02 = client.init(expect_initialized=None) version, platform, edition, unlocked = bitbox02.BitBox02.get_info( client.transport ) @@ -188,25 +192,32 @@ def enumerate(password: str = "") -> List[Dict[str, object]]: assert isinstance(edition, BitBox02Edition) - d_data = { - "type": "bitbox02", - "path": path, - "model": { - BitBox02Edition.MULTI: "bitbox02_multi", - BitBox02Edition.BTCONLY: "bitbox02_btconly", - }[edition], - "needs_pin_sent": False, - "needs_passphrase_sent": False, - } + d_data.update( + { + "type": "bitbox02", + "path": path, + "model": { + BitBox02Edition.MULTI: "bitbox02_multi", + BitBox02Edition.BTCONLY: "bitbox02_btconly", + }[edition], + "needs_pin_sent": False, + "needs_passphrase_sent": False, + } + ) - with handle_errors(common_err_msgs["enumerate"], d_data): - if not unlocked: - raise DeviceNotReadyError( - "Please load wallet to unlock." - if _using_external_gui - else "Please use any subcommand to unlock" - ) - d_data["fingerprint"] = client.get_master_fingerprint_hex() + if bb02 is not None: + with handle_errors(common_err_msgs["enumerate"], d_data): + if not bb02.device_info()["initialized"]: + raise DeviceNotReadyError( + "BitBox02 is not initialized. Please initialize it using the BitBoxApp." + ) + elif not unlocked: + raise DeviceNotReadyError( + "Please load wallet to unlock." + if _using_external_gui + else "Please use any subcommand to unlock" + ) + d_data["fingerprint"] = client.get_master_fingerprint_hex() result.append(d_data) @@ -246,7 +257,7 @@ def __init__(self, path: str, password: str = "", expert: bool = False) -> None: Initializes a new BitBox02 client instance. """ super().__init__(path, password=password, expert=expert) - if password != "": + if password: raise BadArgumentError( "The BitBox02 does not accept a passphrase from the host. Please enable the passphrase option and enter the passphrase on the device during unlock." ) @@ -264,7 +275,7 @@ def __init__(self, path: str, password: str = "", expert: bool = False) -> None: def set_noise_config(self, noise_config: BitBoxNoiseConfig) -> None: self.noise_config = noise_config - def init(self, expect_initialized: bool = True) -> bitbox02.BitBox02: + def init(self, expect_initialized: Optional[bool] = True) -> bitbox02.BitBox02: if self.bb02 is not None: return self.bb02 @@ -282,14 +293,17 @@ def init(self, expect_initialized: bool = True) -> bitbox02.BitBox02: raise self.bb02 = bb02 is_initialized = bb02.device_info()["initialized"] - if expect_initialized: - if not is_initialized: - raise HWWError( - "The BitBox02 must be initialized first.", - DEVICE_NOT_INITIALIZED, + if expect_initialized is not None: + if expect_initialized: + if not is_initialized: + raise HWWError( + "The BitBox02 must be initialized first.", + DEVICE_NOT_INITIALIZED, + ) + elif is_initialized: + raise UnavailableActionError( + "The BitBox02 must be wiped before setup." ) - elif is_initialized: - raise UnavailableActionError("The BitBox02 must be wiped before setup.") return bb02 raise Exception( diff --git a/hwilib/devices/ledger.py b/hwilib/devices/ledger.py index 1f9eb9dbd..4ff3e7e52 100644 --- a/hwilib/devices/ledger.py +++ b/hwilib/devices/ledger.py @@ -40,10 +40,14 @@ SIMULATOR_PATH = 'tcp:127.0.0.1:9999' LEDGER_VENDOR_ID = 0x2c97 -LEDGER_DEVICE_IDS = [ - 0x0001, # Ledger Nano S - 0x0004, # Ledger Nano X -] +LEDGER_MODEL_IDS = { + 0x10: "ledger_nano_s", + 0x40: "ledger_nano_x" +} +LEDGER_LEGACY_PRODUCT_IDS = { + 0x0001: "ledger_nano_s", + 0x0004: "ledger_nano_x" +} # minimal checking of string keypath def check_keypath(key_path): @@ -386,9 +390,8 @@ def toggle_passphrase(self): def enumerate(password=''): results = [] devices = [] - for device_id in LEDGER_DEVICE_IDS: - devices.extend(hid.enumerate(LEDGER_VENDOR_ID, device_id)) - devices.append({'path': SIMULATOR_PATH.encode(), 'interface_number': 0, 'product_id': 1}) + devices.extend(hid.enumerate(LEDGER_VENDOR_ID, 0)) + devices.append({'path': SIMULATOR_PATH.encode(), 'interface_number': 0, 'product_id': 0x1000}) for d in devices: if ('interface_number' in d and d['interface_number'] == 0 @@ -397,7 +400,13 @@ def enumerate(password=''): path = d['path'].decode() d_data['type'] = 'ledger' - d_data['model'] = 'ledger_nano_x' if d['product_id'] == 0x0004 else 'ledger_nano_s' + model = d['product_id'] >> 8 + if model in LEDGER_MODEL_IDS.keys(): + d_data['model'] = LEDGER_MODEL_IDS[model] + elif d['product_id'] in LEDGER_LEGACY_PRODUCT_IDS.keys(): + d_data['model'] = LEDGER_LEGACY_PRODUCT_IDS[d['product_id']] + else: + continue d_data['path'] = path if path == SIMULATOR_PATH: