2923 lines
79 KiB
C
2923 lines
79 KiB
C
/*******************************************************************************
|
|
* Ledger Blue
|
|
* (c) 2016 Ledger
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
********************************************************************************/
|
|
|
|
#include "os.h"
|
|
#include "cx.h"
|
|
#include <stdbool.h>
|
|
#include "ethUstream.h"
|
|
#include "ethUtils.h"
|
|
#include "uint256.h"
|
|
#include "tokens.h"
|
|
|
|
#include "os_io_seproxyhal.h"
|
|
#include "string.h"
|
|
|
|
#include "glyphs.h"
|
|
|
|
#ifdef HAVE_U2F
|
|
|
|
#include "u2f_service.h"
|
|
#include "u2f_transport.h"
|
|
|
|
volatile unsigned char u2fMessageBuffer[U2F_MAX_MESSAGE_SIZE];
|
|
|
|
extern void USB_power_U2F(unsigned char enabled, unsigned char fido);
|
|
extern bool fidoActivated;
|
|
|
|
#endif
|
|
|
|
unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
|
|
|
|
unsigned int io_seproxyhal_touch_settings(const bagl_element_t *e);
|
|
unsigned int io_seproxyhal_touch_exit(const bagl_element_t *e);
|
|
unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e);
|
|
unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e);
|
|
unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e);
|
|
unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e);
|
|
void ui_idle(void);
|
|
|
|
uint32_t set_result_get_publicKey(void);
|
|
|
|
#define MAX_BIP32_PATH 10
|
|
|
|
#define CLA 0xE0
|
|
#define INS_GET_PUBLIC_KEY 0x02
|
|
#define INS_SIGN 0x04
|
|
#define INS_GET_APP_CONFIGURATION 0x06
|
|
#define P1_CONFIRM 0x01
|
|
#define P1_NON_CONFIRM 0x00
|
|
#define P2_NO_CHAINCODE 0x00
|
|
#define P2_CHAINCODE 0x01
|
|
#define P1_FIRST 0x00
|
|
#define P1_MORE 0x80
|
|
|
|
#define OFFSET_CLA 0
|
|
#define OFFSET_INS 1
|
|
#define OFFSET_P1 2
|
|
#define OFFSET_P2 3
|
|
#define OFFSET_LC 4
|
|
#define OFFSET_CDATA 5
|
|
|
|
#define WEI_TO_ETHER 18
|
|
|
|
static const uint8_t const TOKEN_TRANSFER_ID[] = {0xa9, 0x05, 0x9c, 0xbb};
|
|
static const uint8_t const TICKER_ETH[] = "ETH ";
|
|
typedef struct tokenContext_t {
|
|
uint8_t data[4 + 32 + 32];
|
|
uint32_t dataFieldPos;
|
|
bool provisioned;
|
|
} tokenContext_t;
|
|
|
|
typedef struct publicKeyContext_t {
|
|
cx_ecfp_public_key_t publicKey;
|
|
uint8_t address[41];
|
|
uint8_t chainCode[32];
|
|
bool getChaincode;
|
|
} publicKeyContext_t;
|
|
|
|
typedef struct transactionContext_t {
|
|
uint8_t pathLength;
|
|
uint32_t bip32Path[MAX_BIP32_PATH];
|
|
uint8_t hash[32];
|
|
} transactionContext_t;
|
|
|
|
union {
|
|
publicKeyContext_t publicKeyContext;
|
|
transactionContext_t transactionContext;
|
|
} tmpCtx;
|
|
txContext_t txContext;
|
|
txContent_t txContent;
|
|
cx_sha3_t sha3;
|
|
tokenContext_t tokenContext;
|
|
volatile uint8_t dataAllowed;
|
|
volatile uint8_t fidoTransport;
|
|
volatile char addressSummary[32];
|
|
volatile char fullAddress[43];
|
|
volatile char fullAmount[50];
|
|
volatile char maxFee[50];
|
|
volatile bool dataPresent;
|
|
volatile bool skipWarning;
|
|
|
|
bagl_element_t tmp_element;
|
|
|
|
#ifdef HAVE_U2F
|
|
|
|
volatile u2f_service_t u2fService;
|
|
|
|
#endif
|
|
|
|
ux_state_t ux;
|
|
// display stepped screens
|
|
unsigned int ux_step;
|
|
unsigned int ux_step_count;
|
|
|
|
typedef struct internalStorage_t {
|
|
uint8_t dataAllowed;
|
|
uint8_t fidoTransport;
|
|
uint8_t initialized;
|
|
} internalStorage_t;
|
|
|
|
WIDE internalStorage_t N_storage_real;
|
|
#define N_storage (*(WIDE internalStorage_t *)PIC(&N_storage_real))
|
|
|
|
static const char const CONTRACT_ADDRESS[] = "New contract";
|
|
|
|
#ifdef HAVE_U2F
|
|
|
|
void u2f_proxy_response(u2f_service_t *service, unsigned int tx) {
|
|
os_memset(service->messageBuffer, 0, 5);
|
|
os_memmove(service->messageBuffer + 5, G_io_apdu_buffer, tx);
|
|
service->messageBuffer[tx + 5] = 0x90;
|
|
service->messageBuffer[tx + 6] = 0x00;
|
|
u2f_send_fragmented_response(service, U2F_CMD_MSG, service->messageBuffer,
|
|
tx + 7, true);
|
|
}
|
|
|
|
#endif
|
|
|
|
const bagl_element_t *ui_menu_item_out_over(const bagl_element_t *e) {
|
|
// the selection rectangle is after the none|touchable
|
|
e = (const bagl_element_t *)(((unsigned int)e) + sizeof(bagl_element_t));
|
|
return e;
|
|
}
|
|
|
|
const bagl_icon_details_t ui_blue_ethereum_gif = {
|
|
.bpp = GLYPH_badge_ethereum_BPP,
|
|
.colors = C_badge_ethereum_colors,
|
|
.bitmap = C_badge_ethereum_bitmap,
|
|
};
|
|
|
|
#define BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH 10
|
|
#define BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH 8
|
|
#define MAX_CHAR_PER_LINE 25
|
|
|
|
#define COLOR_BG_1 0xF9F9F9
|
|
#define COLOR_APP 0x0ebdcf
|
|
#define COLOR_APP_LIGHT 0x87dee6
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
const bagl_element_t ui_idle_blue[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// erase screen (only under the status bar)
|
|
{{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP,
|
|
COLOR_APP, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
/// TOP STATUS BAR
|
|
{{BAGL_LABELINE, 0x00, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP,
|
|
BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"ETHEREUM",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 19, 56, 44, 0, 0,
|
|
BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
BAGL_FONT_SYMBOLS_0_SETTINGS,
|
|
0,
|
|
COLOR_APP,
|
|
0xFFFFFF,
|
|
io_seproxyhal_touch_settings,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0,
|
|
BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
BAGL_FONT_SYMBOLS_0_DASHBOARD,
|
|
0,
|
|
COLOR_APP,
|
|
0xFFFFFF,
|
|
io_seproxyhal_touch_exit,
|
|
NULL,
|
|
NULL},
|
|
|
|
// BADGE_ETHEREUM.GIF
|
|
{{BAGL_ICON, 0x00, 135, 178, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0},
|
|
&ui_blue_ethereum_gif,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 0, 270, 320, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Open Ethereum wallet",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x00, 0, 308, 320, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Connect your Ledger Blue and open your",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x00, 0, 331, 320, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"preferred wallet to view your accounts.",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 0, 450, 320, 14, 0, 0, 0, 0x999999, COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_8_11PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Validation requests will show automatically.",
|
|
10,
|
|
0,
|
|
COLOR_BG_1,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
unsigned int ui_idle_blue_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
return 0;
|
|
}
|
|
#endif // #if TARGET_ID == 0x31000002
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
const bagl_element_t ui_idle_nanos[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x01, 12, 9, 14, 14, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_ETHEREUM_BADGE},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 33, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"Use wallet to",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 34, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"view accounts",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x01, 118, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_DOWN},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// NO! //{{BAGL_LABELINE , 0x02, 34, 3, 128, 32,
|
|
// 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px, 0
|
|
// }, "view accounts", 0, 0, 0, NULL, NULL, NULL },
|
|
{{BAGL_LABELINE, 0x02, 0, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Settings",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x02, 3, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_UP},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x02, 118, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_DOWN},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x03, 29, 9, 14, 14, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_DASHBOARD_BADGE},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x03, 50, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"Quit app",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x03, 3, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_UP},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
unsigned int ui_idle_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter);
|
|
|
|
unsigned int ui_idle_nanos_state;
|
|
unsigned int ui_idle_nanos_prepro(const bagl_element_t *element) {
|
|
if (element->component.userid > 0) {
|
|
return (ui_idle_nanos_state == element->component.userid - 1);
|
|
}
|
|
return 1;
|
|
}
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
const bagl_element_t *ui_settings_blue_toggle_data(const bagl_element_t *e) {
|
|
// swap setting and request redraw of settings elements
|
|
uint8_t setting = N_storage.dataAllowed ? 0 : 1;
|
|
nvm_write(&N_storage.dataAllowed, (void *)&setting, sizeof(uint8_t));
|
|
|
|
// only refresh settings mutable drawn elements
|
|
UX_REDISPLAY_IDX(12);
|
|
|
|
// won't redisplay the bagl_none
|
|
return 0;
|
|
}
|
|
|
|
const bagl_element_t *ui_settings_blue_toggle_browser(const bagl_element_t *e) {
|
|
// swap setting and request redraw of settings elements
|
|
uint8_t setting = N_storage.fidoTransport ? 0 : 1;
|
|
nvm_write(&N_storage.fidoTransport, (void *)&setting, sizeof(uint8_t));
|
|
|
|
// only refresh settings mutable drawn elements
|
|
UX_REDISPLAY_IDX(12);
|
|
|
|
// won't redisplay the bagl_none
|
|
return 0;
|
|
}
|
|
|
|
// don't perform any draw/color change upon finger event over settings
|
|
const bagl_element_t *ui_settings_out_over(const bagl_element_t *e) {
|
|
return NULL;
|
|
}
|
|
|
|
unsigned int ui_settings_back_callback(const bagl_element_t *e) {
|
|
// go back to idle
|
|
ui_idle();
|
|
return 0;
|
|
}
|
|
|
|
const bagl_icon_details_t ui_blue_item_set_gif = {
|
|
.bpp = GLYPH_icon_toggle_set_BPP,
|
|
.colors = C_icon_toggle_set_colors,
|
|
.bitmap = C_icon_toggle_set_bitmap,
|
|
};
|
|
|
|
const bagl_icon_details_t ui_blue_item_reset_gif = {
|
|
.bpp = GLYPH_icon_toggle_reset_BPP,
|
|
.colors = C_icon_toggle_reset_colors,
|
|
.bitmap = C_icon_toggle_reset_bitmap,
|
|
};
|
|
|
|
const bagl_element_t ui_settings_blue[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// erase screen (only under the status bar)
|
|
{{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP,
|
|
COLOR_APP, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
/// TOP STATUS BAR
|
|
{{BAGL_LABELINE, 0x00, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP,
|
|
BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"SETTINGS",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 19, 50, 44, 0, 0,
|
|
BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
BAGL_FONT_SYMBOLS_0_LEFT,
|
|
0,
|
|
COLOR_APP,
|
|
0xFFFFFF,
|
|
ui_settings_back_callback,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0,
|
|
BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
BAGL_FONT_SYMBOLS_0_DASHBOARD,
|
|
0,
|
|
COLOR_APP,
|
|
0xFFFFFF,
|
|
io_seproxyhal_touch_exit,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 105, 160, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
"Contract data",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x00, 30, 126, 260, 30, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0},
|
|
"Allow contract data in transactions",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_NONE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 78, 320, 68, 0, 0, BAGL_FILL,
|
|
0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0xEEEEEE,
|
|
0x000000,
|
|
ui_settings_blue_toggle_data,
|
|
ui_settings_out_over,
|
|
ui_settings_out_over},
|
|
|
|
#ifdef HAVE_U2F
|
|
{{BAGL_RECTANGLE, 0x00, 30, 146, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0,
|
|
0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 174, 160, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
"Browser support",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x00, 30, 195, 260, 30, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0},
|
|
"Enable integrated browser support",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_NONE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 147, 320, 68, 0, 0, BAGL_FILL,
|
|
0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0xEEEEEE,
|
|
0x000000,
|
|
ui_settings_blue_toggle_browser,
|
|
ui_settings_out_over,
|
|
ui_settings_out_over},
|
|
|
|
// at the end to minimize the number of refreshed items upon setting change
|
|
{{BAGL_ICON, 0x02, 258, 167, 32, 18, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
#endif // HAVE_U2F
|
|
{{BAGL_ICON, 0x01, 258, 98, 32, 18, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
const bagl_element_t *ui_settings_blue_prepro(const bagl_element_t *e) {
|
|
// none elements are skipped
|
|
if ((e->component.type & (~BAGL_FLAG_TOUCHABLE)) == BAGL_NONE) {
|
|
return 0;
|
|
}
|
|
// swap icon buffer to be displayed depending on if corresponding setting is
|
|
// enabled or not.
|
|
if (e->component.userid) {
|
|
os_memmove(&tmp_element, e, sizeof(bagl_element_t));
|
|
switch (e->component.userid) {
|
|
case 0x01:
|
|
// swap icon content
|
|
if (N_storage.dataAllowed) {
|
|
tmp_element.text = &ui_blue_item_set_gif;
|
|
} else {
|
|
tmp_element.text = &ui_blue_item_reset_gif;
|
|
}
|
|
break;
|
|
case 0x02:
|
|
// swap icon content
|
|
if (N_storage.fidoTransport) {
|
|
tmp_element.text = &ui_blue_item_set_gif;
|
|
} else {
|
|
tmp_element.text = &ui_blue_item_reset_gif;
|
|
}
|
|
break;
|
|
}
|
|
return &tmp_element;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
unsigned int ui_settings_blue_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
return 0;
|
|
}
|
|
#endif // #if TARGET_ID == 0x31000002
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
|
|
#ifdef HAVE_U2F
|
|
|
|
const bagl_element_t ui_settings_nanos[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x01, 0, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Contract data",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
//{{BAGL_ICON , 0x01, 3, 14, 7, 4, 0, 0, 0
|
|
//, 0xFFFFFF, 0x000000, 0,
|
|
// BAGL_GLYPH_ICON_UP }, NULL, 0, 0, 0, NULL, NULL, NULL },
|
|
{{BAGL_ICON, 0x01, 118, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_DOWN},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 0, 35, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Browser support",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x02, 3, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_UP},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x02, 0, 3, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Contract data",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x02, 0, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Browser support",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x02, 118, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_DOWN},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x13, 29, 9, 14, 14, 0, 0, 0, 0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x03, 61, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"Back",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x03, 3, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_UP},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
#else // ! HAVE_U2F
|
|
|
|
const bagl_element_t ui_settings_nanos[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x01, 0, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Contract data",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x01, 118, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_DOWN},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x12, 29, 9, 14, 14, 0, 0, 0, 0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x02, 61, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"Back",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x02, 3, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_UP},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
};
|
|
|
|
#endif // ! HAVE_U2F
|
|
|
|
unsigned int ui_settings_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter);
|
|
|
|
unsigned int ui_settings_nanos_state;
|
|
unsigned int ui_settings_nanos_prepro(const bagl_element_t *element) {
|
|
if (element->component.userid > 0) {
|
|
unsigned char displayed = (ui_settings_nanos_state ==
|
|
((element->component.userid - 1) & 0x0F));
|
|
// display custom icon for
|
|
if (displayed && (element->component.userid == 0x13 ||
|
|
element->component.userid == 0x12)) {
|
|
extern unsigned int const C_icon_back_colors[];
|
|
extern unsigned char const C_icon_back_bitmap[];
|
|
io_seproxyhal_display_bitmap(40, 9, 14, 14, C_icon_back_colors, 1,
|
|
C_icon_back_bitmap);
|
|
// superseded
|
|
return 0;
|
|
}
|
|
return displayed;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
const bagl_element_t ui_settings_data_nanos[] = {
|
|
// erase
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x01, 37, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px, 0},
|
|
"Allow",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x02, 74, 11, 16, 10, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_TOGGLE_ON},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x03, 74, 11, 16, 10, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_TOGGLE_OFF},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// icons
|
|
{{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CROSS},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CHECK},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
unsigned int ui_settings_data_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter);
|
|
|
|
unsigned int ui_settings_data_nanos_prepro(const bagl_element_t *element) {
|
|
unsigned int display = 1;
|
|
switch (element->component.userid) {
|
|
case 0x02:
|
|
display = dataAllowed;
|
|
break;
|
|
case 0x03:
|
|
display = !dataAllowed;
|
|
break;
|
|
}
|
|
return display;
|
|
}
|
|
|
|
#ifdef HAVE_U2F
|
|
|
|
const bagl_element_t ui_settings_fido_nanos[] = {
|
|
// erase
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x01, 35, 19, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px, 0},
|
|
"Enable",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x02, 76, 11, 16, 10, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_TOGGLE_ON},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x03, 76, 11, 16, 10, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_TOGGLE_OFF},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// icons
|
|
{{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CROSS},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CHECK},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
unsigned int ui_settings_fido_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter);
|
|
|
|
unsigned int ui_settings_fido_nanos_prepro(const bagl_element_t *element) {
|
|
unsigned int display = 1;
|
|
switch (element->component.userid) {
|
|
case 0x02:
|
|
display = fidoTransport;
|
|
break;
|
|
case 0x03:
|
|
display = !fidoTransport;
|
|
break;
|
|
}
|
|
return display;
|
|
}
|
|
|
|
#endif // HAVE_U2F
|
|
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
const bagl_element_t ui_address_blue[] = {
|
|
{{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// erase screen (only under the status bar)
|
|
{{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP,
|
|
COLOR_APP, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
/// TOP STATUS BAR
|
|
{{BAGL_LABELINE, 0x00, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP,
|
|
BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"CONFIRM ACCOUNT",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0,
|
|
// BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
// BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
// 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF,
|
|
// io_seproxyhal_touch_exit, NULL, NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 106, 320, 30, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0},
|
|
"ACCOUNT",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x10, 30, 136, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x11, 30, 159, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18,
|
|
BAGL_FILL, 0xCCCCCC, COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
"REJECT",
|
|
0,
|
|
0xB7B7B7,
|
|
COLOR_BG_1,
|
|
io_seproxyhal_touch_address_cancel,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18,
|
|
BAGL_FILL, 0x41ccb4, COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
"CONFIRM",
|
|
0,
|
|
0x3ab7a2,
|
|
COLOR_BG_1,
|
|
io_seproxyhal_touch_address_ok,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
unsigned int ui_address_blue_prepro(const bagl_element_t *element) {
|
|
if (element->component.userid > 0) {
|
|
unsigned int length = strlen(fullAddress);
|
|
if (length >= (element->component.userid & 0xF) * MAX_CHAR_PER_LINE) {
|
|
os_memset(addressSummary, 0, MAX_CHAR_PER_LINE + 1);
|
|
os_memmove(
|
|
addressSummary,
|
|
fullAddress +
|
|
(element->component.userid & 0xF) * MAX_CHAR_PER_LINE,
|
|
MIN(length -
|
|
(element->component.userid & 0xF) * MAX_CHAR_PER_LINE,
|
|
MAX_CHAR_PER_LINE));
|
|
return 1;
|
|
}
|
|
// nothing to draw for this line
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
unsigned int ui_address_blue_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
return 0;
|
|
}
|
|
#endif // #if TARGET_ID == 0x31000002
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
const bagl_element_t ui_address_nanos[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x01, 31, 9, 14, 14, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_EYE_BADGE},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 52, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"Confirm",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 53, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"account",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x02, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Account",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
(char *)addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CROSS},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CHECK},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
unsigned int ui_address_prepro(const bagl_element_t *element) {
|
|
if (element->component.userid > 0) {
|
|
unsigned int display = (ux_step == element->component.userid - 1);
|
|
if (display) {
|
|
switch (element->component.userid) {
|
|
case 1:
|
|
UX_CALLBACK_SET_INTERVAL(2000);
|
|
break;
|
|
case 2:
|
|
UX_CALLBACK_SET_INTERVAL(3000);
|
|
break;
|
|
}
|
|
}
|
|
return display;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
unsigned int ui_address_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter);
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
// reuse addressSummary for each line content
|
|
char *ui_details_title;
|
|
char *ui_details_content;
|
|
typedef void (*callback_t)(void);
|
|
callback_t ui_details_back_callback;
|
|
|
|
const bagl_element_t *
|
|
ui_details_blue_back_callback(const bagl_element_t *element) {
|
|
ui_details_back_callback();
|
|
return 0;
|
|
}
|
|
|
|
const bagl_element_t ui_details_blue[] = {
|
|
// erase screen (only under the status bar)
|
|
{{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP,
|
|
COLOR_APP, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
/// TOP STATUS BAR
|
|
{{BAGL_LABELINE, 0x01, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP,
|
|
BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 19, 50, 44, 0, 0,
|
|
BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
BAGL_FONT_SYMBOLS_0_LEFT,
|
|
0,
|
|
COLOR_APP,
|
|
0xFFFFFF,
|
|
ui_details_blue_back_callback,
|
|
NULL,
|
|
NULL},
|
|
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0,
|
|
// BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
// BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
// 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF,
|
|
// io_seproxyhal_touch_exit, NULL, NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 106, 320, 30, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0},
|
|
"VALUE",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x10, 30, 136, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x11, 30, 159, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x12, 30, 182, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x13, 30, 205, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x14, 30, 228, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x15, 30, 251, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x16, 30, 274, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x17, 30, 297, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x18, 30, 320, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
//"..." at the end if too much
|
|
{{BAGL_LABELINE, 0x19, 30, 343, 260, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 0, 450, 320, 14, 0, 0, 0, 0x999999, COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_8_11PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Review the whole value before continuing.",
|
|
10,
|
|
0,
|
|
COLOR_BG_1,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
unsigned int ui_details_blue_prepro(const bagl_element_t *element) {
|
|
if (element->component.userid == 1) {
|
|
strcpy(addressSummary, ui_details_title);
|
|
} else if (element->component.userid > 0) {
|
|
unsigned int length = strlen(ui_details_content);
|
|
if (length >= (element->component.userid & 0xF) * MAX_CHAR_PER_LINE) {
|
|
os_memset(addressSummary, 0, MAX_CHAR_PER_LINE + 1);
|
|
os_memmove(
|
|
addressSummary,
|
|
ui_details_content +
|
|
(element->component.userid & 0xF) * MAX_CHAR_PER_LINE,
|
|
MIN(length -
|
|
(element->component.userid & 0xF) * MAX_CHAR_PER_LINE,
|
|
MAX_CHAR_PER_LINE));
|
|
return 1;
|
|
}
|
|
// nothing to draw for this line
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
unsigned int ui_details_blue_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
return 0;
|
|
}
|
|
|
|
void ui_details_init(const char *title, const char *content,
|
|
callback_t back_callback) {
|
|
ui_details_title = title;
|
|
ui_details_content = content;
|
|
ui_details_back_callback = back_callback;
|
|
UX_DISPLAY(ui_details_blue, ui_details_blue_prepro);
|
|
}
|
|
|
|
const bagl_icon_details_t ui_blue_transaction_gif = {
|
|
.bpp = GLYPH_badge_transaction_BPP,
|
|
.colors = C_badge_transaction_colors,
|
|
.bitmap = C_badge_transaction_bitmap,
|
|
};
|
|
|
|
void ui_approval_blue_init(void);
|
|
|
|
const bagl_element_t *ui_approval_blue_amount_details(const bagl_element_t *e) {
|
|
if (strlen(fullAmount) * BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH >=
|
|
160) {
|
|
// display details screen
|
|
ui_details_init("AMOUNT", fullAmount, ui_approval_blue_init);
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
const bagl_element_t *
|
|
ui_approval_blue_account_details(const bagl_element_t *e) {
|
|
if (strlen(fullAddress) * BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH >=
|
|
160) {
|
|
ui_details_init("ACCOUNT", fullAddress, ui_approval_blue_init);
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
const bagl_element_t *ui_approval_blue_fees_details(const bagl_element_t *e) {
|
|
if (strlen(maxFee) * BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH >= 160) {
|
|
ui_details_init("MAX FEES", maxFee, ui_approval_blue_init);
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
#include "glyphs.h"
|
|
/*
|
|
#define GLYPH_icon_warning_WIDTH 12
|
|
#define GLYPH_icon_warning_HEIGHT 12
|
|
#define GLYPH_icon_warning_BPP 2
|
|
extern
|
|
unsigned int const C_icon_warning_colors[]
|
|
;
|
|
extern
|
|
unsigned char const C_icon_warning_bitmap[];
|
|
*/
|
|
|
|
const bagl_icon_details_t ui_blue_warning_gif = {
|
|
.bpp = GLYPH_icon_warning_BPP,
|
|
.colors = C_icon_warning_colors,
|
|
.bitmap = C_icon_warning_bitmap,
|
|
};
|
|
|
|
const bagl_element_t ui_approval_blue[] = {
|
|
{{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
// erase screen (only under the status bar)
|
|
{{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP,
|
|
COLOR_APP, 0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
/// TOP STATUS BAR
|
|
{{BAGL_LABELINE, 0x00, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP,
|
|
BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"CONFIRM TRANSACTION",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
//{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0,
|
|
// BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT,
|
|
// BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
// 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF,
|
|
// io_seproxyhal_touch_exit, NULL, NULL},
|
|
|
|
// BADGE_TRANSACTION.GIF
|
|
{{BAGL_ICON, 0x00, 30, 98, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0},
|
|
&ui_blue_transaction_gif,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 100, 117, 320, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0},
|
|
"Transaction details",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 100, 138, 320, 30, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0},
|
|
"Check and confirm values",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 196, 100, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0},
|
|
"AMOUNT",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
// x-18 when ...
|
|
{{BAGL_LABELINE, 0x01, 130, 200, 160, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_RIGHT,
|
|
0},
|
|
fullAmount,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x11, 284, 196, 6, 16, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_RIGHT, 0},
|
|
BAGL_FONT_SYMBOLS_0_MINIRIGHT,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_NONE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 168, 320, 48, 0, 9, BAGL_FILL,
|
|
0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0xEEEEEE,
|
|
0x000000,
|
|
ui_approval_blue_amount_details,
|
|
ui_menu_item_out_over,
|
|
ui_menu_item_out_over},
|
|
{{BAGL_RECTANGLE, 0x11, 0, 168, 5, 48, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
COLOR_BG_1, 0, 0},
|
|
NULL,
|
|
0,
|
|
0x41CCB4,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE, 0x00, 30, 216, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0,
|
|
0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 245, 100, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0},
|
|
"ACCOUNT",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
// x-18 when ...
|
|
{{BAGL_LABELINE, 0x02, 130, 245, 160, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0},
|
|
fullAddress,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x12, 284, 245, 6, 16, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_RIGHT, 0},
|
|
BAGL_FONT_SYMBOLS_0_MINIRIGHT,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_NONE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 217, 320, 48, 0, 9, BAGL_FILL,
|
|
0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0xEEEEEE,
|
|
0x000000,
|
|
ui_approval_blue_account_details,
|
|
ui_menu_item_out_over,
|
|
ui_menu_item_out_over},
|
|
{{BAGL_RECTANGLE, 0x12, 0, 217, 5, 48, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
COLOR_BG_1, 0, 0},
|
|
NULL,
|
|
0,
|
|
0x41CCB4,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE, 0x00, 30, 265, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0,
|
|
0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x00, 30, 294, 100, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0},
|
|
"MAX FEES",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
// x-18 when ...
|
|
{{BAGL_LABELINE, 0x03, 130, 294, 160, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0},
|
|
maxFee,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x13, 284, 294, 6, 16, 0, 0, BAGL_FILL, 0x999999,
|
|
COLOR_BG_1, BAGL_FONT_SYMBOLS_0 | BAGL_FONT_ALIGNMENT_RIGHT, 0},
|
|
BAGL_FONT_SYMBOLS_0_MINIRIGHT,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_NONE | BAGL_FLAG_TOUCHABLE, 0x00, 0, 266, 320, 48, 0, 9, BAGL_FILL,
|
|
0xFFFFFF, 0x000000, 0, 0},
|
|
NULL,
|
|
0,
|
|
0xEEEEEE,
|
|
0x000000,
|
|
ui_approval_blue_fees_details,
|
|
ui_menu_item_out_over,
|
|
ui_menu_item_out_over},
|
|
{{BAGL_RECTANGLE, 0x13, 0, 266, 5, 48, 0, 0, BAGL_FILL, COLOR_BG_1,
|
|
COLOR_BG_1, 0, 0},
|
|
NULL,
|
|
0,
|
|
0x41CCB4,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE, 0x06, 30, 314, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0,
|
|
0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x06, 30, 343, 120, 30, 0, 0, BAGL_FILL, 0x000000,
|
|
COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0},
|
|
"CONTRACT DATA",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
//{{BAGL_LABELINE , 0x05, 130, 343, 160, 30, 0, 0,
|
|
// BAGL_FILL, 0x666666, COLOR_BG_1,
|
|
// BAGL_FONT_OPEN_SANS_REGULAR_10_13PX|BAGL_FONT_ALIGNMENT_RIGHT, 0 },
|
|
// "Not
|
|
// present", 0, 0, 0, NULL, NULL, NULL},
|
|
{{BAGL_LABELINE, 0x06, 133, 343, 140, 30, 0, 0, BAGL_FILL, 0x666666,
|
|
COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0},
|
|
"Present",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x06, 278, 333, 12, 12, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0},
|
|
&ui_blue_warning_gif,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18,
|
|
BAGL_FILL, 0xCCCCCC, COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
"REJECT",
|
|
0,
|
|
0xB7B7B7,
|
|
COLOR_BG_1,
|
|
io_seproxyhal_touch_tx_cancel,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18,
|
|
BAGL_FILL, 0x41ccb4, COLOR_BG_1,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER |
|
|
BAGL_FONT_ALIGNMENT_MIDDLE,
|
|
0},
|
|
"CONFIRM",
|
|
0,
|
|
0x3ab7a2,
|
|
COLOR_BG_1,
|
|
io_seproxyhal_touch_tx_ok,
|
|
NULL,
|
|
NULL},
|
|
};
|
|
|
|
const bagl_element_t *ui_approval_blue_prepro(const bagl_element_t *element) {
|
|
// none elements are skipped
|
|
if ((element->component.type & (~BAGL_FLAG_TOUCHABLE)) == BAGL_NONE) {
|
|
return 0;
|
|
} else {
|
|
switch (element->component.userid) {
|
|
case 0x01:
|
|
if (strlen(fullAmount) *
|
|
BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH >=
|
|
160) {
|
|
os_memmove(&tmp_element, element, sizeof(bagl_element_t));
|
|
tmp_element.component.x -= 18;
|
|
return &tmp_element;
|
|
}
|
|
break;
|
|
case 0x11:
|
|
return strlen(fullAmount) *
|
|
BAGL_FONT_OPEN_SANS_LIGHT_16_22PX_AVG_WIDTH >=
|
|
160;
|
|
|
|
case 0x02:
|
|
if (strlen(fullAddress) *
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH >=
|
|
160) {
|
|
os_memmove(&tmp_element, element, sizeof(bagl_element_t));
|
|
tmp_element.component.x -= 18;
|
|
return &tmp_element;
|
|
}
|
|
break;
|
|
case 0x12:
|
|
return strlen(fullAddress) *
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH >=
|
|
160;
|
|
|
|
case 0x03:
|
|
if (strlen(maxFee) *
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH >=
|
|
160) {
|
|
os_memmove(&tmp_element, element, sizeof(bagl_element_t));
|
|
tmp_element.component.x -= 18;
|
|
return &tmp_element;
|
|
}
|
|
break;
|
|
case 0x13:
|
|
return strlen(maxFee) *
|
|
BAGL_FONT_OPEN_SANS_REGULAR_10_13PX_AVG_WIDTH >=
|
|
160;
|
|
|
|
case 0x05:
|
|
return !dataPresent;
|
|
case 0x06:
|
|
return dataPresent;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
unsigned int ui_approval_blue_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
return 0;
|
|
}
|
|
|
|
void ui_approval_blue_init(void) {
|
|
UX_DISPLAY(ui_approval_blue, ui_approval_blue_prepro);
|
|
}
|
|
#endif // #if TARGET_ID == 0x31000002
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
const bagl_element_t ui_approval_nanos[] = {
|
|
// type userid x y w h str rad
|
|
// fill fg bg fid iid txt touchparams... ]
|
|
{{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF,
|
|
0, 0},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CROSS},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_CHECK},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_ICON, 0x01, 21, 9, 14, 14, 0, 0, 0, 0xFFFFFF, 0x000000, 0,
|
|
BAGL_GLYPH_ICON_TRANSACTION_BADGE},
|
|
NULL,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 42, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"Confirm",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x01, 43, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px, 0},
|
|
"transaction",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x02, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"WARNING",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x02, 23, 26, 82, 11, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Data present",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x03, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Amount",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x03, 23, 26, 82, 11, 0x80 | 10, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 26},
|
|
(char *)fullAmount,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x04, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Recipient account",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x04, 16, 26, 96, 11, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
(char *)addressSummary,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
{{BAGL_LABELINE, 0x05, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0},
|
|
"Maximum fees",
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
{{BAGL_LABELINE, 0x05, 23, 26, 82, 11, 0x80 | 10, 0, 0, 0xFFFFFF, 0x000000,
|
|
BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 26},
|
|
(char *)maxFee,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL},
|
|
|
|
};
|
|
|
|
unsigned int ui_approval_prepro(const bagl_element_t *element) {
|
|
unsigned int display = 1;
|
|
if (element->component.userid > 0) {
|
|
display = (ux_step == element->component.userid - 1);
|
|
if (display) {
|
|
switch (element->component.userid) {
|
|
case 1:
|
|
UX_CALLBACK_SET_INTERVAL(2000);
|
|
break;
|
|
case 2:
|
|
if (dataPresent) {
|
|
UX_CALLBACK_SET_INTERVAL(3000);
|
|
} else {
|
|
display = 0;
|
|
ux_step++; // display the next step
|
|
}
|
|
break;
|
|
case 3:
|
|
UX_CALLBACK_SET_INTERVAL(MAX(
|
|
3000, 1000 + bagl_label_roundtrip_duration_ms(element, 7)));
|
|
break;
|
|
case 4:
|
|
UX_CALLBACK_SET_INTERVAL(3000);
|
|
break;
|
|
case 5:
|
|
UX_CALLBACK_SET_INTERVAL(MAX(
|
|
3000, 1000 + bagl_label_roundtrip_duration_ms(element, 7)));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return display;
|
|
}
|
|
|
|
unsigned int ui_approval_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter);
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
void ui_idle(void) {
|
|
skipWarning = false;
|
|
#if TARGET_ID == 0x31000002
|
|
UX_DISPLAY(ui_idle_blue, NULL);
|
|
#elif TARGET_ID == 0x31100002
|
|
ui_idle_nanos_state = 0; // start by displaying the idle first screen
|
|
UX_DISPLAY(ui_idle_nanos, ui_idle_nanos_prepro);
|
|
#endif // #if TARGET_ID
|
|
}
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
unsigned int io_seproxyhal_touch_settings(const bagl_element_t *e) {
|
|
UX_DISPLAY(ui_settings_blue, ui_settings_blue_prepro);
|
|
return 0; // do not redraw button, screen has switched
|
|
}
|
|
#endif // #if TARGET_ID == 0x31000002
|
|
|
|
unsigned int io_seproxyhal_touch_exit(const bagl_element_t *e) {
|
|
// Go back to the dashboard
|
|
os_sched_exit(0);
|
|
return 0; // do not redraw the widget
|
|
}
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
unsigned int ui_idle_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
switch (button_mask) {
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT: // UP
|
|
if (ui_idle_nanos_state != 0) {
|
|
ui_idle_nanos_state--;
|
|
UX_DISPLAY(ui_idle_nanos, ui_idle_nanos_prepro);
|
|
}
|
|
break;
|
|
|
|
case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // DOWN
|
|
if (ui_idle_nanos_state != 2) {
|
|
ui_idle_nanos_state++;
|
|
UX_DISPLAY(ui_idle_nanos, ui_idle_nanos_prepro);
|
|
}
|
|
break;
|
|
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: // Settings, EXIT
|
|
if (ui_idle_nanos_state == 1) {
|
|
ui_settings_nanos_state = 0;
|
|
UX_DISPLAY(ui_settings_nanos, ui_settings_nanos_prepro);
|
|
} else if (ui_idle_nanos_state == 2) {
|
|
io_seproxyhal_touch_exit(NULL);
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int ui_settings_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
switch (button_mask) {
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT: // UP
|
|
if (ui_settings_nanos_state != 0) {
|
|
ui_settings_nanos_state--;
|
|
UX_DISPLAY(ui_settings_nanos, ui_settings_nanos_prepro);
|
|
}
|
|
break;
|
|
|
|
case BUTTON_EVT_RELEASED | BUTTON_RIGHT: // DOWN
|
|
#ifdef HAVE_U2F
|
|
if (ui_settings_nanos_state != 2) {
|
|
#else // !HAVE_U2F
|
|
if (ui_settings_nanos_state != 1) {
|
|
#endif // ! HAVE_U2F
|
|
ui_settings_nanos_state++;
|
|
UX_DISPLAY(ui_settings_nanos, ui_settings_nanos_prepro);
|
|
}
|
|
break;
|
|
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT: // Settings, EXIT
|
|
if (ui_settings_nanos_state == 0) {
|
|
dataAllowed = N_storage.dataAllowed;
|
|
UX_DISPLAY(ui_settings_data_nanos, ui_settings_data_nanos_prepro);
|
|
}
|
|
#ifdef HAVE_U2F
|
|
else if (ui_settings_nanos_state == 1) {
|
|
fidoTransport = N_storage.fidoTransport;
|
|
UX_DISPLAY(ui_settings_fido_nanos, ui_settings_fido_nanos_prepro);
|
|
} else if (ui_settings_nanos_state == 2) {
|
|
UX_DISPLAY(ui_idle_nanos, ui_idle_nanos_prepro);
|
|
}
|
|
#else // ! HAVE_U2F
|
|
else if (ui_settings_nanos_state == 1) {
|
|
UX_DISPLAY(ui_idle_nanos, ui_idle_nanos_prepro);
|
|
}
|
|
#endif // ! HAVE_U2F
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
unsigned int ui_settings_data_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
switch (button_mask) {
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT:
|
|
dataAllowed = 0x00;
|
|
goto set;
|
|
case BUTTON_EVT_RELEASED | BUTTON_RIGHT:
|
|
dataAllowed = 0x01;
|
|
set:
|
|
if (N_storage.dataAllowed != dataAllowed) {
|
|
nvm_write(&N_storage.dataAllowed, (void *)&dataAllowed,
|
|
sizeof(uint8_t));
|
|
}
|
|
// no break is intentional
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT:
|
|
UX_DISPLAY(ui_settings_nanos, ui_settings_nanos_prepro);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef HAVE_U2F
|
|
|
|
unsigned int ui_settings_fido_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
switch (button_mask) {
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT:
|
|
fidoTransport = 0x00;
|
|
goto set;
|
|
case BUTTON_EVT_RELEASED | BUTTON_RIGHT:
|
|
fidoTransport = 0x01;
|
|
set:
|
|
if (N_storage.fidoTransport != fidoTransport) {
|
|
nvm_write(&N_storage.fidoTransport, (void *)&fidoTransport,
|
|
sizeof(uint8_t));
|
|
USB_power_U2F(0, 0);
|
|
USB_power_U2F(1, N_storage.fidoTransport);
|
|
}
|
|
// no break is intentional
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT | BUTTON_RIGHT:
|
|
UX_DISPLAY(ui_settings_nanos, ui_settings_nanos_prepro);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // HAVE_U2F
|
|
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) {
|
|
uint32_t tx = set_result_get_publicKey();
|
|
G_io_apdu_buffer[tx++] = 0x90;
|
|
G_io_apdu_buffer[tx++] = 0x00;
|
|
#ifdef HAVE_U2F
|
|
if (fidoActivated) {
|
|
u2f_proxy_response((u2f_service_t *)&u2fService, tx);
|
|
} else {
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
|
}
|
|
#else // HAVE_U2F
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
|
#endif // HAVE_U2F
|
|
// Display back the original UX
|
|
ui_idle();
|
|
return 0; // do not redraw the widget
|
|
}
|
|
|
|
unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) {
|
|
G_io_apdu_buffer[0] = 0x69;
|
|
G_io_apdu_buffer[1] = 0x85;
|
|
#ifdef HAVE_U2F
|
|
if (fidoActivated) {
|
|
u2f_proxy_response((u2f_service_t *)&u2fService, 2);
|
|
} else {
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
|
}
|
|
#else // HAVE_U2F
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
|
#endif // HAVE_U2F
|
|
// Display back the original UX
|
|
ui_idle();
|
|
return 0; // do not redraw the widget
|
|
}
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
unsigned int ui_address_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
switch (button_mask) {
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT: // CANCEL
|
|
io_seproxyhal_touch_address_cancel(NULL);
|
|
break;
|
|
|
|
case BUTTON_EVT_RELEASED | BUTTON_RIGHT: { // OK
|
|
io_seproxyhal_touch_address_ok(NULL);
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
|
|
uint8_t privateKeyData[32];
|
|
uint8_t signature[100];
|
|
uint8_t signatureLength;
|
|
cx_ecfp_private_key_t privateKey;
|
|
uint32_t tx = 0;
|
|
uint8_t rLength, sLength, rOffset, sOffset;
|
|
os_perso_derive_node_bip32(
|
|
CX_CURVE_256K1, tmpCtx.transactionContext.bip32Path,
|
|
tmpCtx.transactionContext.pathLength, privateKeyData, NULL);
|
|
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
|
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
|
signatureLength =
|
|
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
|
|
tmpCtx.transactionContext.hash,
|
|
sizeof(tmpCtx.transactionContext.hash), signature);
|
|
os_memset(&privateKey, 0, sizeof(privateKey));
|
|
// Parity is present in the sequence tag in the legacy API
|
|
if (txContent.vLength == 0) {
|
|
// Legacy API
|
|
G_io_apdu_buffer[0] = 27 + (signature[0] & 0x01);
|
|
} else {
|
|
// New API
|
|
uint8_t v;
|
|
if (txContent.vLength == 1) {
|
|
v = txContent.v[0];
|
|
} else {
|
|
v = txContent.v[1];
|
|
}
|
|
G_io_apdu_buffer[0] = (v * 2) + 35 + (signature[0] & 0x01);
|
|
}
|
|
rLength = signature[3];
|
|
sLength = signature[4 + rLength + 1];
|
|
rOffset = (rLength == 33 ? 1 : 0);
|
|
sOffset = (sLength == 33 ? 1 : 0);
|
|
os_memmove(G_io_apdu_buffer + 1, signature + 4 + rOffset, 32);
|
|
os_memmove(G_io_apdu_buffer + 1 + 32, signature + 4 + rLength + 2 + sOffset,
|
|
32);
|
|
tx = 65;
|
|
G_io_apdu_buffer[tx++] = 0x90;
|
|
G_io_apdu_buffer[tx++] = 0x00;
|
|
#ifdef HAVE_U2F
|
|
if (fidoActivated) {
|
|
u2f_proxy_response((u2f_service_t *)&u2fService, tx);
|
|
} else {
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
|
}
|
|
#else // HAVE_U2F
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
|
#endif // HAVE_U2F
|
|
// Display back the original UX
|
|
ui_idle();
|
|
return 0; // do not redraw the widget
|
|
}
|
|
|
|
unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
|
|
G_io_apdu_buffer[0] = 0x69;
|
|
G_io_apdu_buffer[1] = 0x85;
|
|
#ifdef HAVE_U2F
|
|
if (fidoActivated) {
|
|
u2f_proxy_response((u2f_service_t *)&u2fService, 2);
|
|
} else {
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
|
}
|
|
#else // HAVE_U2F
|
|
// Send back the response, do not restart the event loop
|
|
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
|
|
#endif // HAVE_U2F
|
|
// Display back the original UX
|
|
ui_idle();
|
|
return 0; // do not redraw the widget
|
|
}
|
|
|
|
#if TARGET_ID == 0x31100002
|
|
unsigned int ui_approval_nanos_button(unsigned int button_mask,
|
|
unsigned int button_mask_counter) {
|
|
switch (button_mask) {
|
|
case BUTTON_EVT_RELEASED | BUTTON_LEFT:
|
|
io_seproxyhal_touch_tx_cancel(NULL);
|
|
break;
|
|
|
|
case BUTTON_EVT_RELEASED | BUTTON_RIGHT: {
|
|
io_seproxyhal_touch_tx_ok(NULL);
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif // #if TARGET_ID == 0x31100002
|
|
|
|
unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
|
|
switch (channel & ~(IO_FLAGS)) {
|
|
case CHANNEL_KEYBOARD:
|
|
break;
|
|
|
|
// multiplexed io exchange over a SPI channel and TLV encapsulated protocol
|
|
case CHANNEL_SPI:
|
|
if (tx_len) {
|
|
io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len);
|
|
|
|
if (channel & IO_RESET_AFTER_REPLIED) {
|
|
reset();
|
|
}
|
|
return 0; // nothing received from the master so far (it's a tx
|
|
// transaction)
|
|
} else {
|
|
return io_seproxyhal_spi_recv(G_io_apdu_buffer,
|
|
sizeof(G_io_apdu_buffer), 0);
|
|
}
|
|
|
|
default:
|
|
THROW(INVALID_PARAMETER);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uint32_t set_result_get_publicKey() {
|
|
uint32_t tx = 0;
|
|
G_io_apdu_buffer[tx++] = 65;
|
|
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.publicKey.W, 65);
|
|
tx += 65;
|
|
G_io_apdu_buffer[tx++] = 40;
|
|
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40);
|
|
tx += 40;
|
|
if (tmpCtx.publicKeyContext.getChaincode) {
|
|
os_memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode,
|
|
32);
|
|
tx += 32;
|
|
}
|
|
return tx;
|
|
}
|
|
|
|
void convertUint256BE(uint8_t *data, uint32_t length, uint256_t *target) {
|
|
uint8_t tmp[32];
|
|
os_memset(tmp, 0, 32);
|
|
os_memmove(tmp + 32 - length, data, length);
|
|
readu256BE(tmp, target);
|
|
}
|
|
|
|
bool customProcessor(txContext_t *context) {
|
|
if ((context->currentField == TX_RLP_DATA) &&
|
|
(context->currentFieldLength != 0)) {
|
|
if (!N_storage.dataAllowed) {
|
|
PRINTF("Data field forbidden\n");
|
|
THROW(EXCEPTION);
|
|
} else {
|
|
dataPresent = true;
|
|
if (context->currentFieldLength == sizeof(tokenContext.data)) {
|
|
if (context->currentFieldPos < context->currentFieldLength) {
|
|
uint32_t copySize = (context->commandLength <
|
|
((context->currentFieldLength -
|
|
context->currentFieldPos))
|
|
? context->commandLength
|
|
: context->currentFieldLength -
|
|
context->currentFieldPos);
|
|
copyTxData(context,
|
|
tokenContext.data + context->currentFieldPos,
|
|
copySize);
|
|
}
|
|
if (context->currentFieldPos == context->currentFieldLength) {
|
|
context->currentField++;
|
|
context->processingField = false;
|
|
// Initial check to see if the token content can be
|
|
// processed
|
|
tokenContext.provisioned =
|
|
(os_memcmp(tokenContext.data, TOKEN_TRANSFER_ID, 4) ==
|
|
0);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer,
|
|
uint16_t dataLength, volatile unsigned int *flags,
|
|
volatile unsigned int *tx) {
|
|
UNUSED(dataLength);
|
|
uint8_t privateKeyData[32];
|
|
uint32_t bip32Path[MAX_BIP32_PATH];
|
|
uint32_t i;
|
|
uint8_t bip32PathLength = *(dataBuffer++);
|
|
cx_ecfp_private_key_t privateKey;
|
|
|
|
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
|
|
PRINTF("Invalid path\n");
|
|
THROW(0x6a80);
|
|
}
|
|
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
|
|
THROW(0x6B00);
|
|
}
|
|
if ((p2 != P2_CHAINCODE) && (p2 != P2_NO_CHAINCODE)) {
|
|
THROW(0x6B00);
|
|
}
|
|
for (i = 0; i < bip32PathLength; i++) {
|
|
bip32Path[i] = (dataBuffer[0] << 24) | (dataBuffer[1] << 16) |
|
|
(dataBuffer[2] << 8) | (dataBuffer[3]);
|
|
dataBuffer += 4;
|
|
}
|
|
tmpCtx.publicKeyContext.getChaincode = (p2 == P2_CHAINCODE);
|
|
os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength,
|
|
privateKeyData,
|
|
(tmpCtx.publicKeyContext.getChaincode
|
|
? tmpCtx.publicKeyContext.chainCode
|
|
: NULL));
|
|
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
|
|
cx_ecfp_generate_pair(CX_CURVE_256K1, &tmpCtx.publicKeyContext.publicKey,
|
|
&privateKey, 1);
|
|
os_memset(&privateKey, 0, sizeof(privateKey));
|
|
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
|
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey,
|
|
tmpCtx.publicKeyContext.address, &sha3);
|
|
if (p1 == P1_NON_CONFIRM) {
|
|
*tx = set_result_get_publicKey();
|
|
THROW(0x9000);
|
|
} else {
|
|
addressSummary[0] = '0';
|
|
addressSummary[1] = 'x';
|
|
os_memmove((unsigned char *)(addressSummary + 2),
|
|
tmpCtx.publicKeyContext.address, 4);
|
|
os_memmove((unsigned char *)(addressSummary + 6), "...", 3);
|
|
os_memmove((unsigned char *)(addressSummary + 9),
|
|
tmpCtx.publicKeyContext.address + 40 - 4, 4);
|
|
addressSummary[13] = '\0';
|
|
|
|
fullAddress[0] = '0';
|
|
fullAddress[1] = 'x';
|
|
os_memmove((unsigned char *)fullAddress + 2,
|
|
tmpCtx.publicKeyContext.address, 40);
|
|
fullAddress[42] = '\0';
|
|
|
|
// prepare for a UI based reply
|
|
skipWarning = false;
|
|
#if TARGET_ID == 0x31000002
|
|
UX_DISPLAY(ui_address_blue, ui_address_blue_prepro);
|
|
#elif TARGET_ID == 0x31100002
|
|
ux_step = 0;
|
|
ux_step_count = 2;
|
|
UX_DISPLAY(ui_address_nanos, ui_address_prepro);
|
|
#endif // #if TARGET_ID
|
|
|
|
*flags |= IO_ASYNCH_REPLY;
|
|
}
|
|
}
|
|
|
|
void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer,
|
|
uint16_t dataLength, volatile unsigned int *flags,
|
|
volatile unsigned int *tx) {
|
|
UNUSED(tx);
|
|
parserStatus_e txResult;
|
|
uint256_t gasPrice, startGas, uint256;
|
|
uint32_t i;
|
|
uint8_t address[41];
|
|
uint8_t decimals = WEI_TO_ETHER;
|
|
uint8_t *ticker = TICKER_ETH;
|
|
uint8_t tickerOffset = 0;
|
|
if (p1 == P1_FIRST) {
|
|
tmpCtx.transactionContext.pathLength = workBuffer[0];
|
|
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
|
|
(tmpCtx.transactionContext.pathLength > MAX_BIP32_PATH)) {
|
|
PRINTF("Invalid path\n");
|
|
THROW(0x6a80);
|
|
}
|
|
workBuffer++;
|
|
dataLength--;
|
|
for (i = 0; i < tmpCtx.transactionContext.pathLength; i++) {
|
|
tmpCtx.transactionContext.bip32Path[i] =
|
|
(workBuffer[0] << 24) | (workBuffer[1] << 16) |
|
|
(workBuffer[2] << 8) | (workBuffer[3]);
|
|
workBuffer += 4;
|
|
dataLength -= 4;
|
|
}
|
|
dataPresent = false;
|
|
tokenContext.provisioned = false;
|
|
initTx(&txContext, &sha3, &txContent, customProcessor, NULL);
|
|
} else if (p1 != P1_MORE) {
|
|
THROW(0x6B00);
|
|
}
|
|
if (p2 != 0) {
|
|
THROW(0x6B00);
|
|
}
|
|
if (txContext.currentField == TX_RLP_NONE) {
|
|
PRINTF("Parser not initialized\n");
|
|
THROW(0x6985);
|
|
}
|
|
txResult = processTx(&txContext, workBuffer, dataLength);
|
|
switch (txResult) {
|
|
case USTREAM_FINISHED:
|
|
break;
|
|
case USTREAM_PROCESSING:
|
|
THROW(0x9000);
|
|
case USTREAM_FAULT:
|
|
THROW(0x6A80);
|
|
default:
|
|
PRINTF("Unexpected parser status\n");
|
|
THROW(0x6A80);
|
|
}
|
|
// Store the hash
|
|
cx_hash((cx_hash_t *)&sha3, CX_LAST, tmpCtx.transactionContext.hash, 0,
|
|
tmpCtx.transactionContext.hash);
|
|
// If there is a token to process, check if it is well known
|
|
if (tokenContext.provisioned) {
|
|
for (i = 0; i < NUM_TOKENS; i++) {
|
|
tokenDefinition_t *currentToken = PIC(&TOKENS[i]);
|
|
if (os_memcmp(currentToken->address, txContent.destination, 20) ==
|
|
0) {
|
|
dataPresent = false;
|
|
decimals = currentToken->decimals;
|
|
ticker = currentToken->ticker;
|
|
txContent.destinationLength = 20;
|
|
os_memmove(txContent.destination, tokenContext.data + 4 + 12,
|
|
20);
|
|
os_memmove(txContent.value.value, tokenContext.data + 4 + 32,
|
|
32);
|
|
txContent.value.length = 32;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Add address
|
|
if (txContent.destinationLength != 0) {
|
|
getEthAddressStringFromBinary(txContent.destination, address, &sha3);
|
|
addressSummary[0] = '0';
|
|
addressSummary[1] = 'x';
|
|
os_memmove((unsigned char *)(addressSummary + 2), address, 4);
|
|
os_memmove((unsigned char *)(addressSummary + 6), "...", 3);
|
|
os_memmove((unsigned char *)(addressSummary + 9), address + 40 - 4, 4);
|
|
addressSummary[13] = '\0';
|
|
|
|
fullAddress[0] = '0';
|
|
fullAddress[1] = 'x';
|
|
os_memmove((unsigned char *)fullAddress + 2, address, 40);
|
|
fullAddress[42] = '\0';
|
|
} else {
|
|
os_memmove((void *)addressSummary, CONTRACT_ADDRESS,
|
|
sizeof(CONTRACT_ADDRESS));
|
|
strcpy(fullAddress, "Contract");
|
|
}
|
|
// Add amount in ethers or tokens
|
|
convertUint256BE(txContent.value.value, txContent.value.length, &uint256);
|
|
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100), 100);
|
|
i = 0;
|
|
while (G_io_apdu_buffer[100 + i]) {
|
|
i++;
|
|
}
|
|
adjustDecimals((char *)(G_io_apdu_buffer + 100), i,
|
|
(char *)G_io_apdu_buffer, 100, decimals);
|
|
i = 0;
|
|
tickerOffset = 0;
|
|
while (ticker[tickerOffset]) {
|
|
fullAmount[tickerOffset] = ticker[tickerOffset];
|
|
tickerOffset++;
|
|
}
|
|
while (G_io_apdu_buffer[i]) {
|
|
fullAmount[tickerOffset + i] = G_io_apdu_buffer[i];
|
|
i++;
|
|
}
|
|
fullAmount[tickerOffset + i] = '\0';
|
|
// Compute maximum fee
|
|
convertUint256BE(txContent.gasprice.value, txContent.gasprice.length,
|
|
&gasPrice);
|
|
convertUint256BE(txContent.startgas.value, txContent.startgas.length,
|
|
&startGas);
|
|
mul256(&gasPrice, &startGas, &uint256);
|
|
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100), 100);
|
|
i = 0;
|
|
while (G_io_apdu_buffer[100 + i]) {
|
|
i++;
|
|
}
|
|
adjustDecimals((char *)(G_io_apdu_buffer + 100), i,
|
|
(char *)G_io_apdu_buffer, 100, WEI_TO_ETHER);
|
|
i = 0;
|
|
maxFee[0] = 'E';
|
|
maxFee[1] = 'T';
|
|
maxFee[2] = 'H';
|
|
maxFee[3] = ' ';
|
|
while (G_io_apdu_buffer[i]) {
|
|
maxFee[4 + i] = G_io_apdu_buffer[i];
|
|
i++;
|
|
}
|
|
maxFee[4 + i] = '\0';
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
skipWarning = false;
|
|
ux_step_count = 0;
|
|
UX_DISPLAY(ui_approval_blue, ui_approval_blue_prepro);
|
|
#elif TARGET_ID == 0x31100002
|
|
skipWarning = !dataPresent;
|
|
ux_step = 0;
|
|
ux_step_count = 5;
|
|
UX_DISPLAY(ui_approval_nanos, ui_approval_prepro);
|
|
#endif // #if TARGET_ID
|
|
|
|
*flags |= IO_ASYNCH_REPLY;
|
|
}
|
|
|
|
void handleGetAppConfiguration(uint8_t p1, uint8_t p2, uint8_t *workBuffer,
|
|
uint16_t dataLength,
|
|
volatile unsigned int *flags,
|
|
volatile unsigned int *tx) {
|
|
UNUSED(p1);
|
|
UNUSED(p2);
|
|
UNUSED(workBuffer);
|
|
UNUSED(dataLength);
|
|
UNUSED(flags);
|
|
G_io_apdu_buffer[0] = (N_storage.dataAllowed ? 0x01 : 0x00);
|
|
G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION;
|
|
G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION;
|
|
G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION;
|
|
*tx = 4;
|
|
THROW(0x9000);
|
|
}
|
|
|
|
void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx) {
|
|
unsigned short sw = 0;
|
|
|
|
BEGIN_TRY {
|
|
TRY {
|
|
if (G_io_apdu_buffer[OFFSET_CLA] != CLA) {
|
|
THROW(0x6E00);
|
|
}
|
|
|
|
switch (G_io_apdu_buffer[OFFSET_INS]) {
|
|
case INS_GET_PUBLIC_KEY:
|
|
handleGetPublicKey(G_io_apdu_buffer[OFFSET_P1],
|
|
G_io_apdu_buffer[OFFSET_P2],
|
|
G_io_apdu_buffer + OFFSET_CDATA,
|
|
G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
|
break;
|
|
|
|
case INS_SIGN:
|
|
handleSign(G_io_apdu_buffer[OFFSET_P1],
|
|
G_io_apdu_buffer[OFFSET_P2],
|
|
G_io_apdu_buffer + OFFSET_CDATA,
|
|
G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
|
break;
|
|
|
|
case INS_GET_APP_CONFIGURATION:
|
|
handleGetAppConfiguration(
|
|
G_io_apdu_buffer[OFFSET_P1], G_io_apdu_buffer[OFFSET_P2],
|
|
G_io_apdu_buffer + OFFSET_CDATA,
|
|
G_io_apdu_buffer[OFFSET_LC], flags, tx);
|
|
break;
|
|
|
|
default:
|
|
THROW(0x6D00);
|
|
break;
|
|
}
|
|
}
|
|
CATCH_OTHER(e) {
|
|
switch (e & 0xF000) {
|
|
case 0x6000:
|
|
// Wipe the transaction context and report the exception
|
|
sw = e;
|
|
os_memset(&txContext, 0, sizeof(txContext));
|
|
break;
|
|
case 0x9000:
|
|
// All is well
|
|
sw = e;
|
|
break;
|
|
default:
|
|
// Internal error
|
|
sw = 0x6800 | (e & 0x7FF);
|
|
break;
|
|
}
|
|
// Unexpected exception => report
|
|
G_io_apdu_buffer[*tx] = sw >> 8;
|
|
G_io_apdu_buffer[*tx + 1] = sw;
|
|
*tx += 2;
|
|
}
|
|
FINALLY {
|
|
}
|
|
}
|
|
END_TRY;
|
|
}
|
|
|
|
void sample_main(void) {
|
|
volatile unsigned int rx = 0;
|
|
volatile unsigned int tx = 0;
|
|
volatile unsigned int flags = 0;
|
|
|
|
// DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only
|
|
// goal is to retrieve APDU.
|
|
// When APDU are to be fetched from multiple IOs, like NFC+USB+BLE, make
|
|
// sure the io_event is called with a
|
|
// switch event, before the apdu is replied to the bootloader. This avoid
|
|
// APDU injection faults.
|
|
for (;;) {
|
|
volatile unsigned short sw = 0;
|
|
|
|
BEGIN_TRY {
|
|
TRY {
|
|
rx = tx;
|
|
tx = 0; // ensure no race in catch_other if io_exchange throws
|
|
// an error
|
|
rx = io_exchange(CHANNEL_APDU | flags, rx);
|
|
flags = 0;
|
|
|
|
// no apdu received, well, reset the session, and reset the
|
|
// bootloader configuration
|
|
if (rx == 0) {
|
|
THROW(0x6982);
|
|
}
|
|
|
|
handleApdu(&flags, &tx);
|
|
}
|
|
CATCH_OTHER(e) {
|
|
switch (e & 0xF000) {
|
|
case 0x6000:
|
|
// Wipe the transaction context and report the exception
|
|
sw = e;
|
|
os_memset(&txContext, 0, sizeof(txContext));
|
|
break;
|
|
case 0x9000:
|
|
// All is well
|
|
sw = e;
|
|
break;
|
|
default:
|
|
// Internal error
|
|
sw = 0x6800 | (e & 0x7FF);
|
|
break;
|
|
}
|
|
// Unexpected exception => report
|
|
G_io_apdu_buffer[tx] = sw >> 8;
|
|
G_io_apdu_buffer[tx + 1] = sw;
|
|
tx += 2;
|
|
}
|
|
FINALLY {
|
|
}
|
|
}
|
|
END_TRY;
|
|
}
|
|
|
|
// return_to_dashboard:
|
|
return;
|
|
}
|
|
|
|
// override point, but nothing more to do
|
|
void io_seproxyhal_display(const bagl_element_t *element) {
|
|
// common icon element display,
|
|
if ((element->component.type & (~BAGL_FLAG_TOUCHABLE)) == BAGL_ICON
|
|
// this is a streamed icon from the app content
|
|
&& element->component.icon_id == 0 && element->text != NULL) {
|
|
bagl_icon_details_t *icon = (bagl_icon_details_t *)PIC(element->text);
|
|
// here could avoid the loop and do a pure aysnch stuff, but it's way
|
|
// too sluggish
|
|
io_seproxyhal_display_icon(element, icon);
|
|
return;
|
|
}
|
|
io_seproxyhal_display_default((bagl_element_t *)element);
|
|
}
|
|
|
|
unsigned char io_event(unsigned char channel) {
|
|
// nothing done with the event, throw an error on the transport layer if
|
|
// needed
|
|
|
|
// can't have more than one tag in the reply, not supported yet.
|
|
switch (G_io_seproxyhal_spi_buffer[0]) {
|
|
case SEPROXYHAL_TAG_FINGER_EVENT:
|
|
UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer);
|
|
break;
|
|
|
|
case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
|
|
UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer);
|
|
break;
|
|
|
|
case SEPROXYHAL_TAG_STATUS_EVENT:
|
|
if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID &&
|
|
!(U4BE(G_io_seproxyhal_spi_buffer, 3) &
|
|
SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) {
|
|
THROW(EXCEPTION_IO_RESET);
|
|
}
|
|
// no break is intentional
|
|
default:
|
|
UX_DEFAULT_EVENT();
|
|
break;
|
|
|
|
case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT:
|
|
UX_DISPLAYED_EVENT({});
|
|
break;
|
|
|
|
case SEPROXYHAL_TAG_TICKER_EVENT:
|
|
UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {
|
|
if (skipWarning && (ux_step == 0)) {
|
|
ux_step++;
|
|
}
|
|
|
|
if (ux_step_count) {
|
|
// prepare next screen
|
|
ux_step = (ux_step + 1) % ux_step_count;
|
|
// redisplay screen
|
|
UX_REDISPLAY();
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
|
|
// close the event if not done previously (by a display or whatever)
|
|
if (!io_seproxyhal_spi_is_status_sent()) {
|
|
io_seproxyhal_general_status();
|
|
}
|
|
|
|
// command has been processed, DO NOT reset the current APDU transport
|
|
return 1;
|
|
}
|
|
|
|
void app_exit(void) {
|
|
BEGIN_TRY_L(exit) {
|
|
TRY_L(exit) {
|
|
os_sched_exit(-1);
|
|
}
|
|
FINALLY_L(exit) {
|
|
}
|
|
}
|
|
END_TRY_L(exit);
|
|
}
|
|
|
|
__attribute__((section(".boot"))) int main(void) {
|
|
// exit critical section
|
|
__asm volatile("cpsie i");
|
|
|
|
os_memset(&txContext, 0, sizeof(txContext));
|
|
|
|
UX_INIT();
|
|
|
|
// ensure exception will work as planned
|
|
os_boot();
|
|
|
|
BEGIN_TRY {
|
|
TRY {
|
|
io_seproxyhal_init();
|
|
|
|
if (N_storage.initialized != 0x01) {
|
|
internalStorage_t storage;
|
|
storage.dataAllowed = 0x00;
|
|
storage.fidoTransport = 0x00;
|
|
storage.initialized = 0x01;
|
|
nvm_write(&N_storage, (void *)&storage,
|
|
sizeof(internalStorage_t));
|
|
}
|
|
|
|
#ifdef HAVE_U2F
|
|
os_memset((unsigned char *)&u2fService, 0, sizeof(u2fService));
|
|
u2fService.inputBuffer = G_io_apdu_buffer;
|
|
u2fService.outputBuffer = G_io_apdu_buffer;
|
|
u2fService.messageBuffer = (uint8_t *)u2fMessageBuffer;
|
|
u2fService.messageBufferSize = U2F_MAX_MESSAGE_SIZE;
|
|
u2f_initialize_service((u2f_service_t *)&u2fService);
|
|
|
|
USB_power_U2F(1, N_storage.fidoTransport);
|
|
#else // HAVE_U2F
|
|
USB_power_U2F(1, 0);
|
|
#endif // HAVE_U2F
|
|
|
|
ui_idle();
|
|
|
|
#if TARGET_ID == 0x31000002
|
|
// setup the status bar colors (remembered after wards, even more if
|
|
// another app does not resetup after app switch)
|
|
UX_SET_STATUS_BAR_COLOR(0xFFFFFF, COLOR_APP);
|
|
#endif // #if TARGET_ID == 0x31000002
|
|
|
|
sample_main();
|
|
}
|
|
CATCH_OTHER(e) {
|
|
}
|
|
FINALLY {
|
|
}
|
|
}
|
|
END_TRY;
|
|
|
|
app_exit();
|
|
|
|
return 0;
|
|
}
|