Skip to content

Commit 3b9dfa7

Browse files
committed
avoid flicker when changing from lockscreen to waiting screen
The BitBox shows the lockscreen ("See the BitBoxApp") first, and when the noise connection is initiazed, switches to the BitBox logo, which stays there as the waiting/default screen until reconnected. The noise connection is initiated by the host after unlock finishes, so in between, "See the BitBoxApP" flashes for a split second. This commit solves this by 1) not pushing the lockscreen as an extra component to be popped, but folding it into the top/default component 2) updating that screen when the app initiates the connection if the device is not initialized 3) if initialized, updating the screen on OP_UNLOCK (see comment in code) This prevents flashing/flickering if the device is initialized. There is still a small flicker when the device is uninitialized, as the screen is updated before the pairing confirmation appears. This was the case before this commit too.
1 parent 29e55e3 commit 3b9dfa7

File tree

9 files changed

+71
-18
lines changed

9 files changed

+71
-18
lines changed

src/rust/bitbox02-rust/src/hww.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ fn api_attestation(usb_in: &[u8]) -> Vec<u8> {
110110
}
111111

112112
async fn _process_packet(hal: &mut impl crate::hal::Hal, usb_in: Vec<u8>) -> Vec<u8> {
113+
// Update the waiting screen from "See the BitBoxApp" to the logo, now that the host is
114+
// connected. When the device is initialized, we delay this until the unlock call, otherwise
115+
// there would be a flicker where the logo would be shown before the host invokes unlock.
116+
if !bitbox02::memory::is_initialized() || usb_in.as_slice() == &[OP_UNLOCK] {
117+
bitbox02::ui::screen_process_host_connected();
118+
}
119+
113120
match usb_in.split_first() {
114121
Some((&OP_UNLOCK, b"")) => return api_unlock(hal).await,
115122
Some((&OP_ATTESTATION, rest)) => return api_attestation(rest),

src/rust/bitbox02-rust/src/hww/noise.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ pub(crate) async fn process(
8282
) -> Result<(), Error> {
8383
match usb_in.split_first() {
8484
Some((&OP_I_CAN_HAS_HANDSHAEK, b"")) => {
85-
// The previous screen was "See the BitBoxApp".
86-
// Since a handshake was requested, a client was connected, so we pop that screen.
8785
// Pairing is the start of a session, so we clean the screen stack in case
8886
// we started a new session in the middle of something.
8987
bitbox02::ui::screen_stack_pop_all();

src/rust/bitbox02-sys/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ const ALLOWLIST_FNS: &[&str] = &[
129129
"reset_ble",
130130
"screen_print_debug",
131131
"screen_process",
132+
"screen_process_host_connected",
132133
"screen_saver_disable",
133134
"screen_saver_enable",
134135
"sd_card_inserted",

src/rust/bitbox02/src/ui.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ mod types;
2525
mod ui;
2626

2727
pub use ui::*;
28+
29+
pub fn screen_process_host_connected() {
30+
unsafe { bitbox02_sys::screen_process_host_connected() }
31+
}

src/ui/components/waiting.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include "waiting.h"
16+
#include "lockscreen.h"
1617

1718
#include "image.h"
1819
#include "ui_images.h"
@@ -21,13 +22,12 @@
2122
#include <screen.h>
2223
#include <ui/ui_util.h>
2324

25+
#include <stdbool.h>
2426
#include <string.h>
2527

26-
static void _render(component_t* component)
27-
{
28-
// TODO - add an interesting animation?
29-
ui_util_component_render_subcomponents(component);
30-
}
28+
typedef struct {
29+
bool host_connected;
30+
} data_t;
3131

3232
/********************************** Component Functions **********************************/
3333

@@ -36,7 +36,7 @@ static void _render(component_t* component)
3636
*/
3737
static component_functions_t _component_functions = {
3838
.cleanup = ui_util_component_cleanup,
39-
.render = _render,
39+
.render = ui_util_component_render_subcomponents,
4040
.on_event = ui_util_on_event_noop,
4141
};
4242

@@ -47,6 +47,12 @@ static component_functions_t _component_functions = {
4747
*/
4848
component_t* waiting_create(void)
4949
{
50+
data_t* data = malloc(sizeof(data_t));
51+
if (!data) {
52+
Abort("Error: malloc waiting data");
53+
}
54+
memset(data, 0, sizeof(data_t));
55+
5056
component_t* waiting = malloc(sizeof(component_t));
5157
if (!waiting) {
5258
Abort("Error: malloc waiting");
@@ -57,14 +63,36 @@ component_t* waiting_create(void)
5763
waiting->dimension.height = SCREEN_HEIGHT;
5864
waiting->position.top = 0;
5965
waiting->position.left = 0;
66+
waiting->data = data;
67+
68+
ui_util_add_sub_component(waiting, lockscreen_create());
69+
70+
return waiting;
71+
}
72+
73+
void waiting_host_connected(component_t* component)
74+
{
75+
data_t* data = (data_t*)component->data;
76+
if (data->host_connected) {
77+
return;
78+
}
79+
data->host_connected = true;
80+
81+
if (component->sub_components.amount != 1) {
82+
// Sanity check to avoid memory bugs, should never happen.
83+
return;
84+
}
85+
86+
ui_util_component_cleanup(component->sub_components.sub_components[0]);
87+
6088
image_logo_data_t logo = image_logo_data();
6189
component_t* bb2_logo = image_create(
6290
logo.buffer.data,
6391
logo.buffer.len,
6492
logo.dimensions.width,
6593
logo.dimensions.height,
6694
CENTER,
67-
waiting);
68-
ui_util_add_sub_component(waiting, bb2_logo);
69-
return waiting;
95+
component);
96+
97+
component->sub_components.sub_components[0] = bb2_logo;
7098
}

src/ui/components/waiting.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818
#include <ui/component.h>
1919

2020
/**
21-
* Creates a waiting screen.
21+
* Creates a waiting screen. It starts out with a lockscreen (see lockscreen.c). Once
22+
* `waiting_host_connected()` is called, the waiting screen will switch to showing the logo image.
2223
*/
2324
component_t* waiting_create(void);
2425

26+
/**
27+
* Switch the waiting screen to show the BitBox logo instead.
28+
*/
29+
void waiting_host_connected(component_t* component);
30+
2531
#endif

src/ui/screen_process.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,21 @@ void ui_screen_render_component(component_t* component)
3232
UG_SendBuffer();
3333
}
3434

35+
static component_t* _waiting_screen = NULL;
3536
static component_t* _get_waiting_screen(void)
3637
{
37-
static component_t* waiting_screen = NULL;
38-
if (waiting_screen == NULL) {
39-
waiting_screen = waiting_create();
40-
if (waiting_screen == NULL) {
38+
if (_waiting_screen == NULL) {
39+
_waiting_screen = waiting_create();
40+
if (_waiting_screen == NULL) {
4141
Abort("Could not create\nwaiting screen");
4242
}
4343
}
44-
return waiting_screen;
44+
return _waiting_screen;
45+
}
46+
47+
void screen_process_host_connected(void)
48+
{
49+
waiting_host_connected(_get_waiting_screen());
4550
}
4651

4752
component_t* screen_process_get_top_component(void)

src/ui/screen_process.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ void ui_screen_render_component(component_t* component);
2727
*/
2828
component_t* screen_process_get_top_component(void);
2929

30+
/**
31+
* Wraps `waiting_host_connected()` for the waiting screen.
32+
*/
33+
void screen_process_host_connected(void);
34+
3035
/**
3136
* Runs the UI once.
3237
*

src/workflow/orientation_screen.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ static void _idle_timer_cb(const struct timer_task* const timer_task)
7373
}
7474

7575
usb_start();
76-
ui_screen_stack_push(lockscreen_create());
7776
}
7877
#endif
7978

0 commit comments

Comments
 (0)