Skip to content

Commit 43f4192

Browse files
committed
Windows: give up earlier on waiting for child device
1 parent b5a4143 commit 43f4192

File tree

3 files changed

+57
-57
lines changed

3 files changed

+57
-57
lines changed

java-does-usb/src/main/java/net/codecrete/usb/windows/WindowsUSBDevice.java

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@ public class WindowsUSBDevice extends USBDeviceImpl {
4444

4545
private static final System.Logger LOG = System.getLogger(WindowsUSBDevice.class.getName());
4646

47-
private static final int RETRY_LATER = 0;
48-
private static final int TRY_NEXT_CHILD = 1;
49-
private static final int SUCCESS = 2;
50-
5147
private final WindowsAsyncTask asyncTask;
5248
/**
5349
* Indicates if the device is a composite device
@@ -125,7 +121,7 @@ public void claimInterface(int interfaceNumber) {
125121

126122
numRetries -= 1;
127123
if (numRetries == 0)
128-
throw new USBException("claiming interface failed (function has no device path, might be missing WinUSB driver)");
124+
throw new USBException("claiming interface failed (function has no device path / interface GUID, might be missing WinUSB driver)");
129125

130126
// sleep and retry
131127
try {
@@ -534,11 +530,9 @@ private String getInterfaceDevicePath(int interfaceNumber) {
534530
LOG.log(DEBUG, "children instance IDs: {0}", childrenInstanceIDs);
535531

536532
for (var instanceId : childrenInstanceIDs) {
537-
var res = fetchChildDevicePath(instanceId, interfaceNumber);
538-
if (res == SUCCESS)
539-
return devicePaths.get(interfaceNumber);
540-
if (res == RETRY_LATER)
541-
return null; // retry later
533+
devicePath = getChildDevicePath(instanceId, interfaceNumber);
534+
if (devicePath != null)
535+
return devicePath;
542536
}
543537
}
544538
}
@@ -552,35 +546,35 @@ private String getCachedInterfaceDevicePath(int interfaceNumber) {
552546
return devicePaths.get(interfaceNumber);
553547
}
554548

555-
private int fetchChildDevicePath(String instanceId, int interfaceNumber) {
549+
private String getChildDevicePath(String instanceId, int interfaceNumber) {
556550
try (var deviceInfoSet = DeviceInfoSet.ofInstance(instanceId)) {
557551

558552
// get hardware IDs (to extract interface number)
559553
var hardwareIds = deviceInfoSet.getStringListProperty(HardwareIds);
560554
if (hardwareIds == null) {
561555
LOG.log(DEBUG, "child device {0} has no hardware IDs", instanceId);
562-
return TRY_NEXT_CHILD;
556+
return null;
563557
}
564558

565559
var extractedNumber = extractInterfaceNumber(hardwareIds);
566560
if (extractedNumber == -1) {
567561
LOG.log(DEBUG, "child device {0} has no interface number", instanceId);
568-
return TRY_NEXT_CHILD;
562+
return null;
569563
}
570564

571565
if (extractedNumber != interfaceNumber)
572-
return TRY_NEXT_CHILD;
566+
return null;
573567

574568
var devicePath = deviceInfoSet.getDevicePathByGUID(instanceId);
575569
if (devicePath == null) {
576-
LOG.log(INFO, "Child device {0} has no device path", instanceId);
577-
return RETRY_LATER;
570+
LOG.log(INFO, "Child device {0} has no device path / interface GUID", instanceId);
571+
throw new USBException("claiming interface failed (function has no device path / interface GUID, might be missing WinUSB driver)");
578572
}
579573

580574
if (devicePaths == null)
581575
devicePaths = new HashMap<>();
582576
devicePaths.put(interfaceNumber, devicePath);
583-
return SUCCESS;
577+
return devicePath;
584578
}
585579
}
586580

reference/windows/USB/usb_device.cpp

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@ void usb_device::close() {
118118
}
119119

120120
void usb_device::claim_interface(int interface_number) {
121+
// When a device is plugged in, a notification is sent. For composite devices, it is a notification
122+
// that the composite device is ready. Each composite function will be registered separately and
123+
// the related information will be available with a delay. So for composite functions, several
124+
// retries might be needed until the device path is available.
125+
int num_retries = 30; // 30 x 100ms
126+
while (true) {
127+
if (try_claim_interface(interface_number))
128+
return; // success
129+
130+
num_retries -= 1;
131+
if (num_retries == 0)
132+
throw usb_error("claiming interface failed (function has no device interface GUID/path, might be missing WinUSB driver)");
133+
134+
// sleep and retry
135+
std::cerr << "Sleeping for 100ms..." << std::endl;
136+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
137+
}
138+
}
139+
140+
bool usb_device::try_claim_interface(int interface_number) {
121141

122142
if (!is_open())
123143
throw usb_error("USB device is not open");
@@ -135,7 +155,7 @@ void usb_device::claim_interface(int interface_number) {
135155
if (first_intf_handle->device_handle == nullptr) {
136156
auto device_path = get_interface_device_path(first_intf_handle->interface_num);
137157
if (device_path.empty())
138-
throw usb_error("failed to claim interface (function has no device path, might be missing WinUSB driver)");
158+
return false;
139159

140160
std::wcerr << "opening device " << device_path << std::endl;
141161

@@ -169,6 +189,7 @@ void usb_device::claim_interface(int interface_number) {
169189

170190
first_intf_handle->device_open_count += 1;
171191
intf->set_claimed(true);
192+
return true;
172193
}
173194

174195
void usb_device::release_interface(int interface_number) {
@@ -465,72 +486,56 @@ std::wstring usb_device::get_interface_device_path(int interface_num) {
465486
if (it != interface_device_paths_.end())
466487
return it->second;
467488

468-
int num_retries = 30; // 30 x 100ms
469-
470-
while (num_retries > 0) {
471-
472-
auto dev_info_set = device_info_set::of_path(device_path_);
473-
474-
auto children_instance_ids = dev_info_set.get_device_property_string_list(DEVPKEY_Device_Children);
475-
if (children_instance_ids.empty()) {
476-
std::wcerr << "missing children IDs for device " << device_path_ << std::endl;
489+
auto dev_info_set = device_info_set::of_path(device_path_);
477490

478-
} else {
491+
auto children_instance_ids = dev_info_set.get_device_property_string_list(DEVPKEY_Device_Children);
479492

480-
std::wcerr << "children IDs: ";
481-
for (auto it = children_instance_ids.begin(); it < children_instance_ids.end(); it++) {
482-
if (it != children_instance_ids.begin())
483-
std::wcerr << ", ";
484-
std::wcerr << *it;
485-
}
486-
std::wcerr << std::endl;
487-
488-
std::wstring child_path;
489-
for (auto& child_id : children_instance_ids) {
490-
auto res = get_child_device_path(child_id, interface_num, child_path);
491-
if (res == 1)
492-
return child_path;
493-
if (res == -1)
494-
break;
495-
}
496-
}
493+
std::wcerr << "children IDs: ";
494+
for (auto it = children_instance_ids.begin(); it < children_instance_ids.end(); it++) {
495+
if (it != children_instance_ids.begin())
496+
std::wcerr << ", ";
497+
std::wcerr << *it;
498+
}
499+
std::wcerr << std::endl;
497500

498-
std::cerr << "Sleeping for 100ms..." << std::endl;
499-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
500-
num_retries -= 1;
501+
std::wstring child_path;
502+
for (auto& child_id : children_instance_ids) {
503+
child_path = get_child_device_path(child_id, interface_num);
504+
if (!child_path.empty())
505+
return child_path;
501506
}
502507

503-
return {};
508+
return {}; // retry later
504509
}
505510

506-
int usb_device::get_child_device_path(const std::wstring& child_id, int interface_num, std::wstring& device_path) {
511+
std::wstring usb_device::get_child_device_path(const std::wstring& child_id, int interface_num) {
507512

508513
auto dev_info_set = device_info_set::of_instance(child_id);
509514

510515
auto hardware_ids = dev_info_set.get_device_property_string_list(DEVPKEY_Device_HardwareIds);
511516
if (hardware_ids.empty()) {
512517
std::wcerr << "child device " << child_id << " has no hardware IDs" << std::endl;
513-
return 0; // continue with next child
518+
return {}; // continue with next child
514519
}
515520

516521
auto intf_num = extract_interface_number(hardware_ids);
517522
if (intf_num == -1) {
518523
std::wcerr << "child device " << child_id << " has no interface number" << std::endl;
519-
return 0; // continue with next child
524+
return {}; // continue with next child
520525
}
521526

522527
if (intf_num != interface_num)
523-
return 0; // continue with next child
528+
return {}; // continue with next child
524529

525-
device_path = dev_info_set.get_device_path_by_guid(child_id);
530+
auto device_path = dev_info_set.get_device_path_by_guid(child_id);
526531
if (device_path.empty()) {
527532
std::wcerr << "child device " << child_id << " has no device path" << std::endl;
528-
return -1; // retry later
533+
throw usb_error("claiming interface failed (function has no device interface GUID/path, might be missing WinUSB driver)");
529534
}
530535

531536
std::wcerr << "child device: interface=" << intf_num << ", device path=" << device_path << std::endl;
532537
interface_device_paths_[interface_num] = device_path;
533-
return 1; // success
538+
return device_path; // success
534539
}
535540

536541
static const std::wregex multiple_interface_id_pattern(L"USB\\\\VID_[0-9A-Fa-f]{4}&PID_[0-9A-Fa-f]{4}&MI_([0-9A-Fa-f]{2})");

reference/windows/USB/usb_device.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ class usb_device {
251251
usb_device(usb_registry* registry, std::wstring&& device_path, int vendor_id, int product_id, const std::vector<uint8_t>& config_desc, bool is_composite);
252252
void set_product_names(const std::string& manufacturer, const std::string& product, const std::string& serial_number);
253253
void build_handles(const std::wstring& device_path);
254+
bool try_claim_interface(int interface_number);
254255
std::wstring get_interface_device_path(int interface_num);
255-
int get_child_device_path(const std::wstring& child_id, int interface_num, std::wstring& device_path);
256+
std::wstring get_child_device_path(const std::wstring& child_id, int interface_num);
256257
static int extract_interface_number(const std::vector<std::wstring>& hardware_ids);
257258

258259
int control_transfer_core(const usb_control_request& request, uint8_t* data, int timeout);

0 commit comments

Comments
 (0)