Merge pull request #7374 from lioncash/iowin
IOWin: Make functions internally linked where applicable
This commit is contained in:
commit
4c75331d5d
|
@ -55,12 +55,14 @@ DYN_FUNC_DECLARE(BluetoothEnumerateInstalledServices);
|
||||||
|
|
||||||
#undef DYN_FUNC_DECLARE
|
#undef DYN_FUNC_DECLARE
|
||||||
|
|
||||||
static HINSTANCE s_hid_lib = nullptr;
|
namespace
|
||||||
static HINSTANCE s_bthprops_lib = nullptr;
|
{
|
||||||
|
HINSTANCE s_hid_lib = nullptr;
|
||||||
|
HINSTANCE s_bthprops_lib = nullptr;
|
||||||
|
|
||||||
static bool s_loaded_ok = false;
|
bool s_loaded_ok = false;
|
||||||
|
|
||||||
std::unordered_map<BTH_ADDR, std::time_t> g_connect_times;
|
std::unordered_map<BTH_ADDR, std::time_t> s_connect_times;
|
||||||
|
|
||||||
#define DYN_FUNC_UNLOAD(func) p##func = nullptr;
|
#define DYN_FUNC_UNLOAD(func) p##func = nullptr;
|
||||||
|
|
||||||
|
@ -161,7 +163,7 @@ bool load_bthprops()
|
||||||
#undef DYN_FUNC_LOAD
|
#undef DYN_FUNC_LOAD
|
||||||
#undef DYN_FUNC_UNLOAD
|
#undef DYN_FUNC_UNLOAD
|
||||||
|
|
||||||
inline void init_lib()
|
void init_lib()
|
||||||
{
|
{
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
|
|
||||||
|
@ -181,6 +183,7 @@ inline void init_lib()
|
||||||
s_loaded_ok = true;
|
s_loaded_ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
|
@ -195,44 +198,138 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_
|
||||||
void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
||||||
bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
||||||
|
|
||||||
WiimoteScannerWindows::WiimoteScannerWindows()
|
namespace
|
||||||
{
|
{
|
||||||
init_lib();
|
std::wstring GetDeviceProperty(const HDEVINFO& device_info, const PSP_DEVINFO_DATA device_data,
|
||||||
|
const DEVPROPKEY* requested_property)
|
||||||
|
{
|
||||||
|
DWORD required_size = 0;
|
||||||
|
DEVPROPTYPE device_property_type;
|
||||||
|
|
||||||
|
SetupDiGetDeviceProperty(device_info, device_data, requested_property, &device_property_type,
|
||||||
|
nullptr, 0, &required_size, 0);
|
||||||
|
|
||||||
|
std::vector<BYTE> unicode_buffer(required_size, 0);
|
||||||
|
|
||||||
|
BOOL result =
|
||||||
|
SetupDiGetDeviceProperty(device_info, device_data, requested_property, &device_property_type,
|
||||||
|
unicode_buffer.data(), required_size, nullptr, 0);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::wstring((PWCHAR)unicode_buffer.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
WiimoteScannerWindows::~WiimoteScannerWindows()
|
int IOWritePerSetOutputReport(HANDLE& dev_handle, const u8* buf, size_t len, DWORD* written)
|
||||||
{
|
{
|
||||||
// TODO: what do we want here?
|
BOOLEAN result = pHidD_SetOutputReport(dev_handle, const_cast<u8*>(buf) + 1, (ULONG)(len - 1));
|
||||||
#if 0
|
if (!result)
|
||||||
ProcessWiimotes(false, [](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
|
{
|
||||||
{
|
DWORD err = GetLastError();
|
||||||
RemoveWiimote(btdi);
|
if (err == ERROR_SEM_TIMEOUT)
|
||||||
});
|
{
|
||||||
#endif
|
NOTICE_LOG(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Unable to send data to the Wiimote");
|
||||||
|
}
|
||||||
|
else if (err != ERROR_GEN_FAILURE)
|
||||||
|
{
|
||||||
|
// Some third-party adapters (DolphinBar) use this
|
||||||
|
// error code to signal the absence of a Wiimote
|
||||||
|
// linked to the HID device.
|
||||||
|
WARN_LOG(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Error: %08x", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
{
|
||||||
|
*written = (result ? (DWORD)len : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiimoteScannerWindows::Update()
|
int IOWritePerWriteFile(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write,
|
||||||
|
WinWriteMethod& write_method, const u8* buf, size_t len, DWORD* written)
|
||||||
{
|
{
|
||||||
if (!s_loaded_ok)
|
DWORD bytes_written;
|
||||||
return;
|
LPCVOID write_buffer = buf + 1;
|
||||||
|
DWORD bytes_to_write = (DWORD)(len - 1);
|
||||||
|
|
||||||
bool forgot_some = false;
|
u8 resized_buffer[MAX_PAYLOAD];
|
||||||
|
|
||||||
ProcessWiimotes(false, [&](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) {
|
// Resize the buffer, if the underlying HID Class driver needs the buffer to be the size of
|
||||||
forgot_some |= ForgetWiimote(btdi);
|
// HidCaps.OuputReportSize
|
||||||
});
|
// In case of Wiimote HidCaps.OuputReportSize is 22 Byte.
|
||||||
|
// This is currently needed by the Toshiba Bluetooth Stack.
|
||||||
|
if ((write_method == WWM_WRITE_FILE_LARGEST_REPORT_SIZE) && (MAX_PAYLOAD > len))
|
||||||
|
{
|
||||||
|
std::copy(buf, buf + len, resized_buffer);
|
||||||
|
std::fill(resized_buffer + len, resized_buffer + MAX_PAYLOAD, 0);
|
||||||
|
write_buffer = resized_buffer + 1;
|
||||||
|
bytes_to_write = MAX_PAYLOAD - 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Some hacks that allows disconnects to be detected before connections are handled
|
ResetEvent(hid_overlap_write.hEvent);
|
||||||
// workaround for Wiimote 1 moving to slot 2 on temporary disconnect
|
BOOLEAN result =
|
||||||
if (forgot_some)
|
WriteFile(dev_handle, write_buffer, bytes_to_write, &bytes_written, &hid_overlap_write);
|
||||||
Common::SleepCurrentThread(100);
|
if (!result)
|
||||||
|
{
|
||||||
|
const DWORD error = GetLastError();
|
||||||
|
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case ERROR_INVALID_USER_BUFFER:
|
||||||
|
INFO_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Falling back to SetOutputReport");
|
||||||
|
write_method = WWM_SET_OUTPUT_REPORT;
|
||||||
|
return IOWritePerSetOutputReport(dev_handle, buf, len, written);
|
||||||
|
case ERROR_IO_PENDING:
|
||||||
|
// Pending is no error!
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Error on WriteFile: %08x", error);
|
||||||
|
CancelIo(dev_handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
{
|
||||||
|
*written = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for completion
|
||||||
|
DWORD wait_result = WaitForSingleObject(hid_overlap_write.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
|
||||||
|
|
||||||
|
if (WAIT_TIMEOUT == wait_result)
|
||||||
|
{
|
||||||
|
WARN_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: A timeout occurred on writing to Wiimote.");
|
||||||
|
CancelIo(dev_handle);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (WAIT_FAILED == wait_result)
|
||||||
|
{
|
||||||
|
WARN_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: A wait error occurred on writing to Wiimote.");
|
||||||
|
CancelIo(dev_handle);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (written)
|
||||||
|
{
|
||||||
|
if (!GetOverlappedResult(dev_handle, &hid_overlap_write, written, TRUE))
|
||||||
|
{
|
||||||
|
*written = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moves up one node in the device tree and returns its device info data along with an info set only
|
// Moves up one node in the device tree and returns its device info data along with an info set only
|
||||||
// including that device for further processing
|
// including that device for further processing
|
||||||
// See https://msdn.microsoft.com/en-us/library/windows/hardware/ff549417(v=vs.85).aspx
|
// See https://msdn.microsoft.com/en-us/library/windows/hardware/ff549417(v=vs.85).aspx
|
||||||
static bool GetParentDevice(const DEVINST& child_device_instance, HDEVINFO* parent_device_info,
|
bool GetParentDevice(const DEVINST& child_device_instance, HDEVINFO* parent_device_info,
|
||||||
PSP_DEVINFO_DATA parent_device_data)
|
PSP_DEVINFO_DATA parent_device_data)
|
||||||
{
|
{
|
||||||
ULONG status;
|
ULONG status;
|
||||||
ULONG problem_number;
|
ULONG problem_number;
|
||||||
|
@ -279,28 +376,6 @@ static bool GetParentDevice(const DEVINST& child_device_instance, HDEVINFO* pare
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring GetDeviceProperty(const HDEVINFO& device_info, const PSP_DEVINFO_DATA device_data,
|
|
||||||
const DEVPROPKEY* requested_property)
|
|
||||||
{
|
|
||||||
DWORD required_size = 0;
|
|
||||||
DEVPROPTYPE device_property_type;
|
|
||||||
|
|
||||||
SetupDiGetDeviceProperty(device_info, device_data, requested_property, &device_property_type,
|
|
||||||
nullptr, 0, &required_size, 0);
|
|
||||||
|
|
||||||
std::vector<BYTE> unicode_buffer(required_size, 0);
|
|
||||||
|
|
||||||
BOOL result =
|
|
||||||
SetupDiGetDeviceProperty(device_info, device_data, requested_property, &device_property_type,
|
|
||||||
unicode_buffer.data(), required_size, nullptr, 0);
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
return std::wstring();
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::wstring((PWCHAR)unicode_buffer.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
// The enumerated device nodes/instances are "empty" PDO's that act as interfaces for the HID Class
|
// The enumerated device nodes/instances are "empty" PDO's that act as interfaces for the HID Class
|
||||||
// Driver.
|
// Driver.
|
||||||
// Since those PDO's normaly don't have a FDO and therefore no driver loaded, we need to move one
|
// Since those PDO's normaly don't have a FDO and therefore no driver loaded, we need to move one
|
||||||
|
@ -308,7 +383,7 @@ std::wstring GetDeviceProperty(const HDEVINFO& device_info, const PSP_DEVINFO_DA
|
||||||
// Then check the provider of the device driver, which will be "Microsoft" in case of the default
|
// Then check the provider of the device driver, which will be "Microsoft" in case of the default
|
||||||
// HID Class Driver
|
// HID Class Driver
|
||||||
// or "TOSHIBA" in case of the Toshiba Bluetooth Stack, because it provides its own Class Driver.
|
// or "TOSHIBA" in case of the Toshiba Bluetooth Stack, because it provides its own Class Driver.
|
||||||
static bool CheckForToshibaStack(const DEVINST& hid_interface_device_instance)
|
bool CheckForToshibaStack(const DEVINST& hid_interface_device_instance)
|
||||||
{
|
{
|
||||||
HDEVINFO parent_device_info = nullptr;
|
HDEVINFO parent_device_info = nullptr;
|
||||||
SP_DEVINFO_DATA parent_device_data = {};
|
SP_DEVINFO_DATA parent_device_data = {};
|
||||||
|
@ -329,7 +404,7 @@ static bool CheckForToshibaStack(const DEVINST& hid_interface_device_instance)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack)
|
WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack)
|
||||||
{
|
{
|
||||||
// Currently Toshiba Bluetooth Stack needs the Output buffer to be the size of the largest output
|
// Currently Toshiba Bluetooth Stack needs the Output buffer to be the size of the largest output
|
||||||
// report
|
// report
|
||||||
|
@ -337,7 +412,7 @@ static WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack)
|
||||||
WWM_WRITE_FILE_ACTUAL_REPORT_SIZE);
|
WWM_WRITE_FILE_ACTUAL_REPORT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int WriteToHandle(HANDLE& dev_handle, WinWriteMethod& method, const u8* buf, size_t size)
|
int WriteToHandle(HANDLE& dev_handle, WinWriteMethod& method, const u8* buf, size_t size)
|
||||||
{
|
{
|
||||||
OVERLAPPED hid_overlap_write = OVERLAPPED();
|
OVERLAPPED hid_overlap_write = OVERLAPPED();
|
||||||
hid_overlap_write.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
hid_overlap_write.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
||||||
|
@ -350,7 +425,7 @@ static int WriteToHandle(HANDLE& dev_handle, WinWriteMethod& method, const u8* b
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ReadFromHandle(HANDLE& dev_handle, u8* buf)
|
int ReadFromHandle(HANDLE& dev_handle, u8* buf)
|
||||||
{
|
{
|
||||||
OVERLAPPED hid_overlap_read = OVERLAPPED();
|
OVERLAPPED hid_overlap_read = OVERLAPPED();
|
||||||
hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
||||||
|
@ -359,7 +434,7 @@ static int ReadFromHandle(HANDLE& dev_handle, u8* buf)
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMethod& method)
|
bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMethod& method)
|
||||||
{
|
{
|
||||||
HANDLE dev_handle = CreateFile(device_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
HANDLE dev_handle = CreateFile(device_path.c_str(), GENERIC_READ | GENERIC_WRITE,
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
|
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
|
||||||
|
@ -393,6 +468,40 @@ static bool IsWiimote(const std::basic_string<TCHAR>& device_path, WinWriteMetho
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
WiimoteScannerWindows::WiimoteScannerWindows()
|
||||||
|
{
|
||||||
|
init_lib();
|
||||||
|
}
|
||||||
|
|
||||||
|
WiimoteScannerWindows::~WiimoteScannerWindows()
|
||||||
|
{
|
||||||
|
// TODO: what do we want here?
|
||||||
|
#if 0
|
||||||
|
ProcessWiimotes(false, [](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
|
||||||
|
{
|
||||||
|
RemoveWiimote(btdi);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiimoteScannerWindows::Update()
|
||||||
|
{
|
||||||
|
if (!s_loaded_ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool forgot_some = false;
|
||||||
|
|
||||||
|
ProcessWiimotes(false, [&](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) {
|
||||||
|
forgot_some |= ForgetWiimote(btdi);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Some hacks that allows disconnects to be detected before connections are handled
|
||||||
|
// workaround for Wiimote 1 moving to slot 2 on temporary disconnect
|
||||||
|
if (forgot_some)
|
||||||
|
Common::SleepCurrentThread(100);
|
||||||
|
}
|
||||||
|
|
||||||
// Find and connect Wiimotes.
|
// Find and connect Wiimotes.
|
||||||
// Does not replace already found Wiimotes even if they are disconnected.
|
// Does not replace already found Wiimotes even if they are disconnected.
|
||||||
|
@ -686,110 +795,6 @@ int WiimoteWindows::IORead(u8* buf)
|
||||||
return WiimoteReal::IORead(m_dev_handle, m_hid_overlap_read, buf, m_index);
|
return WiimoteReal::IORead(m_dev_handle, m_hid_overlap_read, buf, m_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int IOWritePerSetOutputReport(HANDLE& dev_handle, const u8* buf, size_t len, DWORD* written)
|
|
||||||
{
|
|
||||||
BOOLEAN result = pHidD_SetOutputReport(dev_handle, const_cast<u8*>(buf) + 1, (ULONG)(len - 1));
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
DWORD err = GetLastError();
|
|
||||||
if (err == ERROR_SEM_TIMEOUT)
|
|
||||||
{
|
|
||||||
NOTICE_LOG(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Unable to send data to the Wiimote");
|
|
||||||
}
|
|
||||||
else if (err != ERROR_GEN_FAILURE)
|
|
||||||
{
|
|
||||||
// Some third-party adapters (DolphinBar) use this
|
|
||||||
// error code to signal the absence of a Wiimote
|
|
||||||
// linked to the HID device.
|
|
||||||
WARN_LOG(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Error: %08x", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (written)
|
|
||||||
{
|
|
||||||
*written = (result ? (DWORD)len : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int IOWritePerWriteFile(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write,
|
|
||||||
WinWriteMethod& write_method, const u8* buf, size_t len,
|
|
||||||
DWORD* written)
|
|
||||||
{
|
|
||||||
DWORD bytes_written;
|
|
||||||
LPCVOID write_buffer = buf + 1;
|
|
||||||
DWORD bytes_to_write = (DWORD)(len - 1);
|
|
||||||
|
|
||||||
u8 resized_buffer[MAX_PAYLOAD];
|
|
||||||
|
|
||||||
// Resize the buffer, if the underlying HID Class driver needs the buffer to be the size of
|
|
||||||
// HidCaps.OuputReportSize
|
|
||||||
// In case of Wiimote HidCaps.OuputReportSize is 22 Byte.
|
|
||||||
// This is currently needed by the Toshiba Bluetooth Stack.
|
|
||||||
if ((write_method == WWM_WRITE_FILE_LARGEST_REPORT_SIZE) && (MAX_PAYLOAD > len))
|
|
||||||
{
|
|
||||||
std::copy(buf, buf + len, resized_buffer);
|
|
||||||
std::fill(resized_buffer + len, resized_buffer + MAX_PAYLOAD, 0);
|
|
||||||
write_buffer = resized_buffer + 1;
|
|
||||||
bytes_to_write = MAX_PAYLOAD - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResetEvent(hid_overlap_write.hEvent);
|
|
||||||
BOOLEAN result =
|
|
||||||
WriteFile(dev_handle, write_buffer, bytes_to_write, &bytes_written, &hid_overlap_write);
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
const DWORD error = GetLastError();
|
|
||||||
|
|
||||||
switch (error)
|
|
||||||
{
|
|
||||||
case ERROR_INVALID_USER_BUFFER:
|
|
||||||
INFO_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Falling back to SetOutputReport");
|
|
||||||
write_method = WWM_SET_OUTPUT_REPORT;
|
|
||||||
return IOWritePerSetOutputReport(dev_handle, buf, len, written);
|
|
||||||
case ERROR_IO_PENDING:
|
|
||||||
// Pending is no error!
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
WARN_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: Error on WriteFile: %08x", error);
|
|
||||||
CancelIo(dev_handle);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (written)
|
|
||||||
{
|
|
||||||
*written = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for completion
|
|
||||||
DWORD wait_result = WaitForSingleObject(hid_overlap_write.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
|
|
||||||
|
|
||||||
if (WAIT_TIMEOUT == wait_result)
|
|
||||||
{
|
|
||||||
WARN_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: A timeout occurred on writing to Wiimote.");
|
|
||||||
CancelIo(dev_handle);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (WAIT_FAILED == wait_result)
|
|
||||||
{
|
|
||||||
WARN_LOG(WIIMOTE, "IOWrite[WWM_WRITE_FILE]: A wait error occurred on writing to Wiimote.");
|
|
||||||
CancelIo(dev_handle);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (written)
|
|
||||||
{
|
|
||||||
if (!GetOverlappedResult(dev_handle, &hid_overlap_write, written, TRUE))
|
|
||||||
{
|
|
||||||
*written = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// As of https://msdn.microsoft.com/en-us/library/windows/hardware/ff543402(v=vs.85).aspx, WriteFile
|
// As of https://msdn.microsoft.com/en-us/library/windows/hardware/ff543402(v=vs.85).aspx, WriteFile
|
||||||
// is the preferred method
|
// is the preferred method
|
||||||
// to send output reports to the HID. WriteFile sends an IRP_MJ_WRITE to the HID Class Driver
|
// to send output reports to the HID. WriteFile sends an IRP_MJ_WRITE to the HID Class Driver
|
||||||
|
@ -961,7 +966,7 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO& radio_info,
|
||||||
const DWORD hr = pBluetoothSetServiceState(
|
const DWORD hr = pBluetoothSetServiceState(
|
||||||
hRadio, &btdi, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
|
hRadio, &btdi, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
|
||||||
|
|
||||||
g_connect_times[btdi.Address.ullLong] = std::time(nullptr);
|
s_connect_times[btdi.Address.ullLong] = std::time(nullptr);
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
|
@ -985,8 +990,8 @@ bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
|
||||||
// Sometimes SetServiceState takes a while..
|
// Sometimes SetServiceState takes a while..
|
||||||
auto const avoid_forget_seconds = 5.0;
|
auto const avoid_forget_seconds = 5.0;
|
||||||
|
|
||||||
auto pair_time = g_connect_times.find(btdi.Address.ullLong);
|
auto pair_time = s_connect_times.find(btdi.Address.ullLong);
|
||||||
if (pair_time == g_connect_times.end() ||
|
if (pair_time == s_connect_times.end() ||
|
||||||
std::difftime(time(nullptr), pair_time->second) >= avoid_forget_seconds)
|
std::difftime(time(nullptr), pair_time->second) >= avoid_forget_seconds)
|
||||||
{
|
{
|
||||||
// Make Windows forget about device so it will re-find it if visible.
|
// Make Windows forget about device so it will re-find it if visible.
|
||||||
|
|
Loading…
Reference in New Issue