Skip to content

Commit 76b1d7a

Browse files
zbowlingcocool97
authored andcommitted
fix: replace rusb GlobalContext with explicit Context::new() to prevent panics
rusb's GlobalContext uses Once::call_once internally, which panics if libusb_init fails (e.g. in CI servers, containers, or environments without USB support). Replace all uses with explicit rusb::Context::new() which returns a Result instead of panicking.
1 parent 93f7722 commit 76b1d7a

2 files changed

Lines changed: 13 additions & 11 deletions

File tree

adb_client/src/message_devices/usb/usb_transport.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{sync::Arc, time::Duration};
22

33
use rusb::{
4-
Device, DeviceHandle, Direction, GlobalContext, TransferType,
4+
Context, Device, DeviceHandle, Direction, TransferType, UsbContext,
55
constants::LIBUSB_CLASS_VENDOR_SPEC,
66
};
77

@@ -25,8 +25,8 @@ struct Endpoint {
2525
/// Transport running on USB
2626
#[derive(Debug, Clone)]
2727
pub struct USBTransport {
28-
device: Device<GlobalContext>,
29-
handle: Option<Arc<DeviceHandle<GlobalContext>>>,
28+
device: Device<Context>,
29+
handle: Option<Arc<DeviceHandle<Context>>>,
3030
read_endpoint: Option<Endpoint>,
3131
write_endpoint: Option<Endpoint>,
3232
}
@@ -35,7 +35,8 @@ impl USBTransport {
3535
/// Instantiate a new [`USBTransport`].
3636
/// Only the first device with given `vendor_id` and `product_id` is returned.
3737
pub fn new(vendor_id: u16, product_id: u16) -> Result<Self> {
38-
for device in rusb::devices()?.iter() {
38+
let context = Context::new()?;
39+
for device in context.devices()?.iter() {
3940
if let Ok(descriptor) = device.device_descriptor()
4041
&& descriptor.vendor_id() == vendor_id
4142
&& descriptor.product_id() == product_id
@@ -51,9 +52,9 @@ impl USBTransport {
5152

5253
/// Instantiate a new [`USBTransport`] from a [`rusb::Device`].
5354
///
54-
/// Devices can be enumerated using [`rusb::devices()`] and then filtered out to get desired device.
55+
/// Devices can be enumerated using [`rusb::Context::devices()`] and then filtered out to get desired device.
5556
#[must_use]
56-
pub const fn new_from_device(rusb_device: rusb::Device<GlobalContext>) -> Self {
57+
pub const fn new_from_device(rusb_device: rusb::Device<Context>) -> Self {
5758
Self {
5859
device: rusb_device,
5960
handle: None,
@@ -70,7 +71,7 @@ impl USBTransport {
7071
Ok(self.device.device_descriptor().map(|d| d.product_id())?)
7172
}
7273

73-
pub(crate) fn get_raw_connection(&self) -> Result<Arc<DeviceHandle<GlobalContext>>> {
74+
pub(crate) fn get_raw_connection(&self) -> Result<Arc<DeviceHandle<Context>>> {
7475
self.handle
7576
.as_ref()
7677
.ok_or(RustADBError::IOError(std::io::Error::new(
@@ -99,7 +100,7 @@ impl USBTransport {
99100
)))
100101
}
101102

102-
fn configure_endpoint(handle: &DeviceHandle<GlobalContext>, endpoint: &Endpoint) -> Result<()> {
103+
fn configure_endpoint(handle: &DeviceHandle<Context>, endpoint: &Endpoint) -> Result<()> {
103104
match handle.claim_interface(endpoint.iface) {
104105
Ok(()) => Ok(()),
105106
// busy state likely indicates an ADB server is running and has taken the lock over the device
@@ -108,7 +109,7 @@ impl USBTransport {
108109
}
109110
}
110111

111-
fn find_endpoints(handle: &DeviceHandle<GlobalContext>) -> Result<(Endpoint, Endpoint)> {
112+
fn find_endpoints(handle: &DeviceHandle<Context>) -> Result<(Endpoint, Endpoint)> {
112113
let mut read_endpoint: Option<Endpoint> = None;
113114
let mut write_endpoint: Option<Endpoint> = None;
114115

adb_client/src/message_devices/usb/utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rusb::{Device, DeviceDescriptor, UsbContext, constants::LIBUSB_CLASS_VENDOR_SPEC};
1+
use rusb::{Context, Device, DeviceDescriptor, UsbContext, constants::LIBUSB_CLASS_VENDOR_SPEC};
22

33
use crate::{Result, RustADBError};
44

@@ -17,7 +17,8 @@ pub struct ADBDeviceInfo {
1717
pub fn find_all_connected_adb_devices() -> Result<Vec<ADBDeviceInfo>> {
1818
let mut found_devices = vec![];
1919

20-
for device in rusb::devices()?.iter() {
20+
let context = Context::new()?;
21+
for device in context.devices()?.iter() {
2122
let Ok(des) = device.device_descriptor() else {
2223
continue;
2324
};

0 commit comments

Comments
 (0)