diff --git a/Cargo.lock b/Cargo.lock index 215fc277..bac23207 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -474,7 +474,7 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "ledger_device_sdk" -version = "1.15.6" +version = "1.16.0" dependencies = [ "const-zero", "include_gif", diff --git a/ledger_device_sdk/Cargo.toml b/ledger_device_sdk/Cargo.toml index e07e3874..f990e839 100644 --- a/ledger_device_sdk/Cargo.toml +++ b/ledger_device_sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ledger_device_sdk" -version = "1.15.6" +version = "1.16.0" authors = ["yhql", "yogh333", "agrojean-ledger", "kingofpayne"] edition = "2021" license.workspace = true diff --git a/ledger_device_sdk/src/nbgl.rs b/ledger_device_sdk/src/nbgl.rs index 5108d4d9..6200e981 100644 --- a/ledger_device_sdk/src/nbgl.rs +++ b/ledger_device_sdk/src/nbgl.rs @@ -3,7 +3,7 @@ use crate::nvm::*; use const_zero::const_zero; extern crate alloc; use alloc::ffi::CString; -use alloc::vec::Vec; +use alloc::{vec, vec::Vec}; use core::ffi::{c_char, c_int}; use core::mem::transmute; use ledger_secure_sdk_sys::*; @@ -32,10 +32,6 @@ pub use nbgl_status::*; pub use nbgl_streaming_review::*; static mut COMM_REF: Option<&mut Comm> = None; -pub const SETTINGS_SIZE: usize = 10; -static mut NVM_REF: Option<&mut AtomicStorage<[u8; SETTINGS_SIZE]>> = None; -static mut SWITCH_ARRAY: [nbgl_contentSwitch_t; SETTINGS_SIZE] = - [unsafe { const_zero!(nbgl_contentSwitch_t) }; SETTINGS_SIZE]; #[derive(Copy, Clone)] enum SyncNbgl { diff --git a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs index 126eabba..c6460f28 100644 --- a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs +++ b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs @@ -1,5 +1,10 @@ use super::*; +pub const SETTINGS_SIZE: usize = 10; +static mut NVM_REF: Option<&mut AtomicStorage<[u8; SETTINGS_SIZE]>> = None; +static mut SWITCH_ARRAY: [nbgl_contentSwitch_t; SETTINGS_SIZE] = + [unsafe { const_zero!(nbgl_contentSwitch_t) }; SETTINGS_SIZE]; + /// Callback triggered by the NBGL API when a setting switch is toggled. unsafe extern "C" fn settings_callback(token: c_int, _index: u8, _page: c_int) { let idx = token - FIRST_USER_TOKEN as i32; @@ -16,7 +21,7 @@ unsafe extern "C" fn settings_callback(token: c_int, _index: u8, _page: c_int) { } if let Some(data) = NVM_REF.as_mut() { - let mut switch_values: [u8; SETTINGS_SIZE] = data.get_ref().clone(); + let mut switch_values: [u8; SETTINGS_SIZE] = *data.get_ref(); if switch_values[setting_idx] == OFF_STATE { switch_values[setting_idx] = ON_STATE; } else { @@ -49,6 +54,16 @@ pub struct NbglHomeAndSettings { impl SyncNBGL for NbglHomeAndSettings {} +unsafe extern "C" fn quit_cb() { + exit_app(0); +} + +impl<'a> Default for NbglHomeAndSettings { + fn default() -> Self { + Self::new() + } +} + impl<'a> NbglHomeAndSettings { pub fn new() -> NbglHomeAndSettings { NbglHomeAndSettings { @@ -66,7 +81,7 @@ impl<'a> NbglHomeAndSettings { pub fn glyph(self, glyph: &'a NbglGlyph) -> NbglHomeAndSettings { let icon = glyph.into(); - NbglHomeAndSettings { icon: icon, ..self } + NbglHomeAndSettings { icon, ..self } } pub fn infos( @@ -75,9 +90,10 @@ impl<'a> NbglHomeAndSettings { version: &'a str, author: &'a str, ) -> NbglHomeAndSettings { - let mut v: Vec = Vec::new(); - v.push(CString::new(version).unwrap()); - v.push(CString::new(author).unwrap()); + let v: Vec = vec![ + CString::new(version).unwrap(), + CString::new(author).unwrap(), + ]; NbglHomeAndSettings { app_name: CString::new(app_name).unwrap(), @@ -111,6 +127,10 @@ impl<'a> NbglHomeAndSettings { } } + /// Show the home screen and settings page. + /// This function will block until an APDU is received or the user quits the app. + /// DEPRECATED as it constraints to refresh screen for every received APDU. + /// Use `show_and_return` instead. pub fn show>(&mut self) -> Event where Reply: From<>::Error>, @@ -124,8 +144,8 @@ impl<'a> NbglHomeAndSettings { .collect::>(); self.info_list = nbgl_contentInfoList_t { - infoTypes: INFO_FIELDS.as_ptr() as *const *const c_char, - infoContents: self.info_contents_ptr[..].as_ptr() as *const *const c_char, + infoTypes: INFO_FIELDS.as_ptr(), + infoContents: self.info_contents_ptr[..].as_ptr(), nbInfos: INFO_FIELDS.len() as u8, }; @@ -190,4 +210,65 @@ impl<'a> NbglHomeAndSettings { } } } + + /// Show the home screen and settings page. + /// This function returns immediately after the screen is displayed. + pub fn show_and_return(&mut self) { + unsafe { + self.info_contents_ptr = self + .info_contents + .iter() + .map(|s| s.as_ptr()) + .collect::>(); + + self.info_list = nbgl_contentInfoList_t { + infoTypes: INFO_FIELDS.as_ptr(), + infoContents: self.info_contents_ptr[..].as_ptr(), + nbInfos: INFO_FIELDS.len() as u8, + }; + + for (i, setting) in self.setting_contents.iter().enumerate() { + SWITCH_ARRAY[i].text = setting[0].as_ptr(); + SWITCH_ARRAY[i].subText = setting[1].as_ptr(); + let state = if let Some(data) = NVM_REF.as_mut() { + data.get_ref()[i] + } else { + OFF_STATE + }; + SWITCH_ARRAY[i].initState = state; + SWITCH_ARRAY[i].token = (FIRST_USER_TOKEN + i as u32) as u8; + SWITCH_ARRAY[i].tuneId = TuneIndex::TapCasual as u8; + } + + self.content = nbgl_content_t { + content: nbgl_content_u { + switchesList: nbgl_pageSwitchesList_s { + switches: &SWITCH_ARRAY as *const nbgl_contentSwitch_t, + nbSwitches: self.nb_settings, + }, + }, + contentActionCallback: Some(settings_callback), + type_: SWITCHES_LIST, + }; + + self.generic_contents = nbgl_genericContents_t { + callbackCallNeeded: false, + __bindgen_anon_1: nbgl_genericContents_t__bindgen_ty_1 { + contentsList: &self.content as *const nbgl_content_t, + }, + nbContents: if self.nb_settings > 0 { 1 } else { 0 }, + }; + + nbgl_useCaseHomeAndSettings( + self.app_name.as_ptr() as *const c_char, + &self.icon as *const nbgl_icon_details_t, + core::ptr::null(), + INIT_HOME_PAGE as u8, + &self.generic_contents as *const nbgl_genericContents_t, + &self.info_list as *const nbgl_contentInfoList_t, + core::ptr::null(), + Some(quit_cb), + ); + } + } }