parent
f9612898ab
commit
5a991f3244
@ -0,0 +1 @@
|
|||||||
|
Error screens redesign
|
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 9.2 KiB |
@ -0,0 +1 @@
|
|||||||
|
Bootloader redesign
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_cancel[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x10, 0x00, 0x10, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0x52, 0x00, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0x45, 0x4d, 0xc1, 0x09, 0x80, 0x30, 0x10, 0x4b, 0xcf, 0x05, 0xba, 0x80, 0xd0, 0x01, 0x2c, 0xb8, 0xff, 0x47, 0x70, 0x01, 0xb1, 0x0b, 0xdc, 0x20, 0xb6, 0xc4, 0x48, 0x5b, 0x0c, 0x1c, 0x09, 0xe1, 0x92, 0xe0, 0x0c, 0x40, 0xdc, 0x90, 0x5a, 0x06, 0x8a, 0x5b, 0xa1, 0x5b, 0x6a, 0xcc, 0x0f, 0xb9, 0xde, 0xe4, 0xa1, 0xf3, 0x26, 0x9d, 0x2a, 0x85, 0xcb, 0x50, 0x3e, 0xd6, 0x6f, 0x94, 0xeb, 0xe1, 0xe7, 0xe1, 0x2b, 0x2b, 0xb8, 0xcd, 0x5c, 0xed, 0x3d, 0xd7, 0xec, 0xdd, 0xfb, 0xce, 0x82, 0xb1, 0xfb, 0x02,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_confirm[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x14, 0x00, 0x10, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0x69, 0x00, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0x63, 0x60, 0x80, 0x80, 0x48, 0x28, 0xcd, 0x30, 0xe1, 0x3f, 0x2b, 0x94, 0xf5, 0xe3, 0x7f, 0x3c, 0x84, 0xd1, 0xf0, 0xff, 0xff, 0x7a, 0x08, 0xeb, 0xfb, 0xff, 0xff, 0xdc, 0x60, 0x46, 0xc1, 0xff, 0xff, 0xfb, 0x19, 0x18, 0x1c, 0x38, 0x19, 0x18, 0xbe, 0x81, 0x85, 0xbe, 0xcc, 0x67, 0x48, 0x00, 0x0a, 0x31, 0x32, 0x38, 0xfc, 0xff, 0x2f, 0xf1, 0xec, 0xff, 0x7f, 0x69, 0x06, 0x86, 0x05, 0x40, 0xfe, 0x3f, 0x90, 0x10, 0x83, 0xc0, 0xef, 0xff, 0x40, 0xa0, 0x0d, 0xd2, 0xb7, 0x11, 0xc8, 0xd8, 0xcf, 0x04, 0x62, 0x81, 0x04, 0x75, 0x20, 0xa6, 0x6e, 0xfa, 0x7f, 0x9e, 0x19, 0xc2, 0x52, 0xf8, 0x6d, 0x03, 0x73, 0xc7, 0x62, 0x16, 0x30, 0x05, 0x00,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_done[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x40, 0x00, 0x40, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0xce, 0x00, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0x63, 0x60, 0x18, 0x05, 0x23, 0x0f, 0x4c, 0xe0, 0xc6, 0x2f, 0xff, 0xfb, 0x3e, 0x7e, 0xed, 0xff, 0xff, 0x4b, 0xe3, 0x93, 0xff, 0xf5, 0xff, 0xff, 0x79, 0xfc, 0xda, 0xff, 0xff, 0xe7, 0xc1, 0x2d, 0xff, 0x03, 0x24, 0xbf, 0x1f, 0xa7, 0xf4, 0x82, 0xff, 0x60, 0xc0, 0x89, 0x57, 0xfb, 0xff, 0xfb, 0x78, 0x6d, 0xff, 0xff, 0x5f, 0x17, 0xbf, 0xf6, 0xf7, 0x8c, 0x38, 0xa4, 0x1b, 0x88, 0xd3, 0xce, 0x84, 0x5f, 0xbb, 0x2c, 0x86, 0xab, 0xa4, 0xf1, 0x6b, 0x87, 0xc6, 0x08, 0xd4, 0xf1, 0x72, 0x58, 0x3c, 0x25, 0x03, 0xa2, 0xbf, 0x43, 0xfc, 0x8e, 0xa1, 0xfd, 0x27, 0x24, 0x46, 0xa0, 0xb6, 0xeb, 0x61, 0x0d, 0x52, 0x59, 0x98, 0xf6, 0xf7, 0xd8, 0xb4, 0x83, 0x62, 0xa4, 0x00, 0x87, 0xdf, 0xa1, 0xc6, 0xf2, 0x7d, 0x83, 0xd0, 0xcc, 0xe8, 0xf2, 0x06, 0xff, 0x20, 0xce, 0xc2, 0x61, 0x3b, 0x03, 0xc3, 0xe7, 0xff, 0x48, 0x80, 0x19, 0x53, 0xde, 0x00, 0x49, 0x5a, 0x1e, 0x5b, 0xb0, 0x3e, 0x86, 0x4b, 0xbf, 0x67, 0xc6, 0x26, 0x8f, 0x30, 0x40, 0x1f, 0x7b, 0xbc, 0x3c, 0xc5, 0xab, 0x1d, 0x61, 0x80, 0x3d, 0xae, 0x78, 0xff, 0x8a, 0xd3, 0xf1, 0xc8, 0x06, 0xd8, 0xe3, 0x4e, 0xf5, 0x9f, 0xf1, 0x6a, 0x67, 0x60, 0x08, 0x00, 0x4a, 0xfb, 0x33, 0xe0, 0x01, 0x4f, 0xfe, 0xff, 0x67, 0xc1, 0x27, 0x9f, 0x80, 0x5f, 0x3b, 0x03, 0xc3, 0x15, 0x16, 0x86, 0x51, 0x30, 0xc2, 0x00, 0x00,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_fail[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x40, 0x00, 0x40, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0x21, 0x01, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0xed, 0x52, 0x39, 0x12, 0x82, 0x40, 0x10, 0x44, 0x17, 0x88, 0x7d, 0x82, 0x1f, 0xd0, 0xe2, 0x05, 0x2e, 0x0f, 0xb0, 0x84, 0x1f, 0xc0, 0x0f, 0x7c, 0xa2, 0x89, 0xb9, 0x55, 0xfe, 0xc0, 0x23, 0xdf, 0xc0, 0x23, 0xd1, 0x62, 0x14, 0xd8, 0x65, 0xf6, 0xe8, 0x22, 0x36, 0xb0, 0xa3, 0xae, 0x69, 0x66, 0xd8, 0x9e, 0xe9, 0x28, 0xfa, 0xe3, 0x27, 0x30, 0x5f, 0x33, 0xdf, 0x4f, 0x43, 0xfd, 0x44, 0xa9, 0xa1, 0x35, 0x2d, 0xc3, 0xf6, 0x86, 0x0a, 0xc3, 0xef, 0xa4, 0x82, 0x01, 0x47, 0x22, 0x4a, 0x7a, 0x5a, 0x7e, 0xe9, 0x22, 0x6c, 0x27, 0xaa, 0x7a, 0xfe, 0xf8, 0x52, 0x7f, 0x40, 0xdb, 0x4e, 0x14, 0xb7, 0x34, 0xef, 0xa8, 0x3b, 0x60, 0xd6, 0x74, 0xc5, 0x6d, 0xcb, 0x9f, 0x1d, 0x55, 0x13, 0x5b, 0x3f, 0x13, 0x99, 0x01, 0xb9, 0xa6, 0x8e, 0x85, 0x97, 0x2e, 0x16, 0xed, 0xe3, 0x7b, 0xec, 0x6c, 0xfd, 0xa6, 0x8b, 0x94, 0xd6, 0x86, 0x49, 0x5b, 0x37, 0x43, 0xa9, 0x30, 0xed, 0xfd, 0x5b, 0x07, 0x5c, 0x74, 0x55, 0x35, 0x9a, 0xac, 0x5c, 0x7f, 0x19, 0x79, 0x10, 0xde, 0x82, 0xae, 0xae, 0xbc, 0xf1, 0xf7, 0x9b, 0x8d, 0xb7, 0xb3, 0x2f, 0xe3, 0x33, 0x18, 0xd0, 0xb0, 0xac, 0x04, 0x08, 0xc8, 0x8d, 0x75, 0x89, 0x02, 0x94, 0x0f, 0x03, 0x54, 0x0c, 0x13, 0x66, 0x76, 0xe0, 0x7b, 0x0f, 0x2c, 0x6e, 0xa0, 0x5c, 0xf3, 0xff, 0x53, 0xa4, 0xdf, 0x47, 0xed, 0xf1, 0x89, 0xc2, 0xe3, 0x44, 0x1c, 0x1b, 0x8d, 0xed, 0x78, 0x3b, 0x18, 0xf0, 0x70, 0xf5, 0xca, 0x93, 0x4b, 0xff, 0xbe, 0x31, 0x5e, 0xee, 0x90, 0x0f, 0x89, 0xdb, 0xe5, 0x70, 0x85, 0x04, 0x7a, 0x4f, 0x4a, 0xb8, 0x83, 0x77, 0x98, 0xef, 0x03, 0xfa, 0xbd, 0xe0, 0x20, 0x49, 0x90, 0xae, 0xca, 0x72, 0x2a, 0xc0, 0x6d, 0x05, 0x7f, 0x8b, 0xf2, 0x5d, 0x59, 0xab, 0x12, 0x20, 0x1c, 0x31, 0xaf, 0x7a, 0x05, 0xf2, 0x2d, 0xad, 0xd7, 0x0a, 0x10, 0xcf, 0x84, 0xb7, 0x05, 0x02, 0x9a, 0xad, 0x99, 0xef, 0x45, 0xf4, 0xc7, 0x6f, 0xe0, 0x03,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_info[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x20, 0x00, 0x20, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0xde, 0x00, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0x7d, 0x91, 0x3d, 0x0a, 0xc2, 0x40, 0x10, 0x85, 0x27, 0x10, 0xfc, 0x05, 0xe3, 0x0d, 0xbc, 0x82, 0xa0, 0x07, 0x10, 0x3c, 0x80, 0xde, 0x20, 0xf6, 0x22, 0xd8, 0x5b, 0xc4, 0xde, 0x42, 0x6f, 0x60, 0x67, 0x91, 0x46, 0x4b, 0x3b, 0xc5, 0x0b, 0xe4, 0x06, 0xba, 0x17, 0x10, 0x21, 0x10, 0x45, 0x89, 0x3e, 0x37, 0x3b, 0xbb, 0xa8, 0xab, 0x38, 0xc5, 0xce, 0x7e, 0x30, 0x3b, 0xb3, 0xf3, 0x1e, 0x91, 0x8c, 0xfa, 0xfa, 0xb8, 0x9f, 0xb8, 0x64, 0x62, 0x0c, 0x15, 0x45, 0x8d, 0x3d, 0xe8, 0x28, 0x30, 0xa7, 0xc0, 0xa8, 0xd9, 0x5e, 0x00, 0x07, 0x85, 0x02, 0xc8, 0xeb, 0xb2, 0x5a, 0x96, 0x1f, 0x28, 0x73, 0xdd, 0x0c, 0x70, 0x88, 0x56, 0x08, 0x4c, 0xdf, 0x04, 0x15, 0xa2, 0xb3, 0xaa, 0x4e, 0x96, 0xf2, 0xe8, 0x62, 0x4a, 0x84, 0x8d, 0xbc, 0x55, 0x81, 0x9c, 0x4c, 0x57, 0x38, 0x43, 0x78, 0xf2, 0xd2, 0xe2, 0xe9, 0x02, 0x45, 0xc1, 0x53, 0x01, 0x57, 0x3d, 0xf0, 0x62, 0xa8, 0x56, 0xbb, 0x81, 0x4a, 0xf0, 0x2f, 0x11, 0xbd, 0xc5, 0x6d, 0x7e, 0x0b, 0xde, 0x39, 0x89, 0x52, 0x9f, 0x5e, 0xfd, 0x29, 0x3e, 0xdd, 0x3b, 0xff, 0xd9, 0xae, 0xe7, 0x7e, 0x86, 0x93, 0x88, 0xe7, 0x19, 0xbe, 0xce, 0xf9, 0x3f, 0x86, 0xe1, 0x0b, 0xb5, 0x9e, 0x66, 0xf9, 0x5f, 0xde, 0x47, 0xb3, 0x40, 0xc9, 0xde, 0x57, 0xeb, 0x11, 0x86, 0xae, 0xd6, 0x63, 0x6b, 0xe9, 0x65, 0xeb, 0xf9, 0xa5, 0x77, 0xe6, 0x47, 0xbf, 0xd9, 0x90, 0x7e, 0x9c, 0x9c, 0x9f, 0x7e, 0xd9, 0x7e, 0x7e, 0xf8, 0xfd, 0x04,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_install[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x40, 0x00, 0x40, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0xb8, 0x00, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0x63, 0x60, 0x18, 0x05, 0xa3, 0x80, 0x58, 0xe0, 0xec, 0xe2, 0x62, 0x82, 0x4f, 0xfe, 0xcf, 0xff, 0xff, 0xe7, 0x47, 0xe5, 0xc9, 0x93, 0x3f, 0x85, 0x90, 0x5f, 0x83, 0x45, 0x7a, 0xc1, 0x7f, 0x5e, 0x98, 0xfc, 0x85, 0xff, 0x5c, 0x98, 0xf2, 0xbf, 0xfe, 0xef, 0x87, 0xc9, 0xff, 0xfe, 0xbf, 0x1e, 0x43, 0xfa, 0xc0, 0xff, 0xff, 0x40, 0x03, 0xc0, 0xf2, 0x17, 0x80, 0x4c, 0x1e, 0x74, 0x79, 0x07, 0xa0, 0xe0, 0x79, 0x46, 0x90, 0xbc, 0x00, 0x90, 0xf8, 0xcf, 0x82, 0x61, 0xc0, 0x17, 0xa0, 0xa8, 0x2e, 0x48, 0xfe, 0x12, 0x90, 0xe1, 0x8f, 0x69, 0xbf, 0x02, 0x50, 0xf8, 0xfd, 0x3f, 0x08, 0xfe, 0xcf, 0x84, 0xc5, 0x03, 0x20, 0x03, 0xa0, 0xc0, 0x1f, 0x9b, 0xff, 0x15, 0x10, 0xf2, 0x4c, 0x58, 0x03, 0xe8, 0x13, 0x4c, 0x5a, 0x1f, 0x7b, 0x00, 0x1a, 0xc0, 0xe4, 0x99, 0x71, 0x84, 0xf0, 0x63, 0x88, 0xb4, 0x1e, 0xae, 0x18, 0x50, 0x00, 0x39, 0xfd, 0xff, 0x7b, 0x26, 0x9c, 0xd1, 0x77, 0x11, 0x24, 0x2f, 0x8b, 0x3b, 0x7a, 0x05, 0xfe, 0xfe, 0xff, 0x7f, 0x9f, 0x11, 0x4f, 0xfc, 0x1f, 0xfc, 0xff, 0x5f, 0x86, 0x01, 0x6f, 0x02, 0xc1, 0x9b, 0x7c, 0x80, 0x06, 0xe0, 0xd7, 0xce, 0x20, 0xc0, 0xc8, 0x30, 0x0a, 0x46, 0x01, 0xf1, 0x00, 0x00,
|
|
||||||
};
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_welcome[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0xb4, 0x00, 0x1e, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0x32, 0x03, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0xc5, 0x52, 0xc1, 0x4e, 0x13, 0x51, 0x14, 0xbd, 0x50, 0xa0, 0x50, 0x2c, 0x74, 0xa7, 0x0b, 0x11, 0xbe, 0x80, 0xf2, 0x07, 0xf0, 0x07, 0xfa, 0x03, 0x06, 0x56, 0x6c, 0xdb, 0xb8, 0xc2, 0x15, 0x26, 0x2e, 0xd8, 0x90, 0x40, 0x22, 0x89, 0x1b, 0x05, 0x34, 0x26, 0xec, 0x6c, 0xf5, 0x03, 0x04, 0x75, 0xe1, 0xb2, 0xc4, 0x95, 0x3b, 0x4a, 0xe2, 0xc6, 0x28, 0x4e, 0x29, 0x50, 0x5a, 0xa0, 0x73, 0x3c, 0xf7, 0xbe, 0xe9, 0x74, 0x3a, 0x40, 0x62, 0xa4, 0x89, 0x77, 0x31, 0x73, 0xdf, 0x7b, 0xf7, 0x9c, 0x77, 0xdf, 0xb9, 0x47, 0xe4, 0x3f, 0x05, 0x30, 0x7b, 0x13, 0xf8, 0x11, 0xd0, 0xc7, 0xdf, 0x05, 0xb2, 0xfc, 0x56, 0x80, 0xc1, 0x9b, 0x31, 0x47, 0x30, 0x24, 0x4b, 0x86, 0x3b, 0x55, 0xa0, 0xbf, 0x6b, 0xcc, 0x3b, 0x40, 0x4a, 0x64, 0x06, 0xd8, 0xe0, 0xe2, 0x04, 0xe8, 0xe9, 0x1a, 0xf3, 0x2a, 0x90, 0x16, 0xc9, 0x03, 0x25, 0x2e, 0xea, 0xf0, 0xa4, 0x6b, 0xcc, 0x73, 0xc0, 0xa8, 0x48, 0x11, 0x00, 0x17, 0xe7, 0x28, 0x74, 0x8f, 0x79, 0x02, 0x98, 0x16, 0x29, 0x93, 0x39, 0x21, 0xe2, 0x63, 0xb1, 0x7b, 0xcc, 0xcc, 0x73, 0x36, 0x3a, 0x0e, 0x32, 0x63, 0xb7, 0x74, 0x8d, 0xf9, 0x5c, 0x67, 0xc7, 0xd1, 0x61, 0x58, 0xe7, 0x48, 0x65, 0xe4, 0xe9, 0x2f, 0x6f, 0x39, 0xd1, 0xae, 0x5a, 0x3b, 0xf0, 0x5e, 0x24, 0xac, 0x94, 0x07, 0x96, 0xd1, 0x4f, 0x3d, 0x6f, 0x9a, 0x7b, 0x77, 0x24, 0xf3, 0xc5, 0x7f, 0x1b, 0x1e, 0x45, 0x31, 0x16, 0x75, 0x9d, 0x5d, 0x83, 0xcc, 0x23, 0x3a, 0x47, 0x4e, 0xf3, 0x15, 0x73, 0xd3, 0xdb, 0x55, 0x7d, 0xb2, 0xa5, 0x5a, 0xe6, 0x9d, 0x66, 0xdb, 0x3d, 0xc6, 0xfc, 0x9a, 0xa9, 0x97, 0xd0, 0x86, 0x56, 0x94, 0x24, 0x86, 0x71, 0x71, 0xac, 0xb3, 0x6b, 0xa2, 0x89, 0xac, 0x6c, 0x02, 0x43, 0x92, 0x69, 0x6a, 0x15, 0xee, 0x06, 0x55, 0x53, 0xbe, 0x2d, 0xc7, 0x38, 0x11, 0x97, 0x4d, 0x1a, 0xb3, 0xe5, 0x0f, 0x6d, 0x63, 0x40, 0xe2, 0x98, 0x20, 0x0e, 0x81, 0x5e, 0x6e, 0xd4, 0xb8, 0xb5, 0xab, 0x65, 0xbb, 0x56, 0xa4, 0x0d, 0x58, 0xd5, 0xbe, 0x5b, 0x6e, 0x4b, 0xeb, 0x60, 0xcf, 0x98, 0x23, 0x31, 0x22, 0x71, 0x4c, 0x10, 0xb4, 0x45, 0x3f, 0x05, 0xfe, 0x4a, 0xb9, 0x2b, 0x7a, 0x49, 0x1d, 0x58, 0x5f, 0xf2, 0xd5, 0x2a, 0x56, 0x45, 0x9d, 0x96, 0xb7, 0x88, 0xea, 0xd3, 0x6c, 0xfd, 0xb9, 0xaf, 0xcf, 0x52, 0xe6, 0xc7, 0x3f, 0x54, 0x8f, 0x85, 0x33, 0xe0, 0xbe, 0xc4, 0x31, 0x41, 0x50, 0x82, 0xc1, 0x3c, 0xbc, 0x55, 0x36, 0x53, 0x55, 0x61, 0xac, 0xbf, 0x1d, 0x20, 0x65, 0x55, 0xb4, 0xcb, 0x86, 0x29, 0x96, 0x62, 0xc6, 0x81, 0x7c, 0x04, 0xc6, 0x95, 0x79, 0x52, 0x15, 0xc4, 0x2d, 0x99, 0x82, 0x1a, 0xb5, 0x13, 0xd3, 0x0a, 0x8e, 0x2d, 0x55, 0x44, 0xe1, 0x01, 0x59, 0x4f, 0x88, 0x9d, 0x53, 0xa8, 0x02, 0x46, 0xad, 0x2a, 0x6f, 0x76, 0xe1, 0xed, 0x69, 0x1e, 0x64, 0xed, 0x20, 0xa7, 0xcc, 0x14, 0xf7, 0x54, 0x5f, 0x48, 0xfe, 0x95, 0x38, 0xa6, 0x15, 0xdc, 0x48, 0x97, 0x91, 0x63, 0x4b, 0x7d, 0x75, 0x56, 0x6d, 0xea, 0xcd, 0xda, 0x45, 0xd6, 0xaa, 0x8a, 0xea, 0x46, 0x85, 0x8e, 0x6c, 0x6a, 0x8b, 0xca, 0x54, 0x50, 0xe6, 0x7e, 0x91, 0x9a, 0xbe, 0xd0, 0x4c, 0x1b, 0xc3, 0x44, 0xcc, 0x3d, 0x5a, 0xc5, 0xb4, 0xf8, 0x48, 0x9e, 0xbb, 0x29, 0xba, 0xb8, 0x6f, 0x55, 0x9c, 0xc2, 0xa0, 0x2b, 0xdb, 0x75, 0x59, 0x9d, 0xaa, 0x39, 0xe6, 0x93, 0x80, 0xb9, 0x10, 0xc7, 0x84, 0x71, 0x81, 0xe9, 0x1a, 0xdf, 0x71, 0x86, 0x61, 0x9f, 0x8f, 0x2a, 0xb7, 0xaa, 0x66, 0xad, 0xca, 0x3d, 0x5c, 0x83, 0x59, 0x52, 0x4c, 0x83, 0x4b, 0xcc, 0x31, 0x4c, 0x18, 0x0d, 0xe4, 0x1a, 0x7c, 0x72, 0x0d, 0xf7, 0xd4, 0x41, 0x95, 0x4b, 0xcc, 0xfd, 0x21, 0xb3, 0x66, 0x27, 0x57, 0x30, 0x57, 0xae, 0x61, 0xae, 0x61, 0xa3, 0xc9, 0x76, 0xaa, 0x58, 0x54, 0xb9, 0x2a, 0xff, 0xd0, 0xf3, 0x75, 0xcc, 0x55, 0xec, 0xa9, 0x5d, 0xcb, 0xfa, 0x4b, 0xea, 0xcb, 0x86, 0xc2, 0x01, 0xfc, 0xa5, 0xce, 0x11, 0x4c, 0x47, 0xd8, 0x8d, 0xa2, 0x2e, 0xd0, 0x0b, 0x8a, 0x2a, 0x49, 0x9b, 0xd9, 0x79, 0x63, 0x62, 0x7e, 0x7e, 0xa0, 0xe8, 0xbc, 0x71, 0x11, 0x7a, 0xa3, 0xcd, 0x1c, 0xc1, 0x74, 0x84, 0x52, 0x96, 0xcc, 0xd7, 0x5a, 0x9a, 0x57, 0xc3, 0x92, 0x6b, 0x40, 0x22, 0x7e, 0x7e, 0x42, 0x68, 0xde, 0xfc, 0x3c, 0x01, 0x2c, 0x5e, 0x62, 0x8e, 0x60, 0x3a, 0x82, 0x30, 0xfa, 0x58, 0x7d, 0xcd, 0x87, 0x4a, 0xc6, 0x3a, 0x97, 0xef, 0xb3, 0x8e, 0x39, 0x63, 0x67, 0x47, 0xec, 0x3c, 0x63, 0xf7, 0xef, 0x80, 0xfe, 0x89, 0x33, 0x47, 0x30, 0xab, 0xbf, 0x23, 0xba, 0xcc, 0xc0, 0xc9, 0xce, 0xdf, 0x86, 0x09, 0x89, 0xd2, 0xc2, 0x37, 0x2d, 0xb5, 0xed, 0x33, 0x60, 0x79, 0x0b, 0x4a, 0xd5, 0x00, 0xd6, 0x97, 0x7c, 0x95, 0x34, 0xce, 0x1c, 0xc1, 0x34, 0x8c, 0x23, 0x08, 0xbd, 0x71, 0xdc, 0x14, 0xb4, 0x37, 0xb5, 0x6c, 0x9f, 0x72, 0xcc, 0xfb, 0x6e, 0x55, 0x0a, 0x0f, 0x3c, 0xb9, 0xcc, 0xdc, 0xc6, 0xf8, 0x7a, 0x1e, 0x06, 0xfb, 0x48, 0xbb, 0x66, 0xa7, 0xf5, 0xa2, 0xa6, 0x15, 0x6d, 0x3b, 0x35, 0x4c, 0x24, 0xc6, 0x18, 0x65, 0xf4, 0x2d, 0x9b, 0xbc, 0x82, 0xb9, 0x8d, 0xe9, 0x64, 0x3e, 0x73, 0xa6, 0x39, 0xb6, 0x61, 0x51, 0x2a, 0xab, 0x4a, 0x06, 0xcc, 0xf2, 0x59, 0x57, 0x05, 0x3d, 0x78, 0x6f, 0xe8, 0xde, 0x2b, 0x98, 0xdb, 0x98, 0x0e, 0x35, 0xe4, 0x14, 0xd0, 0xa9, 0x1e, 0x3a, 0x5b, 0x89, 0x3c, 0xfa, 0x89, 0x0f, 0xb7, 0xa5, 0xc5, 0x2c, 0x6b, 0x07, 0xde, 0x72, 0xaf, 0x1d, 0x3c, 0x3b, 0xf0, 0x5e, 0xf6, 0xc9, 0x55, 0xcc, 0x21, 0x26, 0x98, 0xe0, 0x1f,
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
// clang-format off
|
|
||||||
static const uint8_t toi_icon_wipe[] = {
|
|
||||||
// magic
|
|
||||||
'T', 'O', 'I', 'G',
|
|
||||||
// width (16-bit), height (16-bit)
|
|
||||||
0x40, 0x00, 0x40, 0x00,
|
|
||||||
// compressed data length (32-bit)
|
|
||||||
0x2f, 0x01, 0x00, 0x00,
|
|
||||||
// compressed data
|
|
||||||
0xed, 0xd2, 0x31, 0x4e, 0x02, 0x41, 0x14, 0x06, 0xe0, 0xc7, 0x62, 0x58, 0x41, 0x5d, 0x48, 0xac, 0x35, 0x14, 0xf6, 0x5a, 0x98, 0x58, 0xe2, 0x0d, 0xc6, 0x1b, 0x48, 0x6d, 0x21, 0x5a, 0xd8, 0x99, 0xc8, 0x0d, 0xbc, 0x82, 0x37, 0xc0, 0x23, 0x10, 0x2f, 0x00, 0x89, 0x85, 0xa5, 0xdb, 0x6b, 0x82, 0x80, 0x68, 0x24, 0xe0, 0x73, 0xde, 0xcc, 0x12, 0x27, 0xd9, 0x7f, 0x86, 0x9a, 0x84, 0x3f, 0xd9, 0xc9, 0x66, 0xbf, 0xec, 0xec, 0xec, 0x7b, 0x8f, 0x68, 0x9d, 0xd5, 0xc9, 0xf5, 0x12, 0x1f, 0xb6, 0xc2, 0x3e, 0xe2, 0x4a, 0xd0, 0x3f, 0xb9, 0x13, 0xf4, 0x6f, 0xe6, 0xcd, 0x90, 0x4f, 0x99, 0xd5, 0x6e, 0xc0, 0x67, 0xcc, 0xbd, 0xb4, 0xe8, 0xe5, 0x3a, 0xeb, 0xdc, 0x28, 0x8f, 0x46, 0xd4, 0x14, 0x4f, 0xd8, 0xb3, 0xc1, 0x09, 0x75, 0xc5, 0xd5, 0x6c, 0x0f, 0xfb, 0x05, 0x0d, 0xc5, 0x5f, 0xa7, 0xf7, 0xd8, 0xdf, 0xe4, 0xf8, 0x3a, 0xbf, 0x9e, 0x0f, 0xf0, 0x01, 0x67, 0xd9, 0x41, 0x5c, 0xe3, 0xdb, 0x85, 0xc3, 0x3f, 0x68, 0xf3, 0x60, 0xe1, 0xb0, 0xc8, 0x7d, 0xfe, 0x4f, 0x01, 0xf8, 0xd8, 0xf1, 0x18, 0xf8, 0x8f, 0xe3, 0xdb, 0xe8, 0xf8, 0x4e, 0xaa, 0x79, 0x6e, 0xba, 0x7e, 0x98, 0xf7, 0xae, 0xeb, 0xe0, 0x07, 0x3f, 0xac, 0x5c, 0x9a, 0xb5, 0x85, 0x46, 0xcf, 0x24, 0x99, 0xc8, 0x7a, 0x97, 0xf7, 0x49, 0x56, 0xda, 0x07, 0x59, 0xcf, 0xe1, 0xe8, 0x49, 0xb6, 0x8e, 0x64, 0x6d, 0xe4, 0xfd, 0x4b, 0x9e, 0xbf, 0xf3, 0x86, 0x69, 0x62, 0x15, 0x8d, 0xb6, 0xce, 0xf3, 0xc0, 0xde, 0x80, 0x06, 0xca, 0x6c, 0x74, 0xfa, 0xca, 0xde, 0xc4, 0xb8, 0x3d, 0x8d, 0x54, 0x17, 0x36, 0xc5, 0xfd, 0x91, 0xfa, 0x25, 0xa3, 0x82, 0x71, 0x38, 0x60, 0x73, 0xe6, 0xf2, 0x31, 0x19, 0xdf, 0x27, 0xdc, 0xdf, 0x52, 0x76, 0x90, 0x08, 0xf9, 0x55, 0x76, 0xac, 0x31, 0xaa, 0x8e, 0xad, 0x60, 0xc5, 0x16, 0xaa, 0x84, 0xfd, 0xcc, 0x96, 0x65, 0xae, 0xc8, 0x93, 0x27, 0xd9, 0xf8, 0xb4, 0x17, 0xf9, 0x9c, 0x5e, 0xf4, 0xf5, 0x18, 0x7b, 0x99, 0x6a, 0xfa, 0xd5, 0x3a, 0xad, 0xb3, 0x42, 0xf9, 0x03,
|
|
||||||
};
|
|
@ -0,0 +1 @@
|
|||||||
|
Bootloader redesign
|
@ -0,0 +1,11 @@
|
|||||||
|
pub fn hexlify(data: &[u8], buffer: &mut [u8]) {
|
||||||
|
const HEX_LOWER: [u8; 16] = *b"0123456789abcdef";
|
||||||
|
let mut i: usize = 0;
|
||||||
|
for b in data.iter().take(buffer.len() / 2) {
|
||||||
|
let hi: usize = ((b & 0xf0) >> 4).into();
|
||||||
|
let lo: usize = (b & 0x0f).into();
|
||||||
|
buffer[i] = HEX_LOWER[hi];
|
||||||
|
buffer[i + 1] = HEX_LOWER[lo];
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,195 @@
|
|||||||
|
use crate::ui::{
|
||||||
|
component::{
|
||||||
|
text::paragraphs::{ParagraphVecShort, Paragraphs},
|
||||||
|
Child, Component, ComponentExt, Event, EventCtx, Label, Pad,
|
||||||
|
},
|
||||||
|
constant,
|
||||||
|
constant::screen,
|
||||||
|
display::{Color, Icon},
|
||||||
|
geometry::{Alignment, Insets, Offset, Point, Rect, TOP_CENTER},
|
||||||
|
model_tt::{
|
||||||
|
bootloader::theme::{
|
||||||
|
button_bld_menu, BUTTON_AREA_START, CLOSE, CONTENT_PADDING, CORNER_BUTTON_AREA,
|
||||||
|
INFO_SMALL, TEXT_TITLE, TITLE_AREA,
|
||||||
|
},
|
||||||
|
component::{Button, ButtonMsg::Clicked},
|
||||||
|
constant::WIDTH,
|
||||||
|
theme::WHITE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, ToPrimitive)]
|
||||||
|
pub enum ConfirmMsg {
|
||||||
|
Cancel = 1,
|
||||||
|
Confirm = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Confirm<'a> {
|
||||||
|
bg: Pad,
|
||||||
|
content_pad: Pad,
|
||||||
|
bg_color: Color,
|
||||||
|
icon: Option<Icon>,
|
||||||
|
title: Option<Child<Label<&'static str>>>,
|
||||||
|
message: Child<Paragraphs<ParagraphVecShort<&'a str>>>,
|
||||||
|
left: Child<Button<&'static str>>,
|
||||||
|
right: Child<Button<&'static str>>,
|
||||||
|
info_button: Option<Button<&'static str>>,
|
||||||
|
close_button: Option<Button<&'static str>>,
|
||||||
|
info_title: Option<Child<Label<&'static str>>>,
|
||||||
|
info_text: Option<Paragraphs<ParagraphVecShort<&'a str>>>,
|
||||||
|
show_info: bool,
|
||||||
|
|
||||||
|
confirm_left: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Confirm<'a> {
|
||||||
|
pub fn new(
|
||||||
|
bg_color: Color,
|
||||||
|
icon: Option<Icon>,
|
||||||
|
left: Button<&'static str>,
|
||||||
|
right: Button<&'static str>,
|
||||||
|
confirm_left: bool,
|
||||||
|
confirm: (Option<&'static str>, Paragraphs<ParagraphVecShort<&'a str>>),
|
||||||
|
info: Option<(&'static str, Paragraphs<ParagraphVecShort<&'a str>>)>,
|
||||||
|
) -> Self {
|
||||||
|
let mut instance = Self {
|
||||||
|
bg: Pad::with_background(bg_color),
|
||||||
|
content_pad: Pad::with_background(bg_color),
|
||||||
|
bg_color,
|
||||||
|
icon,
|
||||||
|
message: Child::new(confirm.1),
|
||||||
|
left: Child::new(left),
|
||||||
|
right: Child::new(right),
|
||||||
|
close_button: None,
|
||||||
|
info_button: None,
|
||||||
|
info_title: None,
|
||||||
|
info_text: None,
|
||||||
|
confirm_left,
|
||||||
|
show_info: false,
|
||||||
|
title: confirm
|
||||||
|
.0
|
||||||
|
.map(|title| Child::new(Label::new(title, Alignment::Start, TEXT_TITLE))),
|
||||||
|
};
|
||||||
|
if let Some((title, text)) = info {
|
||||||
|
instance.info_title = Some(Child::new(Label::new(title, Alignment::Start, TEXT_TITLE)));
|
||||||
|
instance.info_text = Some(text);
|
||||||
|
instance.info_button = Some(
|
||||||
|
Button::with_icon(Icon::new(INFO_SMALL))
|
||||||
|
.styled(button_bld_menu())
|
||||||
|
.with_expanded_touch_area(Insets::uniform(13)),
|
||||||
|
);
|
||||||
|
instance.close_button = Some(
|
||||||
|
Button::with_icon(Icon::new(CLOSE))
|
||||||
|
.styled(button_bld_menu())
|
||||||
|
.with_expanded_touch_area(Insets::uniform(13)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
instance.bg.clear();
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Component for Confirm<'a> {
|
||||||
|
type Msg = ConfirmMsg;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
self.bg.place(constant::screen());
|
||||||
|
self.content_pad.place(Rect::new(
|
||||||
|
Point::zero(),
|
||||||
|
Point::new(WIDTH, BUTTON_AREA_START),
|
||||||
|
));
|
||||||
|
let icon_height = if let Some(icon) = self.icon {
|
||||||
|
icon.toif.height()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
self.message.place(Rect::new(
|
||||||
|
Point::new(CONTENT_PADDING, 32 + icon_height),
|
||||||
|
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START),
|
||||||
|
));
|
||||||
|
|
||||||
|
let button_size = Offset::new(106, 38);
|
||||||
|
self.left.place(Rect::from_top_left_and_size(
|
||||||
|
Point::new(CONTENT_PADDING, BUTTON_AREA_START),
|
||||||
|
button_size,
|
||||||
|
));
|
||||||
|
self.right.place(Rect::from_top_left_and_size(
|
||||||
|
Point::new(124, BUTTON_AREA_START),
|
||||||
|
button_size,
|
||||||
|
));
|
||||||
|
self.info_button.place(CORNER_BUTTON_AREA);
|
||||||
|
self.close_button.place(CORNER_BUTTON_AREA);
|
||||||
|
self.info_title.place(TITLE_AREA);
|
||||||
|
self.title.place(TITLE_AREA);
|
||||||
|
self.info_text.place(Rect::new(
|
||||||
|
Point::new(CONTENT_PADDING, TITLE_AREA.y1),
|
||||||
|
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START),
|
||||||
|
));
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
if self.show_info {
|
||||||
|
if let Some(Clicked) = self.close_button.event(ctx, event) {
|
||||||
|
self.show_info = false;
|
||||||
|
self.content_pad.clear();
|
||||||
|
self.title.request_complete_repaint(ctx);
|
||||||
|
self.message.request_complete_repaint(ctx);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
} else if let Some(Clicked) = self.info_button.event(ctx, event) {
|
||||||
|
self.show_info = true;
|
||||||
|
self.info_text.request_complete_repaint(ctx);
|
||||||
|
self.info_title.request_complete_repaint(ctx);
|
||||||
|
self.content_pad.clear();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if let Some(Clicked) = self.left.event(ctx, event) {
|
||||||
|
return if self.confirm_left {
|
||||||
|
Some(Self::Msg::Confirm)
|
||||||
|
} else {
|
||||||
|
Some(Self::Msg::Cancel)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if let Some(Clicked) = self.right.event(ctx, event) {
|
||||||
|
return if self.confirm_left {
|
||||||
|
Some(Self::Msg::Cancel)
|
||||||
|
} else {
|
||||||
|
Some(Self::Msg::Confirm)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(&mut self) {
|
||||||
|
self.bg.paint();
|
||||||
|
self.content_pad.paint();
|
||||||
|
|
||||||
|
if self.show_info {
|
||||||
|
self.close_button.paint();
|
||||||
|
self.info_title.paint();
|
||||||
|
self.info_text.paint();
|
||||||
|
self.left.paint();
|
||||||
|
self.right.paint();
|
||||||
|
} else {
|
||||||
|
self.info_button.paint();
|
||||||
|
self.title.paint();
|
||||||
|
self.message.paint();
|
||||||
|
self.left.paint();
|
||||||
|
self.right.paint();
|
||||||
|
if let Some(icon) = self.icon {
|
||||||
|
icon.draw(
|
||||||
|
Point::new(screen().center().x, 32),
|
||||||
|
TOP_CENTER,
|
||||||
|
WHITE,
|
||||||
|
self.bg_color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||||
|
self.left.bounds(sink);
|
||||||
|
self.right.bounds(sink);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
use crate::ui::{
|
||||||
|
component::{Component, Event, EventCtx, Never, Pad},
|
||||||
|
constant::screen,
|
||||||
|
display::{self, Font},
|
||||||
|
geometry::{Offset, Rect},
|
||||||
|
model_tt::bootloader::theme::{BLD_BG, BLD_TITLE_COLOR},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Connect {
|
||||||
|
bg: Pad,
|
||||||
|
message: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connect {
|
||||||
|
pub fn new(message: &'static str) -> Self {
|
||||||
|
let mut instance = Self {
|
||||||
|
bg: Pad::with_background(BLD_BG),
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
|
||||||
|
instance.bg.clear();
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Connect {
|
||||||
|
type Msg = Never;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
self.bg.place(screen());
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(&mut self) {
|
||||||
|
let font = Font::NORMAL;
|
||||||
|
|
||||||
|
self.bg.paint();
|
||||||
|
display::text_center(
|
||||||
|
screen().center() + Offset::y(font.text_height() / 2),
|
||||||
|
self.message,
|
||||||
|
Font::NORMAL,
|
||||||
|
BLD_TITLE_COLOR,
|
||||||
|
BLD_BG,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
use crate::ui::{
|
||||||
|
component::{
|
||||||
|
text::paragraphs::{ParagraphVecShort, Paragraphs},
|
||||||
|
Child, Component, Event, EventCtx, Label, Pad,
|
||||||
|
},
|
||||||
|
constant::screen,
|
||||||
|
display::Icon,
|
||||||
|
geometry::{Alignment, Insets, Point, Rect},
|
||||||
|
model_tt::{
|
||||||
|
bootloader::theme::{button_bld_menu, button_bld_menu_item, BLD_BG, MENU},
|
||||||
|
component::ButtonMsg::Clicked,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use heapless::String;
|
||||||
|
|
||||||
|
use crate::ui::model_tt::{
|
||||||
|
bootloader::theme::{CONTENT_PADDING, CORNER_BUTTON_AREA, TEXT_TITLE, TITLE_AREA},
|
||||||
|
component::Button,
|
||||||
|
constant::WIDTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Copy, Clone, ToPrimitive)]
|
||||||
|
pub enum IntroMsg {
|
||||||
|
Menu = 1,
|
||||||
|
Host = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Intro<'a> {
|
||||||
|
bg: Pad,
|
||||||
|
title: Child<Label<String<32>>>,
|
||||||
|
menu: Child<Button<&'static str>>,
|
||||||
|
host: Child<Button<&'static str>>,
|
||||||
|
text: Child<Paragraphs<ParagraphVecShort<&'a str>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Intro<'a> {
|
||||||
|
pub fn new(bld_version: &'static str, content: Paragraphs<ParagraphVecShort<&'a str>>) -> Self {
|
||||||
|
let mut title: String<32> = String::new();
|
||||||
|
unwrap!(title.push_str("BOOTLOADER "));
|
||||||
|
unwrap!(title.push_str(bld_version));
|
||||||
|
|
||||||
|
let mut instance = Self {
|
||||||
|
bg: Pad::with_background(BLD_BG),
|
||||||
|
title: Child::new(Label::new(title, Alignment::Start, TEXT_TITLE)),
|
||||||
|
menu: Child::new(
|
||||||
|
Button::with_icon(Icon::new(MENU))
|
||||||
|
.styled(button_bld_menu())
|
||||||
|
.with_expanded_touch_area(Insets::uniform(13)),
|
||||||
|
),
|
||||||
|
host: Child::new(Button::with_text("INSTALL FIRMWARE").styled(button_bld_menu_item())),
|
||||||
|
text: Child::new(content),
|
||||||
|
};
|
||||||
|
|
||||||
|
instance.bg.clear();
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Component for Intro<'a> {
|
||||||
|
type Msg = IntroMsg;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
const BUTTON_AREA_START: i16 = 188;
|
||||||
|
self.bg.place(screen());
|
||||||
|
self.title.place(TITLE_AREA);
|
||||||
|
self.menu.place(CORNER_BUTTON_AREA);
|
||||||
|
self.host.place(Rect::new(
|
||||||
|
Point::new(10, BUTTON_AREA_START),
|
||||||
|
Point::new(10 + 220, BUTTON_AREA_START + 38),
|
||||||
|
));
|
||||||
|
self.text.place(Rect::new(
|
||||||
|
Point::new(CONTENT_PADDING, 75),
|
||||||
|
Point::new(WIDTH - CONTENT_PADDING, BUTTON_AREA_START),
|
||||||
|
));
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
if let Some(Clicked) = self.menu.event(ctx, event) {
|
||||||
|
return Some(Self::Msg::Menu);
|
||||||
|
};
|
||||||
|
if let Some(Clicked) = self.host.event(ctx, event) {
|
||||||
|
return Some(Self::Msg::Host);
|
||||||
|
};
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(&mut self) {
|
||||||
|
self.bg.paint();
|
||||||
|
self.title.paint();
|
||||||
|
self.text.paint();
|
||||||
|
self.host.paint();
|
||||||
|
self.menu.paint();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||||
|
self.menu.bounds(sink);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
use crate::ui::{
|
||||||
|
component::{Child, Component, Event, EventCtx, Label, Pad},
|
||||||
|
constant::{screen, WIDTH},
|
||||||
|
display::Icon,
|
||||||
|
geometry::{Alignment, Insets, Point, Rect},
|
||||||
|
model_tt::{
|
||||||
|
bootloader::theme::{
|
||||||
|
button_bld_menu, button_bld_menu_item, BLD_BG, CLOSE, CONTENT_PADDING,
|
||||||
|
CORNER_BUTTON_AREA, ERASE, REBOOT, TEXT_TITLE, TITLE_AREA,
|
||||||
|
},
|
||||||
|
component::{Button, ButtonMsg::Clicked, IconText},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use heapless::String;
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
#[derive(Copy, Clone, ToPrimitive)]
|
||||||
|
pub enum MenuMsg {
|
||||||
|
Close = 1,
|
||||||
|
Reboot = 2,
|
||||||
|
FactoryReset = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Menu {
|
||||||
|
bg: Pad,
|
||||||
|
title: Child<Label<String<32>>>,
|
||||||
|
close: Child<Button<&'static str>>,
|
||||||
|
reboot: Child<Button<&'static str>>,
|
||||||
|
reset: Child<Button<&'static str>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Menu {
|
||||||
|
pub fn new(bld_version: &'static str) -> Self {
|
||||||
|
let content_reboot = IconText::new("REBOOT TREZOR", Icon::new(REBOOT));
|
||||||
|
let content_reset = IconText::new("FACTORY RESET", Icon::new(ERASE));
|
||||||
|
|
||||||
|
let mut title: String<32> = String::new();
|
||||||
|
unwrap!(title.push_str("BOOTLOADER "));
|
||||||
|
unwrap!(title.push_str(bld_version));
|
||||||
|
|
||||||
|
let mut instance = Self {
|
||||||
|
bg: Pad::with_background(BLD_BG),
|
||||||
|
title: Child::new(Label::new(title, Alignment::Start, TEXT_TITLE)),
|
||||||
|
close: Child::new(
|
||||||
|
Button::with_icon(Icon::new(CLOSE))
|
||||||
|
.styled(button_bld_menu())
|
||||||
|
.with_expanded_touch_area(Insets::uniform(13)),
|
||||||
|
),
|
||||||
|
reboot: Child::new(
|
||||||
|
Button::with_icon_and_text(content_reboot).styled(button_bld_menu_item()),
|
||||||
|
),
|
||||||
|
reset: Child::new(
|
||||||
|
Button::with_icon_and_text(content_reset).styled(button_bld_menu_item()),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
instance.bg.clear();
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Menu {
|
||||||
|
type Msg = MenuMsg;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
self.bg.place(screen());
|
||||||
|
self.title.place(TITLE_AREA);
|
||||||
|
self.close.place(CORNER_BUTTON_AREA);
|
||||||
|
self.reboot.place(Rect::new(
|
||||||
|
Point::new(CONTENT_PADDING, 64),
|
||||||
|
Point::new(WIDTH - CONTENT_PADDING, 64 + 38),
|
||||||
|
));
|
||||||
|
self.reset.place(Rect::new(
|
||||||
|
Point::new(CONTENT_PADDING, 110),
|
||||||
|
Point::new(WIDTH - CONTENT_PADDING, 110 + 38),
|
||||||
|
));
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
if let Some(Clicked) = self.close.event(ctx, event) {
|
||||||
|
return Some(Self::Msg::Close);
|
||||||
|
}
|
||||||
|
if let Some(Clicked) = self.reboot.event(ctx, event) {
|
||||||
|
return Some(Self::Msg::Reboot);
|
||||||
|
}
|
||||||
|
if let Some(Clicked) = self.reset.event(ctx, event) {
|
||||||
|
return Some(Self::Msg::FactoryReset);
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(&mut self) {
|
||||||
|
self.bg.paint();
|
||||||
|
self.title.paint();
|
||||||
|
self.close.paint();
|
||||||
|
self.reboot.paint();
|
||||||
|
self.reset.paint();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bounds(&self, sink: &mut dyn FnMut(Rect)) {
|
||||||
|
self.close.bounds(sink);
|
||||||
|
self.reboot.bounds(sink);
|
||||||
|
self.reset.bounds(sink);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,513 @@
|
|||||||
|
use crate::{
|
||||||
|
trezorhal::io::io_touch_read,
|
||||||
|
ui::{
|
||||||
|
component::{Component, Event, EventCtx, Never},
|
||||||
|
display::{self, Font},
|
||||||
|
event::TouchEvent,
|
||||||
|
geometry::Point,
|
||||||
|
model_tt::constant,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use heapless::String;
|
||||||
|
use num_traits::ToPrimitive;
|
||||||
|
|
||||||
|
pub mod confirm;
|
||||||
|
mod connect;
|
||||||
|
pub mod intro;
|
||||||
|
pub mod menu;
|
||||||
|
pub mod theme;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
strutil::hexlify,
|
||||||
|
ui::{
|
||||||
|
component::text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt},
|
||||||
|
constant::screen,
|
||||||
|
display::{Color, Icon},
|
||||||
|
geometry::{LinearPlacement, CENTER},
|
||||||
|
model_tt::{
|
||||||
|
bootloader::{
|
||||||
|
connect::Connect,
|
||||||
|
theme::{
|
||||||
|
button_install_cancel, button_install_confirm, button_wipe_cancel,
|
||||||
|
button_wipe_confirm, BLD_BG, BLD_FG, BLD_WIPE_COLOR, ERASE_BIG, LOGO_EMPTY,
|
||||||
|
RECEIVE, TEXT_WIPE_BOLD, WELCOME_COLOR,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
component::{Button, ResultScreen},
|
||||||
|
theme::{
|
||||||
|
BACKLIGHT_DIM, BACKLIGHT_NORMAL, BG, BLACK, FG, GREY_DARK, ICON_SUCCESS_SMALL,
|
||||||
|
ICON_WARN_SMALL, TEXT_ERROR_BOLD, TEXT_ERROR_NORMAL, WHITE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
util::{from_c_array, from_c_str},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use confirm::Confirm;
|
||||||
|
use intro::Intro;
|
||||||
|
use menu::Menu;
|
||||||
|
|
||||||
|
pub trait ReturnToC {
|
||||||
|
fn return_to_c(self) -> u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReturnToC for Never {
|
||||||
|
fn return_to_c(self) -> u32 {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> ReturnToC for T
|
||||||
|
where
|
||||||
|
T: ToPrimitive,
|
||||||
|
{
|
||||||
|
fn return_to_c(self) -> u32 {
|
||||||
|
self.to_u32().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fadein() {
|
||||||
|
display::fade_backlight_duration(BACKLIGHT_NORMAL, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fadeout() {
|
||||||
|
display::fade_backlight_duration(BACKLIGHT_DIM, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run<F>(frame: &mut F) -> u32
|
||||||
|
where
|
||||||
|
F: Component,
|
||||||
|
F::Msg: ReturnToC,
|
||||||
|
{
|
||||||
|
frame.place(constant::screen());
|
||||||
|
fadeout();
|
||||||
|
display::sync();
|
||||||
|
frame.paint();
|
||||||
|
fadein();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let event = touch_eval();
|
||||||
|
if let Some(e) = event {
|
||||||
|
let mut ctx = EventCtx::new();
|
||||||
|
let msg = frame.event(&mut ctx, Event::Touch(e));
|
||||||
|
|
||||||
|
if let Some(message) = msg {
|
||||||
|
return message.return_to_c();
|
||||||
|
}
|
||||||
|
display::sync();
|
||||||
|
frame.paint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show<F>(frame: &mut F, fading: bool)
|
||||||
|
where
|
||||||
|
F: Component,
|
||||||
|
{
|
||||||
|
frame.place(screen());
|
||||||
|
if fading {
|
||||||
|
fadeout()
|
||||||
|
};
|
||||||
|
display::sync();
|
||||||
|
frame.paint();
|
||||||
|
if fading {
|
||||||
|
fadein()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn touch_eval() -> Option<TouchEvent> {
|
||||||
|
let event = io_touch_read();
|
||||||
|
if event == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let event_type = event >> 24;
|
||||||
|
let ex = ((event >> 12) & 0xFFF) as i16;
|
||||||
|
let ey = (event & 0xFFF) as i16;
|
||||||
|
|
||||||
|
TouchEvent::new(event_type, ex as _, ey as _).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_install_confirm(
|
||||||
|
vendor_str: *const cty::c_char,
|
||||||
|
vendor_str_len: u8,
|
||||||
|
version: *const cty::c_char,
|
||||||
|
fingerprint: *const cty::uint8_t,
|
||||||
|
downgrade: bool,
|
||||||
|
vendor: bool,
|
||||||
|
) -> u32 {
|
||||||
|
let text = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
|
||||||
|
let version = unwrap!(unsafe { from_c_str(version) });
|
||||||
|
|
||||||
|
let mut fingerprint_buffer: [u8; 64] = [0; 64];
|
||||||
|
let fingerprint_str = unsafe {
|
||||||
|
let fingerprint_slice = core::slice::from_raw_parts(fingerprint as *const u8, 32);
|
||||||
|
hexlify(fingerprint_slice, &mut fingerprint_buffer);
|
||||||
|
core::str::from_utf8_unchecked(fingerprint_buffer.as_ref())
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut version_str: String<64> = String::new();
|
||||||
|
unwrap!(version_str.push_str("Firmware version "));
|
||||||
|
unwrap!(version_str.push_str(version));
|
||||||
|
|
||||||
|
let mut vendor_str: String<64> = String::new();
|
||||||
|
unwrap!(vendor_str.push_str("by "));
|
||||||
|
unwrap!(vendor_str.push_str(text));
|
||||||
|
|
||||||
|
let title = if downgrade {
|
||||||
|
"DOWNGRADE FW"
|
||||||
|
} else if vendor {
|
||||||
|
"CHANGE FW VENDOR"
|
||||||
|
} else {
|
||||||
|
"UPDATE FIRMWARE"
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_NORMAL, version_str.as_ref()));
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_NORMAL, vendor_str.as_ref()));
|
||||||
|
|
||||||
|
if vendor || downgrade {
|
||||||
|
messages
|
||||||
|
.add(Paragraph::new(&theme::TEXT_BOLD, "Seed will be erased!").with_top_padding(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
let message =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_FINGERPRINT, fingerprint_str));
|
||||||
|
|
||||||
|
let fingerprint =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let left = Button::with_text("CANCEL").styled(button_install_cancel());
|
||||||
|
let right = Button::with_text("INSTALL").styled(button_install_confirm());
|
||||||
|
|
||||||
|
let mut frame = Confirm::new(
|
||||||
|
BLD_BG,
|
||||||
|
None,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
false,
|
||||||
|
(Some(title), message),
|
||||||
|
Some(("FW FINGERPRINT", fingerprint)),
|
||||||
|
);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_wipe_confirm() -> u32 {
|
||||||
|
let icon = Some(Icon::new(ERASE_BIG));
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(
|
||||||
|
Paragraph::new(
|
||||||
|
&TEXT_ERROR_NORMAL,
|
||||||
|
"Are you sure you want to factory reset the device?",
|
||||||
|
)
|
||||||
|
.centered(),
|
||||||
|
);
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "Seed and firmware\nwill be erased!").centered());
|
||||||
|
|
||||||
|
let message =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let left = Button::with_text("RESET").styled(button_wipe_confirm());
|
||||||
|
let right = Button::with_text("CANCEL").styled(button_wipe_cancel());
|
||||||
|
|
||||||
|
let mut frame = Confirm::new(
|
||||||
|
BLD_WIPE_COLOR,
|
||||||
|
icon,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
true,
|
||||||
|
(None, message),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_menu(bld_version: *const cty::c_char) -> u32 {
|
||||||
|
let bld_version = unwrap!(unsafe { from_c_str(bld_version) });
|
||||||
|
|
||||||
|
run(&mut Menu::new(bld_version))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_intro(
|
||||||
|
bld_version: *const cty::c_char,
|
||||||
|
vendor_str: *const cty::c_char,
|
||||||
|
vendor_str_len: u8,
|
||||||
|
version: *const cty::c_char,
|
||||||
|
) -> u32 {
|
||||||
|
let vendor = unwrap!(unsafe { from_c_array(vendor_str, vendor_str_len as usize) });
|
||||||
|
let version = unwrap!(unsafe { from_c_str(version) });
|
||||||
|
let bld_version = unwrap!(unsafe { from_c_str(bld_version) });
|
||||||
|
|
||||||
|
let mut fw: String<64> = String::new();
|
||||||
|
unwrap!(fw.push_str("Firmware "));
|
||||||
|
unwrap!(fw.push_str(version));
|
||||||
|
|
||||||
|
let mut vendor_: String<64> = String::new();
|
||||||
|
unwrap!(vendor_.push_str("by "));
|
||||||
|
unwrap!(vendor_.push_str(vendor));
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_NORMAL, fw.as_ref()));
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_NORMAL, vendor_.as_ref()));
|
||||||
|
|
||||||
|
let p = Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_start());
|
||||||
|
|
||||||
|
let mut frame = Intro::new(bld_version, p);
|
||||||
|
|
||||||
|
run(&mut frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_progress(
|
||||||
|
text: &str,
|
||||||
|
progress: u16,
|
||||||
|
initialize: bool,
|
||||||
|
fg_color: Color,
|
||||||
|
bg_color: Color,
|
||||||
|
icon: Option<(Icon, Color)>,
|
||||||
|
) {
|
||||||
|
if initialize {
|
||||||
|
fadeout();
|
||||||
|
display::rect_fill(constant::screen(), bg_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
display::text_center(
|
||||||
|
Point::new(constant::WIDTH / 2, 214),
|
||||||
|
text,
|
||||||
|
Font::NORMAL,
|
||||||
|
fg_color,
|
||||||
|
bg_color,
|
||||||
|
);
|
||||||
|
display::loader(progress, -20, fg_color, bg_color, icon);
|
||||||
|
if initialize {
|
||||||
|
fadein();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_install_progress(progress: u16, initialize: bool, initial_setup: bool) {
|
||||||
|
let bg_color = if initial_setup { WELCOME_COLOR } else { BG };
|
||||||
|
let fg_color = if initial_setup { FG } else { BLD_FG };
|
||||||
|
|
||||||
|
screen_progress(
|
||||||
|
"Installing firmware...",
|
||||||
|
progress,
|
||||||
|
initialize,
|
||||||
|
fg_color,
|
||||||
|
bg_color,
|
||||||
|
Some((Icon::new(RECEIVE), fg_color)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_wipe_progress(progress: u16, initialize: bool) {
|
||||||
|
screen_progress(
|
||||||
|
"Resetting Trezor...",
|
||||||
|
progress,
|
||||||
|
initialize,
|
||||||
|
theme::BLD_FG,
|
||||||
|
BLD_WIPE_COLOR,
|
||||||
|
Some((Icon::new(ERASE_BIG), theme::BLD_FG)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_connect() {
|
||||||
|
let mut frame = Connect::new("Waiting for host...");
|
||||||
|
show(&mut frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_wipe_success() {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "Trezor reset").centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "successfully.").centered());
|
||||||
|
|
||||||
|
let m_top =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "PLEASE RECONNECT").centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "THE DEVICE").centered());
|
||||||
|
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
WHITE,
|
||||||
|
BLD_WIPE_COLOR,
|
||||||
|
Icon::new(ICON_SUCCESS_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
show(&mut frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_wipe_fail() {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "Trezor reset was").centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "not successful.").centered());
|
||||||
|
let m_top =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "PLEASE RECONNECT").centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_WIPE_BOLD, "THE DEVICE").centered());
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
WHITE,
|
||||||
|
BLD_WIPE_COLOR,
|
||||||
|
Icon::new(ICON_WARN_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
show(&mut frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_boot_empty(firmware_present: bool, fading: bool) {
|
||||||
|
if fading {
|
||||||
|
fadeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
let fg = if firmware_present { GREY_DARK } else { WHITE };
|
||||||
|
let bg = if firmware_present {
|
||||||
|
BLACK
|
||||||
|
} else {
|
||||||
|
WELCOME_COLOR
|
||||||
|
};
|
||||||
|
display::rect_fill(constant::screen(), bg);
|
||||||
|
let icon = Icon::new(LOGO_EMPTY);
|
||||||
|
icon.draw(screen().center(), CENTER, fg, bg);
|
||||||
|
|
||||||
|
if fading {
|
||||||
|
fadein();
|
||||||
|
} else {
|
||||||
|
display::set_backlight(BACKLIGHT_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_install_fail() {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_BOLD, "Firmware installation was").centered());
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_BOLD, "not successful.").centered());
|
||||||
|
|
||||||
|
let m_top =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_SUBMSG, "PLEASE RECONNECT").centered());
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_SUBMSG, "THE DEVICE").centered());
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
WHITE,
|
||||||
|
BLD_BG,
|
||||||
|
Icon::new(ICON_WARN_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
show(&mut frame, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_install_success_bld(msg: &'static str, complete_draw: bool) {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_BOLD, "Firmware installed").centered());
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_BOLD, "successfully.").centered());
|
||||||
|
let m_top =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_SUBMSG, msg).centered());
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
WHITE,
|
||||||
|
BLD_BG,
|
||||||
|
Icon::new(ICON_SUCCESS_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
complete_draw,
|
||||||
|
);
|
||||||
|
show(&mut frame, complete_draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_install_success_initial(msg: &'static str, complete_draw: bool) {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_WELCOME_BOLD, "Firmware installed").centered());
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_WELCOME_BOLD, "successfully.").centered());
|
||||||
|
|
||||||
|
let m_top =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_SUBMSG_INITIAL, msg).centered());
|
||||||
|
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
FG,
|
||||||
|
WELCOME_COLOR,
|
||||||
|
Icon::new(ICON_SUCCESS_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
complete_draw,
|
||||||
|
);
|
||||||
|
show(&mut frame, complete_draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_install_success(
|
||||||
|
reboot_msg: *const cty::c_char,
|
||||||
|
initial_setup: bool,
|
||||||
|
complete_draw: bool,
|
||||||
|
) {
|
||||||
|
let msg = unwrap!(unsafe { from_c_str(reboot_msg) });
|
||||||
|
if initial_setup {
|
||||||
|
screen_install_success_initial(msg, complete_draw)
|
||||||
|
} else {
|
||||||
|
screen_install_success_bld(msg, complete_draw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_welcome() {
|
||||||
|
fadeout();
|
||||||
|
display::rect_fill(screen(), WELCOME_COLOR);
|
||||||
|
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_WELCOME, "Get started with").centered());
|
||||||
|
messages.add(Paragraph::new(&theme::TEXT_WELCOME, "your trezor at").centered());
|
||||||
|
messages.add(
|
||||||
|
Paragraph::new(&theme::TEXT_WELCOME_BOLD, "trezor.io/start")
|
||||||
|
.centered()
|
||||||
|
.with_top_padding(2),
|
||||||
|
);
|
||||||
|
let mut frame =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
show(&mut frame, false);
|
||||||
|
fadein();
|
||||||
|
}
|
@ -0,0 +1,304 @@
|
|||||||
|
use crate::{
|
||||||
|
alpha,
|
||||||
|
ui::{
|
||||||
|
component::{text::TextStyle, LineBreaking::BreakWordsNoHyphen},
|
||||||
|
constant::WIDTH,
|
||||||
|
display::{Color, Font},
|
||||||
|
geometry::{Offset, Point, Rect},
|
||||||
|
model_tt::{
|
||||||
|
component::{ButtonStyle, ButtonStyleSheet},
|
||||||
|
theme::{BLACK, FG, GREY_DARK, GREY_LIGHT, GREY_MEDIUM, WHITE},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BLD_BG: Color = Color::rgb(0x00, 0x17, 0xA3);
|
||||||
|
pub const BLD_FG: Color = WHITE;
|
||||||
|
pub const BLD_WIPE_COLOR: Color = Color::rgb(0xAD, 0x2B, 0x2B);
|
||||||
|
pub const BLD_WIPE_TEXT_COLOR: Color = Color::rgb(0xD6, 0x95, 0x95);
|
||||||
|
|
||||||
|
pub const BLD_WIPE_BTN_COLOR: Color = Color::alpha(BLD_WIPE_COLOR, alpha!(0.3));
|
||||||
|
pub const BLD_WIPE_BTN_COLOR_ACTIVE: Color = Color::rgb(0xB9, 0x4B, 0x4B);
|
||||||
|
pub const BLD_WIPE_CANCEL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xF3, 0xDF, 0xDF);
|
||||||
|
|
||||||
|
pub const BLD_INSTALL_BTN_COLOR: Color = Color::alpha(BLD_BG, alpha!(0.3));
|
||||||
|
pub const BLD_INSTALL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xD9, 0xDC, 0xF1);
|
||||||
|
pub const BLD_INSTALL_CANCEL_BTN_COLOR_ACTIVE: Color = Color::rgb(0x26, 0x3A, 0xB1);
|
||||||
|
|
||||||
|
pub const BLD_COLOR_SUBMSG: Color = Color::rgb(0x80, 0x8B, 0xD1);
|
||||||
|
|
||||||
|
pub const BLD_BTN_MENU_COLOR: Color = Color::alpha(BLD_BG, alpha!(0.22));
|
||||||
|
pub const BLD_BTN_MENU_COLOR_ACTIVE: Color = Color::alpha(BLD_BG, alpha!(0.11));
|
||||||
|
pub const BLD_BTN_MENUITEM_COLOR: Color = Color::alpha(BLD_BG, alpha!(0.33));
|
||||||
|
pub const BLD_BTN_MENUITEM_COLOR_ACTIVE: Color =
|
||||||
|
Color::rgba(BLD_BG, 0xFF, 0xFF, 0xFF, alpha!(0.11));
|
||||||
|
pub const BLD_TITLE_COLOR: Color = Color::rgba(BLD_BG, 0xFF, 0xFF, 0xFF, alpha!(0.75));
|
||||||
|
|
||||||
|
pub const WELCOME_COLOR: Color = BLACK;
|
||||||
|
|
||||||
|
// Commonly used corner radius (i.e. for buttons).
|
||||||
|
pub const RADIUS: u8 = 2;
|
||||||
|
|
||||||
|
// Commonly used constants for UI elements.
|
||||||
|
pub const CONTENT_PADDING: i16 = 10;
|
||||||
|
pub const TITLE_AREA: Rect = Rect::new(Point::new(15, 14), Point::new(200, 30));
|
||||||
|
pub const CORNER_BUTTON_SIZE: i16 = 32;
|
||||||
|
pub const CORNER_BUTTON_PADDING: i16 = 8;
|
||||||
|
pub const CORNER_BUTTON_AREA: Rect = Rect::from_top_left_and_size(
|
||||||
|
Point::new(
|
||||||
|
WIDTH - CORNER_BUTTON_SIZE - CORNER_BUTTON_PADDING,
|
||||||
|
CORNER_BUTTON_PADDING,
|
||||||
|
),
|
||||||
|
Offset::uniform(CORNER_BUTTON_SIZE),
|
||||||
|
);
|
||||||
|
pub const TITLE_AREA_HEIGHT: i16 = 16;
|
||||||
|
pub const TITLE_AREA_START_Y: i16 = 8;
|
||||||
|
pub const BUTTON_AREA_START: i16 = 188;
|
||||||
|
|
||||||
|
// UI icons.
|
||||||
|
pub const ICON_CANCEL: &[u8] = include_res!("model_tt/res/cancel.toif");
|
||||||
|
pub const ICON_CONFIRM: &[u8] = include_res!("model_tt/res/confirm.toif");
|
||||||
|
|
||||||
|
// BLD icons
|
||||||
|
pub const CLOSE: &[u8] = include_res!("model_tt/res/close.toif");
|
||||||
|
pub const ERASE: &[u8] = include_res!("model_tt/res/erase.toif");
|
||||||
|
pub const ERASE_BIG: &[u8] = include_res!("model_tt/res/erase_big.toif");
|
||||||
|
pub const REBOOT: &[u8] = include_res!("model_tt/res/reboot.toif");
|
||||||
|
pub const MENU: &[u8] = include_res!("model_tt/res/menu.toif");
|
||||||
|
pub const RECEIVE: &[u8] = include_res!("model_tt/res/receive.toif");
|
||||||
|
pub const LOGO_EMPTY: &[u8] = include_res!("model_tt/res/trezor_empty.toif");
|
||||||
|
pub const INFO_SMALL: &[u8] = include_res!("model_tt/res/info_small.toif");
|
||||||
|
|
||||||
|
pub fn button_install_cancel() -> ButtonStyleSheet {
|
||||||
|
ButtonStyleSheet {
|
||||||
|
normal: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: WHITE,
|
||||||
|
button_color: BLD_BTN_MENUITEM_COLOR,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
active: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: WHITE,
|
||||||
|
button_color: BLD_INSTALL_CANCEL_BTN_COLOR_ACTIVE,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
disabled: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: GREY_LIGHT,
|
||||||
|
button_color: GREY_DARK,
|
||||||
|
background_color: WHITE,
|
||||||
|
border_color: WHITE,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button_install_confirm() -> ButtonStyleSheet {
|
||||||
|
ButtonStyleSheet {
|
||||||
|
normal: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_BG,
|
||||||
|
button_color: WHITE,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
active: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_BG,
|
||||||
|
button_color: BLD_INSTALL_BTN_COLOR_ACTIVE,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
disabled: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: FG,
|
||||||
|
button_color: GREY_DARK,
|
||||||
|
background_color: FG,
|
||||||
|
border_color: FG,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button_wipe_cancel() -> ButtonStyleSheet {
|
||||||
|
ButtonStyleSheet {
|
||||||
|
normal: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_WIPE_COLOR,
|
||||||
|
button_color: WHITE,
|
||||||
|
background_color: BLD_WIPE_COLOR,
|
||||||
|
border_color: BLD_WIPE_COLOR,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
active: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_WIPE_COLOR,
|
||||||
|
button_color: BLD_WIPE_CANCEL_BTN_COLOR_ACTIVE,
|
||||||
|
background_color: BLD_WIPE_COLOR,
|
||||||
|
border_color: BLD_WIPE_COLOR,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
disabled: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: GREY_LIGHT,
|
||||||
|
button_color: GREY_DARK,
|
||||||
|
background_color: WHITE,
|
||||||
|
border_color: WHITE,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button_wipe_confirm() -> ButtonStyleSheet {
|
||||||
|
ButtonStyleSheet {
|
||||||
|
normal: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: WHITE,
|
||||||
|
button_color: BLD_WIPE_BTN_COLOR,
|
||||||
|
background_color: BLD_WIPE_COLOR,
|
||||||
|
border_color: BLD_WIPE_COLOR,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
active: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: WHITE,
|
||||||
|
button_color: BLD_WIPE_BTN_COLOR_ACTIVE,
|
||||||
|
background_color: BLD_WIPE_COLOR,
|
||||||
|
border_color: BLD_WIPE_COLOR,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
disabled: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: FG,
|
||||||
|
button_color: GREY_DARK,
|
||||||
|
background_color: FG,
|
||||||
|
border_color: FG,
|
||||||
|
border_radius: RADIUS,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button_bld_menu() -> ButtonStyleSheet {
|
||||||
|
ButtonStyleSheet {
|
||||||
|
normal: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_FG,
|
||||||
|
button_color: BLD_BTN_MENU_COLOR,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: 4,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
active: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_FG,
|
||||||
|
button_color: BLD_BTN_MENU_COLOR_ACTIVE,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: 4,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
disabled: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: GREY_LIGHT,
|
||||||
|
button_color: BLD_BTN_MENU_COLOR,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: 4,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button_bld_menu_item() -> ButtonStyleSheet {
|
||||||
|
ButtonStyleSheet {
|
||||||
|
normal: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_FG,
|
||||||
|
button_color: BLD_BTN_MENUITEM_COLOR,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: 4,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
active: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: BLD_FG,
|
||||||
|
button_color: BLD_BTN_MENUITEM_COLOR_ACTIVE,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: 4,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
disabled: &ButtonStyle {
|
||||||
|
font: Font::BOLD,
|
||||||
|
text_color: GREY_LIGHT,
|
||||||
|
button_color: BLD_BTN_MENUITEM_COLOR,
|
||||||
|
background_color: BLD_BG,
|
||||||
|
border_color: BLD_BG,
|
||||||
|
border_radius: 4,
|
||||||
|
border_width: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub const TEXT_WELCOME: TextStyle = TextStyle::new(
|
||||||
|
Font::NORMAL,
|
||||||
|
GREY_MEDIUM,
|
||||||
|
WELCOME_COLOR,
|
||||||
|
GREY_MEDIUM,
|
||||||
|
GREY_MEDIUM,
|
||||||
|
);
|
||||||
|
pub const TEXT_WELCOME_BOLD: TextStyle = TextStyle::new(Font::BOLD, FG, WELCOME_COLOR, FG, FG);
|
||||||
|
pub const TEXT_TITLE: TextStyle = TextStyle::new(
|
||||||
|
Font::BOLD,
|
||||||
|
BLD_TITLE_COLOR,
|
||||||
|
BLD_BG,
|
||||||
|
BLD_TITLE_COLOR,
|
||||||
|
BLD_TITLE_COLOR,
|
||||||
|
);
|
||||||
|
pub const TEXT_SUBMSG_INITIAL: TextStyle = TextStyle::new(
|
||||||
|
Font::BOLD,
|
||||||
|
GREY_MEDIUM,
|
||||||
|
WELCOME_COLOR,
|
||||||
|
GREY_MEDIUM,
|
||||||
|
GREY_MEDIUM,
|
||||||
|
);
|
||||||
|
|
||||||
|
pub const TEXT_NORMAL: TextStyle = TextStyle::new(Font::NORMAL, BLD_FG, BLD_BG, BLD_FG, BLD_FG);
|
||||||
|
pub const TEXT_FINGERPRINT: TextStyle =
|
||||||
|
TextStyle::new(Font::NORMAL, BLD_FG, BLD_BG, BLD_FG, BLD_FG)
|
||||||
|
.with_line_breaking(BreakWordsNoHyphen);
|
||||||
|
pub const TEXT_BOLD: TextStyle = TextStyle::new(Font::BOLD, BLD_FG, BLD_BG, BLD_FG, BLD_FG);
|
||||||
|
pub const TEXT_WIPE_BOLD: TextStyle = TextStyle::new(
|
||||||
|
Font::BOLD,
|
||||||
|
BLD_WIPE_TEXT_COLOR,
|
||||||
|
BLD_WIPE_COLOR,
|
||||||
|
BLD_WIPE_TEXT_COLOR,
|
||||||
|
BLD_WIPE_TEXT_COLOR,
|
||||||
|
);
|
||||||
|
pub const TEXT_SUBMSG: TextStyle = TextStyle::new(
|
||||||
|
Font::BOLD,
|
||||||
|
BLD_COLOR_SUBMSG,
|
||||||
|
BLD_BG,
|
||||||
|
BLD_COLOR_SUBMSG,
|
||||||
|
BLD_COLOR_SUBMSG,
|
||||||
|
);
|
@ -0,0 +1,93 @@
|
|||||||
|
use crate::{
|
||||||
|
alpha,
|
||||||
|
ui::{
|
||||||
|
component::{
|
||||||
|
text::paragraphs::{ParagraphStrType, ParagraphVecShort, Paragraphs},
|
||||||
|
Child, Component, Event, EventCtx, Never, Pad,
|
||||||
|
},
|
||||||
|
constant::screen,
|
||||||
|
display::{self, Color, Icon},
|
||||||
|
geometry::{Offset, Point, Rect, CENTER},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::ui::model_tt::constant::{HEIGHT, WIDTH};
|
||||||
|
|
||||||
|
pub struct ResultScreen<T> {
|
||||||
|
bg: Pad,
|
||||||
|
small_pad: Pad,
|
||||||
|
fg_color: Color,
|
||||||
|
bg_color: Color,
|
||||||
|
icon: Icon,
|
||||||
|
message_top: Child<Paragraphs<ParagraphVecShort<T>>>,
|
||||||
|
message_bottom: Child<Paragraphs<ParagraphVecShort<T>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ParagraphStrType> ResultScreen<T> {
|
||||||
|
pub fn new(
|
||||||
|
fg_color: Color,
|
||||||
|
bg_color: Color,
|
||||||
|
icon: Icon,
|
||||||
|
message_top: Paragraphs<ParagraphVecShort<T>>,
|
||||||
|
message_bottom: Paragraphs<ParagraphVecShort<T>>,
|
||||||
|
complete_draw: bool,
|
||||||
|
) -> Self {
|
||||||
|
let mut instance = Self {
|
||||||
|
bg: Pad::with_background(bg_color),
|
||||||
|
small_pad: Pad::with_background(bg_color),
|
||||||
|
fg_color,
|
||||||
|
bg_color,
|
||||||
|
icon,
|
||||||
|
message_top: Child::new(message_top),
|
||||||
|
message_bottom: Child::new(message_bottom),
|
||||||
|
};
|
||||||
|
|
||||||
|
if complete_draw {
|
||||||
|
instance.bg.clear();
|
||||||
|
} else {
|
||||||
|
instance.small_pad.clear();
|
||||||
|
}
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ParagraphStrType> Component for ResultScreen<T> {
|
||||||
|
type Msg = Never;
|
||||||
|
|
||||||
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
|
self.bg
|
||||||
|
.place(Rect::new(Point::new(0, 0), Point::new(WIDTH, HEIGHT)));
|
||||||
|
|
||||||
|
self.message_top
|
||||||
|
.place(Rect::new(Point::new(15, 59), Point::new(WIDTH - 15, 149)));
|
||||||
|
|
||||||
|
let bottom_area = Rect::new(Point::new(15, 151), Point::new(WIDTH - 15, HEIGHT));
|
||||||
|
|
||||||
|
self.small_pad.place(bottom_area);
|
||||||
|
self.message_bottom.place(bottom_area);
|
||||||
|
|
||||||
|
bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(&mut self) {
|
||||||
|
self.bg.paint();
|
||||||
|
self.small_pad.paint();
|
||||||
|
|
||||||
|
self.icon.draw(
|
||||||
|
Point::new(screen().center().x, 45),
|
||||||
|
CENTER,
|
||||||
|
self.fg_color,
|
||||||
|
self.bg_color,
|
||||||
|
);
|
||||||
|
display::rect_fill(
|
||||||
|
Rect::from_top_left_and_size(Point::new(12, 149), Offset::new(216, 1)),
|
||||||
|
Color::alpha(self.bg_color, alpha!(0.2)),
|
||||||
|
);
|
||||||
|
self.message_top.paint();
|
||||||
|
self.message_bottom.paint();
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,104 @@
|
|||||||
|
#[cfg(feature = "micropython")]
|
||||||
|
use crate::micropython::buffer::StrBuffer;
|
||||||
|
use crate::ui::{
|
||||||
|
component::{
|
||||||
|
text::paragraphs::{Paragraph, ParagraphVecShort, Paragraphs, VecExt},
|
||||||
|
Component,
|
||||||
|
},
|
||||||
|
display::Icon,
|
||||||
|
geometry::LinearPlacement,
|
||||||
|
model_tt::{
|
||||||
|
component::ResultScreen,
|
||||||
|
constant,
|
||||||
|
theme::{FATAL_ERROR_COLOR, ICON_WARN_SMALL, TEXT_ERROR_BOLD, TEXT_ERROR_NORMAL, WHITE},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "micropython"))]
|
||||||
|
// SAFETY: Actually safe but see below
|
||||||
|
unsafe fn get_str(text: &str) -> &str {
|
||||||
|
text
|
||||||
|
}
|
||||||
|
#[cfg(feature = "micropython")]
|
||||||
|
// SAFETY: The caller is responsible for ensuring that the StrBuffer does not
|
||||||
|
// escape the lifetime of the original &str.
|
||||||
|
unsafe fn get_str(text: &str) -> StrBuffer {
|
||||||
|
unsafe { StrBuffer::from_ptr_and_len(text.as_ptr(), text.len()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn screen_fatal_error(msg: Option<&str>, file: &str) {
|
||||||
|
// SAFETY: these will get placed into `frame` which does not outlive this
|
||||||
|
// function
|
||||||
|
let msg = msg.map(|s| unsafe { get_str(s) });
|
||||||
|
let file = unsafe { get_str(file) };
|
||||||
|
|
||||||
|
let m_top = if let Some(msg) = msg {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "FATAL ERROR!".into()).centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, msg).centered());
|
||||||
|
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
|
||||||
|
} else {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "FATAL ERROR!".into()).centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, file).centered());
|
||||||
|
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
|
||||||
|
};
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages
|
||||||
|
.add(Paragraph::new(&TEXT_ERROR_BOLD, "PLEASE CONTACT\nTREZOR SUPPORT".into()).centered());
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
WHITE,
|
||||||
|
FATAL_ERROR_COLOR,
|
||||||
|
Icon::new(ICON_WARN_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
frame.place(constant::screen());
|
||||||
|
frame.paint();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn screen_error_shutdown(label: &str, msg: Option<&str>) {
|
||||||
|
// SAFETY: these will get placed into `frame` which does not outlive this
|
||||||
|
// function
|
||||||
|
let msg = msg.map(|s| unsafe { get_str(s) });
|
||||||
|
let label = unsafe { get_str(label) };
|
||||||
|
|
||||||
|
let m_top = if let Some(msg) = msg {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, label).centered());
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_NORMAL, msg).centered());
|
||||||
|
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
|
||||||
|
} else {
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, label).centered());
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center())
|
||||||
|
};
|
||||||
|
let mut messages = ParagraphVecShort::new();
|
||||||
|
|
||||||
|
messages.add(Paragraph::new(&TEXT_ERROR_BOLD, "PLEASE UNPLUG\nTHE DEVICE".into()).centered());
|
||||||
|
let m_bottom =
|
||||||
|
Paragraphs::new(messages).with_placement(LinearPlacement::vertical().align_at_center());
|
||||||
|
|
||||||
|
let mut frame = ResultScreen::new(
|
||||||
|
WHITE,
|
||||||
|
FATAL_ERROR_COLOR,
|
||||||
|
Icon::new(ICON_WARN_SMALL),
|
||||||
|
m_top,
|
||||||
|
m_bottom,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
frame.place(constant::screen());
|
||||||
|
frame.paint();
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
//! Reexporting the `screens` module according to the
|
||||||
|
//! current feature (Trezor model)
|
||||||
|
|
||||||
|
#[cfg(all(feature = "model_tr", not(feature = "model_tt")))]
|
||||||
|
pub use super::model_tr::screens::*;
|
||||||
|
#[cfg(feature = "model_tt")]
|
||||||
|
pub use super::model_tt::screens::*;
|
||||||
|
use crate::ui::util::from_c_str;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_fatal_error_c(msg: *const cty::c_char, file: *const cty::c_char) {
|
||||||
|
let msg = if msg.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
unsafe { from_c_str(msg) }
|
||||||
|
};
|
||||||
|
let file = if file.is_null() {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
unwrap!(unsafe { from_c_str(file) })
|
||||||
|
};
|
||||||
|
|
||||||
|
screen_fatal_error(msg, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn screen_error_shutdown_c(msg: *const cty::c_char, file: *const cty::c_char) {
|
||||||
|
let msg = if msg.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
unsafe { from_c_str(msg) }
|
||||||
|
};
|
||||||
|
let file = if file.is_null() {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
unwrap!(unsafe { from_c_str(file) })
|
||||||
|
};
|
||||||
|
|
||||||
|
screen_fatal_error(msg, file);
|
||||||
|
}
|
Loading…
Reference in new issue