mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-04 12:56:25 +00:00
feat(core): ble in bootloader
[no changelog]
This commit is contained in:
parent
e1381f901b
commit
f04d8da661
@ -20,7 +20,7 @@ if TREZOR_MODEL in ('1', ):
|
||||
)
|
||||
Return()
|
||||
|
||||
FEATURES_WANTED = ["input", "rgb_led"]
|
||||
FEATURES_WANTED = ["input", "rgb_led", "ble"]
|
||||
|
||||
CCFLAGS_MOD = ''
|
||||
CPPPATH_MOD = []
|
||||
@ -34,9 +34,9 @@ if TREZOR_MODEL in ('1', 'R'):
|
||||
FONT_MONO='Font_PixelOperatorMono_Regular_8'
|
||||
if TREZOR_MODEL in ('T', 'DISC1', ):
|
||||
FONT_NORMAL='Font_TTHoves_Regular_21'
|
||||
FONT_DEMIBOLD=None
|
||||
FONT_DEMIBOLD='Font_TTHoves_Regular_21'
|
||||
FONT_BOLD='Font_TTHoves_Bold_17'
|
||||
FONT_MONO=None
|
||||
FONT_MONO='Font_TTHoves_Regular_21'
|
||||
|
||||
# modtrezorcrypto
|
||||
CCFLAGS_MOD += '-Wno-sequence-point '
|
||||
@ -104,6 +104,7 @@ SOURCE_STMHAL = [
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c',
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c',
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c',
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c',
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c',
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c',
|
||||
'vendor/micropython/lib/stm32lib/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c',
|
||||
@ -126,6 +127,7 @@ SOURCE_BOOTLOADER = [
|
||||
|
||||
SOURCE_TREZORHAL = [
|
||||
'embed/trezorhal/common.c',
|
||||
'embed/trezorhal/dma.c',
|
||||
'embed/trezorhal/image.c',
|
||||
'embed/trezorhal/flash.c',
|
||||
'embed/trezorhal/mini_printf.c',
|
||||
|
@ -49,11 +49,16 @@
|
||||
#ifdef USE_RGB_LED
|
||||
#include "rgb_led.h"
|
||||
#endif
|
||||
#ifdef USE_BLE
|
||||
#include "ble/comm.h"
|
||||
#endif
|
||||
|
||||
#include "usb.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "bootui.h"
|
||||
#include "messages.h"
|
||||
#include "messages.pb.h"
|
||||
#include "rust_ui.h"
|
||||
|
||||
const uint8_t BOOTLOADER_KEY_M = 2;
|
||||
@ -71,8 +76,6 @@ static const uint8_t * const BOOTLOADER_KEYS[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define USB_IFACE_NUM 0
|
||||
|
||||
typedef enum {
|
||||
CONTINUE = 0,
|
||||
RETURN = 1,
|
||||
@ -119,98 +122,221 @@ static void usb_init_all(secbool usb21_landing) {
|
||||
usb_start();
|
||||
}
|
||||
|
||||
static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
|
||||
const image_header *const hdr) {
|
||||
static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr,
|
||||
const image_header *const hdr) {
|
||||
// if both are NULL, we don't have a firmware installed
|
||||
// let's show a webusb landing page in this case
|
||||
usb_init_all((vhdr == NULL && hdr == NULL) ? sectrue : secfalse);
|
||||
|
||||
uint8_t buf[USB_PACKET_SIZE];
|
||||
uint8_t buf_usb[USB_PACKET_SIZE];
|
||||
#ifdef USE_BLE
|
||||
uint8_t ble_buf[BLE_PACKET_SIZE];
|
||||
#endif
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
uint8_t active_iface = 0;
|
||||
int r = 0;
|
||||
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
#ifdef TREZOR_EMULATOR
|
||||
emulator_poll_events();
|
||||
emulator_poll_events();
|
||||
#endif
|
||||
r = usb_webusb_read_blocking(USB_IFACE_NUM, buf_usb, USB_PACKET_SIZE, 20);
|
||||
if (r == USB_PACKET_SIZE) {
|
||||
active_iface = USB_IFACE_NUM;
|
||||
buf = buf_usb;
|
||||
break;
|
||||
}
|
||||
#ifdef USE_BLE
|
||||
r = ble_ext_comm_receive(ble_buf, sizeof(ble_buf));
|
||||
|
||||
if (r == BLE_PACKET_SIZE) {
|
||||
active_iface = BLE_EXT_IFACE_NUM;
|
||||
buf = ble_buf;
|
||||
break;
|
||||
}
|
||||
|
||||
r = ble_int_comm_receive(ble_buf, sizeof(ble_buf));
|
||||
if (r != 0) {
|
||||
active_iface = BLE_INT_IFACE_NUM;
|
||||
buf = ble_buf;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE,
|
||||
USB_TIMEOUT);
|
||||
if (r != USB_PACKET_SIZE) {
|
||||
continue;
|
||||
}
|
||||
uint16_t msg_id;
|
||||
uint32_t msg_size;
|
||||
uint32_t response;
|
||||
if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) {
|
||||
// invalid header -> discard
|
||||
continue;
|
||||
|
||||
#ifdef USE_BLE
|
||||
if (active_iface == BLE_INT_IFACE_NUM) {
|
||||
for (;;) {
|
||||
bool next = false;
|
||||
if (r == 0) {
|
||||
if (active_iface == BLE_INT_IFACE_NUM) {
|
||||
r = ble_int_comm_receive(ble_buf, sizeof(ble_buf));
|
||||
|
||||
if (r == 0) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// unknown interface
|
||||
return CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
uint16_t msg_id;
|
||||
uint32_t msg_size;
|
||||
uint32_t response;
|
||||
if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) {
|
||||
// invalid header -> discard
|
||||
continue;
|
||||
}
|
||||
switch (msg_id) {
|
||||
case MessageType_MessageType_PairingRequest: // pairing request
|
||||
response = process_msg_Pairing(active_iface, msg_size, ble_buf);
|
||||
if (response != INPUT_CONFIRM) {
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
}
|
||||
screen_connect();
|
||||
next = true;
|
||||
|
||||
break;
|
||||
case MessageType_MessageType_RepairRequest: // repairing request
|
||||
response = process_msg_Repair(active_iface, msg_size, ble_buf);
|
||||
if (response != INPUT_CONFIRM) {
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
}
|
||||
// screen_connect();
|
||||
// todo - screen connect or timeout?
|
||||
break;
|
||||
default:
|
||||
process_msg_unknown(active_iface, msg_size, ble_buf);
|
||||
break;
|
||||
}
|
||||
if (next) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (msg_id) {
|
||||
case 0: // Initialize
|
||||
process_msg_Initialize(USB_IFACE_NUM, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
case 1: // Ping
|
||||
process_msg_Ping(USB_IFACE_NUM, msg_size, buf);
|
||||
break;
|
||||
case 5: // WipeDevice
|
||||
response = ui_screen_wipe_confirm();
|
||||
if (INPUT_CANCEL == response) {
|
||||
send_user_abort(USB_IFACE_NUM, "Wipe cancelled");
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
#endif
|
||||
|
||||
if (active_iface == USB_IFACE_NUM || active_iface == BLE_EXT_IFACE_NUM) {
|
||||
for (;;) {
|
||||
#ifdef TREZOR_EMULATOR
|
||||
emulator_poll_events();
|
||||
#endif
|
||||
if (r == 0) {
|
||||
if (active_iface == USB_IFACE_NUM) {
|
||||
r = usb_webusb_read_blocking(active_iface, buf_usb, USB_PACKET_SIZE,
|
||||
USB_TIMEOUT);
|
||||
if (r != USB_PACKET_SIZE) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifdef USE_BLE
|
||||
else if (active_iface == BLE_EXT_IFACE_NUM) {
|
||||
r = ble_ext_comm_receive(ble_buf, sizeof(ble_buf));
|
||||
|
||||
if (r != BLE_PACKET_SIZE) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// unknown interface
|
||||
return CONTINUE;
|
||||
}
|
||||
}
|
||||
ui_screen_wipe();
|
||||
r = process_msg_WipeDevice(USB_IFACE_NUM, msg_size, buf);
|
||||
if (r < 0) { // error
|
||||
screen_wipe_fail();
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
} else { // success
|
||||
screen_wipe_success();
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
|
||||
r = 0;
|
||||
|
||||
uint16_t msg_id;
|
||||
uint32_t msg_size;
|
||||
uint32_t response;
|
||||
int32_t upload_response;
|
||||
if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) {
|
||||
// invalid header -> discard
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 6: // FirmwareErase
|
||||
process_msg_FirmwareErase(USB_IFACE_NUM, msg_size, buf);
|
||||
break;
|
||||
case 7: // FirmwareUpload
|
||||
r = process_msg_FirmwareUpload(USB_IFACE_NUM, msg_size, buf);
|
||||
if (r < 0 && r != UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
||||
ui_screen_fail();
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
} else if (r == UPLOAD_ERR_USER_ABORT) {
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
} else if (r == 0) { // last chunk received
|
||||
ui_screen_install_progress_upload(1000);
|
||||
ui_screen_done(4, sectrue);
|
||||
ui_screen_done(3, secfalse);
|
||||
hal_delay(1000);
|
||||
ui_screen_done(2, secfalse);
|
||||
hal_delay(1000);
|
||||
ui_screen_done(1, secfalse);
|
||||
hal_delay(1000);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
ui_screen_boot_empty(true);
|
||||
return CONTINUE;
|
||||
switch (msg_id) {
|
||||
case 0: // Initialize
|
||||
process_msg_Initialize(active_iface, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
case 1: // Ping
|
||||
process_msg_Ping(active_iface, msg_size, buf);
|
||||
break;
|
||||
case 5: // WipeDevice
|
||||
response = ui_screen_wipe_confirm();
|
||||
if (INPUT_CANCEL == response) {
|
||||
send_user_abort(active_iface, "Wipe cancelled");
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
}
|
||||
ui_screen_wipe();
|
||||
upload_response =
|
||||
process_msg_WipeDevice(active_iface, msg_size, buf);
|
||||
if (upload_response < 0) { // error
|
||||
screen_wipe_fail();
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
} else { // success
|
||||
screen_wipe_success();
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
}
|
||||
break;
|
||||
case 6: // FirmwareErase
|
||||
process_msg_FirmwareErase(active_iface, msg_size, buf);
|
||||
break;
|
||||
case 7: // FirmwareUpload
|
||||
upload_response =
|
||||
process_msg_FirmwareUpload(active_iface, msg_size, buf);
|
||||
if (upload_response < 0 &&
|
||||
upload_response !=
|
||||
UPLOAD_ERR_USER_ABORT) { // error, but not user abort
|
||||
ui_screen_fail();
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return SHUTDOWN;
|
||||
} else if (upload_response == UPLOAD_ERR_USER_ABORT) {
|
||||
hal_delay(100);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
return RETURN;
|
||||
} else if (upload_response == 0) { // last chunk received
|
||||
ui_screen_install_progress_upload(1000);
|
||||
ui_screen_done(4, sectrue);
|
||||
ui_screen_done(3, secfalse);
|
||||
hal_delay(1000);
|
||||
ui_screen_done(2, secfalse);
|
||||
hal_delay(1000);
|
||||
ui_screen_done(1, secfalse);
|
||||
hal_delay(1000);
|
||||
usb_stop();
|
||||
usb_deinit();
|
||||
ui_screen_boot_empty(true);
|
||||
return CONTINUE;
|
||||
}
|
||||
break;
|
||||
case 55: // GetFeatures
|
||||
process_msg_GetFeatures(active_iface, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
default:
|
||||
process_msg_unknown(active_iface, msg_size, buf);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 55: // GetFeatures
|
||||
process_msg_GetFeatures(USB_IFACE_NUM, msg_size, buf, vhdr, hdr);
|
||||
break;
|
||||
default:
|
||||
process_msg_unknown(USB_IFACE_NUM, msg_size, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,6 +469,9 @@ int bootloader_main(void) {
|
||||
#ifdef USE_RGB_LED
|
||||
rgb_led_init();
|
||||
#endif
|
||||
#ifdef USE_BLE
|
||||
ble_comm_init();
|
||||
#endif
|
||||
|
||||
#if PRODUCTION
|
||||
check_bootloader_version();
|
||||
@ -402,7 +531,7 @@ int bootloader_main(void) {
|
||||
NULL);
|
||||
|
||||
// and start the usb loop
|
||||
if (bootloader_usb_loop(NULL, NULL) != CONTINUE) {
|
||||
if (bootloader_comm_loop(NULL, NULL) != CONTINUE) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -461,7 +590,7 @@ int bootloader_main(void) {
|
||||
break;
|
||||
case SCREEN_WAIT_FOR_HOST:
|
||||
screen_connect();
|
||||
switch (bootloader_usb_loop(&vhdr, hdr)) {
|
||||
switch (bootloader_comm_loop(&vhdr, hdr)) {
|
||||
case CONTINUE:
|
||||
continue_to_firmware = true;
|
||||
break;
|
||||
|
@ -24,6 +24,11 @@
|
||||
#include <pb_encode.h>
|
||||
#include "messages.pb.h"
|
||||
|
||||
#include TREZOR_BOARD
|
||||
|
||||
#ifdef USE_BLE
|
||||
#include "ble/comm.h"
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "flash.h"
|
||||
#include "image.h"
|
||||
@ -36,6 +41,7 @@
|
||||
#include "rust_ui.h"
|
||||
|
||||
#include "memzero.h"
|
||||
#include STM32_HAL_H
|
||||
|
||||
#ifdef TREZOR_EMULATOR
|
||||
#include "emulator.h"
|
||||
@ -59,12 +65,11 @@ typedef struct {
|
||||
uint8_t packet_index;
|
||||
uint8_t packet_pos;
|
||||
uint8_t buf[USB_PACKET_SIZE];
|
||||
} usb_write_state;
|
||||
} write_state;
|
||||
|
||||
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
||||
static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf,
|
||||
size_t count) {
|
||||
usb_write_state *state = (usb_write_state *)(stream->state);
|
||||
static bool _write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) {
|
||||
write_state *state = (write_state *)(stream->state);
|
||||
|
||||
size_t written = 0;
|
||||
// while we have data left
|
||||
@ -84,9 +89,20 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
written += USB_PACKET_SIZE - state->packet_pos;
|
||||
// send packet
|
||||
int r = usb_webusb_write_blocking(state->iface_num, state->buf,
|
||||
USB_PACKET_SIZE, USB_TIMEOUT);
|
||||
ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
|
||||
|
||||
if (state->iface_num == USB_IFACE_NUM) {
|
||||
int r = usb_webusb_write_blocking(state->iface_num, state->buf,
|
||||
USB_PACKET_SIZE, USB_TIMEOUT);
|
||||
ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
|
||||
}
|
||||
#ifdef USE_BLE
|
||||
else if (state->iface_num == BLE_INT_IFACE_NUM) {
|
||||
ble_int_comm_send(state->buf, USB_PACKET_SIZE, INTERNAL_MESSAGE);
|
||||
} else if (state->iface_num == BLE_EXT_IFACE_NUM) {
|
||||
ble_int_comm_send(state->buf, USB_PACKET_SIZE, EXTERNAL_MESSAGE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// prepare new packet
|
||||
state->packet_index++;
|
||||
memzero(state->buf, USB_PACKET_SIZE);
|
||||
@ -98,7 +114,7 @@ static bool _usb_write(pb_ostream_t *stream, const pb_byte_t *buf,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _usb_write_flush(usb_write_state *state) {
|
||||
static void _write_flush(write_state *state) {
|
||||
// if packet is not filled up completely
|
||||
if (state->packet_pos < USB_PACKET_SIZE) {
|
||||
// pad it with zeroes
|
||||
@ -106,9 +122,18 @@ static void _usb_write_flush(usb_write_state *state) {
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
}
|
||||
// send packet
|
||||
int r = usb_webusb_write_blocking(state->iface_num, state->buf,
|
||||
USB_PACKET_SIZE, USB_TIMEOUT);
|
||||
ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
|
||||
if (state->iface_num == USB_IFACE_NUM) {
|
||||
int r = usb_webusb_write_blocking(state->iface_num, state->buf,
|
||||
USB_PACKET_SIZE, USB_TIMEOUT);
|
||||
ensure(sectrue * (r == USB_PACKET_SIZE), NULL);
|
||||
}
|
||||
#ifdef USE_BLE
|
||||
else if (state->iface_num == BLE_INT_IFACE_NUM) {
|
||||
ble_int_comm_send(state->buf, USB_PACKET_SIZE, INTERNAL_MESSAGE);
|
||||
} else if (state->iface_num == BLE_EXT_IFACE_NUM) {
|
||||
ble_int_comm_send(state->buf, USB_PACKET_SIZE, EXTERNAL_MESSAGE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static secbool _send_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
@ -124,7 +149,7 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
}
|
||||
const uint32_t msg_size = sizestream.bytes_written;
|
||||
|
||||
usb_write_state state = {
|
||||
write_state state = {
|
||||
.iface_num = iface_num,
|
||||
.packet_index = 0,
|
||||
.packet_pos = MSG_HEADER1_LEN,
|
||||
@ -142,7 +167,7 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
},
|
||||
};
|
||||
|
||||
pb_ostream_t stream = {.callback = &_usb_write,
|
||||
pb_ostream_t stream = {.callback = _write,
|
||||
.state = &state,
|
||||
.max_size = SIZE_MAX,
|
||||
.bytes_written = 0,
|
||||
@ -152,9 +177,17 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
_usb_write_flush(&state);
|
||||
_write_flush(&state);
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
return sectrue;
|
||||
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
||||
static bool _write_authkey(pb_ostream_t *stream, const pb_field_iter_t *field,
|
||||
void *const *arg) {
|
||||
uint8_t *key = (uint8_t *)(*arg);
|
||||
if (!pb_encode_tag_for_field(stream, field)) return false;
|
||||
|
||||
return pb_encode_string(stream, (uint8_t *)key, 6);
|
||||
}
|
||||
|
||||
#define MSG_SEND_INIT(TYPE) TYPE msg_send = TYPE##_init_default
|
||||
@ -185,6 +218,11 @@ static secbool _send_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
MIN(LEN, sizeof(msg_send.FIELD.bytes))); \
|
||||
msg_send.FIELD.size = MIN(LEN, sizeof(msg_send.FIELD.bytes)); \
|
||||
}
|
||||
#define MSG_SEND_CALLBACK(FIELD, CALLBACK, ARGUMENT) \
|
||||
{ \
|
||||
msg_send.FIELD.funcs.encode = &CALLBACK; \
|
||||
msg_send.FIELD.arg = (void *)ARGUMENT; \
|
||||
}
|
||||
#define MSG_SEND(TYPE) \
|
||||
_send_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, &msg_send)
|
||||
|
||||
@ -192,8 +230,9 @@ typedef struct {
|
||||
uint8_t iface_num;
|
||||
uint8_t packet_index;
|
||||
uint8_t packet_pos;
|
||||
uint16_t packet_size;
|
||||
uint8_t *buf;
|
||||
} usb_read_state;
|
||||
} read_state;
|
||||
|
||||
static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) {
|
||||
for (int retry = 0;; retry++) {
|
||||
@ -213,16 +252,54 @@ static void _usb_webusb_read_retry(uint8_t iface_num, uint8_t *buf) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_BLE
|
||||
static void _ble_read_retry(uint8_t iface_num, uint8_t *buf) {
|
||||
for (int retry = 0;; retry++) {
|
||||
int r = ble_ext_comm_receive(buf, BLE_PACKET_SIZE);
|
||||
if (r != BLE_PACKET_SIZE) { // reading failed
|
||||
if (r == 0 && retry < 500) {
|
||||
// only timeout => let's try again
|
||||
HAL_Delay(10);
|
||||
continue;
|
||||
} else {
|
||||
// error
|
||||
error_shutdown("BLE ERROR",
|
||||
"Error reading from BLE. Try different BLE cable.");
|
||||
}
|
||||
}
|
||||
return; // success
|
||||
}
|
||||
}
|
||||
|
||||
static void _ble_read_retry_int(uint8_t iface_num, uint8_t *buf) {
|
||||
for (int retry = 0;; retry++) {
|
||||
int r = ble_int_comm_receive(buf, USB_PACKET_SIZE);
|
||||
if (r == 0) { // reading failed
|
||||
if (retry < 500) {
|
||||
// only timeout => let's try again
|
||||
HAL_Delay(10);
|
||||
continue;
|
||||
} else {
|
||||
// error
|
||||
error_shutdown("BLE ERROR",
|
||||
"Error reading from BLE. Try different BLE cable.");
|
||||
}
|
||||
}
|
||||
return; // success
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
||||
static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) {
|
||||
usb_read_state *state = (usb_read_state *)(stream->state);
|
||||
static bool _read(pb_istream_t *stream, uint8_t *buf, size_t count) {
|
||||
read_state *state = (read_state *)(stream->state);
|
||||
|
||||
size_t read = 0;
|
||||
// while we have data left
|
||||
while (read < count) {
|
||||
size_t remaining = count - read;
|
||||
// if all remaining data fit into our packet
|
||||
if (state->packet_pos + remaining <= USB_PACKET_SIZE) {
|
||||
if (state->packet_pos + remaining <= state->packet_size) {
|
||||
// append data from buf to state->buf
|
||||
memcpy(buf + read, state->buf + state->packet_pos, remaining);
|
||||
// advance position
|
||||
@ -232,10 +309,19 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) {
|
||||
} else {
|
||||
// append data that fits
|
||||
memcpy(buf + read, state->buf + state->packet_pos,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
read += USB_PACKET_SIZE - state->packet_pos;
|
||||
state->packet_size - state->packet_pos);
|
||||
read += state->packet_size - state->packet_pos;
|
||||
// read next packet (with retry)
|
||||
_usb_webusb_read_retry(state->iface_num, state->buf);
|
||||
#ifdef USE_BLE
|
||||
if (state->iface_num == BLE_EXT_IFACE_NUM) {
|
||||
_ble_read_retry(state->iface_num, state->buf);
|
||||
} else if (state->iface_num == BLE_INT_IFACE_NUM) {
|
||||
_ble_read_retry_int(state->iface_num, state->buf);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
_usb_webusb_read_retry(state->iface_num, state->buf);
|
||||
}
|
||||
// prepare next packet
|
||||
state->packet_index++;
|
||||
state->packet_pos = MSG_HEADER2_LEN;
|
||||
@ -245,16 +331,24 @@ static bool _usb_read(pb_istream_t *stream, uint8_t *buf, size_t count) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _usb_read_flush(usb_read_state *state) { (void)state; }
|
||||
static void _read_flush(read_state *state) { (void)state; }
|
||||
|
||||
static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
|
||||
const pb_msgdesc_t *fields, void *msg) {
|
||||
usb_read_state state = {.iface_num = iface_num,
|
||||
.packet_index = 0,
|
||||
.packet_pos = MSG_HEADER1_LEN,
|
||||
.buf = buf};
|
||||
uint16_t packet_size = USB_PACKET_SIZE;
|
||||
#ifdef USE_BLE
|
||||
if (iface_num == BLE_EXT_IFACE_NUM) {
|
||||
packet_size = BLE_PACKET_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
pb_istream_t stream = {.callback = &_usb_read,
|
||||
read_state state = {.iface_num = iface_num,
|
||||
.packet_index = 0,
|
||||
.packet_pos = MSG_HEADER1_LEN,
|
||||
.packet_size = packet_size,
|
||||
.buf = buf};
|
||||
|
||||
pb_istream_t stream = {.callback = &_read,
|
||||
.state = &state,
|
||||
.bytes_left = msg_size,
|
||||
.errmsg = NULL};
|
||||
@ -263,7 +357,7 @@ static secbool _recv_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
_usb_read_flush(&state);
|
||||
_read_flush(&state);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
@ -306,6 +400,39 @@ static void send_msg_features(uint8_t iface_num,
|
||||
MSG_SEND(Features);
|
||||
}
|
||||
|
||||
uint32_t process_msg_Pairing(uint8_t iface_num, uint32_t msg_size,
|
||||
uint8_t *buf) {
|
||||
uint8_t buffer[6];
|
||||
MSG_RECV_INIT(PairingRequest);
|
||||
MSG_RECV(PairingRequest);
|
||||
|
||||
uint32_t result = screen_pairing_confirm(buffer);
|
||||
|
||||
if (result == INPUT_CONFIRM) {
|
||||
MSG_SEND_INIT(AuthKey);
|
||||
MSG_SEND_CALLBACK(key, _write_authkey, buffer);
|
||||
MSG_SEND(AuthKey);
|
||||
} else {
|
||||
send_user_abort(iface_num, "Pairing cancelled");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t process_msg_Repair(uint8_t iface_num, uint32_t msg_size,
|
||||
uint8_t *buf) {
|
||||
MSG_RECV_INIT(RepairRequest);
|
||||
MSG_RECV(RepairRequest);
|
||||
uint32_t result = screen_repair_confirm();
|
||||
if (result == INPUT_CONFIRM) {
|
||||
MSG_SEND_INIT(Success);
|
||||
MSG_SEND(Success);
|
||||
} else {
|
||||
send_user_abort(iface_num, "Pairing cancelled");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void process_msg_Initialize(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
|
||||
const vendor_header *const vhdr,
|
||||
const image_header *const hdr) {
|
||||
|
@ -24,6 +24,9 @@
|
||||
#include "image.h"
|
||||
#include "secbool.h"
|
||||
|
||||
#define USB_IFACE_NUM 0
|
||||
#define BLE_INT_IFACE_NUM 16
|
||||
#define BLE_EXT_IFACE_NUM 17
|
||||
#define USB_TIMEOUT 500
|
||||
#define USB_PACKET_SIZE 64
|
||||
|
||||
@ -68,4 +71,9 @@ void process_msg_unknown(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);
|
||||
|
||||
secbool bootloader_WipeDevice(void);
|
||||
|
||||
uint32_t process_msg_Pairing(uint8_t iface_num, uint32_t msg_size,
|
||||
uint8_t *buf);
|
||||
|
||||
uint32_t process_msg_Repair(uint8_t iface_num, uint32_t msg_size, uint8_t *buf);
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,15 @@ PB_BIND(FirmwareRequest, FirmwareRequest, AUTO)
|
||||
PB_BIND(FirmwareUpload, FirmwareUpload, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PairingRequest, PairingRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(AuthKey, AuthKey, AUTO)
|
||||
|
||||
|
||||
PB_BIND(RepairRequest, RepairRequest, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -10,121 +10,136 @@
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _MessageType {
|
||||
MessageType_MessageType_Initialize = 0,
|
||||
MessageType_MessageType_Ping = 1,
|
||||
MessageType_MessageType_Success = 2,
|
||||
MessageType_MessageType_Failure = 3,
|
||||
MessageType_MessageType_FirmwareErase = 6,
|
||||
MessageType_MessageType_FirmwareUpload = 7,
|
||||
MessageType_MessageType_FirmwareRequest = 8,
|
||||
MessageType_MessageType_Features = 17,
|
||||
MessageType_MessageType_ButtonRequest = 26,
|
||||
MessageType_MessageType_ButtonAck = 27,
|
||||
MessageType_MessageType_GetFeatures = 55
|
||||
typedef enum _MessageType {
|
||||
MessageType_MessageType_Initialize = 0,
|
||||
MessageType_MessageType_Ping = 1,
|
||||
MessageType_MessageType_Success = 2,
|
||||
MessageType_MessageType_Failure = 3,
|
||||
MessageType_MessageType_FirmwareErase = 6,
|
||||
MessageType_MessageType_FirmwareUpload = 7,
|
||||
MessageType_MessageType_FirmwareRequest = 8,
|
||||
MessageType_MessageType_Features = 17,
|
||||
MessageType_MessageType_ButtonRequest = 26,
|
||||
MessageType_MessageType_ButtonAck = 27,
|
||||
MessageType_MessageType_GetFeatures = 55,
|
||||
MessageType_MessageType_PairingRequest = 8003,
|
||||
MessageType_MessageType_AuthKey = 8004,
|
||||
MessageType_MessageType_RepairRequest = 8005
|
||||
} MessageType;
|
||||
|
||||
typedef enum _FailureType {
|
||||
FailureType_Failure_UnexpectedMessage = 1,
|
||||
FailureType_Failure_DataError = 3,
|
||||
FailureType_Failure_ActionCancelled = 4,
|
||||
FailureType_Failure_ProcessError = 9
|
||||
typedef enum _FailureType {
|
||||
FailureType_Failure_UnexpectedMessage = 1,
|
||||
FailureType_Failure_DataError = 3,
|
||||
FailureType_Failure_ActionCancelled = 4,
|
||||
FailureType_Failure_ProcessError = 9
|
||||
} FailureType;
|
||||
|
||||
typedef enum _ButtonRequestType {
|
||||
ButtonRequestType_ButtonRequest_Other = 1
|
||||
typedef enum _ButtonRequestType {
|
||||
ButtonRequestType_ButtonRequest_Other = 1
|
||||
} ButtonRequestType;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _ButtonAck {
|
||||
typedef struct _AuthKey {
|
||||
pb_callback_t key;
|
||||
} AuthKey;
|
||||
|
||||
typedef struct _ButtonAck {
|
||||
char dummy_field;
|
||||
} ButtonAck;
|
||||
|
||||
typedef struct _GetFeatures {
|
||||
typedef struct _GetFeatures {
|
||||
char dummy_field;
|
||||
} GetFeatures;
|
||||
|
||||
typedef struct _Initialize {
|
||||
typedef struct _Initialize {
|
||||
char dummy_field;
|
||||
} Initialize;
|
||||
|
||||
typedef struct _ButtonRequest {
|
||||
typedef struct _PairingRequest {
|
||||
char dummy_field;
|
||||
} PairingRequest;
|
||||
|
||||
typedef struct _RepairRequest {
|
||||
char dummy_field;
|
||||
} RepairRequest;
|
||||
|
||||
typedef struct _ButtonRequest {
|
||||
bool has_code;
|
||||
ButtonRequestType code;
|
||||
ButtonRequestType code;
|
||||
} ButtonRequest;
|
||||
|
||||
typedef struct _Failure {
|
||||
typedef struct _Failure {
|
||||
bool has_code;
|
||||
FailureType code;
|
||||
FailureType code;
|
||||
bool has_message;
|
||||
char message[256];
|
||||
char message[256];
|
||||
} Failure;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(20) Features_revision_t;
|
||||
typedef struct _Features {
|
||||
typedef struct _Features {
|
||||
bool has_vendor;
|
||||
char vendor[33];
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t patch_version;
|
||||
char vendor[33];
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t patch_version;
|
||||
bool has_bootloader_mode;
|
||||
bool bootloader_mode;
|
||||
bool bootloader_mode;
|
||||
bool has_device_id;
|
||||
char device_id[25];
|
||||
char device_id[25];
|
||||
bool has_language;
|
||||
char language[17];
|
||||
char language[17];
|
||||
bool has_label;
|
||||
char label[33];
|
||||
char label[33];
|
||||
bool has_initialized;
|
||||
bool initialized;
|
||||
bool initialized;
|
||||
bool has_revision;
|
||||
Features_revision_t revision;
|
||||
Features_revision_t revision;
|
||||
bool has_firmware_present;
|
||||
bool firmware_present;
|
||||
bool firmware_present;
|
||||
bool has_model;
|
||||
char model[17];
|
||||
char model[17];
|
||||
bool has_fw_major;
|
||||
uint32_t fw_major;
|
||||
uint32_t fw_major;
|
||||
bool has_fw_minor;
|
||||
uint32_t fw_minor;
|
||||
uint32_t fw_minor;
|
||||
bool has_fw_patch;
|
||||
uint32_t fw_patch;
|
||||
uint32_t fw_patch;
|
||||
bool has_fw_vendor;
|
||||
char fw_vendor[256];
|
||||
char fw_vendor[256];
|
||||
} Features;
|
||||
|
||||
typedef struct _FirmwareErase {
|
||||
typedef struct _FirmwareErase {
|
||||
bool has_length;
|
||||
uint32_t length;
|
||||
uint32_t length;
|
||||
} FirmwareErase;
|
||||
|
||||
typedef struct _FirmwareRequest {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
typedef struct _FirmwareRequest {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
} FirmwareRequest;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(32) FirmwareUpload_hash_t;
|
||||
typedef struct _FirmwareUpload {
|
||||
pb_callback_t payload;
|
||||
typedef struct _FirmwareUpload {
|
||||
pb_callback_t payload;
|
||||
bool has_hash;
|
||||
FirmwareUpload_hash_t hash;
|
||||
FirmwareUpload_hash_t hash;
|
||||
} FirmwareUpload;
|
||||
|
||||
typedef struct _Ping {
|
||||
typedef struct _Ping {
|
||||
bool has_message;
|
||||
char message[256];
|
||||
char message[256];
|
||||
} Ping;
|
||||
|
||||
typedef struct _Success {
|
||||
typedef struct _Success {
|
||||
bool has_message;
|
||||
char message[256];
|
||||
char message[256];
|
||||
} Success;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _MessageType_MIN MessageType_MessageType_Initialize
|
||||
#define _MessageType_MAX MessageType_MessageType_GetFeatures
|
||||
#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_GetFeatures+1))
|
||||
#define _MessageType_MAX MessageType_MessageType_RepairRequest
|
||||
#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_RepairRequest+1))
|
||||
|
||||
#define _FailureType_MIN FailureType_Failure_UnexpectedMessage
|
||||
#define _FailureType_MAX FailureType_Failure_ProcessError
|
||||
@ -151,6 +166,9 @@ extern "C" {
|
||||
#define FirmwareErase_init_default {false, 0}
|
||||
#define FirmwareRequest_init_default {0, 0}
|
||||
#define FirmwareUpload_init_default {{{NULL}, NULL}, false, {0, {0}}}
|
||||
#define PairingRequest_init_default {0}
|
||||
#define AuthKey_init_default {{{NULL}, NULL}}
|
||||
#define RepairRequest_init_default {0}
|
||||
#define Initialize_init_zero {0}
|
||||
#define GetFeatures_init_zero {0}
|
||||
#define Features_init_zero {false, "", 0, 0, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, ""}
|
||||
@ -162,8 +180,12 @@ extern "C" {
|
||||
#define FirmwareErase_init_zero {false, 0}
|
||||
#define FirmwareRequest_init_zero {0, 0}
|
||||
#define FirmwareUpload_init_zero {{{NULL}, NULL}, false, {0, {0}}}
|
||||
#define PairingRequest_init_zero {0}
|
||||
#define AuthKey_init_zero {{{NULL}, NULL}}
|
||||
#define RepairRequest_init_zero {0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define AuthKey_key_tag 1
|
||||
#define ButtonRequest_code_tag 1
|
||||
#define Failure_code_tag 1
|
||||
#define Failure_message_tag 2
|
||||
@ -265,6 +287,21 @@ X(a, STATIC, OPTIONAL, BYTES, hash, 2)
|
||||
#define FirmwareUpload_CALLBACK pb_default_field_callback
|
||||
#define FirmwareUpload_DEFAULT NULL
|
||||
|
||||
#define PairingRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define PairingRequest_CALLBACK NULL
|
||||
#define PairingRequest_DEFAULT NULL
|
||||
|
||||
#define AuthKey_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, REQUIRED, BYTES, key, 1)
|
||||
#define AuthKey_CALLBACK pb_default_field_callback
|
||||
#define AuthKey_DEFAULT NULL
|
||||
|
||||
#define RepairRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define RepairRequest_CALLBACK NULL
|
||||
#define RepairRequest_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t Initialize_msg;
|
||||
extern const pb_msgdesc_t GetFeatures_msg;
|
||||
extern const pb_msgdesc_t Features_msg;
|
||||
@ -276,6 +313,9 @@ extern const pb_msgdesc_t ButtonAck_msg;
|
||||
extern const pb_msgdesc_t FirmwareErase_msg;
|
||||
extern const pb_msgdesc_t FirmwareRequest_msg;
|
||||
extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
extern const pb_msgdesc_t PairingRequest_msg;
|
||||
extern const pb_msgdesc_t AuthKey_msg;
|
||||
extern const pb_msgdesc_t RepairRequest_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Initialize_fields &Initialize_msg
|
||||
@ -289,9 +329,13 @@ extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
#define FirmwareErase_fields &FirmwareErase_msg
|
||||
#define FirmwareRequest_fields &FirmwareRequest_msg
|
||||
#define FirmwareUpload_fields &FirmwareUpload_msg
|
||||
#define PairingRequest_fields &PairingRequest_msg
|
||||
#define AuthKey_fields &AuthKey_msg
|
||||
#define RepairRequest_fields &RepairRequest_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* FirmwareUpload_size depends on runtime parameters */
|
||||
/* AuthKey_size depends on runtime parameters */
|
||||
#define ButtonAck_size 0
|
||||
#define ButtonRequest_size 2
|
||||
#define Failure_size 260
|
||||
@ -300,7 +344,9 @@ extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
#define FirmwareRequest_size 12
|
||||
#define GetFeatures_size 0
|
||||
#define Initialize_size 0
|
||||
#define PairingRequest_size 0
|
||||
#define Ping_size 258
|
||||
#define RepairRequest_size 0
|
||||
#define Success_size 258
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -16,6 +16,9 @@ enum MessageType {
|
||||
MessageType_ButtonRequest = 26;
|
||||
MessageType_ButtonAck = 27;
|
||||
MessageType_GetFeatures = 55;
|
||||
MessageType_PairingRequest = 8003;
|
||||
MessageType_AuthKey = 8004;
|
||||
MessageType_RepairRequest = 8005;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,3 +143,32 @@ message FirmwareUpload {
|
||||
required bytes payload = 1; // firmware to be loaded into device
|
||||
optional bytes hash = 2; // hash of the payload
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Request: initiates new pairing request
|
||||
* @start
|
||||
* @next AuthKey
|
||||
* @next Failure
|
||||
*/
|
||||
message PairingRequest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Request: confirms pairing request with auth key entered on the device
|
||||
* @end
|
||||
*/
|
||||
message AuthKey {
|
||||
required bytes key = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Request: initiates repairing request
|
||||
* @start
|
||||
* @next Success
|
||||
* @next Failure
|
||||
*/
|
||||
message RepairRequest {
|
||||
}
|
||||
|
||||
|
@ -26,4 +26,7 @@ void screen_welcome_model(void);
|
||||
void screen_welcome(void);
|
||||
void screen_boot_empty(bool fading);
|
||||
|
||||
uint32_t screen_pairing_confirm(uint8_t* buffer);
|
||||
uint32_t screen_repair_confirm(void);
|
||||
|
||||
void display_image(int16_t x, int16_t y, const uint8_t* data, uint32_t datalen);
|
||||
|
@ -14,17 +14,19 @@ use crate::{
|
||||
theme::{
|
||||
button_bld, button_confirm, button_wipe_cancel, button_wipe_confirm, BLD_BG,
|
||||
BLD_FG, BLD_WIPE_COLOR, CHECK24, CHECK40, DOWNLOAD32, FIRE32, FIRE40,
|
||||
LOGO_EMPTY, TEXT_WIPE_BOLD, TEXT_WIPE_NORMAL, WARNING40, WELCOME_COLOR, X24,
|
||||
LOGO_EMPTY, TEXT_NORMAL, TEXT_WIPE_BOLD, TEXT_WIPE_NORMAL, WARNING40,
|
||||
WELCOME_COLOR, X24,
|
||||
},
|
||||
welcome::Welcome,
|
||||
},
|
||||
component::{Button, ResultScreen, WelcomeScreen},
|
||||
component::{Button, PinKeyboard, ResultScreen, WelcomeScreen},
|
||||
constant,
|
||||
theme::{BACKLIGHT_DIM, BACKLIGHT_NORMAL, BLACK, FG, WHITE},
|
||||
},
|
||||
util::{from_c_array, from_c_str},
|
||||
},
|
||||
};
|
||||
use core::slice;
|
||||
use heapless::String;
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
@ -72,13 +74,16 @@ fn fadeout() {
|
||||
display::fade_backlight_duration(BACKLIGHT_DIM, 150);
|
||||
}
|
||||
|
||||
fn run<F>(frame: &mut F) -> u32
|
||||
fn run<F>(frame: &mut F, clear: bool) -> u32
|
||||
where
|
||||
F: Component,
|
||||
F::Msg: ReturnToC,
|
||||
{
|
||||
frame.place(constant::screen());
|
||||
fadeout();
|
||||
if clear {
|
||||
display::rect_fill(screen(), BLACK);
|
||||
}
|
||||
display::sync();
|
||||
frame.paint();
|
||||
fadein();
|
||||
@ -191,7 +196,7 @@ extern "C" fn screen_install_confirm(
|
||||
Some(("FW FINGERPRINT", fingerprint_str)),
|
||||
);
|
||||
|
||||
run(&mut frame)
|
||||
run(&mut frame, false)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -222,12 +227,12 @@ extern "C" fn screen_wipe_confirm() -> u32 {
|
||||
None,
|
||||
);
|
||||
|
||||
run(&mut frame)
|
||||
run(&mut frame, false)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn screen_menu() -> u32 {
|
||||
run(&mut Menu::new())
|
||||
run(&mut Menu::new(), false)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -253,7 +258,7 @@ extern "C" fn screen_intro(
|
||||
|
||||
let mut frame = Intro::new(title_str.as_str(), version_str.as_str());
|
||||
|
||||
run(&mut frame)
|
||||
run(&mut frame, false)
|
||||
}
|
||||
|
||||
fn screen_progress(
|
||||
@ -419,3 +424,41 @@ extern "C" fn screen_welcome() {
|
||||
let mut frame = Welcome::new();
|
||||
show(&mut frame, true);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn screen_pairing_confirm(buffer: *const cty::uint8_t) -> u32 {
|
||||
let pin_slice = unsafe { slice::from_raw_parts_mut(buffer as *mut u8, 6) };
|
||||
|
||||
let mut pin = PinKeyboard::new("Enter passkey", "", None, true);
|
||||
let res = run(&mut pin, true);
|
||||
|
||||
if res == 2 {
|
||||
let pin = pin.pin().as_bytes();
|
||||
if pin.len() == 6 {
|
||||
pin_slice.copy_from_slice(&pin[0..6]);
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn screen_repair_confirm() -> u32 {
|
||||
let msg = Label::new("Allow repair?", Alignment::Center, TEXT_NORMAL);
|
||||
let right = Button::with_text("ALLOW").styled(button_confirm());
|
||||
let left = Button::with_text("DENY").styled(button_bld());
|
||||
let title = Label::new("REPAIR", Alignment::Start, theme::TEXT_BOLD)
|
||||
.vertically_aligned(Alignment::Center);
|
||||
|
||||
let mut frame = Confirm::new(
|
||||
BLD_BG,
|
||||
left,
|
||||
right,
|
||||
ConfirmTitle::Text(title),
|
||||
msg,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
|
||||
run(&mut frame, true)
|
||||
}
|
||||
|
@ -230,6 +230,8 @@ pub fn button_bld() -> ButtonStyleSheet {
|
||||
}
|
||||
}
|
||||
|
||||
pub const TEXT_NORMAL_BLACK: TextStyle = TextStyle::new(Font::NORMAL, WHITE, BLACK, WHITE, WHITE);
|
||||
|
||||
pub const TEXT_TITLE: TextStyle = TextStyle::new(
|
||||
Font::BOLD,
|
||||
BLD_TITLE_COLOR,
|
||||
|
@ -19,9 +19,10 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, ToPrimitive)]
|
||||
pub enum PinKeyboardMsg {
|
||||
Confirmed,
|
||||
Cancelled,
|
||||
Cancelled = 1,
|
||||
Confirmed = 2,
|
||||
}
|
||||
|
||||
const MAX_LENGTH: usize = 50;
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "comm.h"
|
||||
#include <string.h>
|
||||
#include "buffers.h"
|
||||
#include "dma.h"
|
||||
#include "int_comm_defs.h"
|
||||
#include "state.h"
|
||||
@ -40,7 +41,7 @@ typedef struct {
|
||||
bool ready;
|
||||
} spi_buffer_t;
|
||||
|
||||
spi_buffer_t spi_queue[SPI_QUEUE_SIZE];
|
||||
BUFFER_SECTION spi_buffer_t spi_queue[SPI_QUEUE_SIZE];
|
||||
static int head = 0, tail = 0;
|
||||
static bool overrun = false;
|
||||
volatile uint16_t overrun_count = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user