Skip to content

Commit

Permalink
Add StaticReview
Browse files Browse the repository at this point in the history
  • Loading branch information
agrojean-ledger committed Jan 16, 2024
1 parent 5e67dca commit ebb65e9
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 17 deletions.
10 changes: 7 additions & 3 deletions ledger_device_sdk/examples/stax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ledger_device_sdk as _;

use const_zero::const_zero;
use ledger_device_sdk::io::*;
use ledger_device_sdk::nbgl::Home;
use ledger_device_sdk::nbgl::{Home, StaticReview};
use ledger_device_sdk::uxapp::UxEvent;
use ledger_secure_sdk_sys::seph;
use ledger_secure_sdk_sys::*;
Expand Down Expand Up @@ -91,12 +91,16 @@ extern "C" fn sample_main() {

let mut comm = Comm::new();

let mut myHome = Home::new(Some(&mut comm))
let mut myHome = Home::new(Some(&comm))
.app_name("Stax Sample\0")
.info_contents(env!("CARGO_PKG_VERSION"), env!("CARGO_PKG_AUTHORS"))
.icon(&BTC_BMP);

myHome.show();
let myStaticReview = StaticReview::new(Some(&comm));

myStaticReview.show_and_wait_validation();

// myHome.show();

loop {
match myHome.get_events::<Instruction>() {
Expand Down
6 changes: 6 additions & 0 deletions ledger_device_sdk/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,14 @@ impl Comm {
#[cfg(target_os = "nanox")]
seph::Events::BleReceive => ble::receive(&mut self.apdu_buffer, spi_buffer),

#[cfg(not(target_os = "stax"))]
seph::Events::TickerEvent => return Some(Event::Ticker),

#[cfg(target_os = "stax")]
seph::Events::TickerEvent => unsafe {
ux_process_ticker_event();
},

#[cfg(target_os = "stax")]
seph::Events::ScreenTouch => unsafe {
ux_process_finger_event(spi_buffer.as_mut_ptr());
Expand Down
228 changes: 214 additions & 14 deletions ledger_device_sdk/src/nbgl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,48 @@ use ledger_secure_sdk_sys::seph;
use ledger_secure_sdk_sys::*;

pub struct Home<'a> {
comm: Option<&'a mut Comm>,
comm: Option<&'a Comm>,
}

struct info_struct {
struct NBGLContext {
icon: Option<&'static [u8]>,
name: [u8; 100],
infocontents: [[u8; 20]; 2],
reviewPairs: [ledger_secure_sdk_sys::nbgl_layoutTagValue_t; 10],
nbPairs: u8,
displayHome: bool,
}

const infoTypes: [*const ::core::ffi::c_char; 2] = [
"Version\0".as_ptr() as *const ::core::ffi::c_char,
"Developer\0".as_ptr() as *const ::core::ffi::c_char,
];

static mut infos: info_struct = unsafe { const_zero!(info_struct) };
static mut ctx: NBGLContext = unsafe { const_zero!(NBGLContext) };

impl<'a> Home<'a> {
pub fn new(comm: Option<&'a mut Comm>) -> Home<'a> {
pub fn new(comm: Option<&'a Comm>) -> Home<'a> {
Home { comm }
}

pub fn app_name(self, app_name: &'static str) -> Home<'a> {
unsafe {
infos.name[..app_name.len()].copy_from_slice(app_name.as_bytes());
ctx.name[..app_name.len()].copy_from_slice(app_name.as_bytes());
}
self
}

pub fn icon(self, icon: &'static [u8]) -> Home<'a> {
unsafe {
infos.icon = Some(icon);
ctx.icon = Some(icon);
}
self
}

pub fn info_contents(self, version: &str, author: &str) -> Home<'a> {
unsafe {
infos.infocontents[0][..version.len()].copy_from_slice(version.as_bytes());
infos.infocontents[1][..author.len()].copy_from_slice(author.as_bytes());
ctx.infocontents[0][..version.len()].copy_from_slice(version.as_bytes());
ctx.infocontents[1][..author.len()].copy_from_slice(author.as_bytes());
}
self
}
Expand All @@ -57,18 +60,18 @@ impl<'a> Home<'a> {
(*content).__bindgen_anon_1.infosList.nbInfos = 2;
(*content).__bindgen_anon_1.infosList.infoTypes = infoTypes.as_ptr();
(*content).__bindgen_anon_1.infosList.infoContents = [
infos.infocontents[0].as_ptr() as *const ::core::ffi::c_char,
infos.infocontents[1].as_ptr() as *const ::core::ffi::c_char,
ctx.infocontents[0].as_ptr() as *const ::core::ffi::c_char,
ctx.infocontents[1].as_ptr() as *const ::core::ffi::c_char,
]
.as_ptr();
.as_ptr() as *const *const ::core::ffi::c_char;
} else {
return false;
}
true
};

ledger_secure_sdk_sys::nbgl_useCaseSettings(
infos.name.as_ptr() as *const core::ffi::c_char,
ctx.name.as_ptr() as *const core::ffi::c_char,
0 as u8,
1 as u8,
false as bool,
Expand All @@ -86,11 +89,11 @@ impl<'a> Home<'a> {
height: 64,
bpp: 2,
isFile: true,
bitmap: infos.icon.unwrap().as_ptr(),
bitmap: ctx.icon.unwrap().as_ptr(),
};

ledger_secure_sdk_sys::nbgl_useCaseHome(
infos.name.as_ptr() as *const core::ffi::c_char,
ctx.name.as_ptr() as *const core::ffi::c_char,
&icon as *const nbgl_icon_details_t,
core::ptr::null(),
true as bool,
Expand All @@ -109,6 +112,14 @@ impl<'a> Home<'a> {
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
loop {

unsafe {
if ctx.displayHome {
self.show();
ctx.displayHome = false;
}
}

match &mut self.comm {
None => (),
Some(comm) => {
Expand All @@ -120,3 +131,192 @@ impl<'a> Home<'a> {
}
}
}

// pub struct nbgl_layoutTagValueList_t {
// pub pairs: *mut nbgl_layoutTagValue_t,
// pub callback: nbgl_tagValueCallback_t,
// pub nbPairs: u8,
// pub startIndex: u8,
// pub nbMaxLinesForValue: u8,
// pub token: u8,
// pub smallCaseForValue: bool,
// pub wrapping: bool,
// }


// pub struct nbgl_layoutTagValue_t {
// pub item: *const ::core::ffi::c_char,
// pub value: *const ::core::ffi::c_char,
// pub valueIcon: *const nbgl_icon_details_t,
// }

// pub type nbgl_choiceCallback_t = ::core::option::Option<unsafe extern "C" fn(confirm: bool)>;

pub struct TagValue {
item: &'static str,
value: &'static str,
}

// static void displayTransaction(void) {
// nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject transaction", reviewChoice);
// }

// static void reviewStart() {
// nbgl_callback_t displayFunction = displayTransaction;
// nbgl_useCaseReviewStart(&C_stax_app_tron_64px,
// txctx.flowTitle,
// txctx.flowSubtitle,
// "Reject transaction",
// displayFunction,
// rejectChoice);
// }

// void nbgl_useCaseReviewStart(const nbgl_icon_details_t *icon,
// const char *reviewTitle,
// const char *reviewSubTitle,
// const char *rejectText,
// nbgl_callback_t continueCallback,
// nbgl_callback_t rejectCallback);

// extern "C" {
// pub fn nbgl_useCaseStaticReview(
// tagValueList: *const nbgl_layoutTagValueList_t,
// infoLongPress: *const nbgl_pageInfoLongPress_t,
// rejectText: *const ::core::ffi::c_char,
// callback: nbgl_choiceCallback_t,
// );
// }

pub enum ReviewStatus {
Pending,
Validate,
Reject,
}

pub struct StaticReview<'a> {
status: ReviewStatus,
comm: Option<&'a Comm>,
}

impl<'a> StaticReview<'a> {

pub fn new(comm: Option<&'a Comm>) -> StaticReview<'a> {
StaticReview { status: ReviewStatus::Pending, comm }
}

// called when long press button on 3rd page is long-touched or when reject footer is touched
// static void review_choice(bool confirm) {
// if (confirm) {
// // display a status page and go back to main
// validate_transaction(true);
// nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main);
// } else {
// ask_transaction_rejection_confirmation();
// }
// }

fn choice(confirm: bool) {
let show_home = || {
Home::home();
};

if confirm {
// display a status page and go back to main
// validate_transaction(true);
unsafe {
ledger_secure_sdk_sys::nbgl_useCaseStatus(
"TRANSACTION\nSIGNED\0".as_ptr() as *const ::core::ffi::c_char,
true,
transmute(show_home as fn()));
}
} else {
// ask_transaction_rejection_confirmation();
}
}

fn static_review() {
unsafe {
ctx.reviewPairs[0] = nbgl_layoutTagValue_t {
item: "Pair 1\0".as_ptr() as *const ::core::ffi::c_char,
value: "Value 1\0".as_ptr() as *const ::core::ffi::c_char,
valueIcon: core::ptr::null(),
};
ctx.reviewPairs[1] = nbgl_layoutTagValue_t {
item: "Pair 2\0".as_ptr() as *const ::core::ffi::c_char,
value: "Value 2\0".as_ptr() as *const ::core::ffi::c_char,
valueIcon: core::ptr::null(),
};

let tagValueList: nbgl_layoutTagValueList_t = nbgl_layoutTagValueList_t {
pairs: ctx.reviewPairs.as_mut_ptr() as *mut nbgl_layoutTagValue_t,
callback: None,
nbPairs: 2,
startIndex: 2,
nbMaxLinesForValue: 0,
token: 0,
smallCaseForValue: false,
wrapping: false,
};


// pub struct nbgl_pageInfoLongPress_s {
// pub text: *const ::core::ffi::c_char,
// pub icon: *const nbgl_icon_details_t,
// pub longPressText: *const ::core::ffi::c_char,
// pub longPressToken: u8,
// pub tuneId: tune_index_e,
// }

let icon = nbgl_icon_details_t {
width: 64,
height: 64,
bpp: 2,
isFile: true,
bitmap: ctx.icon.unwrap().as_ptr(),
};

let infoLongPress: nbgl_pageInfoLongPress_t = nbgl_pageInfoLongPress_t {
text: "Validate tx\0".as_ptr() as *const ::core::ffi::c_char,
icon: core::ptr::null(),
longPressText: "Hold to validate\0".as_ptr() as *const ::core::ffi::c_char,
longPressToken: 0,
tuneId: 0,
};

ledger_secure_sdk_sys::nbgl_useCaseStaticReview(
&tagValueList as *const nbgl_layoutTagValueList_t,
&infoLongPress as *const nbgl_pageInfoLongPress_t,
"Reject tx\0".as_ptr() as *const ::core::ffi::c_char,
// None,
transmute((|confirm| Self::choice(confirm)) as fn(confirm: bool)),
);
}
}


pub fn show_and_wait_validation(&self) -> bool {
unsafe {
let icon = nbgl_icon_details_t {
width: 64,
height: 64,
bpp: 2,
isFile: true,
bitmap: ctx.icon.unwrap().as_ptr(),
};

ledger_secure_sdk_sys::nbgl_useCaseReviewStart(
&icon as *const nbgl_icon_details_t,
"Review tx\0".as_ptr() as *const ::core::ffi::c_char,
"Subtitle\0".as_ptr() as *const ::core::ffi::c_char,
"Reject transaction\0".as_ptr() as *const ::core::ffi::c_char,
transmute((|| Self::static_review()) as fn()),
None,
);

// loop {
// if self.
// };
true
}
}
}

0 comments on commit ebb65e9

Please sign in to comment.