xhci: workaround packet size and protocol speed issues on real hardware
This commit is contained in:
+15
-9
@@ -604,12 +604,14 @@ impl Xhci {
|
||||
b |= (new_max_packet_size) << 16;
|
||||
endp_ctx.b.write(b);
|
||||
|
||||
/*TODO: this causes issues on real hardware, maybe it should only be used on USB 2?
|
||||
let (event_trb, command_trb) = self.execute_command(|trb, cycle| {
|
||||
trb.evaluate_context(slot_id, input_context.physical(), false, cycle)
|
||||
}).await;
|
||||
|
||||
self::scheme::handle_event_trb("EVALUATE_CONTEXT", &event_trb, &command_trb)?;
|
||||
self.event_handler_finished();
|
||||
*/
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -838,7 +840,7 @@ impl Xhci {
|
||||
pub fn supported_protocol_speeds(
|
||||
&self,
|
||||
port: u8,
|
||||
) -> Option<impl Iterator<Item = &'static ProtocolSpeed>> {
|
||||
) -> impl Iterator<Item = &'static ProtocolSpeed> {
|
||||
use extended::*;
|
||||
const DEFAULT_SUPP_PROTO_SPEEDS: [ProtocolSpeed; 7] = [
|
||||
// Full-speed
|
||||
@@ -903,16 +905,20 @@ impl Xhci {
|
||||
),
|
||||
];
|
||||
|
||||
let supp_proto = self.supported_protocol(port)?;
|
||||
|
||||
Some(if supp_proto.psic() != 0 {
|
||||
unsafe { supp_proto.protocol_speeds().iter() }
|
||||
} else {
|
||||
DEFAULT_SUPP_PROTO_SPEEDS.iter()
|
||||
})
|
||||
match self.supported_protocol(port) {
|
||||
Some(supp_proto) => if supp_proto.psic() != 0 {
|
||||
unsafe { supp_proto.protocol_speeds().iter() }
|
||||
} else {
|
||||
DEFAULT_SUPP_PROTO_SPEEDS.iter()
|
||||
},
|
||||
None => {
|
||||
log::warn!("falling back to default supported protocol speeds for port {}", port);
|
||||
DEFAULT_SUPP_PROTO_SPEEDS.iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn lookup_psiv(&self, port: u8, psiv: u8) -> Option<&'static ProtocolSpeed> {
|
||||
self.supported_protocol_speeds(port)?
|
||||
self.supported_protocol_speeds(port)
|
||||
.find(|speed| speed.psiv() == psiv)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,6 +626,7 @@ impl Xhci {
|
||||
let endpoints = &config_desc.interface_descs.get(usize::from(req.interface_desc.unwrap_or(0))).ok_or(Error::new(EBADFD))?.endpoints;
|
||||
|
||||
if endpoints.len() >= 31 {
|
||||
warn!("endpoints length {} >= 31", endpoints.len());
|
||||
return Err(Error::new(EIO));
|
||||
}
|
||||
|
||||
@@ -644,7 +645,10 @@ impl Xhci {
|
||||
let port_speed_id = self.ports.lock().unwrap()[port].speed();
|
||||
let speed_id: &ProtocolSpeed = self
|
||||
.lookup_psiv(port as u8, port_speed_id)
|
||||
.ok_or(Error::new(EIO))?;
|
||||
.ok_or_else(|| {
|
||||
warn!("no speed_id");
|
||||
Error::new(EIO)
|
||||
})?;
|
||||
|
||||
{
|
||||
let port_state = self.port_states.get(&port).ok_or(Error::new(EBADFD))?;
|
||||
@@ -677,7 +681,10 @@ impl Xhci {
|
||||
let mut port_state = self.port_states.get_mut(&port).ok_or(Error::new(EBADFD))?;
|
||||
let dev_desc = port_state.dev_desc.as_ref().unwrap();
|
||||
let endpoints = &dev_desc.config_descs.get(usize::from(req.config_desc)).ok_or(Error::new(EBADFD))?.interface_descs.get(usize::from(req.interface_desc.unwrap_or(0))).ok_or(Error::new(EBADFD))?.endpoints;
|
||||
let endp_desc = endpoints.get(endp_idx as usize).ok_or(Error::new(EIO))?;
|
||||
let endp_desc = endpoints.get(endp_idx as usize).ok_or_else(|| {
|
||||
warn!("failed to find endpoint {}", endp_idx);
|
||||
Error::new(EIO)
|
||||
})?;
|
||||
|
||||
let endp_num_xhc = Self::endp_num_to_dci(endp_num, endp_desc);
|
||||
|
||||
@@ -724,7 +731,10 @@ impl Xhci {
|
||||
// driver probably knows better. The spec says that the initial value should be 8 bytes
|
||||
// for control, 1KiB for interrupt and 3KiB for bulk and isoch.
|
||||
let avg_trb_len: u16 = match endp_desc.ty() {
|
||||
EndpointTy::Ctrl => return Err(Error::new(EIO)), // only endpoint zero is of type control, and is configured separately with the address device command.
|
||||
EndpointTy::Ctrl => {
|
||||
warn!("trying to use control endpoint");
|
||||
return Err(Error::new(EIO)); // only endpoint zero is of type control, and is configured separately with the address device command.
|
||||
}
|
||||
EndpointTy::Bulk | EndpointTy::Isoch => 3072, // 3 KiB
|
||||
EndpointTy::Interrupt => 1024, // 1 KiB
|
||||
};
|
||||
@@ -778,7 +788,10 @@ impl Xhci {
|
||||
let mut input_context = port_state.input_context.lock().unwrap();
|
||||
input_context.add_context.writef(1 << endp_num_xhc, true);
|
||||
|
||||
let endp_ctx = input_context.device.endpoints.get_mut(endp_num_xhc as usize - 1).ok_or(Error::new(EIO))?;
|
||||
let endp_ctx = input_context.device.endpoints.get_mut(endp_num_xhc as usize - 1).ok_or_else(|| {
|
||||
warn!("failed to find endpoint {}", endp_num_xhc - 1);
|
||||
Error::new(EIO)
|
||||
})?;
|
||||
|
||||
endp_ctx.a.write(
|
||||
u32::from(mult) << 8
|
||||
|
||||
Reference in New Issue
Block a user