@@ -131,14 +131,15 @@ void usb_device::claim_interface(int interface_number) {
131131 interface_handle* intf_handle = get_interface_handle (interface_number);
132132 interface_handle* first_intf_handle = get_interface_handle (intf_handle->first_interface_num );
133133
134- // open device if needed
134+ // both the device and the first interface must be opened for any interface belonging to the same function
135135 if (first_intf_handle->device_handle == nullptr ) {
136136 auto device_path = get_interface_device_path (first_intf_handle->interface_num );
137137 if (device_path.empty ())
138138 throw usb_error (" failed to claim interface (function has no device path, might be missing WinUSB driver)" );
139139
140140 std::wcerr << " opening device " << device_path << std::endl;
141141
142+ // open device
142143 first_intf_handle->device_handle = CreateFileW (device_path.c_str (),
143144 GENERIC_WRITE | GENERIC_READ,
144145 FILE_SHARE_WRITE | FILE_SHARE_READ,
@@ -147,21 +148,26 @@ void usb_device::claim_interface(int interface_number) {
147148 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
148149 nullptr );
149150 if (first_intf_handle->device_handle == INVALID_HANDLE_VALUE)
150- usb_error::throw_error (" cannot open USB device" );
151+ usb_error::throw_error (" failed to claim interface ( cannot open USB device) " );
151152
152- // open interface
153- if (!WinUsb_Initialize (first_intf_handle->device_handle , &first_intf_handle->intf_handle )) {
153+ // open first interface
154+ if (!WinUsb_Initialize (first_intf_handle->device_handle , &first_intf_handle->winusb_handle )) {
154155 auto err = GetLastError ();
155156 CloseHandle (first_intf_handle->device_handle );
156157 first_intf_handle->device_handle = nullptr ;
157- throw usb_error (" cannot open USB device (2 )" , err);
158+ throw usb_error (" failed to claim interface (cannot open associated interface )" , err);
158159 }
159160
160161 registry_->add_to_completion_port (first_intf_handle->device_handle );
161162 }
162163
164+ // open associated interface
165+ if (intf_handle != first_intf_handle) {
166+ if (!WinUsb_GetAssociatedInterface (first_intf_handle->winusb_handle , intf_handle->interface_num - first_intf_handle->interface_num - 1 , &intf_handle->winusb_handle ))
167+ throw usb_error (" cannot open associated interface" , GetLastError ());
168+ }
169+
163170 first_intf_handle->device_open_count += 1 ;
164- intf_handle->intf_handle = first_intf_handle->intf_handle ;
165171 intf->set_claimed (true );
166172}
167173
@@ -179,32 +185,38 @@ void usb_device::release_interface(int interface_number) {
179185 interface_handle* intf_handle = get_interface_handle (interface_number);
180186 interface_handle* first_intf_handle = get_interface_handle (intf_handle->first_interface_num );
181187
182- intf_handle->intf_handle = nullptr ;
183188 intf->set_claimed (false );
184189
190+ if (intf_handle != first_intf_handle) {
191+ // close assicated interface
192+ if (!WinUsb_Free (intf_handle->winusb_handle ))
193+ throw usb_error (" failed to release associated interface" , GetLastError ());
194+ intf_handle->winusb_handle = nullptr ;
195+ }
196+
185197 // close device if needed
186198 first_intf_handle->device_open_count -= 1 ;
187199 if (first_intf_handle->device_open_count == 0 ) {
188- WinUsb_Free (first_intf_handle->intf_handle );
200+ WinUsb_Free (first_intf_handle->winusb_handle );
189201 CloseHandle (first_intf_handle->device_handle );
190202 first_intf_handle->device_handle = nullptr ;
191203 }
192204}
193205
194206std::vector<uint8_t > usb_device::transfer_in (int endpoint_number, int timeout) {
195207
196- auto intf_handle = check_valid_endpoint (usb_direction::in, endpoint_number)->intf_handle ;
208+ auto winusb_handle = check_valid_endpoint (usb_direction::in, endpoint_number)->winusb_handle ;
197209 UCHAR endpoint_address = ep_address (usb_direction::in, endpoint_number);
198210 auto endpoint = get_endpoint_ptr (usb_direction::in, endpoint_number);
199211
200212 ULONG value = timeout;
201- if (!WinUsb_SetPipePolicy (intf_handle , endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof (value), &value))
213+ if (!WinUsb_SetPipePolicy (winusb_handle , endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof (value), &value))
202214 usb_error::throw_error (" Failed to set endpoint timeout" );
203215
204216 std::vector<uint8_t > data (endpoint->packet_size ());
205217
206218 DWORD len = 0 ;
207- if (!WinUsb_ReadPipe (intf_handle , endpoint_address, static_cast <PUCHAR>(data.data ()), endpoint->packet_size (), &len, nullptr ))
219+ if (!WinUsb_ReadPipe (winusb_handle , endpoint_address, static_cast <PUCHAR>(data.data ()), endpoint->packet_size (), &len, nullptr ))
208220 usb_error::throw_error (" Cannot receive from USB endpoint" );
209221
210222 data.resize (len);
@@ -215,15 +227,15 @@ void usb_device::transfer_out(int endpoint_number, const std::vector<uint8_t>& d
215227 if (len < 0 || len > data.size ())
216228 len = static_cast <int >(data.size ());
217229
218- auto intf_handle = check_valid_endpoint (usb_direction::out, endpoint_number)->intf_handle ;
230+ auto winusb_handle = check_valid_endpoint (usb_direction::out, endpoint_number)->winusb_handle ;
219231 UCHAR endpoint_address = ep_address (usb_direction::out, endpoint_number);
220232
221233 ULONG value = timeout;
222- if (!WinUsb_SetPipePolicy (intf_handle , endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof (value), &value))
234+ if (!WinUsb_SetPipePolicy (winusb_handle , endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof (value), &value))
223235 usb_error::throw_error (" Failed to set endpoint timeout" );
224236
225237 DWORD tlen = 0 ;
226- if (!WinUsb_WritePipe (intf_handle , endpoint_address, const_cast <PUCHAR>(data.data ()), len, &tlen, nullptr ))
238+ if (!WinUsb_WritePipe (winusb_handle , endpoint_address, const_cast <PUCHAR>(data.data ()), len, &tlen, nullptr ))
227239 usb_error::throw_error (" Failed to transmit to USB endpoint" );
228240}
229241
@@ -232,10 +244,10 @@ int usb_device::control_transfer_core(const usb_control_request &request, uint8_
232244 if (!is_open ())
233245 throw usb_error (" USB device is not open" );
234246
235- auto handle = get_control_transfer_interface_handle (request)->intf_handle ;
247+ auto winusb_handle = get_control_transfer_interface_handle (request)->winusb_handle ;
236248
237249 ULONG value = timeout;
238- if (!WinUsb_SetPipePolicy (handle , 0 , PIPE_TRANSFER_TIMEOUT, sizeof (value), &value))
250+ if (!WinUsb_SetPipePolicy (winusb_handle , 0 , PIPE_TRANSFER_TIMEOUT, sizeof (value), &value))
239251 usb_error::throw_error (" Failed to set endpoint timeout" );
240252
241253 WINUSB_SETUP_PACKET setup_packet = { 0 };
@@ -246,7 +258,7 @@ int usb_device::control_transfer_core(const usb_control_request &request, uint8_
246258 setup_packet.Length = request.wLength ;
247259
248260 DWORD len = 0 ;
249- if (!WinUsb_ControlTransfer (handle , setup_packet, data, request.wLength , &len, nullptr ))
261+ if (!WinUsb_ControlTransfer (winusb_handle , setup_packet, data, request.wLength , &len, nullptr ))
250262 usb_error::throw_error (" Control transfer failed" );
251263
252264 return len;
@@ -400,24 +412,24 @@ void usb_device::remove_completion_handler(OVERLAPPED* overlapped) {
400412}
401413
402414void usb_device::configure_for_async_io (usb_direction direction, int endpoint_number) {
403- auto intf_handle = check_valid_endpoint (direction, endpoint_number)->intf_handle ;
415+ auto winusb_handle = check_valid_endpoint (direction, endpoint_number)->winusb_handle ;
404416 UCHAR endpoint_address = ep_address (direction, endpoint_number);
405417
406418 ULONG timeout = 0 ;
407- if (!WinUsb_SetPipePolicy (intf_handle , endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof (timeout), &timeout))
419+ if (!WinUsb_SetPipePolicy (winusb_handle , endpoint_address, PIPE_TRANSFER_TIMEOUT, sizeof (timeout), &timeout))
408420 usb_error::throw_error (" Failed to set endpoint timeout" );
409421
410422 UCHAR raw_io = 1 ;
411- if (!WinUsb_SetPipePolicy (intf_handle , endpoint_address, RAW_IO, sizeof (raw_io), &raw_io))
423+ if (!WinUsb_SetPipePolicy (winusb_handle , endpoint_address, RAW_IO, sizeof (raw_io), &raw_io))
412424 usb_error::throw_error (" Failed to set endpoint for raw IO" );
413425}
414426
415427void usb_device::submit_transfer_in (int endpoint_number, uint8_t * buffer, int buffer_len, OVERLAPPED* overlapped) {
416428
417- auto intf_handle = check_valid_endpoint (usb_direction::in, endpoint_number)->intf_handle ;
429+ auto winusb_handle = check_valid_endpoint (usb_direction::in, endpoint_number)->winusb_handle ;
418430 UCHAR endpoint_address = ep_address (usb_direction::in, endpoint_number);
419431
420- if (!WinUsb_ReadPipe (intf_handle , endpoint_address, buffer, buffer_len, nullptr , overlapped)) {
432+ if (!WinUsb_ReadPipe (winusb_handle , endpoint_address, buffer, buffer_len, nullptr , overlapped)) {
421433 DWORD err = GetLastError ();
422434 if (err == ERROR_IO_PENDING)
423435 return ;
@@ -427,10 +439,10 @@ void usb_device::submit_transfer_in(int endpoint_number, uint8_t* buffer, int bu
427439
428440void usb_device::submit_transfer_out (int endpoint_number, uint8_t * data, int data_len, OVERLAPPED* overlapped) {
429441
430- auto intf_handle = check_valid_endpoint (usb_direction::out, endpoint_number)->intf_handle ;
442+ auto winusb_handle = check_valid_endpoint (usb_direction::out, endpoint_number)->winusb_handle ;
431443 UCHAR endpoint_address = ep_address (usb_direction::out, endpoint_number);
432444
433- if (!WinUsb_WritePipe (intf_handle , endpoint_address, data, data_len, nullptr , overlapped)) {
445+ if (!WinUsb_WritePipe (winusb_handle , endpoint_address, data, data_len, nullptr , overlapped)) {
434446 DWORD err = GetLastError ();
435447 if (err == ERROR_IO_PENDING)
436448 return ;
@@ -543,4 +555,4 @@ int usb_device::extract_interface_number(const std::vector<std::wstring>& hardwa
543555
544556usb_device::interface_handle::interface_handle (int intf_num, int first_num, std::wstring&& path)
545557 : interface_num(intf_num), first_interface_num(first_num),
546- device_handle(nullptr ), intf_handle (nullptr ), device_open_count(0 ) { }
558+ device_handle(nullptr ), winusb_handle (nullptr ), device_open_count(0 ) { }
0 commit comments