diff --git a/improvements.md b/improvements.md index 519080d..fad14d3 100644 --- a/improvements.md +++ b/improvements.md @@ -42,7 +42,7 @@ ### 7. Missing standard control requests (simulated devices) - **File:** `lib/src/device.rs:346-778` - **Issue:** `GetStatus`, `ClearFeature`, `SetFeature`, `GetConfiguration`, `SetAddress` are unhandled for simulated devices. -- **Status:** [ ] TODO +- **Status:** [x] DONE — Added GetConfiguration, GetStatus (device/interface/endpoint), ClearFeature, SetFeature, SetAddress handlers. ### 8. ISO `actual_length` sum not validated - **File:** `lib/src/lib.rs:551-552` @@ -60,7 +60,7 @@ ### 10. `server()` panics on bind failure - **File:** `lib/src/lib.rs:773` - **Issue:** `expect("bind to addr")` panics instead of returning `Result`. -- **Status:** [ ] TODO +- **Status:** [x] DONE — Changed return type to `Result<()>`, replaced `expect` with `?`. ### 11. Error status mapping via string matching - **File:** `lib/src/lib.rs:584-592` @@ -75,4 +75,4 @@ ### 13. `debug_assert` for path/bus_id length - **File:** `lib/src/device.rs:252-260` - **Issue:** `debug_assert!` compiled out in release; silent truncation if path > 256 bytes. -- **Status:** [ ] TODO +- **Status:** [x] DONE — Replaced `debug_assert!` + `resize` with `truncate` + `resize`. diff --git a/lib/src/device.rs b/lib/src/device.rs index 6f2a661..4b77aaa 100644 --- a/lib/src/device.rs +++ b/lib/src/device.rs @@ -257,12 +257,12 @@ impl UsbDevice { let mut result = Vec::with_capacity(312); let mut path = self.path.as_bytes().to_vec(); - debug_assert!(path.len() <= 256); + path.truncate(256); path.resize(256, 0); result.extend_from_slice(path.as_slice()); let mut bus_id = self.bus_id.as_bytes().to_vec(); - debug_assert!(bus_id.len() <= 32); + bus_id.truncate(32); bus_id.resize(32, 0); result.extend_from_slice(bus_id.as_slice()); @@ -609,6 +609,25 @@ impl UsbDevice { } } } + (0b10000000, Some(GetConfiguration)) => { + debug!("Get configuration value"); + Ok(UrbResponse { data: vec![self.configuration_value], ..Default::default() }) + } + (0b10000000, Some(GetStatus)) => { + // Device recipient: self-powered=0, remote-wakeup=0 + debug!("Get status (device)"); + Ok(UrbResponse { data: vec![0x00, 0x00], ..Default::default() }) + } + (0b10000001, Some(GetStatus)) => { + // Interface recipient: reserved, always zero + debug!("Get status (interface)"); + Ok(UrbResponse { data: vec![0x00, 0x00], ..Default::default() }) + } + (0b10000010, Some(GetStatus)) => { + // Endpoint recipient: halt=0 + debug!("Get status (endpoint)"); + Ok(UrbResponse { data: vec![0x00, 0x00], ..Default::default() }) + } (0b10000001, Some(GetInterface)) => { let intf_index = setup_packet.index as usize & 0xFF; match self.interface_states.get(intf_index) { @@ -718,6 +737,21 @@ impl UsbDevice { )), } } + (0b00000010, Some(ClearFeature)) => { + // Endpoint recipient: no-op (simulated device doesn't stall) + debug!("Clear feature (endpoint)"); + Ok(UrbResponse::default()) + } + (0b00000010, Some(SetFeature)) => { + // Endpoint recipient: no-op + debug!("Set feature (endpoint)"); + Ok(UrbResponse::default()) + } + (0b00000000, Some(SetAddress)) => { + // No-op: address already assigned by bus + debug!("Set address (no-op)"); + Ok(UrbResponse::default()) + } _ if setup_packet.request_type & 0xF == 1 => { // to interface // see https://www.beyondlogic.org/usbnutshell/usb6.shtml diff --git a/lib/src/lib.rs b/lib/src/lib.rs index a374c63..4c2fd44 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -874,8 +874,8 @@ pub async fn handler( } /// Spawn a USB/IP server at `addr` using [TcpListener] -pub async fn server(addr: SocketAddr, server: Arc) { - let listener = TcpListener::bind(addr).await.expect("bind to addr"); +pub async fn server(addr: SocketAddr, server: Arc) -> Result<()> { + let listener = TcpListener::bind(addr).await?; let server = async move { loop {