124 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			124 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use core::cell::RefCell;
 | 
						|
use core::future::poll_fn;
 | 
						|
use core::task::Poll;
 | 
						|
 | 
						|
use embassy_sync::waitqueue::WakerRegistration;
 | 
						|
 | 
						|
use crate::fmt::Bytes;
 | 
						|
 | 
						|
#[derive(Clone, Copy)]
 | 
						|
pub struct PendingIoctl {
 | 
						|
    pub buf: *mut [u8],
 | 
						|
    pub req_len: usize,
 | 
						|
}
 | 
						|
 | 
						|
#[derive(Clone, Copy)]
 | 
						|
enum IoctlState {
 | 
						|
    Pending(PendingIoctl),
 | 
						|
    Sent { buf: *mut [u8] },
 | 
						|
    Done { resp_len: usize },
 | 
						|
}
 | 
						|
 | 
						|
pub struct Shared(RefCell<SharedInner>);
 | 
						|
 | 
						|
struct SharedInner {
 | 
						|
    ioctl: IoctlState,
 | 
						|
    is_init: bool,
 | 
						|
    control_waker: WakerRegistration,
 | 
						|
    runner_waker: WakerRegistration,
 | 
						|
}
 | 
						|
 | 
						|
impl Shared {
 | 
						|
    pub fn new() -> Self {
 | 
						|
        Self(RefCell::new(SharedInner {
 | 
						|
            ioctl: IoctlState::Done { resp_len: 0 },
 | 
						|
            is_init: false,
 | 
						|
            control_waker: WakerRegistration::new(),
 | 
						|
            runner_waker: WakerRegistration::new(),
 | 
						|
        }))
 | 
						|
    }
 | 
						|
 | 
						|
    pub async fn ioctl_wait_complete(&self) -> usize {
 | 
						|
        poll_fn(|cx| {
 | 
						|
            let mut this = self.0.borrow_mut();
 | 
						|
            if let IoctlState::Done { resp_len } = this.ioctl {
 | 
						|
                Poll::Ready(resp_len)
 | 
						|
            } else {
 | 
						|
                this.control_waker.register(cx.waker());
 | 
						|
                Poll::Pending
 | 
						|
            }
 | 
						|
        })
 | 
						|
        .await
 | 
						|
    }
 | 
						|
 | 
						|
    pub async fn ioctl_wait_pending(&self) -> PendingIoctl {
 | 
						|
        let pending = poll_fn(|cx| {
 | 
						|
            let mut this = self.0.borrow_mut();
 | 
						|
            if let IoctlState::Pending(pending) = this.ioctl {
 | 
						|
                Poll::Ready(pending)
 | 
						|
            } else {
 | 
						|
                this.runner_waker.register(cx.waker());
 | 
						|
                Poll::Pending
 | 
						|
            }
 | 
						|
        })
 | 
						|
        .await;
 | 
						|
 | 
						|
        self.0.borrow_mut().ioctl = IoctlState::Sent { buf: pending.buf };
 | 
						|
        pending
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn ioctl_cancel(&self) {
 | 
						|
        self.0.borrow_mut().ioctl = IoctlState::Done { resp_len: 0 };
 | 
						|
    }
 | 
						|
 | 
						|
    pub async fn ioctl(&self, buf: &mut [u8], req_len: usize) -> usize {
 | 
						|
        trace!("ioctl req bytes: {:02x}", Bytes(&buf[..req_len]));
 | 
						|
 | 
						|
        {
 | 
						|
            let mut this = self.0.borrow_mut();
 | 
						|
            this.ioctl = IoctlState::Pending(PendingIoctl { buf, req_len });
 | 
						|
            this.runner_waker.wake();
 | 
						|
        }
 | 
						|
 | 
						|
        self.ioctl_wait_complete().await
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn ioctl_done(&self, response: &[u8]) {
 | 
						|
        let mut this = self.0.borrow_mut();
 | 
						|
        if let IoctlState::Sent { buf } = this.ioctl {
 | 
						|
            trace!("ioctl resp bytes: {:02x}", Bytes(response));
 | 
						|
 | 
						|
            // TODO fix this
 | 
						|
            (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
 | 
						|
 | 
						|
            this.ioctl = IoctlState::Done {
 | 
						|
                resp_len: response.len(),
 | 
						|
            };
 | 
						|
            this.control_waker.wake();
 | 
						|
        } else {
 | 
						|
            warn!("IOCTL Response but no pending Ioctl");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // // // // // // // // // // // // // // // // // // // //
 | 
						|
 | 
						|
    pub fn init_done(&self) {
 | 
						|
        let mut this = self.0.borrow_mut();
 | 
						|
        this.is_init = true;
 | 
						|
        this.control_waker.wake();
 | 
						|
    }
 | 
						|
 | 
						|
    pub async fn init_wait(&self) {
 | 
						|
        poll_fn(|cx| {
 | 
						|
            let mut this = self.0.borrow_mut();
 | 
						|
            if this.is_init {
 | 
						|
                Poll::Ready(())
 | 
						|
            } else {
 | 
						|
                this.control_waker.register(cx.waker());
 | 
						|
                Poll::Pending
 | 
						|
            }
 | 
						|
        })
 | 
						|
        .await
 | 
						|
    }
 | 
						|
}
 |