From 875332184171a0a336c93e0371f52573ff79beed Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 27 Aug 2018 16:08:07 -0400 Subject: [PATCH] IOWin: Use anonymous namespaces where applicable Several functions (and one variable) were being given external linkage. Instead, relocate them all to anonymous namespaces to make them internally linked. --- Source/Core/Core/HW/WiimoteReal/IOWin.cpp | 329 +++++++++++----------- 1 file 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 g_connect_times; +std::unordered_map 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 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(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 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& device_path, WinWriteMethod& method) +bool IsWiimote(const std::basic_string& 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& 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(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.