Simplify the endpoint interface.

This commit is contained in:
4lDO2
2020-02-11 23:07:20 +01:00
parent 127ef077c2
commit dd9124eb82
7 changed files with 331 additions and 318 deletions
+7 -4
View File
@@ -47,8 +47,11 @@ fn main() {
let control = 0; // TODO: NACA?
scsi::cmds::ReportIdentInfo::new(alloc_len, info_ty, control)
};*/
let inquiry = scsi::cmds::Inquiry::new(false, 0, 36, 0);
let mut buffer = [0u8; 36];
use protocol::Protocol;
protocol.send_command(unsafe { plain::as_bytes(&inquiry) }, DeviceReqData::In(&mut buffer)).expect("Failed to send command");
let mut buffer = [0u8; 5];
let mut command_buffer = [0u8; 6];
{
let mut inquiry = plain::from_mut_bytes(&mut command_buffer).unwrap();
*inquiry = scsi::cmds::Inquiry::new(false, 0, 5, 0);
}
protocol.send_command(&command_buffer, DeviceReqData::In(&mut buffer)).expect("Failed to send command");
}
+39 -38
View File
@@ -4,7 +4,7 @@ use std::io::prelude::*;
use std::{io, slice};
use thiserror::Error;
use xhcid_interface::{ConfDesc, DeviceReqData, EndpBinaryDirection, EndpDirection, EndpointStatus, IfDesc, Invalid, PortReqDirection, PortReqTy, PortReqRecipient, PortTransferStatus, XhciClientHandle, XhciClientHandleError, XhciEndpStatusHandle, XhciEndpTransferHandle};
use xhcid_interface::{ConfDesc, DeviceReqData, EndpBinaryDirection, EndpDirection, EndpointStatus, IfDesc, Invalid, PortReqDirection, PortReqTy, PortReqRecipient, PortTransferStatus, XhciClientHandle, XhciClientHandleError, XhciEndpHandle};
use super::{Protocol, ProtocolError};
@@ -77,10 +77,8 @@ impl CommandStatusWrapper {
pub struct BulkOnlyTransport<'a> {
handle: &'a XhciClientHandle,
bulk_in: XhciEndpTransferHandle,
bulk_out: XhciEndpTransferHandle,
bulk_in_status: XhciEndpStatusHandle,
bulk_out_status: XhciEndpStatusHandle,
bulk_in: XhciEndpHandle,
bulk_out: XhciEndpHandle,
bulk_in_num: u8,
bulk_out_num: u8,
max_lun: u8,
@@ -103,10 +101,8 @@ impl<'a> BulkOnlyTransport<'a> {
println!("BOT_MAX_LUN {}", max_lun);
Ok(Self {
bulk_in: handle.open_endpoint(bulk_in_num, PortReqDirection::DeviceToHost)?,
bulk_out: handle.open_endpoint(bulk_out_num, PortReqDirection::HostToDevice)?,
bulk_in_status: handle.open_endpoint_status(bulk_in_num)?,
bulk_out_status: handle.open_endpoint_status(bulk_out_num)?,
bulk_in: handle.open_endpoint(bulk_in_num)?,
bulk_out: handle.open_endpoint(bulk_out_num)?,
bulk_in_num,
bulk_out_num,
handle,
@@ -115,15 +111,20 @@ impl<'a> BulkOnlyTransport<'a> {
interface_num: if_desc.number,
})
}
fn clear_stall(&mut self, endp_num: u8) -> Result<(), XhciClientHandleError> {
self.handle.clear_feature(PortReqRecipient::Endpoint, u16::from(endp_num), FEATURE_ENDPOINT_HALT)
fn clear_stall_in(&mut self) -> Result<(), XhciClientHandleError> {
self.bulk_in.reset(false);
self.handle.clear_feature(PortReqRecipient::Endpoint, u16::from(self.bulk_in_num), FEATURE_ENDPOINT_HALT)
}
fn clear_stall_out(&mut self) -> Result<(), XhciClientHandleError> {
self.bulk_out.reset(false);
self.handle.clear_feature(PortReqRecipient::Endpoint, u16::from(self.bulk_out_num), FEATURE_ENDPOINT_HALT)
}
fn reset_recovery(&mut self) -> Result<(), ProtocolError> {
bulk_only_mass_storage_reset(self.handle, self.interface_num.into())?;
self.clear_stall(self.bulk_in_num.into())?;
self.clear_stall(self.bulk_out_num.into())?;
self.clear_stall_in()?;
self.clear_stall_out()?;
if self.bulk_in_status.current_status()? == EndpointStatus::Halted || self.bulk_out_status.current_status()? == EndpointStatus::Halted {
if self.bulk_in.status()? == EndpointStatus::Halted || self.bulk_out.status()? == EndpointStatus::Halted {
return Err(ProtocolError::RecoveryFailed)
}
Ok(())
@@ -135,25 +136,23 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
self.current_tag += 1;
let tag = self.current_tag;
let mut command_block = [0u8; 16];
if cb.len() > 16 {
return Err(ProtocolError::TooLargeCommandBlock(cb.len()));
}
command_block[..cb.len()].copy_from_slice(&cb);
println!("{}", base64::encode(cb));
println!();
let cbw = CommandBlockWrapper {
signature: CBW_SIGNATURE,
tag,
data_transfer_len: data.len() as u32,
lun: 0, // TODO
flags: u8::from(data.direction() == PortReqDirection::DeviceToHost) << 7,
cb_len: cb.len().try_into().or(Err(ProtocolError::TooLargeCommandBlock(cb.len())))?,
command_block,
};
match self.bulk_out.transfer_write(unsafe { plain::as_bytes(&cbw) })? {
let mut cbw_bytes = [0u8; 31];
let cbw = plain::from_mut_bytes::<CommandBlockWrapper>(&mut cbw_bytes).unwrap();
*cbw = CommandBlockWrapper::new(tag, data.len() as u32, data.direction().into(), 0, cb)?;
println!("{}", base64::encode(&cbw_bytes));
dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
match self.bulk_out.transfer_write(&cbw_bytes)? {
PortTransferStatus::ShortPacket(31) => (),
PortTransferStatus::Stalled => {
panic!("bulk out endpoint stalled when sending CBW");
println!("bulk out endpoint stalled when sending CBW");
self.reset_recovery()?;
dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
}
_ => panic!("invalid number of CBW bytes written; expected a short packed of length 31 (0x1F)"),
}
@@ -165,7 +164,7 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
PortTransferStatus::ShortPacket(len) => panic!("received short packed (len {}) when transferring data", len),
PortTransferStatus::Stalled => {
println!("bulk in endpoint stalled when reading data");
self.clear_stall(self.bulk_in_num)?;
self.clear_stall_in()?;
}
PortTransferStatus::Unknown => return Err(ProtocolError::XhciError(XhciClientHandleError::InvalidResponse(Invalid("unknown transfer status")))),
};
@@ -173,27 +172,29 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
}
DeviceReqData::Out(ref buffer) => todo!(),
DeviceReqData::NoData => todo!(),
};
}
let mut csw = CommandStatusWrapper::default();
let mut csw_buffer = [0u8; 13];
match self.bulk_in.transfer_read(unsafe { plain::as_mut_bytes(&mut csw) })? {
match self.bulk_in.transfer_read(&mut csw_buffer)? {
PortTransferStatus::ShortPacket(13) => (),
PortTransferStatus::Stalled => {
println!("bulk in endpoint stalled when reading CSW");
self.clear_stall(self.bulk_in_num)?;
self.clear_stall_in()?;
}
_ => panic!("invalid number of CSW bytes read; expected a short packet of length 13 (0xD)"),
};
println!("{}", base64::encode(&csw_buffer));
let csw = plain::from_bytes::<CommandStatusWrapper>(&csw_buffer).unwrap();
if !csw.is_valid() {
self.reset_recovery()?;
}
dbg!(csw);
if self.bulk_in_status.current_status()? == EndpointStatus::Halted || self.bulk_out_status.current_status()? == EndpointStatus::Halted {
if self.bulk_in.status()? == EndpointStatus::Halted || self.bulk_out.status()? == EndpointStatus::Halted {
println!("Trying to recover from stall");
dbg!(self.bulk_in_status.current_status()?, self.bulk_out_status.current_status()?);
dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
}
Ok(())
@@ -204,7 +205,7 @@ pub fn bulk_only_mass_storage_reset(handle: &XhciClientHandle, if_num: u16) -> R
handle.device_request(PortReqTy::Class, PortReqRecipient::Interface, 0xFF, 0, if_num, DeviceReqData::NoData)
}
pub fn get_max_lun(handle: &XhciClientHandle, if_num: u16) -> Result<u8, XhciClientHandleError> {
let mut lun = 0;
let mut lun = 0u8;
let buffer = slice::from_mut(&mut lun);
handle.device_request(PortReqTy::Class, PortReqRecipient::Interface, 0xFE, 0, if_num, DeviceReqData::In(buffer))?;
Ok(lun)
+6
View File
@@ -13,6 +13,8 @@ pub struct ReportIdentInfo {
pub info_ty: u8,
pub control: u8,
}
unsafe impl plain::Plain for ReportIdentInfo {}
impl ReportIdentInfo {
pub fn new(alloc_len: u32, info_ty: ReportIdInfoInfoTy, control: u8) -> Self {
Self {
@@ -52,6 +54,8 @@ pub struct ReportSuppOpcodes {
pub _rsvd: u8,
pub control: u8,
}
unsafe impl plain::Plain for ReportSuppOpcodes {}
impl ReportSuppOpcodes {
pub const fn new(rep_opts: ReportSuppOpcodesOptions, rctd: bool, req_opcode: u8, req_serviceaction: u16, alloc_len: u32, control: u8) -> Self {
Self {
@@ -115,6 +119,7 @@ pub struct CommandDescriptor {
/// little endian
pub cdb_len: u16,
}
#[repr(packed)]
pub struct OneCommandParam {
pub _rsvd: u8,
@@ -133,6 +138,7 @@ pub struct Inquiry {
pub alloc_len: u16,
pub control: u8,
}
unsafe impl plain::Plain for Inquiry {}
impl Inquiry {
pub fn new(evpd: bool, page_code: u8, alloc_len: u16, control: u8) -> Self {