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(
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_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1':
elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx'

@ -123,11 +123,11 @@ env.Replace(
env.Replace(
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_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1':
elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx'

@ -123,11 +123,11 @@ env.Replace(
env.Replace(
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_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1':
elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx'

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

@ -101,11 +101,11 @@ env.Replace(
env.Replace(
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_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1':
elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx'

@ -95,11 +95,11 @@ env.Replace(
env.Replace(
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_CCFLAGS = '-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 '
CPU_MODEL = 'STM32F427xx'
elif TREZOR_MODEL == '1':
elif TREZOR_MODEL in ('1',):
CPU_ASFLAGS = '-mthumb -mcpu=cortex-m3 -mfloat-abi=soft'
CPU_CCFLAGS = '-mthumb -mtune=cortex-m3 -mcpu=cortex-m3 -mfloat-abi=soft '
CPU_MODEL = 'STM32F405xx'

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

@ -25,7 +25,7 @@
#define NORCOW_HEADER_LEN 0
#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)
#elif defined TREZOR_MODEL_1
#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;
}
}
#elif defined TREZOR_MODEL_1
#elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
else if (iface == BUTTON_IFACE) {
const uint32_t evt = button_read();
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_MOVE), MP_ROM_INT((TOUCH_MOVE >> 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_PRESSED),
MP_ROM_INT((BTN_EVT_DOWN >> 24) & 0x3U)},

@ -39,7 +39,7 @@
#define TOUCH_OFFSET_Y 110
#endif
#elif defined TREZOR_MODEL_1
#elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#define WINDOW_WIDTH 200
#define WINDOW_HEIGHT 340
@ -76,7 +76,7 @@ static struct {
#define PIXELDATA_DIRTY()
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
// bin(10000 100000 10000) = hex(0x8410)
// otherwise set to black
@ -181,6 +181,10 @@ void display_init(void) {
#include "background_1.h"
BACKGROUND = IMG_LoadTexture_RW(
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
if (BACKGROUND) {

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

@ -40,6 +40,14 @@
#define DISPLAY_RESY 64
#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
#error Unknown Trezor model
#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)},
#elif defined TREZOR_MODEL_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
#error Unknown Trezor model
#endif

@ -39,7 +39,7 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[9] = 0x080A0000, // - 0x080BFFFF | 128 KiB
[10] = 0x080C0000, // - 0x080DFFFF | 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
[13] = 0x08104000, // - 0x08107FFF | 16 KiB
[14] = 0x08108000, // - 0x0810BFFF | 16 KiB

@ -26,7 +26,7 @@
// 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
#elif defined TREZOR_MODEL_1
#define FLASH_SECTOR_COUNT 12
@ -40,7 +40,7 @@
// 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_2 16
#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
[10] = 0x080C0000, // - 0x080DFFFF | 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
[13] = 0x08104000, // - 0x08107FFF | 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;
}
#elif defined TREZOR_MODEL_1
#elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#include "button.h"

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

@ -55,7 +55,6 @@ def get_features() -> Features:
Capability.Crypto,
Capability.Shamir,
Capability.ShamirGroups,
Capability.PassphraseEntry,
]
else:
f.capabilities = [
@ -74,8 +73,12 @@ def get_features() -> Features:
Capability.U2F,
Capability.Shamir,
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.initialized = storage.device.is_initialized()

@ -4,7 +4,7 @@ from micropython import const
import storage
import storage.cache
import storage.device
from trezor import config, ui
from trezor import config, ui, utils
from trezor.ui.loader import Loader, LoaderNeutral
from apps.base import lock_device
@ -53,7 +53,10 @@ class Homescreen(HomescreenBase):
# homescreen with shifted avatar and text on bottom
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:
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:
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"
# bitcoin

@ -4,6 +4,7 @@ from ubinascii import hexlify
import storage.cache
from storage import common
from trezor import utils
if TYPE_CHECKING:
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 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)

@ -49,7 +49,7 @@ else:
# 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
@ -240,7 +240,7 @@ class Component:
def __init__(self) -> None:
self.repaint = True
if utils.MODEL == "T":
if utils.MODEL in ("T",):
def dispatch(self, event: int, x: int, y: int) -> None:
if event is RENDER:
@ -263,7 +263,7 @@ class Component:
def on_touch_end(self, x: int, y: int) -> None:
pass
elif utils.MODEL == "1":
elif utils.MODEL in ("1", "R"):
def dispatch(self, event: int, x: int, y: int) -> None:
if event is RENDER:
@ -374,7 +374,7 @@ class Layout(Component):
Usually overridden to add another tasks to the list."""
return self.handle_input(), self.handle_rendering()
if utils.MODEL == "T":
if utils.MODEL in ("T",):
def handle_input(self) -> Generator:
"""Task that is waiting for the user input."""
@ -388,7 +388,7 @@ class Layout(Component):
# way to get the lowest input-to-render latency.
self.dispatch(RENDER, 0, 0)
elif utils.MODEL == "1":
elif utils.MODEL in ("1", "R"):
def handle_input(self) -> Generator:
"""Task that is waiting for the user input."""

@ -1,8 +1,10 @@
from trezor import utils
if utils.MODEL == "1":
if utils.MODEL in ("1",):
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
else:
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
# layout type signatures across models
if utils.MODEL == "1":
if utils.MODEL in ("1",):
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:
from .tt import * # noqa: F401,F403
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