qr: Show brightness controls when displaying animated qrcodes
What changed, and why it matters
This commit is a straightforward user-interface change for Blockstream Jade hardware wallets. It replaces a 'help' button with a 'brightness' button on QR code display screens and removes the now-unused help button code. There is no security-relevant change visible in the diff.
No security action required. Treat as normal UI/UX maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies the QR display UI to always show brightness controls when displaying animated QR codes. It removes the BTN_QR_DISPLAY_HELP event/button, drops the show_help_btn parameter from make_show_qr_activity(), and wires BTN_QR_BRIGHTNESS to gui_next_qrcode_color() in both single and animated QR display loops. The help_url parameter is no longer passed through create_display_bcur_qr_activity() or await_single_qr_activity(), but await_qr_help_activity() remains available and is still used from the QR options menu via handle_qr_options().
Changed components
main/qrmode.cmain/qrmode.hmain/ui/qrmode.cmain/button_events.hInspect captured patch +27 / −41
diff --git a/main/button_events.h b/main/button_events.h
index b1d09c1..fdce240 100644
--- a/main/button_events.h
+++ b/main/button_events.h
@@ -259,7 +259,6 @@ typedef enum {
BTN_QR_OPTIONS_FRAMERATE,
BTN_QR_OPTIONS_HELP,
BTN_QR_OPTIONS_EXIT,
- BTN_QR_DISPLAY_HELP,
BTN_QR_DISPLAY_EXIT,
// NOTE: Always leave these ones last as keyboard buttons use
diff --git a/main/qrmode.c b/main/qrmode.c
index 34c3b7f..10092fe 100644
--- a/main/qrmode.c
+++ b/main/qrmode.c
@@ -67,7 +67,7 @@ gui_activity_t* make_search_address_options_activity(
bool show_account, gui_view_node_t** account_textbox, gui_view_node_t** change_textbox);
gui_activity_t* make_show_qr_activity(const char* message[], size_t message_size, Icon* icons, size_t num_icons,
- size_t frames_per_qr_icon, bool show_options_button, bool show_help_btn);
+ size_t frames_per_qr_icon, bool show_options_button);
gui_activity_t* make_qr_options_activity(gui_view_node_t** density_textbox, gui_view_node_t** framerate_textbox);
bool import_mnemonic(const uint8_t* bytes, size_t bytes_len, char* buf, size_t buf_len, size_t* written);
@@ -905,14 +905,13 @@ static bool handle_qr_options(uint32_t* qr_flags, const char* help_url)
// Create activity to display (potentially multi-frame/animated) qr
static gui_activity_t* create_display_bcur_qr_activity(const char* message[], const size_t message_size,
- const char* bcur_type, const uint8_t* cbor, const size_t cbor_len, const uint32_t qr_flags, const char* help_url)
+ const char* bcur_type, const uint8_t* cbor, const size_t cbor_len, const uint32_t qr_flags)
{
JADE_ASSERT(message);
JADE_ASSERT(message_size);
JADE_ASSERT(bcur_type);
JADE_ASSERT(cbor);
JADE_ASSERT(cbor_len);
- // help_url is optional
// Map BCUR cbor into a series of QR-code icons
Icon* icons = NULL;
@@ -923,10 +922,10 @@ static gui_activity_t* create_display_bcur_qr_activity(const char* message[], co
// Create qr activity for those icons
const bool show_options_button = true;
const uint8_t frames_per_qr = qr_framerate_from_flags(qr_flags);
- return make_show_qr_activity(message, message_size, icons, num_icons, frames_per_qr, show_options_button, help_url);
+ return make_show_qr_activity(message, message_size, icons, num_icons, frames_per_qr, show_options_button);
}
-// Display a QR code, with access to size_speed options
+// Display a QR code, with access to size/speed options
static void display_bcur_qr(const char* message[], const size_t message_size, const char* bcur_type,
const uint8_t* cbor, const size_t cbor_len, const char* help_url)
{
@@ -944,8 +943,7 @@ static void display_bcur_qr(const char* message[], const size_t message_size, co
idletimer_set_min_timeout_secs(BCUR_QR_DISPLAY_MIN_TIMEOUT_SECS);
// Create show psbt activity for those icons
- gui_activity_t* act
- = create_display_bcur_qr_activity(message, message_size, bcur_type, cbor, cbor_len, qr_flags, help_url);
+ gui_activity_t* act = create_display_bcur_qr_activity(message, message_size, bcur_type, cbor, cbor_len, qr_flags);
while (true) {
// Show, and await button click
@@ -954,13 +952,13 @@ static void display_bcur_qr(const char* message[], const size_t message_size, co
const int32_t ev_id = gui_activity_wait_button(act, BTN_QR_DISPLAY_EXIT);
if (ev_id == BTN_QR_OPTIONS) {
if (handle_qr_options(&qr_flags, help_url)) {
- // Options were updated - re-create psbt qr screen
+ // Options were updated - re-create bcur qr screen
display_processing_message_activity();
- act = create_display_bcur_qr_activity(
- message, message_size, bcur_type, cbor, cbor_len, qr_flags, help_url);
+ act = create_display_bcur_qr_activity(message, message_size, bcur_type, cbor, cbor_len, qr_flags);
}
- } else if (ev_id == BTN_QR_DISPLAY_HELP) {
- await_qr_help_activity(help_url);
+ } else if (ev_id == BTN_QR_BRIGHTNESS) {
+ gui_next_qrcode_color();
+ gui_repaint(act->root_node);
} else if (ev_id == BTN_QR_DISPLAY_EXIT) {
// Done
break;
@@ -1001,7 +999,7 @@ static bool handle_qr_bytes(const uint8_t* bytes, const size_t bytes_len)
JADE_ASSERT(sig[written - 1] == '\0');
const char* message[] = { "Scan QR", "signature" };
- await_single_qr_activity(message, 2, sig, written - 1, NULL);
+ await_single_qr_activity(message, 2, sig, written - 1);
return true;
}
@@ -1380,23 +1378,20 @@ bool display_bcur_bytes_qr(
return true;
}
-// Display screen with help url and qr code
-// Handles up to v6. codes - ie text up to 134 bytes
-// help_url is optional
void await_single_qr_activity(
- const char* message[], const size_t message_size, const uint8_t* data, const size_t data_len, const char* help_url)
+ const char* message[], const size_t message_size, const uint8_t* data, const size_t data_len)
{
JADE_ASSERT(message);
JADE_ASSERT(message_size);
JADE_ASSERT(data);
JADE_ASSERT(data_len);
- // help_url is optional
Icon* const qr_icon = JADE_MALLOC(sizeof(Icon));
bytes_to_qr_icon(data, data_len, qr_icon);
// Show, and await button click - note gui takes ownership of icon
- gui_activity_t* const act = make_show_qr_activity(message, message_size, qr_icon, 1, 0, false, help_url);
+ const bool show_options_button = false;
+ gui_activity_t* const act = make_show_qr_activity(message, message_size, qr_icon, 1, 0, show_options_button);
while (true) {
gui_set_current_activity(act);
@@ -1405,8 +1400,9 @@ void await_single_qr_activity(
if (ev_id == BTN_QR_DISPLAY_EXIT) {
// Done
break;
- } else if (ev_id == BTN_QR_DISPLAY_HELP) {
- await_qr_help_activity(help_url);
+ } else if (ev_id == BTN_QR_BRIGHTNESS) {
+ gui_next_qrcode_color();
+ gui_repaint(act->root_node);
}
}
}
diff --git a/main/qrmode.h b/main/qrmode.h
index 936993b..96172d0 100644
--- a/main/qrmode.h
+++ b/main/qrmode.h
@@ -15,11 +15,9 @@ void handle_scan_qr(void);
bool display_bcur_bytes_qr(
const char* message[], size_t message_size, const uint8_t* data, size_t data_len, const char* help_url);
-// Display screen with single arbitrary qr code
-// Handles up to v6 codes - ie. text up to 134 bytes
-// help_url is optional
-void await_single_qr_activity(
- const char* message[], size_t message_size, const uint8_t* data, size_t data_len, const char* help_url);
+// Display screen with qr code
+// Handles up to v6. codes - ie text up to 134 bytes
+void await_single_qr_activity(const char* message[], size_t message_size, const uint8_t* data, size_t data_len);
// Display screen with help url and qr code
void await_qr_help_activity(const char* url);
diff --git a/main/ui/qrmode.c b/main/ui/qrmode.c
index 541f446..db0fb37 100644
--- a/main/ui/qrmode.c
+++ b/main/ui/qrmode.c
@@ -228,7 +228,7 @@ gui_activity_t* make_qr_options_activity(gui_view_node_t** density_textbox, gui_
// NOTE: 'icons' passed in here must be heap-allocated as the gui element takes ownership
gui_activity_t* make_show_qr_activity(const char* message[], const size_t message_size, Icon* icons,
- const size_t num_icons, const size_t frames_per_qr_icon, const bool show_options_button, const bool show_help_btn)
+ const size_t num_icons, const size_t frames_per_qr_icon, const bool show_options_button)
{
JADE_ASSERT(message);
JADE_ASSERT(message_size < 4);
@@ -249,19 +249,12 @@ gui_activity_t* make_show_qr_activity(const char* message[], const size_t messag
gui_make_vsplit(&vsplit, GUI_SPLIT_RELATIVE, 3, 20, 56, 24);
gui_set_parent(vsplit, hsplit);
- // tick button
- btn_data_t hdrbtns[]
- = { { .txt = "S", .font = VARIOUS_SYMBOLS_FONT, .ev_id = BTN_QR_DISPLAY_EXIT, .borders = GUI_BORDER_ALL },
- { .txt = NULL, .font = GUI_DEFAULT_FONT, .ev_id = GUI_BUTTON_EVENT_NONE },
- { .txt = "?", .font = GUI_TITLE_FONT, .ev_id = BTN_QR_DISPLAY_HELP, .borders = GUI_BORDER_ALL } };
-
- if (!show_help_btn) {
- // Remove help button if not needed
- hdrbtns[2].txt = NULL;
- hdrbtns[2].font = GUI_DEFAULT_FONT;
- hdrbtns[2].ev_id = GUI_BUTTON_EVENT_NONE;
- hdrbtns[2].borders = 0; // None
- }
+ // back button, space, brightness button
+ btn_data_t hdrbtns[] = {
+ { .txt = "S", .font = VARIOUS_SYMBOLS_FONT, .ev_id = BTN_QR_DISPLAY_EXIT, .borders = GUI_BORDER_ALL },
+ { .txt = NULL, .font = GUI_DEFAULT_FONT, .ev_id = GUI_BUTTON_EVENT_NONE },
+ { .txt = "P", .font = JADE_SYMBOLS_16x16_FONT, .ev_id = BTN_QR_BRIGHTNESS, .borders = GUI_BORDER_ALL }
+ };
add_buttons(vsplit, UI_ROW, hdrbtns, 3); // 44 (hsplit) / 3 == 14 - almost 15 so ok
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.