Skip to content

Commit 2790909

Browse files
committed
Remove Hidapi::new_without_enumerate().
The issue with HidApi::new_without_enumerate() is that it makes both it and HidApi::new() potentially panic, with no way out in library contexts. Instead, on platforms that need it, the same effect can be achieved by calling HidApi::disable_device_discovery() before any HidApi contexts are created.
1 parent 2f37587 commit 2790909

File tree

1 file changed

+42
-60
lines changed

1 file changed

+42
-60
lines changed

src/lib.rs

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -125,21 +125,53 @@ cfg_if! {
125125
pub type HidResult<T> = Result<T, HidError>;
126126
pub const MAX_REPORT_DESCRIPTOR_SIZE: usize = 4096;
127127

128-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129128
enum InitState {
130-
NotInit,
131-
Init { enumerate: bool },
129+
Uninit { device_discovery: bool },
130+
Init,
132131
}
133132

134-
static INIT_STATE: Mutex<InitState> = Mutex::new(InitState::NotInit);
133+
static INIT_STATE: Mutex<InitState> = Mutex::new(InitState::Uninit {
134+
device_discovery: true,
135+
});
135136

136-
fn lazy_init(do_enumerate: bool) -> HidResult<()> {
137-
let mut init_state = INIT_STATE.lock().unwrap();
137+
/// `hidapi` context.
138+
///
139+
/// The `hidapi` C library is lazily initialized when creating the first instance,
140+
/// and never deinitialized. Therefore, it is allowed to create multiple `HidApi`
141+
/// instances.
142+
///
143+
/// Each instance has its own device list cache.
144+
pub struct HidApi {
145+
device_list: Vec<DeviceInfo>,
146+
}
147+
148+
impl HidApi {
149+
/// Disable device discovery.
150+
///
151+
/// This is needed on Android, where access to USB device enumeration is limited.
152+
///
153+
/// # Panics
154+
///
155+
/// Panics if an hidapi context has already been initialized.
156+
pub fn disable_device_discovery() {
157+
if let InitState::Uninit { device_discovery } = &mut *INIT_STATE.lock().unwrap() {
158+
*device_discovery = false;
159+
return;
160+
}
161+
162+
panic!("Cannot disable device discovery after HidApi has been initialized")
163+
}
138164

139-
match *init_state {
140-
InitState::NotInit => {
165+
/// Create a new hidapi context.
166+
///
167+
/// Will also initialize the currently available device list.
168+
pub fn new() -> HidResult<Self> {
169+
let mut init_state = INIT_STATE.lock().expect("HidApi context initialization");
170+
171+
#[allow(unused_variables)]
172+
if let InitState::Uninit { device_discovery } = *init_state {
141173
#[cfg(all(libusb, not(target_os = "freebsd")))]
142-
if !do_enumerate {
174+
if !device_discovery {
143175
// Do not scan for devices in libusb_init()
144176
// Must be set before calling it.
145177
// This is needed on Android, where access to USB devices is limited
@@ -157,42 +189,8 @@ fn lazy_init(do_enumerate: bool) -> HidResult<()> {
157189
ffi::macos::hid_darwin_set_open_exclusive(0)
158190
}
159191

160-
*init_state = InitState::Init {
161-
enumerate: do_enumerate,
162-
}
192+
*init_state = InitState::Init;
163193
}
164-
InitState::Init { enumerate } => {
165-
if enumerate != do_enumerate {
166-
panic!("Trying to initialize hidapi with enumeration={}, but it is already initialized with enumeration={}.", do_enumerate, enumerate)
167-
}
168-
}
169-
}
170-
171-
Ok(())
172-
}
173-
174-
/// `hidapi` context.
175-
///
176-
/// The `hidapi` C library is lazily initialized when creating the first instance,
177-
/// and never deinitialized. Therefore, it is allowed to create multiple `HidApi`
178-
/// instances.
179-
///
180-
/// Each instance has its own device list cache.
181-
pub struct HidApi {
182-
device_list: Vec<DeviceInfo>,
183-
}
184-
185-
impl HidApi {
186-
/// Create a new hidapi context.
187-
///
188-
/// Will also initialize the currently available device list.
189-
///
190-
/// # Panics
191-
///
192-
/// Panics if hidapi is already initialized in "without enumerate" mode
193-
/// (i.e. if `new_without_enumerate()` has been called before).
194-
pub fn new() -> HidResult<Self> {
195-
lazy_init(true)?;
196194

197195
let mut api = HidApi {
198196
device_list: Vec::with_capacity(8),
@@ -201,22 +199,6 @@ impl HidApi {
201199
Ok(api)
202200
}
203201

204-
/// Create a new hidapi context, in "do not enumerate" mode.
205-
///
206-
/// This is needed on Android, where access to USB device enumeration is limited.
207-
///
208-
/// # Panics
209-
///
210-
/// Panics if hidapi is already initialized in "do enumerate" mode
211-
/// (i.e. if `new()` has been called before).
212-
pub fn new_without_enumerate() -> HidResult<Self> {
213-
lazy_init(false)?;
214-
215-
Ok(HidApi {
216-
device_list: Vec::new(),
217-
})
218-
}
219-
220202
/// Refresh devices list and information about them (to access them use
221203
/// `device_list()` method)
222204
/// Identical to `reset_devices()` followed by `add_devices(0, 0)`.

0 commit comments

Comments
 (0)