Skip to content

Commit 22a529e

Browse files
committed
Modify process_event so that it does not mutate self, nor the buffer.
Better type annotations in the C SDK make it possible to not mutate the seph_buffer, which can therefore be passed as a reference instead of copying. In order for this to work, however, process_event need to not mutate &self, which was necessary in order to call self.reply() and update the buttons state (on X/S+ only). By changing the return value to a Result, we can bubble up the error instead; for the buttons, we can work on a temporary copy instead of borrowing the entirety of &self mutably. This avoids having to copy the io_buffer into the seph_buffer before calling process_event. This is technically a breaking change because process_event is public. However, no app uses it.
1 parent 259946a commit 22a529e

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

ledger_device_sdk/src/io.rs

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#[cfg(any(target_os = "nanosplus", target_os = "nanox"))]
2-
use ledger_secure_sdk_sys::buttons::{get_button_event, ButtonEvent, ButtonsState};
2+
use ledger_secure_sdk_sys::buttons::{get_button_event, ButtonEvent};
3+
4+
use ledger_secure_sdk_sys::buttons::ButtonsState;
35
use ledger_secure_sdk_sys::seph as sys_seph;
46
use ledger_secure_sdk_sys::*;
57

@@ -343,17 +345,25 @@ impl Comm {
343345
None
344346
}
345347

346-
pub fn process_event<T>(&mut self, mut seph_buffer: [u8; 272], length: i32) -> Option<Event<T>>
348+
pub fn process_event<T>(
349+
&self,
350+
seph_buffer: &[u8],
351+
length: i32,
352+
_buttons_state: Option<&mut ButtonsState>, // only used on NanoX/NanoS+
353+
) -> Result<Option<Event<T>>, StatusWords>
347354
where
348355
T: TryFrom<ApduHeader>,
349356
Reply: From<<T as TryFrom<ApduHeader>>::Error>,
350357
{
358+
if seph_buffer.len() < 3 {
359+
panic!("Invalid SEPH buffer length");
360+
}
361+
351362
let tag = seph_buffer[0];
352363
let _len: usize = u16::from_be_bytes([seph_buffer[1], seph_buffer[2]]) as usize;
353364

354365
if (length as usize) < _len + 3 {
355-
self.reply(StatusWords::BadLen);
356-
return None;
366+
return Err(StatusWords::BadLen);
357367
}
358368

359369
match seph::Events::from(tag) {
@@ -362,19 +372,21 @@ impl Comm {
362372
seph::Events::ButtonPushEvent => {
363373
#[cfg(feature = "nano_nbgl")]
364374
unsafe {
365-
ux_process_button_event(seph_buffer.as_mut_ptr());
375+
ux_process_button_event(seph_buffer.as_ptr());
366376
}
367-
let button_info = seph_buffer[3] >> 1;
368-
if let Some(btn_evt) = get_button_event(&mut self.buttons, button_info) {
369-
return Some(Event::Button(btn_evt));
377+
if let Some(buttons_state) = _buttons_state {
378+
let button_info = seph_buffer[3] >> 1;
379+
if let Some(btn_evt) = get_button_event(buttons_state, button_info) {
380+
return Ok(Some(Event::Button(btn_evt)));
381+
}
370382
}
371383
}
372384

373385
// SCREEN TOUCH EVENT
374386
#[cfg(any(target_os = "stax", target_os = "flex", target_os = "apex_p"))]
375387
seph::Events::ScreenTouchEvent => unsafe {
376-
ux_process_finger_event(seph_buffer.as_mut_ptr());
377-
return Some(Event::TouchEvent);
388+
ux_process_finger_event(seph_buffer.as_ptr());
389+
return Ok(Some(Event::TouchEvent));
378390
},
379391

380392
// TICKER EVENT
@@ -388,7 +400,7 @@ impl Comm {
388400
unsafe {
389401
ux_process_ticker_event();
390402
}
391-
return Some(Event::Ticker);
403+
return Ok(Some(Event::Ticker));
392404
}
393405

394406
// ITC EVENT
@@ -435,9 +447,9 @@ impl Comm {
435447
}
436448
}
437449

438-
_ => return None,
450+
_ => return Ok(None),
439451
}
440-
return None;
452+
return Ok(None);
441453
}
442454

443455
// DEFAULT EVENT
@@ -457,7 +469,7 @@ impl Comm {
457469
}
458470
}
459471
}
460-
None
472+
Ok(None)
461473
}
462474

463475
pub fn decode_event<T>(&mut self, length: i32) -> Option<Event<T>>
@@ -469,11 +481,30 @@ impl Comm {
469481

470482
match seph::PacketTypes::from(packet_type) {
471483
seph::PacketTypes::PacketTypeSeph | seph::PacketTypes::PacketTypeSeEvent => {
484+
// On devices with buttons, we make a copy of the current button state
485+
#[cfg(any(target_os = "nanosplus", target_os = "nanox"))]
486+
let mut buttons_copy = self.buttons;
487+
#[cfg(any(target_os = "nanosplus", target_os = "nanox"))]
488+
let buttons_state = Some(&mut buttons_copy);
489+
490+
#[cfg(not(any(target_os = "nanosplus", target_os = "nanox")))]
491+
let buttons_state = None;
492+
472493
// SE or SEPH event
473-
let mut seph_buffer = [0u8; 272];
474-
seph_buffer[0..272].copy_from_slice(&self.io_buffer[1..273]);
475-
if let Some(event) = self.process_event(seph_buffer, length - 1) {
476-
return Some(event);
494+
let result = self.process_event(&self.io_buffer[1..273], length - 1, buttons_state);
495+
496+
// update buttons state, in case it was modified
497+
#[cfg(any(target_os = "nanosplus", target_os = "nanox"))]
498+
{
499+
self.buttons = buttons_copy;
500+
}
501+
502+
match result {
503+
Ok(e) => return e,
504+
Err(status) => {
505+
self.reply(status);
506+
return None;
507+
}
477508
}
478509
}
479510

ledger_secure_sdk_sys/src/buttons.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// Structure keeping track of button pushes
22
/// 1 -> left button, 2 -> right button
3-
#[derive(Default)]
3+
#[derive(Default, Debug, Copy, Clone)]
44
pub struct ButtonsState {
55
pub button_mask: u8,
66
pub cmd_buffer: [u8; 4],
@@ -17,7 +17,7 @@ impl ButtonsState {
1717

1818
/// Event types needed by
1919
/// an application
20-
#[derive(Eq, PartialEq)]
20+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
2121
pub enum ButtonEvent {
2222
LeftButtonPress,
2323
RightButtonPress,

0 commit comments

Comments
 (0)