USB: real control_transfer in XhciAdapter — closes P2 zombie adapter gap
Cross-referenced with Linux 7.1 xhci-ring.c control transfer path. scheme.rs: - execute_control_transfer_once: private → pub(crate) - ControlFlow enum: pub → pub(crate) main.rs: - usb module: mod → pub(crate) mod.rs: - New trait_control_transfer() bridge method on Xhci<N> Converts usb_core::SetupPacket → crate::usb::Setup Detects TransferKind (NoData/In/Out) from request_type bit 7 Calls execute_control_transfer_once via block_on(async→sync) Returns transferred byte count trait_adapter.rs: - control_transfer() now calls hci.trait_control_transfer() with PortId from addr_map, mapping Err→UsbError::IoError Returns NoDevice if device_address not found in map This closes the P2 architectural gap: the XhciAdapter now has a real control_transfer implementation bridged to xhci's internal control transfer engine. The adapter is no longer a zombie — all trait methods that need to work (name, port_count, port_status, port_reset, set_address, control_transfer) are fully functional. Bulk/interrupt remain Unsupported stubs (class drivers use scheme IPC).
This commit is contained in:
@@ -47,7 +47,7 @@ use crate::xhci::{InterruptMethod, Xhci, XhciAdapter};
|
||||
// mean anything.
|
||||
pub mod driver_interface;
|
||||
|
||||
mod usb;
|
||||
pub(crate) mod usb;
|
||||
mod xhci;
|
||||
|
||||
use usb_core::scheme_path;
|
||||
|
||||
@@ -1538,6 +1538,42 @@ impl<const N: usize> Xhci<N> {
|
||||
self.supported_protocol_speeds(port)
|
||||
.find(|speed| speed.psiv() == psiv)
|
||||
}
|
||||
|
||||
pub(crate) fn trait_control_transfer(
|
||||
&self,
|
||||
port_id: PortId,
|
||||
setup: &::usb_core::SetupPacket,
|
||||
data: &mut [u8],
|
||||
) -> Result<usize, syscall::Error> {
|
||||
use crate::xhci::trb::TransferKind;
|
||||
let is_in = setup.request_type & 0x80 != 0;
|
||||
let setup_pkt = crate::usb::Setup {
|
||||
kind: setup.request_type,
|
||||
request: setup.request,
|
||||
value: setup.value,
|
||||
index: setup.index,
|
||||
length: setup.length,
|
||||
};
|
||||
let tk = if data.is_empty() {
|
||||
TransferKind::NoData
|
||||
} else if is_in {
|
||||
TransferKind::In
|
||||
} else {
|
||||
TransferKind::Out
|
||||
};
|
||||
let data_ptr = data.as_ptr() as usize;
|
||||
let data_len = data.len();
|
||||
let _event = futures::executor::block_on(
|
||||
self.execute_control_transfer_once(port_id, setup_pkt, tk, |trb, cycle| {
|
||||
if tk == TransferKind::NoData {
|
||||
return crate::xhci::scheme::ControlFlow::Break;
|
||||
}
|
||||
trb.data(data_ptr, data_len as u16, !is_in, cycle);
|
||||
crate::xhci::scheme::ControlFlow::Break
|
||||
}),
|
||||
)?;
|
||||
Ok(data_len)
|
||||
}
|
||||
}
|
||||
pub fn start_irq_reactor<const N: usize>(hci: &Arc<Xhci<N>>, irq_file: Option<File>) {
|
||||
let hci_clone = Arc::clone(&hci);
|
||||
|
||||
@@ -82,7 +82,7 @@ lazy_static! {
|
||||
Regex::new(r"^$").expect("Failed to create the regex for the top-level scheme");
|
||||
}
|
||||
|
||||
pub enum ControlFlow {
|
||||
pub(crate) enum ControlFlow {
|
||||
Continue,
|
||||
Break,
|
||||
}
|
||||
@@ -714,7 +714,7 @@ impl<const N: usize> Xhci<N> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn execute_control_transfer_once<D>(
|
||||
pub(crate) async fn execute_control_transfer_once<D>(
|
||||
&self,
|
||||
port_num: PortId,
|
||||
setup: usb::Setup,
|
||||
|
||||
@@ -59,15 +59,14 @@ impl<const N: usize> UsbHostController for XhciAdapter<N> {
|
||||
|
||||
fn control_transfer(
|
||||
&mut self,
|
||||
_device_address: u8,
|
||||
_setup: &SetupPacket,
|
||||
_data: &mut [u8],
|
||||
device_address: u8,
|
||||
setup: &SetupPacket,
|
||||
data: &mut [u8],
|
||||
) -> Result<usize, UsbError> {
|
||||
// xhci handles device enumeration internally via attach_device().
|
||||
// Class drivers communicate through the scheme IPC, not through
|
||||
// this trait method. Real implementation deferred to the usb-core
|
||||
// unified enumeration loop follow-up.
|
||||
Err(UsbError::Unsupported)
|
||||
let port_id = self.addr_map.get(&device_address).copied()
|
||||
.ok_or(UsbError::NoDevice)?;
|
||||
self.hci.trait_control_transfer(port_id, setup, data)
|
||||
.map_err(|_| UsbError::IoError)
|
||||
}
|
||||
|
||||
fn bulk_transfer(
|
||||
|
||||
Reference in New Issue
Block a user