From 6ff633863e5fa5aa75be318de0b16af1f2eb1f34 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 4 Nov 2024 16:15:53 -0700 Subject: [PATCH] Allow usbhidd to run on multiple interfaces --- usbhidd/src/main.rs | 29 ++++++++++++++++++----------- xhcid/src/xhci/mod.rs | 3 +-- xhcid/src/xhci/scheme.rs | 40 ++++++++++++++++++++++++++++------------ 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/usbhidd/src/main.rs b/usbhidd/src/main.rs index f34b0f692d..423ab4b51b 100644 --- a/usbhidd/src/main.rs +++ b/usbhidd/src/main.rs @@ -205,19 +205,21 @@ fn main() { .expect("Failed to get standard descriptors"); log::info!("{:X?}", desc); - let (conf_desc, conf_num, (if_desc, endpoint_num_opt, hid_desc)) = + let mut endp_count = 0; + let (conf_desc, conf_num, (if_desc, endp_desc_opt, hid_desc)) = desc.config_descs .iter() .enumerate() .find_map(|(conf_num, conf_desc)| { let if_desc = conf_desc.interface_descs.iter().find_map(|if_desc| { if if_desc.number == interface_num { - let endpoint_num_opt = if_desc.endpoints.iter().enumerate().find_map( - |(endpoint_i, endpoint)| { - if endpoint.ty() == EndpointTy::Interrupt - && endpoint.direction() == EndpDirection::In + let endp_desc_opt = if_desc.endpoints.iter().find_map( + |endp_desc| { + endp_count += 1; + if endp_desc.ty() == EndpointTy::Interrupt + && endp_desc.direction() == EndpDirection::In { - Some(endpoint_i + 1) + Some((endp_count, endp_desc.clone())) } else { None } @@ -227,8 +229,9 @@ fn main() { //TODO: should we do any filtering? Some(hid_desc) })?; - Some((if_desc.clone(), endpoint_num_opt, hid_desc)) + Some((if_desc.clone(), endp_desc_opt, hid_desc)) } else { + endp_count += if_desc.endpoints.len(); None } })?; @@ -268,17 +271,21 @@ fn main() { let mut handler = ReportHandler::new(&report_desc_bytes).expect("failed to parse report descriptor"); - let mut report_buffer = vec![0u8; handler.total_byte_length]; + let report_len = match endp_desc_opt { + Some((_endp_num, endp_desc)) => endp_desc.max_packet_size as usize, + None => handler.total_byte_length as usize, + }; + let mut report_buffer = vec![0u8; report_len]; let report_ty = ReportTy::Input; let report_id = 0; let mut display = File::open("/scheme/input/producer").expect("Failed to open orbital input socket"); - let mut endpoint_opt = match endpoint_num_opt { - Some(endpoint_num) => match handle.open_endpoint(endpoint_num as u8) { + let mut endpoint_opt = match endp_desc_opt { + Some((endp_num, _endp_desc)) => match handle.open_endpoint(endp_num as u8) { Ok(ok) => Some(ok), Err(err) => { - log::warn!("failed to open endpoint {endpoint_num}: {err}"); + log::warn!("failed to open endpoint {endp_num}: {err}"); None } }, diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index 5a2d17f2be..04e2f1717d 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -970,8 +970,7 @@ impl Xhci { let drivers_usercfg: &DriversConfig = &DRIVERS_CONFIG; - //TODO: allow spawning on all interfaces (will require fixing port state) - for ifdesc in config_desc.interface_descs.iter().take(1) { + for ifdesc in config_desc.interface_descs.iter() { if let Some(driver) = drivers_usercfg.drivers.iter().find(|driver| { driver.class == ifdesc.class && driver diff --git a/xhcid/src/xhci/scheme.rs b/xhcid/src/xhci/scheme.rs index dd011c9736..4637672bc3 100644 --- a/xhcid/src/xhci/scheme.rs +++ b/xhcid/src/xhci/scheme.rs @@ -912,19 +912,8 @@ impl Xhci { ) -> Result> { self.port_states.get_mut(&port).ok_or(Error::new(EBADF)) } - async fn configure_endpoints(&self, port: usize, json_buf: &[u8]) -> Result<()> { - let mut req: ConfigureEndpointsReq = - serde_json::from_slice(json_buf).or(Err(Error::new(EBADMSG)))?; - - info!( - "Running configure endpoints command, at port {}, request: {:?}", - port, req - ); - - if req.interface_desc.is_some() != req.alternate_setting.is_some() { - return Err(Error::new(EBADMSG)); - } + async fn configure_endpoints_once(&self, port: usize, req: &ConfigureEndpointsReq) -> Result<()> { let (endp_desc_count, new_context_entries, configuration_value) = { let mut port_state = self.port_states.get_mut(&port).ok_or(Error::new(EBADFD))?; @@ -1144,6 +1133,8 @@ impl Xhci { endp_ctx .c .write(u32::from(avg_trb_len) | (u32::from(max_esit_payload_lo) << 16)); + + log::info!("INITIALIZED ENDPOINT {}", endp_num); } { @@ -1165,6 +1156,31 @@ impl Xhci { // Tell the device about this configuration. self.set_configuration(port, configuration_value).await?; + Ok(()) + } + + async fn configure_endpoints(&self, port: usize, json_buf: &[u8]) -> Result<()> { + let mut req: ConfigureEndpointsReq = + serde_json::from_slice(json_buf).or(Err(Error::new(EBADMSG)))?; + + info!( + "Running configure endpoints command, at port {}, request: {:?}", + port, req + ); + + if req.interface_desc.is_some() != req.alternate_setting.is_some() { + return Err(Error::new(EBADMSG)); + } + + let already_configured = { + let port_state = self.port_states.get(&port).ok_or(Error::new(EBADFD))?; + port_state.cfg_idx == Some(req.config_desc) + }; + + if ! already_configured { + self.configure_endpoints_once(port, &req).await?; + } + if let Some(interface_num) = req.interface_desc { if let Some(alternate_setting) = req.alternate_setting { self.set_interface(port, interface_num, alternate_setting)