use crate::io_legacy::{ApduHeader, Reply};
#[cfg(feature = "stack_usage")]
use super::bolos::handle_bolos_apdu;
use super::{Comm, DecodedEventType};
static mut CURRENT_COMM: *mut core::ffi::c_void = core::ptr::null_mut();
static mut PANIC_REPLY_FN: Option<fn(Reply)> = None;
pub(super) fn set_comm<const N: usize>(comm: &mut Comm<N>) {
unsafe {
CURRENT_COMM = (comm as *mut Comm<N>) as *mut core::ffi::c_void;
}
}
pub(super) fn clear_comm() {
unsafe {
CURRENT_COMM = core::ptr::null_mut();
}
}
#[allow(dead_code)]
pub(super) fn is_comm_null() -> bool {
unsafe { CURRENT_COMM.is_null() }
}
unsafe fn get_comm<const N: usize>() -> &'static mut Comm<N> {
unsafe { &mut *(CURRENT_COMM as *mut Comm<N>) }
}
pub fn register_panic_handler<const N: usize>() {
unsafe {
PANIC_REPLY_FN = Some(panic_reply_impl::<N>);
}
}
pub(super) fn clear_panic_handler() {
unsafe {
PANIC_REPLY_FN = None;
}
}
pub fn send_panic_reply(reply: Reply) {
unsafe {
if let Some(f) = PANIC_REPLY_FN {
f(reply);
}
}
}
fn panic_reply_impl<const N: usize>(reply: Reply) {
let comm = unsafe { get_comm::<N>() };
let _ = comm.begin_response().send(reply);
}
pub(super) fn next_event_ahead_impl<const N: usize>() -> bool {
let comm = unsafe { get_comm::<N>() };
if comm.pending_apdu {
return true;
}
match comm.next_event().into_type() {
DecodedEventType::Apdu {
header,
offset,
length,
} => {
#[cfg(feature = "stack_usage")]
if header.cla == 0xB0 {
handle_bolos_apdu::<N>(comm, header.ins, header.p1, header.p2);
return false;
}
comm.pending_apdu = true;
comm.pending_header = header;
comm.pending_offset = offset;
comm.pending_length = length;
return true;
}
_ => {}
}
false
}
pub(super) fn fetch_apdu_header_impl<const N: usize>() -> Option<ApduHeader> {
let comm = unsafe { get_comm::<N>() };
if comm.pending_apdu {
Some(comm.pending_header)
} else {
None
}
}
pub(super) fn reply_status_impl<const N: usize>(reply: Reply) {
let comm = unsafe { get_comm::<N>() };
if comm.pending_apdu {
comm.pending_apdu = false;
}
let _ = comm.begin_response().send(reply);
}