86 lines
2.4 KiB
Rust

use core::{mem::MaybeUninit, ops::Deref};
use alloc::boxed::Box;
use async_trait::async_trait;
use libk::dma::DmaBuffer;
use crate::error::{TransferError, UsbError};
use super::UsbGenericPipe;
#[async_trait]
pub trait UsbNormalPipeIn: UsbGenericPipe {
async fn read_dma(
&self,
buffer: &mut DmaBuffer<[MaybeUninit<u8>]>,
limit: usize,
) -> Result<usize, UsbError>;
async fn read(&self, buffer: &mut [u8]) -> Result<usize, UsbError> {
let mut dma_buffer = self.allocate_dma_buffer(buffer.len())?;
let len = self.read_dma(&mut dma_buffer, buffer.len()).await?;
let dma_slice = unsafe { MaybeUninit::slice_assume_init_ref(&dma_buffer[..len]) };
buffer[..len].copy_from_slice(dma_slice);
Ok(len)
}
async fn read_exact(&self, buffer: &mut [u8]) -> Result<(), UsbError> {
match self.read(buffer).await {
Ok(len) if len == buffer.len() => Ok(()),
Ok(len) => Err(UsbError::TransferFailed(TransferError::ShortPacket(len))),
Err(error) => Err(error),
}
}
}
#[async_trait]
pub trait UsbNormalPipeOut: UsbGenericPipe {
async fn write_dma(&self, buffer: &DmaBuffer<[u8]>) -> Result<usize, UsbError>;
async fn write(&self, buffer: &[u8]) -> Result<usize, UsbError> {
let mut dma_buffer = self.allocate_dma_buffer(buffer.len())?;
MaybeUninit::copy_from_slice(&mut dma_buffer, buffer);
let dma_buffer = unsafe { DmaBuffer::assume_init_slice(dma_buffer) };
self.write_dma(&dma_buffer).await
}
}
pub struct UsbBulkInPipeAccess(pub Box<dyn UsbNormalPipeIn>);
pub struct UsbBulkOutPipeAccess(pub Box<dyn UsbNormalPipeOut>);
pub struct UsbInterruptInPipeAccess(pub Box<dyn UsbNormalPipeIn>);
pub struct UsbInterruptOutPipeAccess(pub Box<dyn UsbNormalPipeOut>);
impl Deref for UsbBulkInPipeAccess {
type Target = dyn UsbNormalPipeIn;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl Deref for UsbBulkOutPipeAccess {
type Target = dyn UsbNormalPipeOut;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl Deref for UsbInterruptInPipeAccess {
type Target = dyn UsbNormalPipeIn;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl Deref for UsbInterruptOutPipeAccess {
type Target = dyn UsbNormalPipeOut;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}