Skip to content

Commit

Permalink
Improve POC so that screens stay the same when navigating.
Browse files Browse the repository at this point in the history
  • Loading branch information
agrojean-ledger committed Jan 11, 2024
1 parent f5561ae commit 5e67dca
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 139 deletions.
55 changes: 7 additions & 48 deletions ledger_device_sdk/examples/stax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
// Force boot section to be embedded in
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::uxapp::UxEvent;
use ledger_device_sdk::io::*;
use ledger_secure_sdk_sys::seph;
use ledger_secure_sdk_sys::*;
use const_zero::const_zero;

use include_gif::include_gif;

Expand Down Expand Up @@ -66,48 +66,14 @@ extern "C" fn io_seproxyhal_play_tune(tune_index: u8) {
}
}

// Special handler for finger events, that are an 8 byte packet
pub fn get_touch_event() -> Option<()> {
if !seph::is_status_sent() {
seph::send_general_status();
}

let mut buf = [0u8; 8];
while seph::is_status_sent() {
seph::seph_recv(&mut buf, 0);

match buf[0] as u32 {
SEPROXYHAL_TAG_FINGER_EVENT => {
unsafe {
ux_process_finger_event(buf.as_mut_ptr());
}
// return Some(());
}
// SEPROXYHAL_TAG_TICKER_EVENT => unsafe {
// ledger_sdk_sys::ux_process_default_event();
// }
_ => (),
}
}
None
}

fn wait_any() {
loop {
if get_touch_event().is_some() {
return;
}
}
}

pub enum Instruction {
GetVersion,
GetAppName,
}

impl TryFrom<ApduHeader> for Instruction {
type Error = StatusWords;

fn try_from(value: ApduHeader) -> Result<Self, Self::Error> {
match value.ins {
3 => Ok(Instruction::GetVersion),
Expand All @@ -125,20 +91,13 @@ extern "C" fn sample_main() {

let mut comm = Comm::new();

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

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

myHome.show();

loop {
match myHome.get_events::<Instruction>() {
Event::Command(ins) => (),
Expand Down
8 changes: 3 additions & 5 deletions ledger_device_sdk/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,9 @@ impl Comm {
seph::Events::TickerEvent => return Some(Event::Ticker),

#[cfg(target_os = "stax")]
seph::Events::ScreenTouch => {
unsafe {
ux_process_finger_event(spi_buffer.as_mut_ptr());
}
}
seph::Events::ScreenTouch => unsafe {
ux_process_finger_event(spi_buffer.as_mut_ptr());
},

_ => (),
}
Expand Down
155 changes: 69 additions & 86 deletions ledger_device_sdk/src/nbgl.rs
Original file line number Diff line number Diff line change
@@ -1,128 +1,112 @@
use crate::io::{self, ApduHeader, Comm, Event, Reply};
use const_zero::const_zero;
use core::mem::transmute;
use ledger_secure_sdk_sys::nbgl_icon_details_t;
use crate::io::{self, ApduHeader, Comm, Event, Reply};
use ledger_secure_sdk_sys::seph;
use ledger_secure_sdk_sys::*;

pub struct Home<'a> {
app_name: &'static str,
icon: Option<&'a nbgl_icon_details_t>,
tagline: Option<&'static str>,
with_settings: bool,
top_right_cb: Option<fn()>,
quit_cb: Option<fn()>,
comm: Option<&'a mut Comm>,
}

struct info_struct {
icon: Option<&'static [u8]>,
name: [u8; 100],
infocontents: [[u8; 20]; 2],
}

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,
];

const infoContents: [*const ::core::ffi::c_char; 2] = [
env!("CARGO_PKG_VERSION").as_ptr() as *const ::core::ffi::c_char,
"Ledger\0".as_ptr() as *const ::core::ffi::c_char,
];

fn settings_nav(page: u8, content: *mut nbgl_pageContent_s) -> bool
{
if page == 0 {
unsafe {
(*content).type_ = ledger_secure_sdk_sys::INFOS_LIST;
(*content).__bindgen_anon_1.infosList.nbInfos = 2;
(*content).__bindgen_anon_1.infosList.infoTypes = infoTypes.as_ptr();
(*content).__bindgen_anon_1.infosList.infoContents = infoContents.as_ptr();
}
} else {
return false;
}
true
}

fn settings() {
unsafe {
ledger_secure_sdk_sys::nbgl_useCaseSettings(
"My App\0".as_ptr() as *const core::ffi::c_char,
0 as u8,
1 as u8,
false as bool,
transmute((|| home_nav()) as fn()),
transmute((|arg1,arg2| settings_nav(arg1,arg2)) as fn(u8, *mut nbgl_pageContent_s) -> bool),
transmute((|| exit_app(12)) as fn()),
);
}
}

fn home_nav() {
unsafe {
ledger_secure_sdk_sys::nbgl_useCaseHome(
"My App\0".as_ptr() as *const core::ffi::c_char,
core::ptr::null(),
core::ptr::null(),
true as bool,
transmute((|| settings()) as fn()),
transmute((|| exit_app(12)) as fn()),
);
}
}

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

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

Home {
app_name: "AppName\0",
icon: None,
tagline: None,
with_settings: false,
top_right_cb: None,
quit_cb: None,
comm,
}
Home { comm }
}

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

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

pub fn top_right_cb(self, top_right_cb: fn()) -> Home<'a> {
Home {
top_right_cb: Some(top_right_cb),
..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());
}
self
}

pub fn quit_cb(self, quit_cb: fn()) -> Home<'a> {
Home {
quit_cb: Some(quit_cb),
..self
fn settings() {
unsafe {
let nav = |page: u8, content: *mut nbgl_pageContent_s| {
if page == 0 {
(*content).type_ = ledger_secure_sdk_sys::INFOS_LIST;
(*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,
]
.as_ptr();
} else {
return false;
}
true
};

ledger_secure_sdk_sys::nbgl_useCaseSettings(
infos.name.as_ptr() as *const core::ffi::c_char,
0 as u8,
1 as u8,
false as bool,
transmute((|| Self::home()) as fn()),
transmute(nav as fn(u8, *mut nbgl_pageContent_s) -> bool),
transmute((|| exit_app(12)) as fn()),
);
}
}

pub fn show(&mut self)
{
fn home() {
unsafe {
let icon = nbgl_icon_details_t {
width: 64,
height: 64,
bpp: 2,
isFile: true,
bitmap: infos.icon.unwrap().as_ptr(),
};

ledger_secure_sdk_sys::nbgl_useCaseHome(
self.app_name.as_ptr() as *const core::ffi::c_char,
self.icon.unwrap() as *const nbgl_icon_details_t,
infos.name.as_ptr() as *const core::ffi::c_char,
&icon as *const nbgl_icon_details_t,
core::ptr::null(),
true as bool,
transmute((|| settings()) as fn()),
transmute((|| Self::settings()) as fn()),
transmute((|| exit_app(12)) as fn()),
);

}
}

pub fn get_events<T: TryFrom<ApduHeader>>(&mut self) -> Event<T>
where Reply: From<<T as TryFrom<ApduHeader>>::Error>
pub fn show(&mut self) {
Self::home();
}

pub fn get_events<T: TryFrom<ApduHeader>>(&mut self) -> Event<T>
where
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
{
loop {
match &mut self.comm {
Expand All @@ -136,4 +120,3 @@ impl<'a> Home<'a> {
}
}
}

0 comments on commit 5e67dca

Please sign in to comment.