Fix get_mode_sense10 and some bbb error handling.

This commit is contained in:
4lDO2
2020-02-16 21:27:41 +01:00
parent 3c9527206f
commit fab13d6404
6 changed files with 121 additions and 80 deletions
+84 -57
View File
@@ -3,7 +3,7 @@ use std::slice;
use xhcid_interface::{
ConfDesc, DeviceReqData, EndpBinaryDirection, EndpDirection, EndpointStatus, IfDesc, Invalid,
PortReqRecipient, PortReqTy, PortTransferStatus, XhciClientHandle, XhciClientHandleError,
PortReqRecipient, PortReqTy, PortTransferStatus, PortTransferStatusKind, XhciClientHandle, XhciClientHandleError,
XhciEndpHandle,
};
@@ -129,20 +129,26 @@ impl<'a> BulkOnlyTransport<'a> {
})
}
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,
)
if self.bulk_in.status()? == EndpointStatus::Halted {
self.bulk_in.reset(false)?;
self.handle.clear_feature(
PortReqRecipient::Endpoint,
u16::from(self.bulk_in_num),
FEATURE_ENDPOINT_HALT,
)?;
}
Ok(())
}
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,
)
if self.bulk_out.status()? == EndpointStatus::Halted {
self.bulk_out.reset(false)?;
self.handle.clear_feature(
PortReqRecipient::Endpoint,
u16::from(self.bulk_out_num),
FEATURE_ENDPOINT_HALT,
)?;
}
Ok(())
}
fn reset_recovery(&mut self) -> Result<(), ProtocolError> {
bulk_only_mass_storage_reset(self.handle, self.interface_num.into())?;
@@ -156,6 +162,26 @@ impl<'a> BulkOnlyTransport<'a> {
}
Ok(())
}
fn read_csw_raw(&mut self, csw_buffer: &mut [u8; 13], already: bool) -> Result<(), ProtocolError> {
match self.bulk_in.transfer_read(&mut csw_buffer[..])? {
PortTransferStatus { kind: PortTransferStatusKind::Stalled, .. } => {
if already {
self.reset_recovery()?;
}
println!("bulk in endpoint stalled when reading CSW");
self.clear_stall_in()?;
self.read_csw_raw(csw_buffer, true)?;
}
PortTransferStatus { kind: PortTransferStatusKind::ShortPacket, bytes_transferred } if bytes_transferred != 13 => {
panic!("received a short packet when reading CSW ({} != 13)", bytes_transferred)
}
_ => (),
}
Ok(())
}
fn read_csw(&mut self, csw_buffer: &mut [u8; 13]) -> Result<(), ProtocolError> {
self.read_csw_raw(csw_buffer, false)
}
}
impl<'a> Protocol for BulkOnlyTransport<'a> {
@@ -172,77 +198,78 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
*cbw = CommandBlockWrapper::new(tag, data.len() as u32, data.direction().into(), 0, cb)?;
let cbw = *cbw;
// TODO: Is this needed?
bulk_only_mass_storage_reset(&self.handle, self.interface_num.into())?;
match self.bulk_out.transfer_write(&cbw_bytes)? {
PortTransferStatus::Stalled => {
PortTransferStatus { kind: PortTransferStatusKind::Stalled, .. } => {
// TODO: Error handling
panic!("bulk out endpoint stalled when sending CBW {:?}", cbw);
//self.clear_stall_out()?;
//dbg!(self.bulk_in.status()?, self.bulk_out.status()?);
}
PortTransferStatus::ShortPacket(n) if n != 31 => {
//panic!("received short packet when sending CBW ({} != 31)", n);
PortTransferStatus { bytes_transferred, .. } if bytes_transferred != 31 => {
panic!("received short packet when sending CBW ({} != 31)", bytes_transferred);
}
_ => (),
}
match data {
DeviceReqData::In(buffer) => {
match self.bulk_in.transfer_read(buffer)? {
PortTransferStatus::Success => (),
PortTransferStatus::ShortPacket(len) => {
panic!("received short packed (len {}) when transferring data", len)
let early_residue: Option<NonZeroU32> = match data {
DeviceReqData::In(buffer) => match self.bulk_in.transfer_read(buffer)? {
PortTransferStatus { kind, bytes_transferred } => match kind {
PortTransferStatusKind::Success => None,
PortTransferStatusKind::ShortPacket => {
println!("received short packet (len {}) when transferring data", bytes_transferred);
NonZeroU32::new(bytes_transferred)
}
PortTransferStatus::Stalled => {
PortTransferStatusKind::Stalled => {
panic!("bulk in endpoint stalled when reading data");
//self.clear_stall_in()?;
}
PortTransferStatus::Unknown => {
PortTransferStatusKind::Unknown => {
return Err(ProtocolError::XhciError(
XhciClientHandleError::InvalidResponse(Invalid(
"unknown transfer status",
)),
))
));
}
};
}
}
DeviceReqData::Out(buffer) => match self.bulk_out.transfer_write(buffer)? {
PortTransferStatus::Success => (),
PortTransferStatus::ShortPacket(len) => {
panic!("received short packet (len {}) when transferring data", len)
}
PortTransferStatus::Stalled => {
panic!("bulk out endpoint stalled when reading data");
//self.clear_stall_out()?;
}
PortTransferStatus::Unknown => {
return Err(ProtocolError::XhciError(
XhciClientHandleError::InvalidResponse(Invalid("unknown transfer status")),
))
PortTransferStatus { kind, bytes_transferred } => match kind {
PortTransferStatusKind::Success => None,
PortTransferStatusKind::ShortPacket => {
println!("received short packet (len {}) when transferring data", bytes_transferred);
NonZeroU32::new(bytes_transferred)
}
PortTransferStatusKind::Stalled => {
panic!("bulk out endpoint stalled when reading data");
//self.clear_stall_out()?;
}
PortTransferStatusKind::Unknown => {
return Err(ProtocolError::XhciError(
XhciClientHandleError::InvalidResponse(Invalid("unknown transfer status")),
));
}
}
},
DeviceReqData::NoData => (),
}
DeviceReqData::NoData => None,
};
let mut csw_buffer = [0u8; 13];
match self.bulk_in.transfer_read(&mut csw_buffer)? {
PortTransferStatus::Stalled => {
panic!("bulk in endpoint stalled when reading CSW");
//self.clear_stall_in()?;
}
PortTransferStatus::ShortPacket(n) if n != 13 => {
panic!("received a short packet when reading CSW ({} != 13)", n)
}
_ => (),
};
self.read_csw(&mut csw_buffer)?;
let csw = plain::from_bytes::<CommandStatusWrapper>(&csw_buffer).unwrap();
let residue = early_residue.or(NonZeroU32::new(csw.data_residue));
if csw.status == CswStatus::Failed as u8 {
println!("CSW indicated failure (CSW {:?}, CBW {:?})", csw, cbw);
}
if !csw.is_valid() || csw.tag != cbw.tag {
panic!("Invald CSW {:?} (for CBW {:?})", csw, cbw);
//self.reset_recovery()?;
println!("Invald CSW {:?} (for CBW {:?})", csw, cbw);
self.reset_recovery()?;
if self.bulk_in.status()? == EndpointStatus::Halted || self.bulk_out.status()? == EndpointStatus::Halted {
return Err(ProtocolError::ProtocolError("Reset Recovery didn't reset endpoints"));
}
return Err(ProtocolError::ProtocolError("CSW invalid, but a recover was successful"));
}
/*if self.bulk_in.status()? == EndpointStatus::Halted
@@ -262,7 +289,7 @@ impl<'a> Protocol for BulkOnlyTransport<'a> {
"bulk-only transport phase error, or other",
));
},
residue: NonZeroU32::new(csw.data_residue),
residue,
})
}
}