Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-pro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: "build-pro"

on:
push:
branches: [master]
branches: [main]
workflow_dispatch:

jobs:
Expand Down
157 changes: 94 additions & 63 deletions core/embed/trezorhal/usart.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ static DMA_HandleTypeDef hdma_rx;

static bool uart_tx_done = false;

#define UART_PACKET_MAX_LEN 128
#define UART_PACKET_MAX_LEN 256
static uint8_t dma_uart_rev_buf[UART_PACKET_MAX_LEN]
__attribute__((section(".sram3")));
static uint8_t dma_uart_send_buf[UART_PACKET_MAX_LEN]
__attribute__((section(".sram3")));
uint32_t usart_fifo_len = 0;
static uint32_t usart_dma_rx_read_pos = 0;

uint8_t uart_data_in[UART_BUF_MAX_LEN];

Expand Down Expand Up @@ -103,7 +103,7 @@ void ble_usart_init(void) {
hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_rx.Init.Mode = DMA_NORMAL;
hdma_rx.Init.Mode = DMA_CIRCULAR;
hdma_rx.Init.Priority = DMA_PRIORITY_MEDIUM;

HAL_DMA_Init(&hdma_rx);
Expand All @@ -129,6 +129,7 @@ void ble_usart_init(void) {
HAL_UART_ReceiverTimeout_Config(
huart, (UART_TIMEOUT_MS * 1000) / UART_ONE_BIT_TIME_US);
__HAL_UART_ENABLE_IT(huart, UART_IT_RTO);
usart_dma_rx_read_pos = 0;
HAL_UART_Receive_DMA(huart, dma_uart_rev_buf, sizeof(dma_uart_rev_buf));
}

Expand Down Expand Up @@ -189,6 +190,7 @@ void ble_usart_irq_ctrl(bool enable) {
if (enable) {
HAL_NVIC_EnableIRQ(UART4_IRQn);
HAL_UART_Abort(huart);
usart_dma_rx_read_pos = 0;
HAL_UART_Receive_DMA(huart, dma_uart_rev_buf, sizeof(dma_uart_rev_buf));
} else {
HAL_UART_Abort(huart);
Expand All @@ -206,74 +208,110 @@ uint32_t ble_usart_read(uint8_t *buf, uint32_t lenth) {
return len + 3;
}

static uint8_t calXor(uint8_t *buf, uint32_t len) {
uint8_t tmp = 0;
uint32_t i;
for (i = 0; i < len; i++) {
tmp ^= buf[i];
static void usart_rx_dma_process(void) {
uint32_t write_pos =
sizeof(dma_uart_rev_buf) - __HAL_DMA_GET_COUNTER(huart->hdmarx);
if (write_pos == usart_dma_rx_read_pos) {
return;
}
return tmp;
}

static void usart_rev_package_dma(uint8_t *buf, uint32_t len) {
if (len < 5) {
return;
uint32_t available_len;
if (write_pos > usart_dma_rx_read_pos) {
available_len = write_pos - usart_dma_rx_read_pos;
} else {
available_len =
sizeof(dma_uart_rev_buf) - usart_dma_rx_read_pos + write_pos;
}
uint32_t index = 0;
uint8_t *p_header;
while (len > 0) {
if (buf[index] != 0xA5 || buf[index + 1] != 0x5A) {
index++;
len--;

uint32_t processed_len = 0;
uint32_t current_read_pos = usart_dma_rx_read_pos;
const uint32_t buf_len = sizeof(dma_uart_rev_buf);

while (processed_len < available_len) {
uint32_t remaining = available_len - processed_len;

if (remaining < 2) {
break;
}

uint8_t b0 = dma_uart_rev_buf[current_read_pos % buf_len];
uint8_t b1 = dma_uart_rev_buf[(current_read_pos + 1) % buf_len];
if (b0 != 0xA5 || b1 != 0x5A) {
current_read_pos = (current_read_pos + 1) % buf_len;
processed_len += 1;
continue;
}
p_header = buf + index;
index += 2;
len -= 2;
if (len < 2) {
return;

if (remaining < 4) {
break;
}
// length include xor byte
uint16_t data_len = (buf[index] << 8) + buf[index + 1];
index += 2;
len -= 2;
if (len < data_len) {
return;

uint16_t data_len =
(dma_uart_rev_buf[(current_read_pos + 2) % buf_len] << 8) +
dma_uart_rev_buf[(current_read_pos + 3) % buf_len];

// Packet format: [0xA5][0x5A][LH][LL][payload...][XOR]
// data_len = len(payload) + len(XOR)
uint32_t packet_total_len = data_len + 4; // Including header
uint32_t packet_store_len = data_len + 3; // Excluding XOR byte

// Validate packet length
if (packet_total_len < 5 || packet_total_len > buf_len) {
current_read_pos = (current_read_pos + 1) % buf_len;
processed_len += 1;
continue;
}
index += data_len;
len -= data_len;

uint8_t xor = calXor(p_header, data_len + 3);
if (buf[index - 1] != xor) {
return;
if (remaining < packet_total_len) {
break;
}

uint8_t xor = 0;
uint32_t first_part_len = buf_len - current_read_pos;
if (first_part_len > packet_store_len) {
first_part_len = packet_store_len;
}
uint32_t second_part_len = packet_store_len - first_part_len;
for (uint32_t i = 0; i < first_part_len; i++) {
xor ^= dma_uart_rev_buf[current_read_pos + i];
}
for (uint32_t i = 0; i < second_part_len; i++) {
xor ^= dma_uart_rev_buf[i];
}
if (xor !=
dma_uart_rev_buf[(current_read_pos + packet_total_len - 1) % buf_len]) {
current_read_pos = (current_read_pos + 1) % buf_len;
processed_len += 1;
continue;
}
fifo_write_no_overflow(&uart_fifo_in, p_header, data_len + 3);

for (uint32_t i = 0; i < first_part_len; i++) {
fifo_put_no_overflow(&uart_fifo_in,
dma_uart_rev_buf[current_read_pos + i]);
}
for (uint32_t i = 0; i < second_part_len; i++) {
fifo_put_no_overflow(&uart_fifo_in, dma_uart_rev_buf[i]);
}

fifo_lockpos_set(&uart_fifo_in);

current_read_pos = (current_read_pos + packet_total_len) % buf_len;
processed_len += packet_total_len;
}
}

// void UART4_IRQHandler(void) {
// volatile uint8_t data = 0;
// (void)data;
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_WUF)) {
// __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_WUF);
// }
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != 0) {
// data = (uint8_t)(huart->Instance->RDR);
// __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF);
// }
// if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXFNE) != 0) {
// memset(dma_uart_rev_buf, 0x00, sizeof(dma_uart_rev_buf));
// usart_rev_package(dma_uart_rev_buf);
// }
// }
usart_dma_rx_read_pos = current_read_pos;
}

void UARTx_DMA_TX_IRQHandler(void) { HAL_DMA_IRQHandler(huart->hdmatx); }

void UARTx_DMA_RX_IRQHandler(void) { HAL_DMA_IRQHandler(huart->hdmarx); }

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
usart_rev_package_dma(dma_uart_rev_buf, sizeof(dma_uart_rev_buf));
HAL_UART_Receive_DMA(huart, dma_uart_rev_buf, sizeof(dma_uart_rev_buf));
usart_rx_dma_process();
}

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) {
usart_rx_dma_process();
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { uart_tx_done = true; }
Expand All @@ -284,16 +322,9 @@ void UART4_IRQHandler(void) {
}
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RTOF)) {
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_RTOF);
HAL_UART_Abort(huart);
usart_fifo_len =
sizeof(dma_uart_rev_buf) - __HAL_DMA_GET_COUNTER(huart->hdmarx);
if (usart_fifo_len > 0) {
usart_rev_package_dma(dma_uart_rev_buf, usart_fifo_len);
}
HAL_UART_Receive_DMA(huart, dma_uart_rev_buf, sizeof(dma_uart_rev_buf));
} else {
HAL_UART_IRQHandler(huart);
usart_rx_dma_process();
}
HAL_UART_IRQHandler(huart);
}

void usart_print(const char *text, int text_len) {
Expand Down
6 changes: 6 additions & 0 deletions core/src/trezor/uart.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,14 @@ async def _deal_button_press(value: bytes) -> None:
return
if res == _PRESS_SHORT:
if display.backlight():
utils.request_sleep_after_cancel()
if utils.is_wire_busy():
workflow.close_others()
return
display.backlight(0)
if storage_device.is_initialized():
if utils.is_initialization_processing():
utils.clear_sleep_after_cancel()
return
utils.AUTO_POWER_OFF = True
utils.RESTART_MAIN_LOOP = True
Expand All @@ -444,6 +449,7 @@ async def _deal_button_press(value: bytes) -> None:
workflow.spawn(utils.internal_reloop())
base.set_homescreen()
return
utils.clear_sleep_after_cancel()
else:
utils.turn_on_lcd_if_possible()

Expand Down
36 changes: 36 additions & 0 deletions core/src/trezor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ def board_version() -> str:
CHARGING = False
USB_STATE_CHANGED = False
RESTART_MAIN_LOOP = False
_WIRE_BUSY = False
_PENDING_SLEEP_AFTER_CANCEL = False

if __debug__:
MAX_FP_ATTEMPTS = 50
Expand Down Expand Up @@ -200,6 +202,7 @@ def lcd_resume(timeouts_ms: int | None = None) -> bool:
async def internal_reloop():
from trezor import loop

clear_sleep_after_cancel()
loop.clear()


Expand All @@ -219,6 +222,39 @@ async def turn_off_lcd():
loop.clear()


def set_wire_busy(is_busy: bool) -> None:
global _WIRE_BUSY
_WIRE_BUSY = is_busy


def is_wire_busy() -> bool:
return _WIRE_BUSY


def request_sleep_after_cancel() -> None:
global _PENDING_SLEEP_AFTER_CANCEL
_PENDING_SLEEP_AFTER_CANCEL = True


def clear_sleep_after_cancel() -> None:
global _PENDING_SLEEP_AFTER_CANCEL
_PENDING_SLEEP_AFTER_CANCEL = False


def has_pending_sleep_after_cancel() -> bool:
return _PENDING_SLEEP_AFTER_CANCEL


async def sleep_after_action_cancel() -> None:
from apps import base

if is_initialization_processing():
await turn_off_lcd()
return
base.lock_device()
await turn_off_lcd()


def play_dead():
from trezor import io, loop
import usb
Expand Down
27 changes: 27 additions & 0 deletions core/src/trezor/wire/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,11 @@ async def _handle_single_message(
)

res_msg: protobuf.MessageType | None = None
if use_workflow and utils.has_pending_sleep_after_cancel():
res_msg = failure(loop.TASK_CLOSED)
await ctx.write(res_msg)
await _handle_pending_sleep_after_cancel(res_msg)
return None

# We need to find a handler for this message type. Should not raise.
handler = find_handler(ctx.iface, msg.type) # pylint: disable=assignment-from-none
Expand Down Expand Up @@ -506,6 +511,8 @@ async def _handle_single_message(
# perform the write outside the big try-except block, so that usb write
# problem bubbles up
await ctx.write(res_msg)
if use_workflow:
await _handle_pending_sleep_after_cancel(res_msg)
return None


Expand Down Expand Up @@ -537,6 +544,7 @@ async def handle_session(
# wait for a new one coming from the wire.
try:
msg = await ctx.read_from_wire()
utils.set_wire_busy(True)
change_state(is_busy=True)
except codec_v1.CodecError as exc:
if __debug__:
Expand Down Expand Up @@ -567,6 +575,7 @@ async def handle_session(
utils.unimport_end(modules)

if next_msg is None and msg.type not in AVOID_RESTARTING_FOR:
utils.set_wire_busy(False)
# Shut down the loop if there is no next message waiting.
# Let the session be restarted from `main`.
change_state()
Expand All @@ -580,6 +589,24 @@ async def handle_session(
log.exception(__name__, exc)


async def _handle_pending_sleep_after_cancel(
res_msg: protobuf.MessageType | None,
) -> None:

if not utils.has_pending_sleep_after_cancel():
return

try:
if (
res_msg is not None
and Failure.is_type_of(res_msg)
and res_msg.code == FailureType.ActionCancelled
):
await utils.sleep_after_action_cancel()
finally:
utils.clear_sleep_after_cancel()


def _find_handler_placeholder(iface: WireInterface, msg_type: int) -> Handler | None:
"""Placeholder handler lookup before a proper one is registered."""
return None
Expand Down
Loading