use alloc::boxed::Box;
use core::cell::Cell;
use wasefire_applet_api::usb::ctap as api;
pub use self::api::Event;
use crate::{Error, convert_bool, convert_unit};
pub fn read(packet: &mut [u8; 64]) -> Result<bool, Error> {
let params = api::read::Params { ptr: packet.as_mut_ptr() };
convert_bool(unsafe { api::read(params) })
}
pub fn write(packet: &[u8; 64]) -> Result<bool, Error> {
let params = api::write::Params { ptr: packet.as_ptr() };
convert_bool(unsafe { api::write(params) })
}
pub struct Listener {
event: api::Event,
notified: *const Cell<bool>,
}
impl Listener {
pub fn new(event: api::Event) -> Self {
let notified = Box::into_raw(Box::new(Cell::new(true)));
let handler_func = Self::call;
let handler_data = notified as *const u8;
let params = api::register::Params { event: event as usize, handler_func, handler_data };
convert_unit(unsafe { api::register(params) }).unwrap();
Listener { event, notified }
}
pub fn is_notified(&mut self) -> bool {
unsafe { &*self.notified }.replace(false)
}
extern "C" fn call(data: *const u8) {
let notified = unsafe { &*(data as *const Cell<bool>) };
notified.set(true);
}
}
impl Drop for Listener {
fn drop(&mut self) {
let params = api::unregister::Params { event: self.event as usize };
convert_unit(unsafe { api::unregister(params) }).unwrap();
drop(unsafe { Box::from_raw(self.notified as *mut Cell<bool>) });
}
}