summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2018-08-27 22:13:24 +0200
committerGitHub <noreply@github.com>2018-08-27 22:13:24 +0200
commit4c75331d5df35850ff393f6e0f0b0011e63cd6b7 (patch)
tree704adfbf9e97f9b80a0dabf4f3e191ea1e121fa3 /Source/Core
parentc3ed39caef0bef934990c506c807c9024ce2e1ed (diff)
parent875332184171a0a336c93e0371f52573ff79beed (diff)
Merge pull request #7374 from lioncash/iowin
IOWin: Make functions internally linked where applicable
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/WiimoteReal/IOWin.cpp329
1 files changed, 167 insertions, 162 deletions
diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp
index 4701fdcef6..244fe07f69 100644
--- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp
+++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp
@@ -55,12 +55,14 @@ DYN_FUNC_DECLARE(BluetoothEnumerateInstalledServices);
#undef DYN_FUNC_DECLARE
-static HINSTANCE s_hid_lib = nullptr;
-static HINSTANCE s_bthprops_lib = nullptr;
+namespace
+{
+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;
@@ -161,7 +163,7 @@ bool load_bthprops()
#undef DYN_FUNC_LOAD
#undef DYN_FUNC_UNLOAD
-inline void init_lib()
+void init_lib()
{
static bool initialized = false;
@@ -181,6 +183,7 @@ inline void init_lib()
s_loaded_ok = true;
}
}
+} // Anonymous namespace
namespace WiimoteReal
{
@@ -195,44 +198,138 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_
void RemoveWiimote(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?
-#if 0
- ProcessWiimotes(false, [](HANDLE, BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
- {
- RemoveWiimote(btdi);
- });
-#endif
+ 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;
}
-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)
- return;
+ DWORD bytes_written;
+ 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) {
- forgot_some |= ForgetWiimote(btdi);
- });
+ // 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;
+ }
- // 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);
+ 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;
}
// 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
// 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,
- PSP_DEVINFO_DATA parent_device_data)
+bool GetParentDevice(const DEVINST& child_device_instance, HDEVINFO* parent_device_info,
+ PSP_DEVINFO_DATA parent_device_data)
{
ULONG status;
ULONG problem_number;
@@ -279,28 +376,6 @@ static bool GetParentDevice(const DEVINST& child_device_instance, HDEVINFO* pare
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
// Driver.
// 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
// HID 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;
SP_DEVINFO_DATA parent_device_data = {};
@@ -329,7 +404,7 @@ static bool CheckForToshibaStack(const DEVINST& hid_interface_device_instance)
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
// report
@@ -337,7 +412,7 @@ static WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack)
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();
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;
}
-static int ReadFromHandle(HANDLE& dev_handle, u8* buf)
+int ReadFromHandle(HANDLE& dev_handle, u8* buf)
{
OVERLAPPED hid_overlap_read = OVERLAPPED();
hid_overlap_read.hEvent = CreateEvent(nullptr, true, false, nullptr);
@@ -359,7 +434,7 @@ static int ReadFromHandle(HANDLE& dev_handle, u8* buf)
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,
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;
}
+} // 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.
// 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);
}
-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
// is the preferred method
// 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(
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))
{
@@ -985,8 +990,8 @@ bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
// Sometimes SetServiceState takes a while..
auto const avoid_forget_seconds = 5.0;
- auto pair_time = g_connect_times.find(btdi.Address.ullLong);
- if (pair_time == g_connect_times.end() ||
+ auto pair_time = s_connect_times.find(btdi.Address.ullLong);
+ if (pair_time == s_connect_times.end() ||
std::difftime(time(nullptr), pair_time->second) >= avoid_forget_seconds)
{
// Make Windows forget about device so it will re-find it if visible.