Skip to content

Commit 752dfdc

Browse files
committed
orientation-screen: Migrate to rust
create an async friendly hardware supported delayin C and wrap it in rust using Future.
1 parent 5bfe9be commit 752dfdc

File tree

26 files changed

+488
-159
lines changed

26 files changed

+488
-159
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
set(DBB-FIRMWARE-SOURCES
1818
${CMAKE_SOURCE_DIR}/src/firmware_main_loop.c
19+
${CMAKE_SOURCE_DIR}/src/delay.c
1920
${CMAKE_SOURCE_DIR}/src/keystore.c
2021
${CMAKE_SOURCE_DIR}/src/random.c
2122
${CMAKE_SOURCE_DIR}/src/hardfault.c
@@ -36,7 +37,6 @@ set(DBB-FIRMWARE-SOURCES
3637
${CMAKE_SOURCE_DIR}/src/touch/gestures.c
3738
${CMAKE_SOURCE_DIR}/src/reset.c
3839
${CMAKE_SOURCE_DIR}/src/cipher/cipher.c
39-
${CMAKE_SOURCE_DIR}/src/workflow/orientation_screen.c
4040
${CMAKE_SOURCE_DIR}/src/queue.c
4141
${CMAKE_SOURCE_DIR}/src/usb/usb_processing.c
4242
)

src/bootloader/startup.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ int main(void)
104104

105105
// Set product to bootloader string, this is necessary if we have rebooted from firmware. Must
106106
// be done after usb_processing is initalized to avoid getting request from the app to early.
107-
da14531_handler_current_product = (const uint8_t*)DEVICE_MODE;
108-
da14531_handler_current_product_len = sizeof(DEVICE_MODE) - 1;
107+
size_t product_len;
108+
da14531_handler_current_product = (const uint8_t*)platform_product(&product_len);
109+
da14531_handler_current_product_len = product_len;
109110
da14531_set_product(
110111
da14531_handler_current_product, da14531_handler_current_product_len, &uart_write_queue);
111112

src/da14531/da14531_handler.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@
2525
#include <ui/components/ui_images.h>
2626
#include <ui/fonts/monogram_5X9.h>
2727

28-
// These are set from interrupt context in the orientation workflow :/ therefore they need to be
29-
// volatile
30-
volatile const uint8_t* da14531_handler_current_product = NULL;
31-
volatile uint16_t da14531_handler_current_product_len = 0;
28+
const uint8_t* da14531_handler_current_product = NULL;
29+
uint16_t da14531_handler_current_product_len = 0;
3230

3331
struct da14531_ctrl_frame {
3432
enum da14531_protocol_packet_type type;

src/da14531/da14531_handler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include <platform/platform_config.h>
2020
#include <utils_ringbuffer.h>
2121

22-
extern volatile const uint8_t* da14531_handler_current_product;
23-
extern volatile uint16_t da14531_handler_current_product_len;
22+
extern const uint8_t* da14531_handler_current_product;
23+
extern uint16_t da14531_handler_current_product_len;
2424

2525
#if FACTORYSETUP == 1
2626
bool da14531_handler_bond_db_set(void);

src/delay.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2025 Shift Crypto AG
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <delay.h>
16+
#include <hal_timer.h>
17+
#include <platform/driver_init.h>
18+
#include <stdbool.h>
19+
#include <stdint.h>
20+
#include <string.h>
21+
#include <util.h>
22+
#include <utils_assert.h>
23+
24+
struct task {
25+
struct timer_task timer;
26+
volatile bool done;
27+
};
28+
29+
static struct task _tasks[10] = {0};
30+
31+
static void _hal_timer_cb(const struct timer_task* const timer)
32+
{
33+
for (size_t i = 0; i < COUNT_OF(_tasks); i++) {
34+
if (&_tasks[i].timer == timer) {
35+
_tasks[i].done = true;
36+
}
37+
}
38+
}
39+
40+
bool delay_init_ms(delay_t* self, uint32_t ms)
41+
{
42+
// find an unused slot in tasks
43+
size_t i;
44+
CRITICAL_SECTION_ENTER();
45+
for (i = 0; i < COUNT_OF(_tasks); i++) {
46+
if (_tasks[i].timer.cb == NULL) {
47+
break;
48+
}
49+
}
50+
CRITICAL_SECTION_LEAVE();
51+
if (i == COUNT_OF(_tasks)) {
52+
return false;
53+
}
54+
_tasks[i].done = false;
55+
memset(&_tasks[i], 0, sizeof(struct task));
56+
_tasks[i].timer.interval = ms;
57+
_tasks[i].timer.cb = _hal_timer_cb;
58+
_tasks[i].timer.mode = TIMER_TASK_ONE_SHOT;
59+
self->id = i;
60+
return true;
61+
}
62+
63+
void delay_start(const delay_t* self)
64+
{
65+
ASSERT(self->id < COUNT_OF(_tasks));
66+
ASSERT(!_tasks[self->id].done);
67+
timer_add_task(&TIMER_0, &_tasks[self->id].timer);
68+
}
69+
70+
bool delay_poll(const delay_t* self)
71+
{
72+
ASSERT(self->id < COUNT_OF(_tasks));
73+
if (_tasks[self->id].done) {
74+
memset(&_tasks[self->id], 0, sizeof(struct task));
75+
return true;
76+
}
77+
return false;
78+
}
Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2019 Shift Cryptosecurity AG
1+
// Copyright 2025 Shift Crypto AG
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -12,15 +12,23 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
#ifndef DELAY_H
16+
#define DELAY_H
17+
#include <stdbool.h>
18+
#include <stddef.h>
1519
#include <stdint.h>
16-
#include <unistd.h>
1720

18-
void delay_ms(const uint16_t ms)
19-
{
20-
usleep(1000 * ms);
21-
}
21+
typedef struct {
22+
size_t id;
23+
} delay_t;
2224

23-
void delay_us(const uint16_t us)
24-
{
25-
usleep(us);
26-
}
25+
// Create a non-blocking delay instance. Poll with delay_poll to completion
26+
// Limited to 10 concurrent delays, will return false if it fails to allocate one
27+
bool delay_init_ms(delay_t* self, uint32_t ms);
28+
29+
// Start the delay
30+
void delay_start(const delay_t* self);
31+
32+
// returns true if time has passed. After it has returned true once it must not be called again
33+
bool delay_poll(const delay_t* self);
34+
#endif

src/firmware_main_loop.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "usb/usb.h"
3333
#include "usb/usb_frame.h"
3434
#include "usb/usb_processing.h"
35-
#include "workflow/orientation_screen.h"
35+
#include <platform/platform_init.h>
3636
#include <rust/rust.h>
3737
#include <ui/fonts/monogram_5X9.h>
3838
#include <utils_ringbuffer.h>
@@ -45,6 +45,27 @@
4545
// Must be power of 2
4646
#define UART_OUT_BUF_LEN 2048
4747

48+
static void _orientation_screen_poll(struct ringbuffer* uart_write_queue)
49+
{
50+
static bool orientation_set = false;
51+
bool _orientation;
52+
if (!orientation_set && rust_workflow_orientation_screen_poll(&_orientation)) {
53+
orientation_set = true;
54+
// hww handler in usb_process must be setup before we can allow ble connections
55+
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
56+
size_t len;
57+
da14531_handler_current_product = (const uint8_t*)platform_product(&len);
58+
da14531_handler_current_product_len = len;
59+
util_log("%s %d", da14531_handler_current_product, da14531_handler_current_product_len);
60+
da14531_set_product(
61+
da14531_handler_current_product,
62+
da14531_handler_current_product_len,
63+
uart_write_queue);
64+
}
65+
usb_start();
66+
}
67+
}
68+
4869
void firmware_main_loop(void)
4970
{
5071
// Set the size of uart_read_buf to the size of the ringbuffer in the UART driver so we can read
@@ -63,7 +84,7 @@ void firmware_main_loop(void)
6384
da14531_set_name(buf, strlen(buf), &uart_write_queue);
6485

6586
// This starts the async orientation screen workflow, which is processed by the loop below.
66-
orientation_screen(&uart_write_queue);
87+
rust_workflow_spawn_orientation_screen();
6788

6889
const uint8_t* hww_data = NULL;
6990
uint8_t hww_frame[USB_REPORT_SIZE] = {0};
@@ -178,5 +199,7 @@ void firmware_main_loop(void)
178199

179200
rust_workflow_spin();
180201
rust_async_usb_spin();
202+
203+
_orientation_screen_poll(&uart_write_queue);
181204
}
182205
}

src/platform/platform_init.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@
1717
#include "memory/spi_mem.h"
1818
#include <driver_init.h>
1919
#include <ui/oled/oled.h>
20-
#if !defined(BOOTLOADER)
20+
#if defined(BOOTLOADER)
21+
#include <bootloader_version.h>
22+
#else
2123
#include "sd_mmc/sd_mmc_start.h"
2224
#endif
2325
#include "util.h"
26+
#include <platform/platform_config.h>
27+
#include <version.h>
2428

2529
#if !(defined(BOOTLOADER) && PLATFORM_BITBOX02 == 1)
2630
#include "uart.h"
@@ -50,3 +54,38 @@ void platform_init(void)
5054
spi_mem_protected_area_lock();
5155
}
5256
}
57+
58+
#if !(defined(BOOTLOADER) && PLATFORM_BITBOX02PLUS == 0)
59+
#if defined(BOOTLOADER)
60+
#if PRODUCT_BITBOX_PLUS_MULTI == 1
61+
#define DEVICE_MODE "{\"p\":\"bb02p-bl-multi\",\"v\":\"" BOOTLOADER_VERSION "\"}"
62+
#elif PRODUCT_BITBOX_PLUS_BTCONLY == 1
63+
#define DEVICE_MODE "{\"p\":\"bb02p-bl-btconly\",\"v\":\"" BOOTLOADER_VERSION "\"}"
64+
#else
65+
#error "unknown product"
66+
#endif
67+
#else
68+
// Currently we have one firmware for both BB02 and BB02_PLUS, and only the
69+
// PRODUCT_BITBOX_MULTI/BTCONLY definitions apply. The PRODUCT_BITBOX_PLUS_MULTI/BTCONLY
70+
// defs currently only apply in the bootloader, which we don't need here.
71+
#if PRODUCT_BITBOX_MULTI == 1
72+
#define PRODUCT_STRING_SUFFIX "multi"
73+
#elif PRODUCT_BITBOX_BTCONLY == 1
74+
#define PRODUCT_STRING_SUFFIX "btconly"
75+
#elif PRODUCT_BITBOX02_FACTORYSETUP == 1
76+
// Dummy, not actually needed, but this file is currently needlessly compiled for
77+
// factorysetup.
78+
#define PRODUCT_STRING_SUFFIX "factory"
79+
#else
80+
#error "unknown edition"
81+
#endif
82+
#define DEVICE_MODE \
83+
"{\"p\":\"bb02p-" PRODUCT_STRING_SUFFIX "\",\"v\":\"" DIGITAL_BITBOX_VERSION "\"}"
84+
#endif
85+
86+
const char* platform_product(size_t* len)
87+
{
88+
*len = sizeof(DEVICE_MODE) - 1;
89+
return DEVICE_MODE;
90+
}
91+
#endif

src/platform/platform_init.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,12 @@
1414

1515
#ifndef _PLATFORM_INIT_H_
1616
#define _PLATFORM_INIT_H_
17+
#include <platform/platform_config.h>
18+
#include <stddef.h>
1719
void platform_init(void);
20+
21+
#if !(defined(BOOTLOADER) && PLATFORM_BITBOX02PLUS == 0)
22+
// Returns a json string representing the firmware type and version
23+
const char* platform_product(size_t* len);
24+
#endif
1825
#endif

src/rust/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)