From a99024c7377d8cbda846a52b7bbb11bbb9238829 Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Sep 2024 10:08:21 +0200 Subject: [PATCH 1/8] HomeAndSettings: stop filtering ADPU --- ledger_device_sdk/src/lib.rs | 2 + ledger_device_sdk/src/nbgl2.rs | 12 ++ .../src/nbgl2/nbgl2_home_and_settings.rs | 180 ++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 ledger_device_sdk/src/nbgl2.rs create mode 100644 ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs diff --git a/ledger_device_sdk/src/lib.rs b/ledger_device_sdk/src/lib.rs index 7d76c310..2af61dcd 100644 --- a/ledger_device_sdk/src/lib.rs +++ b/ledger_device_sdk/src/lib.rs @@ -25,6 +25,8 @@ pub mod testing; #[cfg(any(target_os = "stax", target_os = "flex"))] pub mod nbgl; +#[cfg(any(target_os = "stax", target_os = "flex"))] +pub mod nbgl2; #[cfg(not(any(target_os = "stax", target_os = "flex")))] pub mod ui; diff --git a/ledger_device_sdk/src/nbgl2.rs b/ledger_device_sdk/src/nbgl2.rs new file mode 100644 index 00000000..ac0fb228 --- /dev/null +++ b/ledger_device_sdk/src/nbgl2.rs @@ -0,0 +1,12 @@ +use crate::io::{ApduHeader, Comm, Event, Reply}; +use crate::nvm::*; +use const_zero::const_zero; +extern crate alloc; +use alloc::ffi::CString; +use alloc::vec::Vec; +use core::ffi::{c_char, c_int}; +use core::mem::transmute; +use ledger_secure_sdk_sys::*; + +pub mod nbgl2_home_and_settings; +pub use nbgl2_home_and_settings::*; diff --git a/ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs b/ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs new file mode 100644 index 00000000..b562f07a --- /dev/null +++ b/ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs @@ -0,0 +1,180 @@ +use super::*; +use crate::nbgl::*; + +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; + if idx < 0 || idx >= SETTINGS_SIZE as i32 { + panic!("Invalid token."); + } + + let setting_idx: usize = idx as usize; + + match SWITCH_ARRAY[setting_idx].initState { + OFF_STATE => SWITCH_ARRAY[setting_idx].initState = ON_STATE, + ON_STATE => SWITCH_ARRAY[setting_idx].initState = OFF_STATE, + _ => panic!("Invalid state."), + } + + if let Some(data) = NVM_REF.as_mut() { + let mut switch_values: [u8; SETTINGS_SIZE] = data.get_ref().clone(); + if switch_values[setting_idx] == OFF_STATE { + switch_values[setting_idx] = ON_STATE; + } else { + switch_values[setting_idx] = OFF_STATE; + } + data.update(&switch_values); + } +} + +/// Informations fields name to display in the dedicated +/// page of the home screen. +const INFO_FIELDS: [*const c_char; 2] = [ + "Version\0".as_ptr() as *const c_char, + "Developer\0".as_ptr() as *const c_char, +]; + +/// Used to display the home screen of the application, with an optional glyph, +/// information fields, and settings switches. +pub struct Nbgl2HomeAndSettings { + app_name: CString, + info_contents: Vec, + info_contents_ptr: Vec<*const c_char>, + setting_contents: Vec<[CString; 2]>, + nb_settings: u8, + content: nbgl_content_t, + generic_contents: nbgl_genericContents_t, + info_list: nbgl_contentInfoList_t, + icon: nbgl_icon_details_t, +} + +unsafe extern "C" fn quit_callback() { + exit_app(0); +} + +impl<'a> Nbgl2HomeAndSettings { + pub fn new() -> Nbgl2HomeAndSettings { + Nbgl2HomeAndSettings { + app_name: CString::new("").unwrap(), + info_contents: Vec::default(), + info_contents_ptr: Vec::default(), + setting_contents: Vec::default(), + nb_settings: 0, + content: nbgl_content_t::default(), + generic_contents: nbgl_genericContents_t::default(), + info_list: nbgl_contentInfoList_t::default(), + icon: nbgl_icon_details_t::default(), + } + } + + pub fn glyph(self, glyph: &'a NbglGlyph) -> Nbgl2HomeAndSettings { + let icon = glyph.into(); + Nbgl2HomeAndSettings { icon: icon, ..self } + } + + pub fn infos( + self, + app_name: &'a str, + version: &'a str, + author: &'a str, + ) -> Nbgl2HomeAndSettings { + let mut v: Vec = Vec::new(); + v.push(CString::new(version).unwrap()); + v.push(CString::new(author).unwrap()); + + Nbgl2HomeAndSettings { + app_name: CString::new(app_name).unwrap(), + info_contents: v, + ..self + } + } + + pub fn settings( + self, + nvm_data: &'a mut AtomicStorage<[u8; SETTINGS_SIZE]>, + settings_strings: &[[&'a str; 2]], + ) -> Nbgl2HomeAndSettings { + unsafe { + NVM_REF = Some(transmute(nvm_data)); + } + + if settings_strings.len() > SETTINGS_SIZE { + panic!("Too many settings."); + } + + let v: Vec<[CString; 2]> = settings_strings + .iter() + .map(|s| [CString::new(s[0]).unwrap(), CString::new(s[1]).unwrap()]) + .collect(); + + Nbgl2HomeAndSettings { + nb_settings: settings_strings.len() as u8, + setting_contents: v, + ..self + } + } + + pub fn show(&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() as *const *const c_char, + infoContents: self.info_contents_ptr[..].as_ptr() as *const *const c_char, + 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_callback), + ); + } + } +} From 471a2baa31333118e3fbdaaeefe2c9a3635087f6 Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Sep 2024 11:52:21 +0200 Subject: [PATCH 2/8] Update NBGL HomeAndSettings: stop filtering APDU --- ledger_device_sdk/src/lib.rs | 2 - ledger_device_sdk/src/nbgl.rs | 6 +- .../src/nbgl/nbgl_home_and_settings.rs | 134 ++++++------- ledger_device_sdk/src/nbgl2.rs | 12 -- .../src/nbgl2/nbgl2_home_and_settings.rs | 180 ------------------ 5 files changed, 61 insertions(+), 273 deletions(-) delete mode 100644 ledger_device_sdk/src/nbgl2.rs delete mode 100644 ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs diff --git a/ledger_device_sdk/src/lib.rs b/ledger_device_sdk/src/lib.rs index 2af61dcd..7d76c310 100644 --- a/ledger_device_sdk/src/lib.rs +++ b/ledger_device_sdk/src/lib.rs @@ -25,8 +25,6 @@ pub mod testing; #[cfg(any(target_os = "stax", target_os = "flex"))] pub mod nbgl; -#[cfg(any(target_os = "stax", target_os = "flex"))] -pub mod nbgl2; #[cfg(not(any(target_os = "stax", target_os = "flex")))] pub mod ui; diff --git a/ledger_device_sdk/src/nbgl.rs b/ledger_device_sdk/src/nbgl.rs index 5108d4d9..80072660 100644 --- a/ledger_device_sdk/src/nbgl.rs +++ b/ledger_device_sdk/src/nbgl.rs @@ -1,4 +1,4 @@ -use crate::io::{ApduHeader, Comm, Event, Reply}; +use crate::io::{ApduHeader, Comm}; use crate::nvm::*; use const_zero::const_zero; extern crate alloc; @@ -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..295c61eb 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; @@ -47,7 +52,9 @@ pub struct NbglHomeAndSettings { icon: nbgl_icon_details_t, } -impl SyncNBGL for NbglHomeAndSettings {} +unsafe extern "C" fn quit_callback() { + exit_app(0); +} impl<'a> NbglHomeAndSettings { pub fn new() -> NbglHomeAndSettings { @@ -111,83 +118,62 @@ impl<'a> NbglHomeAndSettings { } } - pub fn show>(&mut self) -> Event - where - Reply: From<>::Error>, - { + pub fn show(&mut self) { unsafe { - loop { - 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() as *const *const c_char, - infoContents: self.info_contents_ptr[..].as_ptr() as *const *const c_char, - 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.info_contents_ptr = self + .info_contents + .iter() + .map(|s| s.as_ptr()) + .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, + 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.generic_contents = nbgl_genericContents_t { - callbackCallNeeded: false, - __bindgen_anon_1: nbgl_genericContents_t__bindgen_ty_1 { - contentsList: &self.content as *const nbgl_content_t, + 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, }, - nbContents: if self.nb_settings > 0 { 1 } else { 0 }, - }; - - self.ux_sync_init(); - 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_callback), - ); - match self.ux_sync_wait(true) { - SyncNbgl::UxSyncRetApduReceived => { - if let Some(comm) = COMM_REF.as_mut() { - if let Some(value) = comm.check_event() { - return value; - } - } - } - SyncNbgl::UxSyncRetQuitted => { - exit_app(0); - } - _ => { - panic!("Unexpected return value from ux_sync_homeAndSettings"); - } - } - } + }, + 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_callback), + ); } } } diff --git a/ledger_device_sdk/src/nbgl2.rs b/ledger_device_sdk/src/nbgl2.rs deleted file mode 100644 index ac0fb228..00000000 --- a/ledger_device_sdk/src/nbgl2.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::io::{ApduHeader, Comm, Event, Reply}; -use crate::nvm::*; -use const_zero::const_zero; -extern crate alloc; -use alloc::ffi::CString; -use alloc::vec::Vec; -use core::ffi::{c_char, c_int}; -use core::mem::transmute; -use ledger_secure_sdk_sys::*; - -pub mod nbgl2_home_and_settings; -pub use nbgl2_home_and_settings::*; diff --git a/ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs b/ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs deleted file mode 100644 index b562f07a..00000000 --- a/ledger_device_sdk/src/nbgl2/nbgl2_home_and_settings.rs +++ /dev/null @@ -1,180 +0,0 @@ -use super::*; -use crate::nbgl::*; - -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; - if idx < 0 || idx >= SETTINGS_SIZE as i32 { - panic!("Invalid token."); - } - - let setting_idx: usize = idx as usize; - - match SWITCH_ARRAY[setting_idx].initState { - OFF_STATE => SWITCH_ARRAY[setting_idx].initState = ON_STATE, - ON_STATE => SWITCH_ARRAY[setting_idx].initState = OFF_STATE, - _ => panic!("Invalid state."), - } - - if let Some(data) = NVM_REF.as_mut() { - let mut switch_values: [u8; SETTINGS_SIZE] = data.get_ref().clone(); - if switch_values[setting_idx] == OFF_STATE { - switch_values[setting_idx] = ON_STATE; - } else { - switch_values[setting_idx] = OFF_STATE; - } - data.update(&switch_values); - } -} - -/// Informations fields name to display in the dedicated -/// page of the home screen. -const INFO_FIELDS: [*const c_char; 2] = [ - "Version\0".as_ptr() as *const c_char, - "Developer\0".as_ptr() as *const c_char, -]; - -/// Used to display the home screen of the application, with an optional glyph, -/// information fields, and settings switches. -pub struct Nbgl2HomeAndSettings { - app_name: CString, - info_contents: Vec, - info_contents_ptr: Vec<*const c_char>, - setting_contents: Vec<[CString; 2]>, - nb_settings: u8, - content: nbgl_content_t, - generic_contents: nbgl_genericContents_t, - info_list: nbgl_contentInfoList_t, - icon: nbgl_icon_details_t, -} - -unsafe extern "C" fn quit_callback() { - exit_app(0); -} - -impl<'a> Nbgl2HomeAndSettings { - pub fn new() -> Nbgl2HomeAndSettings { - Nbgl2HomeAndSettings { - app_name: CString::new("").unwrap(), - info_contents: Vec::default(), - info_contents_ptr: Vec::default(), - setting_contents: Vec::default(), - nb_settings: 0, - content: nbgl_content_t::default(), - generic_contents: nbgl_genericContents_t::default(), - info_list: nbgl_contentInfoList_t::default(), - icon: nbgl_icon_details_t::default(), - } - } - - pub fn glyph(self, glyph: &'a NbglGlyph) -> Nbgl2HomeAndSettings { - let icon = glyph.into(); - Nbgl2HomeAndSettings { icon: icon, ..self } - } - - pub fn infos( - self, - app_name: &'a str, - version: &'a str, - author: &'a str, - ) -> Nbgl2HomeAndSettings { - let mut v: Vec = Vec::new(); - v.push(CString::new(version).unwrap()); - v.push(CString::new(author).unwrap()); - - Nbgl2HomeAndSettings { - app_name: CString::new(app_name).unwrap(), - info_contents: v, - ..self - } - } - - pub fn settings( - self, - nvm_data: &'a mut AtomicStorage<[u8; SETTINGS_SIZE]>, - settings_strings: &[[&'a str; 2]], - ) -> Nbgl2HomeAndSettings { - unsafe { - NVM_REF = Some(transmute(nvm_data)); - } - - if settings_strings.len() > SETTINGS_SIZE { - panic!("Too many settings."); - } - - let v: Vec<[CString; 2]> = settings_strings - .iter() - .map(|s| [CString::new(s[0]).unwrap(), CString::new(s[1]).unwrap()]) - .collect(); - - Nbgl2HomeAndSettings { - nb_settings: settings_strings.len() as u8, - setting_contents: v, - ..self - } - } - - pub fn show(&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() as *const *const c_char, - infoContents: self.info_contents_ptr[..].as_ptr() as *const *const c_char, - 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_callback), - ); - } - } -} From 0937f0ca54e8421d313b6255a7194978a738984e Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Sep 2024 14:36:36 +0200 Subject: [PATCH 3/8] Keep backward compatibility with show() API --- ledger_device_sdk/src/nbgl.rs | 2 +- .../src/nbgl/nbgl_home_and_settings.rs | 90 ++++++++++++++++++- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/ledger_device_sdk/src/nbgl.rs b/ledger_device_sdk/src/nbgl.rs index 80072660..251926c2 100644 --- a/ledger_device_sdk/src/nbgl.rs +++ b/ledger_device_sdk/src/nbgl.rs @@ -1,4 +1,4 @@ -use crate::io::{ApduHeader, Comm}; +use crate::io::{ApduHeader, Comm, Event, Reply}; use crate::nvm::*; use const_zero::const_zero; extern crate alloc; 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 295c61eb..d9261de5 100644 --- a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs +++ b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs @@ -56,6 +56,12 @@ unsafe extern "C" fn quit_callback() { exit_app(0); } +impl SyncNBGL for NbglHomeAndSettings {} + +unsafe extern "C" fn quit_cb() { + exit_app(0); +} + impl<'a> NbglHomeAndSettings { pub fn new() -> NbglHomeAndSettings { NbglHomeAndSettings { @@ -118,7 +124,87 @@ impl<'a> NbglHomeAndSettings { } } - pub fn show(&mut self) { + pub fn show>(&mut self) -> Event + where + Reply: From<>::Error>, + { + unsafe { + loop { + 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() as *const *const c_char, + infoContents: self.info_contents_ptr[..].as_ptr() as *const *const c_char, + 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 }, + }; + + self.ux_sync_init(); + 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_callback), + ); + match self.ux_sync_wait(true) { + SyncNbgl::UxSyncRetApduReceived => { + if let Some(comm) = COMM_REF.as_mut() { + if let Some(value) = comm.check_event() { + return value; + } + } + } + SyncNbgl::UxSyncRetQuitted => { + exit_app(0); + } + _ => { + panic!("Unexpected return value from ux_sync_homeAndSettings"); + } + } + } + } + } + + pub fn display(&mut self) { unsafe { self.info_contents_ptr = self .info_contents @@ -172,7 +258,7 @@ impl<'a> NbglHomeAndSettings { &self.generic_contents as *const nbgl_genericContents_t, &self.info_list as *const nbgl_contentInfoList_t, core::ptr::null(), - Some(quit_callback), + Some(quit_cb), ); } } From d4165fa543c2bfe8787094d927bf58e74ee891bd Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Sep 2024 14:38:54 +0200 Subject: [PATCH 4/8] Delete duplicated callback definition --- ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs | 4 ---- 1 file changed, 4 deletions(-) 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 d9261de5..6db7cd2e 100644 --- a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs +++ b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs @@ -52,10 +52,6 @@ pub struct NbglHomeAndSettings { icon: nbgl_icon_details_t, } -unsafe extern "C" fn quit_callback() { - exit_app(0); -} - impl SyncNBGL for NbglHomeAndSettings {} unsafe extern "C" fn quit_cb() { From 1772a3facd9ab5f031efe0477a68bd38a5dcc961 Mon Sep 17 00:00:00 2001 From: GroM Date: Fri, 20 Sep 2024 14:48:59 +0200 Subject: [PATCH 5/8] Add comments --- ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs | 6 ++++++ 1 file changed, 6 insertions(+) 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 6db7cd2e..bee5dfd1 100644 --- a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs +++ b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs @@ -120,6 +120,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 `display` instead. pub fn show>(&mut self) -> Event where Reply: From<>::Error>, @@ -200,6 +204,8 @@ impl<'a> NbglHomeAndSettings { } } + /// Show the home screen and settings page. + /// This function returns immediately after the screen is displayed. pub fn display(&mut self) { unsafe { self.info_contents_ptr = self From 59b6ec2c29393e47ec8ca94d55de837bf1089016 Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 23 Sep 2024 10:57:08 +0200 Subject: [PATCH 6/8] Rename function --- ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 bee5dfd1..09cc062a 100644 --- a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs +++ b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs @@ -123,7 +123,7 @@ 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 `display` instead. + /// Use `show_and_return` instead. pub fn show>(&mut self) -> Event where Reply: From<>::Error>, @@ -206,7 +206,7 @@ impl<'a> NbglHomeAndSettings { /// Show the home screen and settings page. /// This function returns immediately after the screen is displayed. - pub fn display(&mut self) { + pub fn show_and_return(&mut self) { unsafe { self.info_contents_ptr = self .info_contents From 8993baee3423ec5bc1d0b5baa27d18dbdd71f9ca Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 23 Sep 2024 14:48:40 +0200 Subject: [PATCH 7/8] Fix clippy issues in HomeAndSettings --- ledger_device_sdk/src/nbgl.rs | 2 +- .../src/nbgl/nbgl_home_and_settings.rs | 25 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ledger_device_sdk/src/nbgl.rs b/ledger_device_sdk/src/nbgl.rs index 251926c2..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::*; 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 09cc062a..c6460f28 100644 --- a/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs +++ b/ledger_device_sdk/src/nbgl/nbgl_home_and_settings.rs @@ -21,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 { @@ -58,6 +58,12 @@ 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 { @@ -75,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( @@ -84,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(), @@ -137,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, }; @@ -215,8 +222,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, }; From 85df212408f961446a4c50dc2c13dfe82c56d1ba Mon Sep 17 00:00:00 2001 From: GroM Date: Mon, 23 Sep 2024 16:27:13 +0200 Subject: [PATCH 8/8] Bump version --- Cargo.lock | 2 +- ledger_device_sdk/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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