feat(core): implement basic R emulator

Can be built by `TREZOR_MODEL=R make build_unix`, `make build_unix_frozen` does not work yet.

All the dialogs are not very pretty, they are just meant to work.
pull/2243/head
grdddj 2 years ago committed by matejcik
parent 396d81f272
commit 6b5f578d02

@ -0,0 +1 @@
Add model R emulator

@ -97,11 +97,11 @@ env.Replace(
env.Replace( env.Replace(
TREZOR_MODEL=TREZOR_MODEL, ) TREZOR_MODEL=TREZOR_MODEL, )
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 ' CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx' CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft ' CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx' CPU_MODEL = 'STM32F405xx'

@ -123,11 +123,11 @@ env.Replace(
env.Replace( env.Replace(
TREZOR_MODEL=TREZOR_MODEL, ) TREZOR_MODEL=TREZOR_MODEL, )
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 ' CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx' CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft ' CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx' CPU_MODEL = 'STM32F405xx'

@ -123,11 +123,11 @@ env.Replace(
env.Replace( env.Replace(
TREZOR_MODEL=TREZOR_MODEL, ) TREZOR_MODEL=TREZOR_MODEL, )
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 ' CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx' CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft ' CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx' CPU_MODEL = 'STM32F405xx'

@ -6,7 +6,7 @@ import os
BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0')
EVERYTHING = BITCOIN_ONLY != '1' EVERYTHING = BITCOIN_ONLY != '1'
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
UI2 = ARGUMENTS.get('UI2', '0') == '1' or TREZOR_MODEL == '1' UI2 = ARGUMENTS.get('UI2', '0') == '1' or TREZOR_MODEL in ('1', 'R')
FEATURE_FLAGS = { FEATURE_FLAGS = {
"RDI": True, "RDI": True,
@ -151,7 +151,7 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]:
SOURCE_MOD += [ SOURCE_MOD += [
'embed/extmod/modtrezorio/modtrezorio.c', 'embed/extmod/modtrezorio/modtrezorio.c',
] ]
if TREZOR_MODEL == "T": if TREZOR_MODEL in ("T",):
SOURCE_MOD += [ SOURCE_MOD += [
'embed/extmod/modtrezorio/ff.c', 'embed/extmod/modtrezorio/ff.c',
'embed/extmod/modtrezorio/ffunicode.c', 'embed/extmod/modtrezorio/ffunicode.c',
@ -380,13 +380,13 @@ SOURCE_TREZORHAL = [
'embed/trezorhal/util.s', 'embed/trezorhal/util.s',
'embed/trezorhal/vectortable.s', 'embed/trezorhal/vectortable.s',
] ]
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T',):
SOURCE_TREZORHAL += [ SOURCE_TREZORHAL += [
'embed/trezorhal/sbu.c', 'embed/trezorhal/sbu.c',
'embed/trezorhal/sdcard.c', 'embed/trezorhal/sdcard.c',
'embed/trezorhal/touch.c', 'embed/trezorhal/touch.c',
] ]
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1', 'R'):
SOURCE_TREZORHAL += [ SOURCE_TREZORHAL += [
'embed/trezorhal/button.c', 'embed/trezorhal/button.c',
] ]
@ -433,13 +433,13 @@ env.Replace(
env.Replace( env.Replace(
TREZOR_MODEL=TREZOR_MODEL, ) TREZOR_MODEL=TREZOR_MODEL, )
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 ' CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx' CPU_MODEL = 'STM32F427xx'
LD_VARIANT = '' LD_VARIANT = ''
RUST_TARGET = 'thumbv7em-none-eabihf' RUST_TARGET = 'thumbv7em-none-eabihf'
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft ' CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx' CPU_MODEL = 'STM32F405xx'
@ -562,7 +562,7 @@ if FROZEN:
if EVERYTHING: if EVERYTHING:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/altcoin.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/altcoin.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/webauthn.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/webauthn.py'))
if TREZOR_MODEL == 'T' and UI2: if TREZOR_MODEL in ('T') and UI2:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/__init__.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/__init__.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/reset.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/reset.py'))
@ -570,7 +570,7 @@ if FROZEN:
if EVERYTHING: if EVERYTHING:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/altcoin.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/altcoin.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/webauthn.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/webauthn.py'))
elif TREZOR_MODEL == 'T': elif TREZOR_MODEL in ('T',):
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/components/tt/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/components/tt/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/__init__.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/__init__.py'))
@ -579,10 +579,12 @@ if FROZEN:
if EVERYTHING: if EVERYTHING:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/altcoin.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/altcoin.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/webauthn.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/webauthn.py'))
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/components/t1/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/t1.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/t1.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
elif TREZOR_MODEL in ('R',):
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tr.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tr/__init__.py'))
else: else:
raise ValueError('Unknown Trezor model') raise ValueError('Unknown Trezor model')
@ -614,7 +616,7 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py', SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py',
exclude=[ exclude=[
SOURCE_PY_DIR + 'apps/management/sd_protect.py', SOURCE_PY_DIR + 'apps/management/sd_protect.py',
] if TREZOR_MODEL != 'T' else []) ] if TREZOR_MODEL not in ('T',) else [])
) )
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py'))
@ -727,8 +729,10 @@ def cargo_build():
profile = '--release' profile = '--release'
else: else:
profile = '' profile = ''
if TREZOR_MODEL == "1": if TREZOR_MODEL in ("1",):
features = ["model_t1"] features = ["model_t1"]
elif TREZOR_MODEL in ("R",):
features = ["model_tr"]
else: else:
features = ["model_tt"] features = ["model_tt"]
if BITCOIN_ONLY == "1": if BITCOIN_ONLY == "1":
@ -796,7 +800,7 @@ program_elf = env.Command(
env.Depends(program_elf, rust) env.Depends(program_elf, rust)
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
action_bin=[ action_bin=[
'$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data --pad-to 0x08100000 $SOURCE ${TARGET}.p1', '$OBJCOPY -O binary -j .vendorheader -j .header -j .flash -j .data --pad-to 0x08100000 $SOURCE ${TARGET}.p1',
'$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2', '$OBJCOPY -O binary -j .flash2 $SOURCE ${TARGET}.p2',
@ -804,7 +808,7 @@ if TREZOR_MODEL == 'T':
'$HEADERTOOL -h $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''), '$HEADERTOOL -h $TARGET ' + ('-D' if ARGUMENTS.get('PRODUCTION', '0') == '0' else ''),
'$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6', '$DD if=$TARGET of=${TARGET}.p1 skip=0 bs=128k count=6',
] ]
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
action_bin=[ action_bin=[
'$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET', '$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET',
'../legacy/bootloader/firmware_sign.py -f $TARGET', '../legacy/bootloader/firmware_sign.py -f $TARGET',

@ -101,11 +101,11 @@ env.Replace(
env.Replace( env.Replace(
TREZOR_MODEL=TREZOR_MODEL, ) TREZOR_MODEL=TREZOR_MODEL, )
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 ' CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx' CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft ' CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx' CPU_MODEL = 'STM32F405xx'

@ -95,11 +95,11 @@ env.Replace(
env.Replace( env.Replace(
TREZOR_MODEL=TREZOR_MODEL, ) TREZOR_MODEL=TREZOR_MODEL, )
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T', 'R'):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16'
CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 ' CPU_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx' CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft' CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft ' CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx' CPU_MODEL = 'STM32F405xx'

@ -6,7 +6,7 @@ import os
BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0') BITCOIN_ONLY = ARGUMENTS.get('BITCOIN_ONLY', '0')
EVERYTHING = BITCOIN_ONLY != '1' EVERYTHING = BITCOIN_ONLY != '1'
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
UI2 = ARGUMENTS.get('UI2', '0') == '1' or TREZOR_MODEL == '1' UI2 = ARGUMENTS.get('UI2', '0') == '1' or TREZOR_MODEL in ('1', 'R')
FEATURE_FLAGS = { FEATURE_FLAGS = {
"SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot) "SECP256K1_ZKP": True, # required for trezor.crypto.curve.bip340 (BIP340/Taproot)
@ -147,7 +147,7 @@ if FEATURE_FLAGS["SECP256K1_ZKP"]:
SOURCE_MOD += [ SOURCE_MOD += [
'embed/extmod/modtrezorio/modtrezorio.c', 'embed/extmod/modtrezorio/modtrezorio.c',
] ]
if TREZOR_MODEL == "T": if TREZOR_MODEL in ("T",):
SOURCE_MOD += [ SOURCE_MOD += [
'embed/extmod/modtrezorio/ff.c', 'embed/extmod/modtrezorio/ff.c',
'embed/extmod/modtrezorio/ffunicode.c', 'embed/extmod/modtrezorio/ffunicode.c',
@ -353,7 +353,7 @@ SOURCE_UNIX = [
'vendor/micropython/ports/unix/input.c', 'vendor/micropython/ports/unix/input.c',
'vendor/micropython/ports/unix/unix_mphal.c', 'vendor/micropython/ports/unix/unix_mphal.c',
] ]
if TREZOR_MODEL == 'T': if TREZOR_MODEL in ('T',):
SOURCE_UNIX += [ SOURCE_UNIX += [
'embed/unix/sbu.c', 'embed/unix/sbu.c',
'embed/unix/sdcard.c', 'embed/unix/sdcard.c',
@ -525,7 +525,7 @@ if FROZEN:
if EVERYTHING: if EVERYTHING:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/altcoin.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/altcoin.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/webauthn.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/webauthn.py'))
if TREZOR_MODEL == 'T' and UI2: if TREZOR_MODEL in ('T',) and UI2:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/__init__.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/__init__.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/reset.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/reset.py'))
@ -533,7 +533,7 @@ if FROZEN:
if EVERYTHING: if EVERYTHING:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/altcoin.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/altcoin.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/webauthn.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt_v2/webauthn.py'))
elif TREZOR_MODEL == 'T': elif TREZOR_MODEL in ('T',):
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/components/tt/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/components/tt/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tt.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/__init__.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/__init__.py'))
@ -542,10 +542,12 @@ if FROZEN:
if EVERYTHING: if EVERYTHING:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/altcoin.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/altcoin.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/webauthn.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tt/webauthn.py'))
elif TREZOR_MODEL == '1': elif TREZOR_MODEL in ('1',):
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/components/t1/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/t1.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/t1.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/t1.py'))
elif TREZOR_MODEL in ('R',):
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/constants/tr.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/ui/layouts/tr/__init__.py'))
else: else:
raise ValueError('Unknown Trezor model') raise ValueError('Unknown Trezor model')
@ -577,7 +579,7 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py', SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*.py',
exclude=[ exclude=[
SOURCE_PY_DIR + 'apps/management/sd_protect.py', SOURCE_PY_DIR + 'apps/management/sd_protect.py',
] if TREZOR_MODEL != 'T' else []) ] if TREZOR_MODEL not in ('T',) else [])
) )
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/management/*/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py')) SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/misc/*.py'))
@ -689,8 +691,10 @@ RUST_LIB = 'trezor_lib'
RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a' RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a'
def cargo_build(): def cargo_build():
if TREZOR_MODEL == "1": if TREZOR_MODEL in ('1',):
features = ["model_t1"] features = ["model_t1"]
elif TREZOR_MODEL in ('R',):
features = ["model_tr"]
else: else:
features = ["model_tt"] features = ["model_tt"]
if BITCOIN_ONLY == "1": if BITCOIN_ONLY == "1":

@ -25,7 +25,7 @@
#define NORCOW_HEADER_LEN 0 #define NORCOW_HEADER_LEN 0
#define NORCOW_SECTOR_COUNT 2 #define NORCOW_SECTOR_COUNT 2
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R
#define NORCOW_SECTOR_SIZE (64 * 1024) #define NORCOW_SECTOR_SIZE (64 * 1024)
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1
#define NORCOW_SECTOR_SIZE (16 * 1024) #define NORCOW_SECTOR_SIZE (16 * 1024)

@ -110,7 +110,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref,
return mp_const_true; return mp_const_true;
} }
} }
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
else if (iface == BUTTON_IFACE) { else if (iface == BUTTON_IFACE) {
const uint32_t evt = button_read(); const uint32_t evt = button_read();
if (evt & (BTN_EVT_DOWN | BTN_EVT_UP)) { if (evt & (BTN_EVT_DOWN | BTN_EVT_UP)) {

@ -81,7 +81,7 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_TOUCH_START), MP_ROM_INT((TOUCH_START >> 24) & 0xFFU)}, {MP_ROM_QSTR(MP_QSTR_TOUCH_START), MP_ROM_INT((TOUCH_START >> 24) & 0xFFU)},
{MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), MP_ROM_INT((TOUCH_MOVE >> 24) & 0xFFU)}, {MP_ROM_QSTR(MP_QSTR_TOUCH_MOVE), MP_ROM_INT((TOUCH_MOVE >> 24) & 0xFFU)},
{MP_ROM_QSTR(MP_QSTR_TOUCH_END), MP_ROM_INT((TOUCH_END >> 24) & 0xFFU)}, {MP_ROM_QSTR(MP_QSTR_TOUCH_END), MP_ROM_INT((TOUCH_END >> 24) & 0xFFU)},
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
{MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_INT(BUTTON_IFACE)}, {MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_INT(BUTTON_IFACE)},
{MP_ROM_QSTR(MP_QSTR_BUTTON_PRESSED), {MP_ROM_QSTR(MP_QSTR_BUTTON_PRESSED),
MP_ROM_INT((BTN_EVT_DOWN >> 24) & 0x3U)}, MP_ROM_INT((BTN_EVT_DOWN >> 24) & 0x3U)},

@ -39,7 +39,7 @@
#define TOUCH_OFFSET_Y 110 #define TOUCH_OFFSET_Y 110
#endif #endif
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#define WINDOW_WIDTH 200 #define WINDOW_WIDTH 200
#define WINDOW_HEIGHT 340 #define WINDOW_HEIGHT 340
@ -76,7 +76,7 @@ static struct {
#define PIXELDATA_DIRTY() #define PIXELDATA_DIRTY()
void PIXELDATA(uint16_t c) { void PIXELDATA(uint16_t c) {
#if defined TREZOR_MODEL_1 #if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
// set to white if highest bits of all R, G, B values are set to 1 // set to white if highest bits of all R, G, B values are set to 1
// bin(10000 100000 10000) = hex(0x8410) // bin(10000 100000 10000) = hex(0x8410)
// otherwise set to black // otherwise set to black
@ -181,6 +181,10 @@ void display_init(void) {
#include "background_1.h" #include "background_1.h"
BACKGROUND = IMG_LoadTexture_RW( BACKGROUND = IMG_LoadTexture_RW(
RENDERER, SDL_RWFromMem(background_1_jpg, background_1_jpg_len), 0); RENDERER, SDL_RWFromMem(background_1_jpg, background_1_jpg_len), 0);
#elif defined TREZOR_MODEL_R
#include "background_R.h"
BACKGROUND = IMG_LoadTexture_RW(
RENDERER, SDL_RWFromMem(background_R_jpg, background_R_jpg_len), 0);
#endif #endif
#endif #endif
if (BACKGROUND) { if (BACKGROUND) {

@ -75,7 +75,7 @@
#endif #endif
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#ifdef TREZOR_FONT_NORMAL_ENABLE #ifdef TREZOR_FONT_NORMAL_ENABLE
#include "font_pixeloperator_regular_8.h" #include "font_pixeloperator_regular_8.h"
@ -117,7 +117,7 @@ static struct { int x, y; } DISPLAY_OFFSET;
#else #else
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T
#include "display-stm32_T.h" #include "display-stm32_T.h"
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#include "display-stm32_1.h" #include "display-stm32_1.h"
#else #else
#error Unknown Trezor model #error Unknown Trezor model
@ -917,7 +917,7 @@ int display_orientation(int degrees) {
if (degrees != DISPLAY_ORIENTATION) { if (degrees != DISPLAY_ORIENTATION) {
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T
if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) { if (degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270) {
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
if (degrees == 0 || degrees == 180) { if (degrees == 0 || degrees == 180) {
#else #else
#error Unknown Trezor model #error Unknown Trezor model
@ -930,7 +930,7 @@ int display_orientation(int degrees) {
} }
int display_backlight(int val) { int display_backlight(int val) {
#if defined TREZOR_MODEL_1 #if defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
val = 255; val = 255;
#endif #endif
if (DISPLAY_BACKLIGHT != val && val >= 0 && val <= 255) { if (DISPLAY_BACKLIGHT != val && val >= 0 && val <= 255) {

@ -40,6 +40,14 @@
#define DISPLAY_RESY 64 #define DISPLAY_RESY 64
#define TREZOR_FONT_BPP 1 #define TREZOR_FONT_BPP 1
#elif defined TREZOR_MODEL_R
#define MAX_DISPLAY_RESX 128
#define MAX_DISPLAY_RESY 128
#define DISPLAY_RESX 128
#define DISPLAY_RESY 128
#define TREZOR_FONT_BPP 1
#else #else
#error Unknown Trezor model #error Unknown Trezor model
#endif #endif

@ -283,6 +283,8 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR_1)}, {MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR_1)},
#elif defined TREZOR_MODEL_T #elif defined TREZOR_MODEL_T
{MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR_T)}, {MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR_T)},
#elif defined TREZOR_MODEL_R
{MP_ROM_QSTR(MP_QSTR_MODEL), MP_ROM_QSTR(MP_QSTR_R)},
#else #else
#error Unknown Trezor model #error Unknown Trezor model
#endif #endif

@ -39,7 +39,7 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[9] = 0x080A0000, // - 0x080BFFFF | 128 KiB [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
[10] = 0x080C0000, // - 0x080DFFFF | 128 KiB [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
[11] = 0x080E0000, // - 0x080FFFFF | 128 KiB [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R
[12] = 0x08100000, // - 0x08103FFF | 16 KiB [12] = 0x08100000, // - 0x08103FFF | 16 KiB
[13] = 0x08104000, // - 0x08107FFF | 16 KiB [13] = 0x08104000, // - 0x08107FFF | 16 KiB
[14] = 0x08108000, // - 0x0810BFFF | 16 KiB [14] = 0x08108000, // - 0x0810BFFF | 16 KiB

@ -26,7 +26,7 @@
// see docs/memory.md for more information // see docs/memory.md for more information
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R
#define FLASH_SECTOR_COUNT 24 #define FLASH_SECTOR_COUNT 24
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1
#define FLASH_SECTOR_COUNT 12 #define FLASH_SECTOR_COUNT 12
@ -40,7 +40,7 @@
// 3 // 3
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R
#define FLASH_SECTOR_STORAGE_1 4 #define FLASH_SECTOR_STORAGE_1 4
#define FLASH_SECTOR_STORAGE_2 16 #define FLASH_SECTOR_STORAGE_2 16
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@ -47,7 +47,7 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[9] = 0x080A0000, // - 0x080BFFFF | 128 KiB [9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
[10] = 0x080C0000, // - 0x080DFFFF | 128 KiB [10] = 0x080C0000, // - 0x080DFFFF | 128 KiB
[11] = 0x080E0000, // - 0x080FFFFF | 128 KiB [11] = 0x080E0000, // - 0x080FFFFF | 128 KiB
#if defined TREZOR_MODEL_T #if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R
[12] = 0x08100000, // - 0x08103FFF | 16 KiB [12] = 0x08100000, // - 0x08103FFF | 16 KiB
[13] = 0x08104000, // - 0x08107FFF | 16 KiB [13] = 0x08104000, // - 0x08107FFF | 16 KiB
[14] = 0x08108000, // - 0x0810BFFF | 16 KiB [14] = 0x08108000, // - 0x0810BFFF | 16 KiB

@ -0,0 +1,34 @@
"""
Creates a header file containing image data.
"""
background_image = "background_R.jpg"
h_file_name = "background_R.h"
h_file_template = """\
// clang-format off
unsigned char background_R_jpg[] = {content};
unsigned int background_R_jpg_len = {length};
"""
with open(background_image, "rb") as f:
image_data = f.read()
column_count = 12
content = "{{\n{image_bytes}\n}}"
image_bytes = " " # begin with indent
for index, byte in enumerate(image_data, start=1):
image_bytes += f"0x{byte:02x},"
# If at the end of line, include a newline with indent, otherwise just space
if index % column_count == 0:
image_bytes += "\n "
else:
image_bytes += " "
# Get rid of trailing coma
image_bytes = image_bytes.rstrip(", \n")
with open(h_file_name, "w") as f:
f.write(h_file_template.format(content=content.format(image_bytes=image_bytes), length=len(image_data)))

@ -102,7 +102,7 @@ uint32_t touch_read(void) {
return 0; return 0;
} }
#elif defined TREZOR_MODEL_1 #elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#include "button.h" #include "button.h"

@ -186,6 +186,8 @@ trezor.ui.constants
import trezor.ui.constants import trezor.ui.constants
trezor.ui.constants.t1 trezor.ui.constants.t1
import trezor.ui.constants.t1 import trezor.ui.constants.t1
trezor.ui.constants.tr
import trezor.ui.constants.tr
trezor.ui.constants.tt trezor.ui.constants.tt
import trezor.ui.constants.tt import trezor.ui.constants.tt
trezor.ui.container trezor.ui.container
@ -202,6 +204,8 @@ trezor.ui.layouts.reset
import trezor.ui.layouts.reset import trezor.ui.layouts.reset
trezor.ui.layouts.t1 trezor.ui.layouts.t1
import trezor.ui.layouts.t1 import trezor.ui.layouts.t1
trezor.ui.layouts.tr
import trezor.ui.layouts.tr
trezor.ui.layouts.tt trezor.ui.layouts.tt
import trezor.ui.layouts.tt import trezor.ui.layouts.tt
trezor.ui.layouts.tt.altcoin trezor.ui.layouts.tt.altcoin

@ -55,7 +55,6 @@ def get_features() -> Features:
Capability.Crypto, Capability.Crypto,
Capability.Shamir, Capability.Shamir,
Capability.ShamirGroups, Capability.ShamirGroups,
Capability.PassphraseEntry,
] ]
else: else:
f.capabilities = [ f.capabilities = [
@ -74,8 +73,12 @@ def get_features() -> Features:
Capability.U2F, Capability.U2F,
Capability.Shamir, Capability.Shamir,
Capability.ShamirGroups, Capability.ShamirGroups,
Capability.PassphraseEntry,
] ]
# Other models are not capable of PassphraseEntry
if utils.MODEL in ("T",):
f.capabilities.append(Capability.PassphraseEntry)
f.sd_card_present = sdcard.is_present() f.sd_card_present = sdcard.is_present()
f.initialized = storage.device.is_initialized() f.initialized = storage.device.is_initialized()

@ -4,7 +4,7 @@ from micropython import const
import storage import storage
import storage.cache import storage.cache
import storage.device import storage.device
from trezor import config, ui from trezor import config, ui, utils
from trezor.ui.loader import Loader, LoaderNeutral from trezor.ui.loader import Loader, LoaderNeutral
from apps.base import lock_device from apps.base import lock_device
@ -53,7 +53,10 @@ class Homescreen(HomescreenBase):
# homescreen with shifted avatar and text on bottom # homescreen with shifted avatar and text on bottom
ui.display.avatar(48, 48 - 10, self.get_image(), ui.WHITE, ui.BLACK) ui.display.avatar(48, 48 - 10, self.get_image(), ui.WHITE, ui.BLACK)
ui.display.text_center(ui.WIDTH // 2, 220, self.label, ui.BOLD, ui.FG, ui.BG) label_heights = {"1": 54, "R": 110, "T": 220}
ui.display.text_center(
ui.WIDTH // 2, label_heights[utils.MODEL], self.label, ui.BOLD, ui.FG, ui.BG
)
def on_touch_start(self, _x: int, _y: int) -> None: def on_touch_start(self, _x: int, _y: int) -> None:
if self.loader.start_ms is not None: if self.loader.start_ms is not None:

@ -50,7 +50,7 @@ def find_message_handler_module(msg_type: int) -> str:
elif msg_type == MessageType.GetNonce: elif msg_type == MessageType.GetNonce:
return "apps.management.get_nonce" return "apps.management.get_nonce"
if utils.MODEL == "T" and msg_type == MessageType.SdProtect: if utils.MODEL in ("T",) and msg_type == MessageType.SdProtect:
return "apps.management.sd_protect" return "apps.management.sd_protect"
# bitcoin # bitcoin

@ -4,6 +4,7 @@ from ubinascii import hexlify
import storage.cache import storage.cache
from storage import common from storage import common
from trezor import utils
if TYPE_CHECKING: if TYPE_CHECKING:
from trezor.enums import BackupType from trezor.enums import BackupType
@ -199,6 +200,9 @@ def get_passphrase_always_on_device() -> bool:
- If DEVICE(1) => returns True, the check against b"\x01" in get_bool succeeds. - If DEVICE(1) => returns True, the check against b"\x01" in get_bool succeeds.
- If HOST(2) => returns False, the check against b"\x01" in get_bool fails. - If HOST(2) => returns False, the check against b"\x01" in get_bool fails.
""" """
# Some models do not support passphrase input on device
if utils.MODEL in ("1", "R"):
return False
return common.get_bool(_NAMESPACE, _PASSPHRASE_ALWAYS_ON_DEVICE) return common.get_bool(_NAMESPACE, _PASSPHRASE_ALWAYS_ON_DEVICE)

@ -49,7 +49,7 @@ else:
# in both debug and production, emulator needs to draw the screen explicitly # in both debug and production, emulator needs to draw the screen explicitly
if utils.EMULATOR or utils.MODEL == "1": if utils.EMULATOR or utils.MODEL in ("1", "R"):
loop.after_step_hook = refresh loop.after_step_hook = refresh
@ -240,7 +240,7 @@ class Component:
def __init__(self) -> None: def __init__(self) -> None:
self.repaint = True self.repaint = True
if utils.MODEL == "T": if utils.MODEL in ("T",):
def dispatch(self, event: int, x: int, y: int) -> None: def dispatch(self, event: int, x: int, y: int) -> None:
if event is RENDER: if event is RENDER:
@ -263,7 +263,7 @@ class Component:
def on_touch_end(self, x: int, y: int) -> None: def on_touch_end(self, x: int, y: int) -> None:
pass pass
elif utils.MODEL == "1": elif utils.MODEL in ("1", "R"):
def dispatch(self, event: int, x: int, y: int) -> None: def dispatch(self, event: int, x: int, y: int) -> None:
if event is RENDER: if event is RENDER:
@ -374,7 +374,7 @@ class Layout(Component):
Usually overridden to add another tasks to the list.""" Usually overridden to add another tasks to the list."""
return self.handle_input(), self.handle_rendering() return self.handle_input(), self.handle_rendering()
if utils.MODEL == "T": if utils.MODEL in ("T",):
def handle_input(self) -> Generator: def handle_input(self) -> Generator:
"""Task that is waiting for the user input.""" """Task that is waiting for the user input."""
@ -388,7 +388,7 @@ class Layout(Component):
# way to get the lowest input-to-render latency. # way to get the lowest input-to-render latency.
self.dispatch(RENDER, 0, 0) self.dispatch(RENDER, 0, 0)
elif utils.MODEL == "1": elif utils.MODEL in ("1", "R"):
def handle_input(self) -> Generator: def handle_input(self) -> Generator:
"""Task that is waiting for the user input.""" """Task that is waiting for the user input."""

@ -1,8 +1,10 @@
from trezor import utils from trezor import utils
if utils.MODEL == "1": if utils.MODEL in ("1",):
from .t1 import * # noqa: F401,F403 from .t1 import * # noqa: F401,F403
elif utils.MODEL == "T": elif utils.MODEL in ("R",):
from .tr import * # noqa: F401,F403
elif utils.MODEL in ("T",):
from .tt import * # noqa: F401,F403 from .tt import * # noqa: F401,F403
else: else:
raise ValueError("Unknown Trezor model") raise ValueError("Unknown Trezor model")

@ -0,0 +1,9 @@
from micropython import const
TEXT_HEADER_HEIGHT = const(13)
TEXT_LINE_HEIGHT = const(9)
TEXT_LINE_HEIGHT_HALF = const(4)
TEXT_MARGIN_LEFT = const(0)
TEXT_MAX_LINES = const(4)
TEXT_MAX_LINES_NO_HEADER = const(5)
PAGINATION_MARGIN_RIGHT = const(4)

@ -10,9 +10,11 @@ except ImportError:
# NOTE: using any import magic probably causes mypy not to check equivalence of # NOTE: using any import magic probably causes mypy not to check equivalence of
# layout type signatures across models # layout type signatures across models
if utils.MODEL == "1": if utils.MODEL in ("1",):
from .t1 import * # noqa: F401,F403 from .t1 import * # noqa: F401,F403
elif utils.MODEL == "T": elif utils.MODEL in ("R",):
from .tr import * # noqa: F401,F403
elif utils.MODEL in ("T",):
if not UI2: if not UI2:
from .tt import * # noqa: F401,F403 from .tt import * # noqa: F401,F403
else: else:

@ -0,0 +1,295 @@
from typing import TYPE_CHECKING, Sequence
from trezor import io, log, loop, ui, wire, workflow
from trezor.enums import ButtonRequestType
import trezorui2
from ..common import button_request, interact
if TYPE_CHECKING:
from typing import Any, NoReturn, Type
ExceptionType = BaseException | Type[BaseException]
class _RustLayout(ui.Layout):
# pylint: disable=super-init-not-called
def __init__(self, layout: Any):
self.layout = layout
self.timer = loop.Timer()
self.layout.set_timer_fn(self.set_timer)
def set_timer(self, token: int, deadline: int) -> None:
self.timer.schedule(deadline, token)
def create_tasks(self) -> tuple[loop.Task, ...]:
return self.handle_input_and_rendering(), self.handle_timers()
def handle_input_and_rendering(self) -> loop.Task: # type: ignore [awaitable-is-generator]
button = loop.wait(io.BUTTON)
ui.display.clear()
self.layout.paint()
while True:
# Using `yield` instead of `await` to avoid allocations.
event, button_num = yield button
workflow.idle_timer.touch()
msg = None
if event in (io.BUTTON_PRESSED, io.BUTTON_RELEASED):
msg = self.layout.button_event(event, button_num)
self.layout.paint()
if msg is not None:
raise ui.Result(msg)
def handle_timers(self) -> loop.Task: # type: ignore [awaitable-is-generator]
while True:
# Using `yield` instead of `await` to avoid allocations.
token = yield self.timer
msg = self.layout.timer(token)
self.layout.paint()
if msg is not None:
raise ui.Result(msg)
async def confirm_action(
ctx: wire.GenericContext,
br_type: str,
title: str,
action: str | None = None,
description: str | None = None,
description_param: str | None = None,
description_param_font: int = ui.BOLD,
verb: str | bytes | None = "OK",
verb_cancel: str | bytes | None = "cancel",
hold: bool = False,
hold_danger: bool = False,
icon: str | None = None,
icon_color: int | None = None,
reverse: bool = False,
larger_vspace: bool = False,
exc: ExceptionType = wire.ActionCancelled,
br_code: ButtonRequestType = ButtonRequestType.Other,
) -> None:
if isinstance(verb, bytes) or isinstance(verb_cancel, bytes):
raise NotImplementedError
if description is not None and description_param is not None:
if description_param_font != ui.BOLD:
log.error(__name__, "confirm_action description_param_font not implemented")
description = description.format(description_param)
if hold:
log.error(__name__, "confirm_action hold not implemented")
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_action(
title=title.upper(),
action=action,
description=description,
verb=verb,
verb_cancel=verb_cancel,
hold=hold,
reverse=reverse,
)
),
br_type,
br_code,
)
if result is not trezorui2.CONFIRMED:
raise exc
async def confirm_text(
ctx: wire.GenericContext,
br_type: str,
title: str,
data: str,
description: str | None = None,
br_code: ButtonRequestType = ButtonRequestType.Other,
icon: str = ui.ICON_SEND, # TODO cleanup @ redesign
icon_color: int = ui.GREEN, # TODO cleanup @ redesign
) -> None:
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_text(
title=title.upper(),
data=data,
description=description,
)
),
br_type,
br_code,
)
if result is not trezorui2.CONFIRMED:
raise wire.ActionCancelled
async def show_success(
ctx: wire.GenericContext,
br_type: str,
content: str,
) -> None:
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_text(
title="Success",
data=content,
description="",
)
),
br_type,
br_code=ButtonRequestType.Other,
)
if result is not trezorui2.CONFIRMED:
raise wire.ActionCancelled
async def show_address(
ctx: wire.GenericContext,
address: str,
*,
case_sensitive: bool = True,
address_qr: str | None = None,
title: str = "Confirm address",
network: str | None = None,
multisig_index: int | None = None,
xpubs: Sequence[str] = (),
address_extra: str | None = None,
title_qr: str | None = None,
) -> None:
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_text(
title="ADDRESS",
data=address,
description="Confirm address",
)
),
"show_address",
ButtonRequestType.Address,
)
if result is not trezorui2.CONFIRMED:
raise wire.ActionCancelled
async def confirm_output(
ctx: wire.GenericContext,
address: str,
amount: str,
font_amount: int = ui.NORMAL, # TODO cleanup @ redesign
title: str = "Confirm sending",
icon: str = ui.ICON_SEND,
) -> None:
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_text(
title=title,
data=f"Send {amount} to {address}?",
description="Confirm Output",
)
),
"confirm_output",
ButtonRequestType.Other,
)
if result is not trezorui2.CONFIRMED:
raise wire.ActionCancelled
async def confirm_total(
ctx: wire.GenericContext,
total_amount: str,
fee_amount: str,
title: str = "Confirm transaction",
total_label: str = "Total amount:\n",
fee_label: str = "\nincluding fee:\n",
icon_color: int = ui.GREEN,
br_type: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_text(
title=title,
data=f"{total_label}{total_amount}\n{fee_label}{fee_amount}",
description="Confirm Output",
)
),
br_type,
br_code,
)
if result is not trezorui2.CONFIRMED:
raise wire.ActionCancelled
async def confirm_blob(
ctx: wire.GenericContext,
br_type: str,
title: str,
data: bytes | str,
description: str | None = None,
hold: bool = False,
br_code: ButtonRequestType = ButtonRequestType.Other,
icon: str = ui.ICON_SEND, # TODO cleanup @ redesign
icon_color: int = ui.GREEN, # TODO cleanup @ redesign
ask_pagination: bool = False,
) -> None:
result = await interact(
ctx,
_RustLayout(
trezorui2.confirm_text(
title=title,
data=str(data),
description=description,
)
),
br_type,
br_code,
)
if result is not trezorui2.CONFIRMED:
raise wire.ActionCancelled
def draw_simple_text(title: str, description: str = "") -> None:
log.error(__name__, "draw_simple_text not implemented")
async def request_pin_on_device(
ctx: wire.GenericContext,
prompt: str,
attempts_remaining: int | None,
allow_cancel: bool,
) -> str:
await button_request(ctx, "pin_device", code=ButtonRequestType.PinEntry)
# TODO: this should not be callable on TR
return "1234"
async def show_error_and_raise(
ctx: wire.GenericContext,
br_type: str,
content: str,
header: str = "Error",
subheader: str | None = None,
button: str = "Close",
red: bool = False,
exc: ExceptionType = wire.ActionCancelled,
) -> NoReturn:
raise NotImplementedError
async def show_popup(
title: str,
description: str,
subtitle: str | None = None,
description_param: str = "",
timeout_ms: int = 3000,
) -> None:
raise NotImplementedError
Loading…
Cancel
Save