diff options
author | Ryan Metcalfe <ryan.metcalfe@novanta.com> | 2021-07-26 16:16:54 -0400 |
---|---|---|
committer | Tormod Volden <debian.tormod@gmail.com> | 2023-01-19 15:02:11 +0100 |
commit | 5ec2821fdc491b470306d3cbb7175e53388d46fd (patch) | |
tree | de5bd9b242d17f420d318bda13d856f8f89a6ff9 /libusb/os/windows_common.h | |
parent | 809a6df614b87be780df9b0c97ba6c0bb6172aab (diff) | |
download | libusb-5ec2821fdc491b470306d3cbb7175e53388d46fd.tar.gz |
windows: Allow claiming all interfaces for a WINUSBX composite function
On Windows 10, when a USB composite device is using usbccgp to manage
the parent device, there can be problems when an application tries to
claim multiple interfaces for a WINSBX-enabled subfunction. For example,
a common scenario is that an application is able to claim the first
interface of a given child function, but not the others.
This commit attempts to resolve this issue by making use of
(potentially) available interface association descriptors (IADs).
Within set_composite_interface(), which is normally called for the first
interface of a composite child function (Some MI_XX device, where XX is
the first interface), the set of IADs for the current configuration is
retrieved and, if the current interface matches the 'bFirstInterface'
for one of the returned IADs then the API backend, sub_api is also set
up for the other 'associated' interfaces. Subsequent calls to
libusb_claim_interface for any of these 'associated' interfaces will get
properly routed to winusbx_claim_interface.
Two fields have been added to winusb_device_priv.usb_interface:
num_associated_interfaces
first_associated_interface
These are made use of by winusbx_claim_interface() to decide whether
Initialize() or GetAssociatedInterface() function calls are needed, as
well as within winusbx_close() to perform proper cleanup for groups of
associated functions.
About composite functions in Windows (by Maciej T. Nowak):
(1) Non-composite device: Single device is created with all interfaces
grouped (associated) together. WinUSB_Initialize gives access to first
interface and WinUSB_GetAssociatedInteface can be used to get access to
remaining interfaces.
(2) Composite device without IAD is presented by set of devices each
containing single interface. As they are separate devices, separate
WinUSB_Initialize calls are required to gain access to each interface.
As there are no more interfaces in each device,
WinUSB_GetAssociatedInterface has no use in this case. In other words:
Each interface is grouped (associated) with itself.
(3) When we add IAD to a composite device, interfaces specified in each
IAD are grouped (associated) into single devices where WinUSB_Initialize
is required to open the first interface in each association and
WinUSB_GetAssociatedInterface for the remaining interfaces in each
group. Effectively this case is a mix of (1) and (2).
Closes #965
Signed-off-by: Ryan Metcalfe <ryan.metcalfe@novanta.com>
[Tormod: Removed redundant is_associated_interface member]
Signed-off-by: Tormod Volden <debian.tormod@gmail.com>
Diffstat (limited to 'libusb/os/windows_common.h')
-rw-r--r-- | libusb/os/windows_common.h | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index 4582ce4..ff0a5b7 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -257,6 +257,13 @@ struct winusb_device_priv { int current_altsetting; bool restricted_functionality; // indicates if the interface functionality is restricted // by Windows (eg. HID keyboards or mice cannot do R/W) + uint8_t num_associated_interfaces; // If non-zero, the interface is part of a grouped + // set of associated interfaces (defined by an IAD) + // and this is the number of interfaces within the + // associated group (bInterfaceCount in IAD). + uint8_t first_associated_interface; // For associated interfaces, this is the index of + // the first interface (bFirstInterface in IAD) for + // the grouped set of associated interfaces. } usb_interface[USB_MAXINTERFACES]; struct hid_device_priv *hid; PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors |