use crate::endpoint::*; use std::fmt; use std::io; use std::io::Write; use std::io::{Error, ErrorKind}; pub(crate) type Deallocate = Box; pub struct ControlTransfer { pub buffer: *mut u8, // buffer length is the value sent to kernel pub(crate) buffer_length: u16, // capacity of the buffer needed when call deallocator pub(crate) buffer_capacity: u16, // given back from kernel pub(crate) actual_length: u16, deallocate: Deallocate, } impl fmt::Display for ControlTransfer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "|Control|{}|{}|{}|", self.buffer_length, self.actual_length, self.buffer_capacity ) } } impl ControlTransfer { pub(crate) fn new( buffer: *mut u8, buffer_capacity: u16, buffer_length: u16, deallocate: DEALOC, ) -> Self where DEALOC: Fn(*mut u8, usize) + 'static, { Self { buffer, buffer_length, buffer_capacity, actual_length: 0, deallocate: Box::new(deallocate), } } } impl Drop for ControlTransfer { fn drop(&mut self) { if !self.buffer.is_null() { (self.deallocate)(self.buffer, self.buffer_capacity as usize); } } } impl Write for ControlTransfer { fn write(&mut self, inbuf: &[u8]) -> io::Result { let buf = unsafe { let buf = self.buffer; std::slice::from_raw_parts_mut( buf.offset(self.buffer_length as isize), self.buffer_capacity as usize - self.buffer_length as usize, ) }; for (i, byte) in inbuf.iter().enumerate() { buf[i] = *byte; self.buffer_length += 1; } Ok(inbuf.len()) } fn flush(&mut self) -> io::Result<()> { self.actual_length = 0; Ok(()) } } pub struct BulkTransfer { pub(crate) buffer: *mut u8, // Lower layer write or read length pub buffer_length: usize, pub actual_length: usize, pub status: i32, // allocedata size pub buffer_capacity: usize, pub endpoint: Endpoint, // give back allocated memory deallocate: Deallocate, } impl fmt::Display for BulkTransfer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "|{}|{}|{}|{}|", self.endpoint, self.buffer_length, self.actual_length, self.buffer_capacity ) } } impl BulkTransfer { /// Create new bulk input (Read) /// the deallocate is called when BulkTransfer goes out of scope to cleanup /// allocated memory pub fn input( ep: u8, buffer: *mut u8, buffer_capacity: usize, deallocate: DEALOC, ) -> Self where DEALOC: Fn(*mut u8, usize) + 'static, { Self { buffer, buffer_capacity, buffer_length: buffer_capacity, actual_length: 0, status: 0, endpoint: Endpoint::bulk_in(ep), deallocate: Box::new(deallocate), } } /// Create a write pub fn output( ep: u8, buffer: *mut u8, buffer_capacity: usize, deallocate: DEALOC, ) -> Self where DEALOC: Fn(*mut u8, usize) + 'static, { Self { buffer, buffer_capacity, buffer_length: 0, // incremented when we put data in the buffer actual_length: 0, status: 0, endpoint: Endpoint::bulk_out(ep), deallocate: Box::new(deallocate), } } } impl Drop for BulkTransfer { fn drop(&mut self) { if !self.buffer.is_null() { (self.deallocate)(self.buffer, self.buffer_capacity); } } } impl Write for BulkTransfer { fn write(&mut self, inbuf: &[u8]) -> io::Result { if self.endpoint.is_bulk_in() { return Err(Error::new( ErrorKind::InvalidData, "Can not write to an bulk in endpoint.", )); } let buf = unsafe { let buf = self.buffer; std::slice::from_raw_parts_mut( buf.add(self.buffer_length), self.buffer_capacity - self.buffer_length, ) }; assert!(!buf.is_empty()); for (i, byte) in inbuf.iter().enumerate() { buf[i] = *byte; self.buffer_length += 1; } Ok(inbuf.len()) } fn flush(&mut self) -> io::Result<()> { self.actual_length = 0; if self.endpoint.is_bulk_out() { self.buffer_length = 0; } Ok(()) } } pub enum TransferKind { Control(ControlTransfer), Bulk(BulkTransfer), Invalid(Endpoint), } impl fmt::Display for TransferKind { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TransferKind::Control(control) => write!(f, "Control Transfer: {}", control), TransferKind::Bulk(bulk) => write!(f, "Control Transfer: {}", bulk), TransferKind::Invalid(ep) => write!(f, "Invalid {}", ep), } } } pub trait BufferSlice { fn buffer_from_raw<'a>(&self) -> &'a [u8]; } pub trait UsbCoreDriver { fn new_bulk_in(&mut self, ep: u8, read_capacity: usize) -> io::Result; fn new_bulk_out(&mut self, ep: u8, capacity: usize) -> io::Result; // Create a new control fn new_control( &mut self, request_type: u8, // bRequestType request: u8, // bRequest value: u16, // wValue index: u16, // wIndex length: u16, // wLength ) -> io::Result; fn new_control_out( &mut self, request_type: u8, request: u8, value: u16, index: u16, buffer: &[u8], ) -> io::Result { let mut ctrl = self.new_control( request_type | ENDPOINT_OUT, request, value, index, buffer.len() as u16, // wLength )?; ctrl.write_all(buffer)?; Ok(ctrl) } fn new_control_in( &mut self, request_type: u8, request: u8, value: u16, index: u16, length: u16, // wLength (Read length) ) -> io::Result { let mut ctrl = self.new_control(request_type | ENDPOINT_IN, request, value, index, length)?; ctrl.buffer_length += length; Ok(ctrl) } // Create a new control fn new_control_nodata( &mut self, request_type: u8, request: u8, value: u16, index: u16, ) -> io::Result { self.new_control(request_type, request, value, index, 0) } }