milestone: desktop path Phases 1-5

Phase 1 (Runtime Substrate): 4 check binaries, --probe, POSIX tests
Phase 2 (Wayland Compositor): bounded scaffold, zero warnings
Phase 3 (KWin Session): preflight checker (KWin stub, gated on Qt6Quick)
Phase 4 (KDE Plasma): 18 KF6 enabled, preflight checker
Phase 5 (Hardware GPU): DRM/firmware/Mesa preflight checker

Build: zero warnings, all scripts syntax-clean. Oracle-verified.
This commit is contained in:
2026-04-29 09:54:06 +01:00
parent b23714f542
commit 8acc73d774
508 changed files with 76526 additions and 396 deletions
@@ -0,0 +1 @@
/target
@@ -0,0 +1,18 @@
[package]
name = "usbhubd"
description = "USB Hub driver"
version = "0.1.0"
edition = "2018"
license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log.workspace = true
redox_syscall.workspace = true
xhcid = { path = "../xhcid" }
common = { path = "../../common" }
[lints]
workspace = true
@@ -0,0 +1,249 @@
use std::{env, thread, time};
use xhcid_interface::{
plain, usb, ConfigureEndpointsReq, DevDesc, DeviceReqData, PortId, PortReqRecipient, PortReqTy,
XhciClientHandle,
};
fn main() {
common::init();
let mut args = env::args().skip(1);
const USAGE: &'static str = "usbhubd <scheme> <port> <interface>";
let scheme = args.next().expect(USAGE);
let port_id = args
.next()
.expect(USAGE)
.parse::<PortId>()
.expect("Expected port ID");
let interface_num = args
.next()
.expect(USAGE)
.parse::<u8>()
.expect("Expected integer as input of interface");
log::info!(
"USB HUB driver spawned with scheme `{}`, port {}, interface {}",
scheme,
port_id,
interface_num
);
let name = format!("{}_{}_{}_hub", scheme, port_id, interface_num);
common::setup_logging(
"usb",
"device",
&name,
common::output_level(),
common::file_level(),
);
let handle =
XhciClientHandle::new(scheme.clone(), port_id).expect("Failed to open XhciClientHandle");
let desc: DevDesc = handle
.get_standard_descs()
.expect("Failed to get standard descriptors");
let (conf_desc, if_desc) = desc
.config_descs
.iter()
.find_map(|conf_desc| {
let if_desc = conf_desc.interface_descs.iter().find_map(|if_desc| {
if if_desc.number == interface_num {
Some(if_desc.clone())
} else {
None
}
})?;
Some((conf_desc.clone(), if_desc))
})
.expect("Failed to find suitable configuration");
// Read hub descriptor
let (ports, usb_3) = if desc.major_version() >= 3 {
// USB 3.0 hubs
let mut hub_desc = usb::HubDescriptorV3::default();
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Device,
usb::SetupReq::GetDescriptor as u8,
u16::from(usb::HubDescriptorV3::DESCRIPTOR_KIND) << 8,
0,
DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut hub_desc) }),
)
.expect("Failed to read hub descriptor");
(hub_desc.ports, true)
} else {
// USB 2.0 and earlier hubs
let mut hub_desc = usb::HubDescriptorV2::default();
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Device,
usb::SetupReq::GetDescriptor as u8,
u16::from(usb::HubDescriptorV2::DESCRIPTOR_KIND) << 8,
0,
DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut hub_desc) }),
)
.expect("Failed to read hub descriptor");
(hub_desc.ports, false)
};
// Configure as hub device
handle
.configure_endpoints(&ConfigureEndpointsReq {
config_desc: conf_desc.configuration_value,
interface_desc: None, //TODO: stalls on USB 3 hub: Some(interface_num),
alternate_setting: None, //TODO: stalls on USB 3 hub: Some(if_desc.alternate_setting),
hub_ports: Some(ports),
})
.expect("Failed to configure endpoints after reading hub descriptor");
if usb_3 {
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Device,
0x0c, // SET_HUB_DEPTH
port_id.hub_depth().into(),
0,
DeviceReqData::NoData,
)
.expect("Failed to set hub depth");
}
// Initialize states
struct PortState {
port_id: PortId,
port_sts: usb::HubPortStatus,
handle: XhciClientHandle,
attached: bool,
}
impl PortState {
pub fn ensure_attached(&mut self, attached: bool) {
if attached == self.attached {
return;
}
if attached {
self.handle.attach().expect("Failed to attach");
} else {
self.handle.detach().expect("Failed to detach");
}
self.attached = attached;
}
}
let mut states = Vec::new();
for port in 1..=ports {
let child_port_id = port_id.child(port).expect("Cannot get child port ID");
states.push(PortState {
port_id: child_port_id,
port_sts: if usb_3 {
usb::HubPortStatus::V3(usb::HubPortStatusV3::default())
} else {
usb::HubPortStatus::V2(usb::HubPortStatusV2::default())
},
handle: XhciClientHandle::new(scheme.clone(), child_port_id)
.expect("Failed to open XhciClientHandle"),
attached: false,
});
}
//TODO: use change flags?
loop {
for port in 1..=ports {
let port_idx: usize = port.checked_sub(1).unwrap().into();
let state = states.get_mut(port_idx).unwrap();
let port_sts = if usb_3 {
let mut port_sts = usb::HubPortStatusV3::default();
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::GetStatus as u8,
0,
port as u16,
DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut port_sts) }),
)
.expect("Failed to retrieve port status");
usb::HubPortStatus::V3(port_sts)
} else {
let mut port_sts = usb::HubPortStatusV2::default();
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::GetStatus as u8,
0,
port as u16,
DeviceReqData::In(unsafe { plain::as_mut_bytes(&mut port_sts) }),
)
.expect("Failed to retrieve port status");
usb::HubPortStatus::V2(port_sts)
};
if state.port_sts != port_sts {
state.port_sts = port_sts;
log::info!("port {} status {:X?}", port, port_sts);
}
// Ensure port is powered on
if !port_sts.is_powered() {
log::info!("power on port {port}");
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::SetFeature as u8,
usb::HubPortFeature::PortPower as u16,
port as u16,
DeviceReqData::NoData,
)
.expect("Failed to set port power");
state.ensure_attached(false);
continue;
}
// Ignore disconnected port
if !port_sts.is_connected() {
state.ensure_attached(false);
continue;
}
// Ignore port in reset
if port_sts.is_resetting() {
state.ensure_attached(false);
continue;
}
// Ensure port is enabled
if !port_sts.is_enabled() {
log::info!("reset port {port}");
handle
.device_request(
PortReqTy::Class,
PortReqRecipient::Other,
usb::SetupReq::SetFeature as u8,
usb::HubPortFeature::PortReset as u16,
port as u16,
DeviceReqData::NoData,
)
.expect("Failed to set port enable");
state.ensure_attached(false);
continue;
}
state.ensure_attached(true);
}
//TODO: use interrupts or poll faster?
thread::sleep(time::Duration::new(1, 0));
}
//TODO: read interrupt port for changes
}