diff --git a/src/parsec-vusb-api/parsec-vusb-api.cc b/src/parsec-vusb-api/parsec-vusb-api.cc index 8c48b14..1abfadb 100644 --- a/src/parsec-vusb-api/parsec-vusb-api.cc +++ b/src/parsec-vusb-api/parsec-vusb-api.cc @@ -1,7 +1,6 @@ #include "parsec-vusb-api.h" #include #include -#include #include #include @@ -13,6 +12,7 @@ constexpr DWORD IOCTL_VIRTUAL_USB_DEVICE_CREATE = 0x2ae804; constexpr DWORD IOCTL_CONFIGURE_ENDPOINTS = 0x2aa808; constexpr DWORD IOCTL_CONFIGURE_ENDPOINT_TYPES = 0x2aa81c; constexpr DWORD IOCTL_PLUG_IN_DEVICE = 0x2aac04; +constexpr DWORD IOCTL_UNPLUG_DEVICE = 0x2aac08; constexpr DWORD IOCTL_QUERY_MEDIA = 0x2af014; constexpr DWORD IOCTL_SUBMIT_AUDIO = 0x2ab018; @@ -84,8 +84,10 @@ static void vusb_ioctl_in_out(HANDLE handle, DWORD code, if (!GetOverlappedResult(handle, &overlapped, &bytes_returned, TRUE)) { DWORD error = GetLastError(); - CloseHandle(overlapped.hEvent); - throw VUSBError("GetOverlappedResult failed.", error); + if (error != ERROR_NOT_READY) { + CloseHandle(overlapped.hEvent); + throw VUSBError("GetOverlappedResult failed.", error); + } } CloseHandle(overlapped.hEvent); @@ -200,6 +202,8 @@ VirtualUSBDevice::VirtualUSBDevice( vusb_ioctl_in_out(_hub_handle, IOCTL_VIRTUAL_USB_DEVICE_CREATE, buffer); _device_id = *reinterpret_cast(buffer.data() + 4); + _device_handle = *reinterpret_cast(buffer.data() + 4); + _unknown_handle = *reinterpret_cast(buffer.data() + 12); wchar_t event_name[MAX_PATH]; swprintf_s(event_name, MAX_PATH, @@ -249,6 +253,25 @@ VirtualUSBDevice::operator=(VirtualUSBDevice &&other) noexcept { return *this; } +void VirtualUSBDevice::destroy_device() { + if (_device_handle == INVALID_HANDLE_VALUE || _device_id == 0) { + return; + } + + std::vector buffer(8); + write_to_buffer(buffer, 0, static_cast(8)); + write_to_buffer(buffer, 4, _device_id); + + vusb_ioctl(_hub_handle, IOCTL_UNPLUG_DEVICE, buffer); + + SetEvent(_device_handle); + CloseHandle(_device_handle); + CloseHandle(_unknown_handle); + + _device_handle = INVALID_HANDLE_VALUE; + _device_id = 0; +} + void VirtualUSBDevice::close() { if (_control_wait_event) { CloseHandle(_control_wait_event); @@ -456,9 +479,12 @@ bool VirtualUSBDevice::submit_audio_data(const std::vector &data) { } if (!GetOverlappedResult(_hub_handle, &overlapped, &bytes_returned, TRUE)) { - CloseHandle(overlapped.hEvent); - throw VUSBError("Submit audio GetOverlappedResult failed.", - GetLastError()); + DWORD error = GetLastError(); + if (error != ERROR_NOT_READY) { + CloseHandle(overlapped.hEvent); + throw VUSBError("Submit audio GetOverlappedResult failed.", + GetLastError()); + } } CloseHandle(overlapped.hEvent); diff --git a/src/parsec-vusb-api/parsec-vusb-api.h b/src/parsec-vusb-api/parsec-vusb-api.h index c69e93d..43a41e7 100644 --- a/src/parsec-vusb-api/parsec-vusb-api.h +++ b/src/parsec-vusb-api/parsec-vusb-api.h @@ -100,6 +100,7 @@ class VirtualUSBDevice { void configure_endpoint_types(const std::vector &endpointTypes); void plug_in(); void unplug(); + void destroy_device(); bool submit_audio_data(const std::vector &data); inline bool submit_audio_data(const std::vector &data) { return submit_audio_data(std::vector( @@ -117,6 +118,8 @@ class VirtualUSBDevice { void close(); HANDLE _hub_handle = INVALID_HANDLE_VALUE; + HANDLE _device_handle = INVALID_HANDLE_VALUE; + HANDLE _unknown_handle = INVALID_HANDLE_VALUE; uint32_t _device_id = 0; HANDLE _control_wait_event = nullptr; HANDLE _cancelled_wait_event = nullptr;