Skip to content

Commit f2f8560

Browse files
committed
Fixup timeout
1 parent 731db76 commit f2f8560

2 files changed

Lines changed: 29 additions & 31 deletions

File tree

src/webusb_device.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use nusb::{descriptors::language_id::US_ENGLISH, transfer::Buffer, transfer::Bul
44
use std::time::Duration;
55

66
const ENDPOINT_NUMBER_MASK: u8 = 0x7f;
7+
const DESC_TIMEOUT: Duration = Duration::from_millis(100);
78

89
fn decode_version(version: u16) -> (u8, u8, u8) {
910
let major: u8 = (version >> 8) as u8;
@@ -63,7 +64,7 @@ pub struct UsbAlternateInterface {
6364
impl UsbAlternateInterface {
6465
pub fn new(device: &nusb::Device, iface: nusb::descriptors::InterfaceDescriptor) -> Self {
6566
let interfaceName = match iface.string_index() {
66-
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, Duration::from_millis(100)).wait().unwrap()),
67+
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, DESC_TIMEOUT).wait().unwrap()),
6768
None => None,
6869
};
6970

@@ -114,7 +115,7 @@ pub struct UsbConfiguration {
114115
impl UsbConfiguration {
115116
pub fn new(usb_device: &UsbDevice, device: &nusb::Device, config: nusb::descriptors::ConfigurationDescriptor) -> Self {
116117
let configurationName = match config.string_index() {
117-
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, Duration::from_millis(100)).wait().unwrap()),
118+
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, DESC_TIMEOUT).wait().unwrap()),
118119
None => None,
119120
};
120121

@@ -208,7 +209,7 @@ impl UsbDevice {
208209
None => self._open().unwrap(),
209210
};
210211
match device.device_descriptor().manufacturer_string_index() {
211-
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, Duration::from_millis(100)).wait().unwrap()),
212+
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, DESC_TIMEOUT).wait().unwrap()),
212213
None => None,
213214
}
214215
}
@@ -225,7 +226,7 @@ impl UsbDevice {
225226
None => self._open().unwrap(),
226227
};
227228
match device.device_descriptor().product_string_index() {
228-
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, Duration::from_millis(100)).wait().unwrap()),
229+
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, DESC_TIMEOUT).wait().unwrap()),
229230
None => None,
230231
}
231232
}
@@ -242,7 +243,7 @@ impl UsbDevice {
242243
None => self._open().unwrap(),
243244
};
244245
match device.device_descriptor().serial_number_string_index() {
245-
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, Duration::from_millis(100)).wait().unwrap()),
246+
Some(desc_index) => Some(device.get_string_descriptor(desc_index, US_ENGLISH, DESC_TIMEOUT).wait().unwrap()),
246247
None => None,
247248
}
248249
}
@@ -374,7 +375,7 @@ impl UsbDevice {
374375
}
375376

376377
#[napi(js_name = "nativeControlTransferIn")]
377-
pub async fn controlTransferIn(&self, setup: UsbControlTransferParameters, length: u16) -> Result<Option<Uint8Array>> {
378+
pub async fn controlTransferIn(&self, setup: UsbControlTransferParameters, timeout: u32, length: u16) -> Result<Option<Uint8Array>> {
378379
let control_type = match setup.requestType.as_str() {
379380
"standard" => nusb::transfer::ControlType::Standard,
380381
"class" => nusb::transfer::ControlType::Class,
@@ -400,7 +401,7 @@ impl UsbDevice {
400401
index: setup.index,
401402
length,
402403
},
403-
Duration::from_millis(100),
404+
Duration::from_millis(timeout as u64),
404405
)
405406
.wait()
406407
.map_err(|e| napi::Error::from_reason(format!("controlTransferIn error: {e}")))?;
@@ -411,7 +412,7 @@ impl UsbDevice {
411412
}
412413

413414
#[napi(js_name = "nativeControlTransferOut")]
414-
pub async fn controlTransferOut(&self, setup: UsbControlTransferParameters, data: Option<Uint8Array>) -> Result<u32> {
415+
pub async fn controlTransferOut(&self, setup: UsbControlTransferParameters, timeout: u32, data: Option<Uint8Array>) -> Result<u32> {
415416
let control_type = match setup.requestType.as_str() {
416417
"standard" => nusb::transfer::ControlType::Standard,
417418
"class" => nusb::transfer::ControlType::Class,
@@ -438,7 +439,7 @@ impl UsbDevice {
438439
index: setup.index,
439440
data: &bytes,
440441
},
441-
Duration::from_millis(100),
442+
Duration::from_millis(timeout as u64),
442443
)
443444
.wait()
444445
.map_err(|e| napi::Error::from_reason(format!("controlTransferOut error: {e}")))?;
@@ -449,13 +450,13 @@ impl UsbDevice {
449450
}
450451

451452
#[napi(js_name = "nativeTransferIn")]
452-
pub async fn transferIn(&self, endpointNumber: u8, length: u32) -> Result<Option<Uint8Array>> {
453+
pub async fn transferIn(&self, endpointNumber: u8, timeout: u32, length: u32) -> Result<Option<Uint8Array>> {
453454
match self.get_endpoint::<nusb::transfer::In>(endpointNumber) {
454455
Some(mut endpoint) => {
455456
let packet_size = endpoint.max_packet_size();
456457
let req = (((length as usize) + packet_size - 1) / packet_size) * packet_size;
457458
let buf = Buffer::new(req);
458-
let completion = endpoint.transfer_blocking(buf, Duration::from_millis(100));
459+
let completion = endpoint.transfer_blocking(buf, Duration::from_millis(timeout as u64));
459460
completion.status.map_err(|e| napi::Error::from_reason(format!("transferIn error: {e:?}")))?;
460461
let mut v = completion.buffer.into_vec();
461462
v.truncate(completion.actual_len.min(length as usize));
@@ -468,12 +469,12 @@ impl UsbDevice {
468469
}
469470

470471
#[napi(js_name = "nativeTransferOut")]
471-
pub async fn transferOut(&self, endpointNumber: u8, data: Uint8Array) -> Result<u32> {
472+
pub async fn transferOut(&self, endpointNumber: u8, timeout:u32, data: Uint8Array) -> Result<u32> {
472473
match self.get_endpoint::<nusb::transfer::Out>(endpointNumber) {
473474
Some(mut endpoint) => {
474475
let mut buf = Buffer::new(data.len());
475476
buf.extend_from_slice(&data);
476-
let completion = endpoint.transfer_blocking(buf, Duration::from_millis(100));
477+
let completion = endpoint.transfer_blocking(buf, Duration::from_millis(timeout as u64));
477478
completion.status.map_err(|e| napi::Error::from_reason(format!("transferOut error: {e:?}")))?;
478479
return Ok(completion.actual_len as u32);
479480
}

tsc/index.ts

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { nativeGetDeviceList, nativeFindByIds, nativeFindBySerialNumber, UsbDevice, Emitter } from '../index.js'
22

3+
const DEFAULT_TIMEOUT = 1000;
4+
35
/**
46
* USB Options
57
*/
@@ -23,11 +25,6 @@ interface USBOptions {
2325
* Optional timeout (in milliseconds) to use for the device control transfers
2426
*/
2527
deviceTimeout?: number;
26-
27-
/**
28-
* Optional flag to enable/disable automatic kernal driver detaching (defaults to true)
29-
*/
30-
autoDetachKernelDriver?: boolean;
3128
}
3229

3330
class NamedError extends Error {
@@ -46,7 +43,7 @@ class ConnectionEvent extends Event implements USBConnectionEvent {
4643
}
4744
}
4845

49-
const augmentDevice = (device: UsbDevice): USBDevice => {
46+
const augmentDevice = (device: UsbDevice, timeout: number): USBDevice => {
5047

5148
const toUint8Array = (data: BufferSource): Uint8Array => {
5249
if (data instanceof ArrayBuffer) {
@@ -65,7 +62,7 @@ const augmentDevice = (device: UsbDevice): USBDevice => {
6562
enumerable: false,
6663
configurable: false,
6764
value: async function (setup: USBControlTransferParameters, length: number): Promise<USBInTransferResult> {
68-
const res = await this.nativeControlTransferIn(setup, length);
65+
const res = await this.nativeControlTransferIn(setup, timeout, length);
6966
return {
7067
data: res ? new DataView(res.buffer) : undefined,
7168
status: res ? 'ok' : 'stall',
@@ -77,7 +74,7 @@ const augmentDevice = (device: UsbDevice): USBDevice => {
7774
enumerable: false,
7875
configurable: false,
7976
value: async function (setup: USBControlTransferParameters, data: BufferSource): Promise<USBOutTransferResult> {
80-
const res = await this.nativeControlTransferOut(setup, toUint8Array(data));
77+
const res = await this.nativeControlTransferOut(setup, timeout, toUint8Array(data));
8178
return {
8279
bytesWritten: res,
8380
status: res >= 0 ? 'ok' : 'stall',
@@ -89,7 +86,7 @@ const augmentDevice = (device: UsbDevice): USBDevice => {
8986
enumerable: false,
9087
configurable: false,
9188
value: async function (endpointNumber: number, length: number): Promise<USBInTransferResult> {
92-
const res = await this.nativeTransferIn(endpointNumber, length);
89+
const res = await this.nativeTransferIn(endpointNumber, timeout, length);
9390
return {
9491
data: res ? new DataView(res.buffer) : undefined,
9592
status: res ? 'ok' : 'stall',
@@ -101,7 +98,7 @@ const augmentDevice = (device: UsbDevice): USBDevice => {
10198
enumerable: false,
10299
configurable: false,
103100
value: async function (endpointNumber: number, data: BufferSource): Promise<USBOutTransferResult> {
104-
const res = await this.nativeTransferOut(endpointNumber, toUint8Array(data));
101+
const res = await this.nativeTransferOut(endpointNumber, timeout, toUint8Array(data));
105102
return {
106103
bytesWritten: res,
107104
status: res >= 0 ? 'ok' : 'stall',
@@ -145,7 +142,7 @@ class WebUSB extends EventTarget implements USB {
145142
super();
146143

147144
const deviceConnectCallback = async (nativeDevice: UsbDevice) => {
148-
const device = augmentDevice(nativeDevice);
145+
const device = augmentDevice(nativeDevice, this.options.deviceTimeout || DEFAULT_TIMEOUT);
149146
this.knownDevices.set(nativeDevice.handle, device);
150147

151148
// When connected, emit an event if it is an allowed device
@@ -168,7 +165,7 @@ class WebUSB extends EventTarget implements USB {
168165
this.nativeEmitter.start();
169166
this.nativeEmitter.addAttach(deviceConnectCallback);
170167
this.nativeEmitter.addDetach(deviceDisconnectCallback);
171-
nativeGetDeviceList().then(devices => devices.forEach(device => this.knownDevices.set(device.handle, augmentDevice(device))));
168+
nativeGetDeviceList().then(devices => devices.forEach(device => this.knownDevices.set(device.handle, augmentDevice(device, this.options.deviceTimeout || DEFAULT_TIMEOUT))));
172169
}
173170

174171
private _onconnect: ((ev: USBConnectionEvent) => void) | undefined;
@@ -389,28 +386,28 @@ class WebUSB extends EventTarget implements USB {
389386
/**
390387
* Convenience method to get an array of all connected devices.
391388
*/
392-
const getDeviceList = async (): Promise<USBDevice[]> => {
389+
const getDeviceList = async (timeout = DEFAULT_TIMEOUT): Promise<USBDevice[]> => {
393390
const devices = await nativeGetDeviceList();
394-
return devices.map(device => augmentDevice(device));
391+
return devices.map(device => augmentDevice(device, timeout));
395392
};
396393

397394
/**
398395
* Convenience method to get the first device with the specified VID and PID, or `undefined` if no such device is present.
399396
* @param vid
400397
* @param pid
401398
*/
402-
const findByIds = async (vid: number, pid: number): Promise<USBDevice | undefined> => {
399+
const findByIds = async (vid: number, pid: number, timeout = DEFAULT_TIMEOUT): Promise<USBDevice | undefined> => {
403400
const device = await nativeFindByIds(vid, pid);
404-
return device ? augmentDevice(device) : undefined;
401+
return device ? augmentDevice(device, timeout) : undefined;
405402
};
406403

407404
/**
408405
* Convenience method to get the device with the specified serial number, or `undefined` if no such device is present.
409406
* @param serialNumber
410407
*/
411-
const findBySerialNumber = async (serialNumber: string): Promise<USBDevice | undefined> => {
408+
const findBySerialNumber = async (serialNumber: string, timeout = DEFAULT_TIMEOUT): Promise<USBDevice | undefined> => {
412409
const device = await nativeFindBySerialNumber(serialNumber);
413-
return device ? augmentDevice(device) : undefined;
410+
return device ? augmentDevice(device, timeout) : undefined;
414411
};
415412

416413
const webusb = typeof navigator !== 'undefined' && navigator.usb ? navigator.usb : new WebUSB();

0 commit comments

Comments
 (0)