From 864bde01f6c0a7f8e9db2f6939b6b8c36a16550a Mon Sep 17 00:00:00 2001 From: LIAUD Corentin Date: Wed, 30 Apr 2025 14:24:10 +0200 Subject: [PATCH] feat: add zero-length packet if final_packet_size % endpoint_max_packet_size == 0 --- adb_client/src/transports/usb_transport.rs | 105 ++++++++++----------- 1 file changed, 51 insertions(+), 54 deletions(-) diff --git a/adb_client/src/transports/usb_transport.rs b/adb_client/src/transports/usb_transport.rs index da84732..95d4c8b 100644 --- a/adb_client/src/transports/usb_transport.rs +++ b/adb_client/src/transports/usb_transport.rs @@ -15,6 +15,7 @@ use crate::{ struct Endpoint { iface: u8, address: u8, + max_packet_size: usize, } /// Transport running on USB @@ -111,6 +112,7 @@ impl USBTransport { let endpoint = Endpoint { iface: interface_desc.interface_number(), address: endpoint_desc.address(), + max_packet_size: endpoint_desc.max_packet_size() as usize, }; match endpoint_desc.direction() { Direction::In => { @@ -136,6 +138,34 @@ impl USBTransport { Err(RustADBError::USBNoDescriptorFound) } + + fn write_bulk_data(&self, data: &[u8], timeout: Duration) -> Result<()> { + let endpoint = self.get_write_endpoint()?; + let handle = self.get_raw_connection()?; + let max_packet_size = endpoint.max_packet_size; + + let mut offset = 0; + let data_len = data.len(); + while offset < data_len { + let end = (offset + max_packet_size).min(data_len); + let write_amount = handle.write_bulk(endpoint.address, &data[offset..end], timeout)?; + offset += write_amount; + + log::trace!( + "wrote chunk of size {} - {}/{}", + write_amount, + offset, + data_len + ) + } + + if offset % max_packet_size == 0 { + log::trace!("must send final zero-length packet"); + handle.write_bulk(endpoint.address, &[], timeout)?; + } + + Ok(()) + } } impl ADBTransport for USBTransport { @@ -145,9 +175,11 @@ impl ADBTransport for USBTransport { let (read_endpoint, write_endpoint) = self.find_endpoints(&device)?; Self::configure_endpoint(&device, &read_endpoint)?; + log::debug!("got read endpoint: {:?}", read_endpoint); self.read_endpoint = Some(read_endpoint); Self::configure_endpoint(&device, &write_endpoint)?; + log::debug!("got write endpoint: {:?}", write_endpoint); self.write_endpoint = Some(write_endpoint); self.handle = Some(Arc::new(device)); @@ -165,10 +197,10 @@ impl Drop for USBTransport { fn drop(&mut self) { if let Some(handle) = &self.handle { let endpoint = self.read_endpoint.as_ref().or(self.write_endpoint.as_ref()); - if let Some(endpoint) = &endpoint { - if let Err(e) = handle.release_interface(endpoint.iface) { - log::error!("error while release interface: {e}"); + match handle.release_interface(endpoint.iface) { + Ok(_) => log::debug!("succesfully released interface"), + Err(e) => log::error!("error while release interface: {e}"), } } } @@ -181,41 +213,15 @@ impl ADBMessageTransport for USBTransport { message: ADBTransportMessage, timeout: Duration, ) -> Result<()> { - let endpoint = self.get_write_endpoint()?; - let handle = self.get_raw_connection()?; - let message_bytes = message.header().as_bytes()?; - let mut total_written = 0; - loop { - total_written += - handle.write_bulk(endpoint.address, &message_bytes[total_written..], timeout)?; - if total_written == message_bytes.len() { - break; - } - } + self.write_bulk_data(&message_bytes, timeout)?; - log::trace!( - "Wrote header: {} bytes over {}", - total_written, - message_bytes.len() - ); + log::trace!("successfully write header: {} bytes", message_bytes.len()); let payload = message.into_payload(); if !payload.is_empty() { - let mut total_written = 0; - loop { - total_written += - handle.write_bulk(endpoint.address, &payload[total_written..], timeout)?; - if total_written == payload.len() { - break; - } - } - - log::trace!( - "Wrote payload: {} bytes over {}", - total_written, - payload.len() - ); + self.write_bulk_data(&payload, timeout)?; + log::trace!("successfully write payload: {} bytes", payload.len()); } Ok(()) @@ -224,35 +230,26 @@ impl ADBMessageTransport for USBTransport { fn read_message_with_timeout(&mut self, timeout: Duration) -> Result { let endpoint = self.get_read_endpoint()?; let handle = self.get_raw_connection()?; + let max_packet_size = endpoint.max_packet_size; - let mut data = [0; 24]; - let mut total_read = 0; - - log::trace!( - "waiting for data to be readable: timeout={}s", - timeout.as_secs() - ); - - loop { - total_read += handle.read_bulk(endpoint.address, &mut data[total_read..], timeout)?; - if total_read == data.len() { - break; - } + let mut data = [0u8; 24]; + let mut offset = 0; + while offset < data.len() { + let end = (offset + max_packet_size).min(data.len()); + let chunk = &mut data[offset..end]; + offset += handle.read_bulk(endpoint.address, chunk, timeout)?; } let header = ADBTransportMessageHeader::try_from(data)?; - log::trace!("received header {header:?}"); if header.data_length() != 0 { let mut msg_data = vec![0_u8; header.data_length() as usize]; - let mut total_read = 0; - loop { - total_read += - handle.read_bulk(endpoint.address, &mut msg_data[total_read..], timeout)?; - if total_read == msg_data.capacity() { - break; - } + let mut offset = 0; + while offset < msg_data.len() { + let end = (offset + max_packet_size).min(msg_data.len()); + let chunk = &mut msg_data[offset..end]; + offset += handle.read_bulk(endpoint.address, chunk, timeout)?; } let message = ADBTransportMessage::from_header_and_payload(header, msg_data);