From 9455e2bca4a5ff64974974dd29ab4f1689ddf120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 23 Jul 2016 19:07:14 +0200 Subject: [PATCH] WiimoteReal: Change the scanner to support several backends This makes WiimoteScanner support several scanner backends. This adds a WiimoteScannerBackend base class, which scanner backends derive from, and which allows backend-specific things to be moved out of the common code. Also removes IODummy which is not needed anymore. --- Source/Core/Core/CMakeLists.txt | 2 - Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp | 48 +--------- Source/Core/Core/HW/WiimoteReal/IOAndroid.h | 57 +++++++++++ Source/Core/Core/HW/WiimoteReal/IODummy.cpp | 32 ------- Source/Core/Core/HW/WiimoteReal/IODummy.h | 20 ++++ Source/Core/Core/HW/WiimoteReal/IONix.cpp | 57 +++-------- Source/Core/Core/HW/WiimoteReal/IONix.h | 58 +++++++++++ Source/Core/Core/HW/WiimoteReal/IOWin.cpp | 41 ++------ Source/Core/Core/HW/WiimoteReal/IOWin.h | 66 +++++++++++++ Source/Core/Core/HW/WiimoteReal/IOdarwin.h | 95 +++++++++++++++++++ Source/Core/Core/HW/WiimoteReal/IOdarwin.mm | 74 +-------------- .../Core/Core/HW/WiimoteReal/WiimoteReal.cpp | 51 +++++++--- Source/Core/Core/HW/WiimoteReal/WiimoteReal.h | 33 +++---- .../Core/HW/WiimoteReal/WiimoteRealBase.h | 27 ------ 14 files changed, 380 insertions(+), 281 deletions(-) create mode 100644 Source/Core/Core/HW/WiimoteReal/IOAndroid.h delete mode 100644 Source/Core/Core/HW/WiimoteReal/IODummy.cpp create mode 100644 Source/Core/Core/HW/WiimoteReal/IODummy.h create mode 100644 Source/Core/Core/HW/WiimoteReal/IONix.h create mode 100644 Source/Core/Core/HW/WiimoteReal/IOWin.h create mode 100644 Source/Core/Core/HW/WiimoteReal/IOdarwin.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 5a2d89d518..04b6130c94 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -260,8 +260,6 @@ elseif(UNIX) set(LIBS ${LIBS} bluetooth) elseif(ANDROID) set(SRCS ${SRCS} HW/WiimoteReal/IOAndroid.cpp) - else() - set(SRCS ${SRCS} HW/WiimoteReal/IODummy.cpp) endif() endif() diff --git a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp index d69eef4e10..abc33c88a2 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOAndroid.cpp @@ -12,7 +12,7 @@ #include "Common/Thread.h" #include "Common/Timer.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" +#include "Core/HW/WiimoteReal/IOAndroid.h" // Global java_vm class extern JavaVM* g_java_vm; @@ -22,45 +22,8 @@ namespace WiimoteReal // Java classes static jclass s_adapter_class; -class WiimoteAndroid final : public Wiimote -{ -public: - WiimoteAndroid(int index); - ~WiimoteAndroid() override; - -protected: - bool ConnectInternal() override; - void DisconnectInternal() override; - bool IsConnected() const override; - void IOWakeup() {} - int IORead(u8* buf) override; - int IOWrite(u8 const* buf, size_t len) override; - -private: - int m_mayflash_index; - bool is_connected = true; - - JNIEnv* m_env; - - jmethodID m_input_func; - jmethodID m_output_func; - - jbyteArray m_java_wiimote_payload; -}; - -WiimoteScanner::WiimoteScanner() -{ -} - -WiimoteScanner::~WiimoteScanner() -{ -} - -void WiimoteScanner::Update() -{ -} - -void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) +void WiimoteScannerAndroid::FindWiimotes(std::vector& found_wiimotes, + Wiimote*& found_board) { found_wiimotes.clear(); found_board = nullptr; @@ -87,11 +50,6 @@ void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote g_java_vm->DetachCurrentThread(); } -bool WiimoteScanner::IsReady() const -{ - return true; -} - WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index) { } diff --git a/Source/Core/Core/HW/WiimoteReal/IOAndroid.h b/Source/Core/Core/HW/WiimoteReal/IOAndroid.h new file mode 100644 index 0000000000..988d8794ed --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IOAndroid.h @@ -0,0 +1,57 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#ifdef ANDROID +#include + +#include "Core/HW/WiimoteReal/WiimoteReal.h" + +namespace WiimoteReal +{ +class WiimoteAndroid final : public Wiimote +{ +public: + WiimoteAndroid(int index); + ~WiimoteAndroid() override; + +protected: + bool ConnectInternal() override; + void DisconnectInternal() override; + bool IsConnected() const override; + void IOWakeup() override{}; + int IORead(u8* buf) override; + int IOWrite(u8 const* buf, size_t len) override; + +private: + int m_mayflash_index; + bool is_connected = true; + + JNIEnv* m_env; + + jmethodID m_input_func; + jmethodID m_output_func; + + jbyteArray m_java_wiimote_payload; +}; + +class WiimoteScannerAndroid final : public WiimoteScannerBackend +{ +public: + WiimoteScannerAndroid() = default; + ~WiimoteScannerAndroid() override = default; + bool IsReady() const override { return true; } + void FindWiimotes(std::vector&, Wiimote*&) override; + void Update() override {} +}; +} + +#else +#include "Core/HW/WiimoteReal/IODummy.h" +namespace WiimoteReal +{ +using WiimoteScannerAndroid = WiimoteScannerDummy; +} +#endif diff --git a/Source/Core/Core/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/HW/WiimoteReal/IODummy.cpp deleted file mode 100644 index 9f0ed27f56..0000000000 --- a/Source/Core/Core/HW/WiimoteReal/IODummy.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "Common/CommonTypes.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" - -namespace WiimoteReal -{ -WiimoteScanner::WiimoteScanner() -{ -} - -WiimoteScanner::~WiimoteScanner() -{ -} - -void WiimoteScanner::Update() -{ -} - -void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) -{ - found_wiimotes.clear(); - found_board = nullptr; -} - -bool WiimoteScanner::IsReady() const -{ - return false; -} -}; diff --git a/Source/Core/Core/HW/WiimoteReal/IODummy.h b/Source/Core/Core/HW/WiimoteReal/IODummy.h new file mode 100644 index 0000000000..97cd5b1e88 --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IODummy.h @@ -0,0 +1,20 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Core/HW/WiimoteReal/WiimoteReal.h" + +namespace WiimoteReal +{ +class WiimoteScannerDummy final : public WiimoteScannerBackend +{ +public: + WiimoteScannerDummy() = default; + ~WiimoteScannerDummy() override = default; + bool IsReady() const override { return false; } + void FindWiimotes(std::vector&, Wiimote*&) override {} + void Update() override {} +}; +} diff --git a/Source/Core/Core/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/HW/WiimoteReal/IONix.cpp index 2313914a0f..76dd255c9d 100644 --- a/Source/Core/Core/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IONix.cpp @@ -2,78 +2,49 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. -#ifndef _WIN32 -#include -#endif #include #include #include #include +#include #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" +#include "Core/HW/WiimoteReal/IONix.h" namespace WiimoteReal { -class WiimoteLinux final : public Wiimote -{ -public: - WiimoteLinux(bdaddr_t bdaddr); - ~WiimoteLinux() override; - const bdaddr_t& Address() const; - -protected: - bool ConnectInternal() override; - void DisconnectInternal() override; - bool IsConnected() const override; - void IOWakeup() override; - int IORead(u8* buf) override; - int IOWrite(u8 const* buf, size_t len) override; - -private: - bdaddr_t m_bdaddr; // Bluetooth address - int m_cmd_sock; // Command socket - int m_int_sock; // Interrupt socket - int m_wakeup_pipe_w; - int m_wakeup_pipe_r; -}; - -WiimoteScanner::WiimoteScanner() : device_id(-1), device_sock(-1) +WiimoteScannerLinux::WiimoteScannerLinux() : m_device_id(-1), m_device_sock(-1) { // Get the id of the first Bluetooth device. - device_id = hci_get_route(nullptr); - if (device_id < 0) + m_device_id = hci_get_route(nullptr); + if (m_device_id < 0) { NOTICE_LOG(WIIMOTE, "Bluetooth not found."); return; } // Create a socket to the device - device_sock = hci_open_dev(device_id); - if (device_sock < 0) + m_device_sock = hci_open_dev(m_device_id); + if (m_device_sock < 0) { ERROR_LOG(WIIMOTE, "Unable to open Bluetooth."); return; } } -bool WiimoteScanner::IsReady() const -{ - return device_sock > 0; -} - -WiimoteScanner::~WiimoteScanner() +WiimoteScannerLinux::~WiimoteScannerLinux() { if (IsReady()) - close(device_sock); + close(m_device_sock); } -void WiimoteScanner::Update() +bool WiimoteScannerLinux::IsReady() const { + return m_device_sock > 0; } -void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) +void WiimoteScannerLinux::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) { // supposedly 1.28 seconds int const wait_len = 1; @@ -88,7 +59,7 @@ void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote // Scan for Bluetooth devices int const found_devices = - hci_inquiry(device_id, wait_len, max_infos, lap, &scan_infos_ptr, IREQ_CACHE_FLUSH); + hci_inquiry(m_device_id, wait_len, max_infos, lap, &scan_infos_ptr, IREQ_CACHE_FLUSH); if (found_devices < 0) { ERROR_LOG(WIIMOTE, "Error searching for Bluetooth devices."); @@ -104,7 +75,7 @@ void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote // BT names are a maximum of 248 bytes apparently char name[255] = {}; - if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0) + if (hci_read_remote_name(m_device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0) { ERROR_LOG(WIIMOTE, "name request failed"); continue; diff --git a/Source/Core/Core/HW/WiimoteReal/IONix.h b/Source/Core/Core/HW/WiimoteReal/IONix.h new file mode 100644 index 0000000000..dde31f8e18 --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IONix.h @@ -0,0 +1,58 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#if defined(__linux__) && HAVE_BLUEZ +#include + +#include "Core/HW/WiimoteReal/WiimoteReal.h" + +namespace WiimoteReal +{ +class WiimoteLinux final : public Wiimote +{ +public: + WiimoteLinux(bdaddr_t bdaddr); + ~WiimoteLinux() override; + const bdaddr_t& Address() const; + +protected: + bool ConnectInternal() override; + void DisconnectInternal() override; + bool IsConnected() const override; + void IOWakeup() override; + int IORead(u8* buf) override; + int IOWrite(u8 const* buf, size_t len) override; + +private: + bdaddr_t m_bdaddr; // Bluetooth address + int m_cmd_sock; // Command socket + int m_int_sock; // Interrupt socket + int m_wakeup_pipe_w; + int m_wakeup_pipe_r; +}; + +class WiimoteScannerLinux final : public WiimoteScannerBackend +{ +public: + WiimoteScannerLinux(); + ~WiimoteScannerLinux() override; + bool IsReady() const override; + void FindWiimotes(std::vector&, Wiimote*&) override; + void Update() override{}; // not needed on Linux + +private: + int m_device_id; + int m_device_sock; +}; +} + +#else +#include "Core/HW/WiimoteReal/IODummy.h" +namespace WiimoteReal +{ +using WiimoteScannerLinux = WiimoteScannerDummy; +} +#endif diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index e57d549d94..b0e6e4d4ef 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -27,8 +27,7 @@ #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "Common/Thread.h" -#include "Core/HW/WiimoteEmu/WiimoteHid.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" +#include "Core/HW/WiimoteReal/IOWin.h" //#define AUTHENTICATE_WIIMOTES #define SHARE_WRITE_WIIMOTES @@ -192,28 +191,6 @@ inline void init_lib() namespace WiimoteReal { -class WiimoteWindows final : public Wiimote -{ -public: - WiimoteWindows(const std::basic_string& path, WinWriteMethod initial_write_method); - ~WiimoteWindows() override; - -protected: - bool ConnectInternal() override; - void DisconnectInternal() override; - bool IsConnected() const override; - void IOWakeup() override; - int IORead(u8* buf) override; - int IOWrite(u8 const* buf, size_t len) override; - -private: - std::basic_string m_devicepath; // Unique Wiimote reference - HANDLE m_dev_handle; // HID handle - OVERLAPPED m_hid_overlap_read; // Overlap handles - OVERLAPPED m_hid_overlap_write; - WinWriteMethod m_write_method; // Type of Write Method to use -}; - int IOWrite(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write, enum WinWriteMethod& stack, const u8* buf, size_t len, DWORD* written); int IORead(HANDLE& dev_handle, OVERLAPPED& hid_overlap_read, u8* buf, int index); @@ -225,12 +202,12 @@ bool AttachWiimote(HANDLE hRadio, const BLUETOOTH_RADIO_INFO&, BLUETOOTH_DEVICE_ void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&); -WiimoteScanner::WiimoteScanner() +WiimoteScannerWindows::WiimoteScannerWindows() { init_lib(); } -WiimoteScanner::~WiimoteScanner() +WiimoteScannerWindows::~WiimoteScannerWindows() { // TODO: what do we want here? #if 0 @@ -241,7 +218,7 @@ WiimoteScanner::~WiimoteScanner() #endif } -void WiimoteScanner::Update() +void WiimoteScannerWindows::Update() { if (!s_loaded_ok) return; @@ -371,7 +348,8 @@ static WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack) // Does not replace already found Wiimotes even if they are disconnected. // wm is an array of max_wiimotes Wiimotes // Returns the total number of found and connected Wiimotes. -void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) +void WiimoteScannerWindows::FindWiimotes(std::vector& found_wiimotes, + Wiimote*& found_board) { if (!s_loaded_ok) return; @@ -480,8 +458,9 @@ int CheckDeviceType_Read(HANDLE& dev_handle, u8* buf, int attempts) // Wiimote. // Because nothing on Windows should be easy. // (We can't seem to easily identify the Bluetooth device an HID device belongs to...) -void WiimoteScanner::CheckDeviceType(std::basic_string& devicepath, - WinWriteMethod& write_method, bool& real_wiimote, bool& is_bb) +void WiimoteScannerWindows::CheckDeviceType(std::basic_string& devicepath, + WinWriteMethod& write_method, bool& real_wiimote, + bool& is_bb) { real_wiimote = false; is_bb = false; @@ -606,7 +585,7 @@ void WiimoteScanner::CheckDeviceType(std::basic_string& devicepath, CloseHandle(dev_handle); } -bool WiimoteScanner::IsReady() const +bool WiimoteScannerWindows::IsReady() const { if (!s_loaded_ok) { diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.h b/Source/Core/Core/HW/WiimoteReal/IOWin.h new file mode 100644 index 0000000000..b3561c7f0c --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.h @@ -0,0 +1,66 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#ifdef _WIN32 +#include + +#include "Core/HW/WiimoteEmu/WiimoteHid.h" +#include "Core/HW/WiimoteReal/WiimoteReal.h" + +namespace WiimoteReal +{ +// Different methods to send data Wiimote on Windows depending on OS and Bluetooth Stack +enum WinWriteMethod +{ + WWM_WRITE_FILE_LARGEST_REPORT_SIZE, + WWM_WRITE_FILE_ACTUAL_REPORT_SIZE, + WWM_SET_OUTPUT_REPORT +}; + +class WiimoteWindows final : public Wiimote +{ +public: + WiimoteWindows(const std::basic_string& path, WinWriteMethod initial_write_method); + ~WiimoteWindows() override; + +protected: + bool ConnectInternal() override; + void DisconnectInternal() override; + bool IsConnected() const override; + void IOWakeup() override; + int IORead(u8* buf) override; + int IOWrite(u8 const* buf, size_t len) override; + +private: + std::basic_string m_devicepath; // Unique Wiimote reference + HANDLE m_dev_handle; // HID handle + OVERLAPPED m_hid_overlap_read; // Overlap handles + OVERLAPPED m_hid_overlap_write; + WinWriteMethod m_write_method; // Type of Write Method to use +}; + +class WiimoteScannerWindows final : public WiimoteScannerBackend +{ +public: + WiimoteScannerWindows(); + ~WiimoteScannerWindows() override; + bool IsReady() const override; + void FindWiimotes(std::vector&, Wiimote*&) override; + void Update() override; + +private: + void CheckDeviceType(std::basic_string& devicepath, WinWriteMethod& write_method, + bool& real_wiimote, bool& is_bb); +}; +} + +#else +#include "Core/HW/WiimoteReal/IODummy.h" +namespace WiimoteReal +{ +using WiimoteScannerWindows = WiimoteScannerDummy; +} +#endif diff --git a/Source/Core/Core/HW/WiimoteReal/IOdarwin.h b/Source/Core/Core/HW/WiimoteReal/IOdarwin.h new file mode 100644 index 0000000000..de450d63de --- /dev/null +++ b/Source/Core/Core/HW/WiimoteReal/IOdarwin.h @@ -0,0 +1,95 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#ifdef __APPLE__ +// Work around an Apple bug: for some reason, IOBluetooth.h errors on +// inclusion in Mavericks, but only in Objective-C++ C++11 mode. I filed +// this as ; in the meantime... +#import +#undef NS_ENUM_AVAILABLE +#define NS_ENUM_AVAILABLE(...) +// end hack +#import +#include +#include + +#include "Core/HW/WiimoteReal/WiimoteReal.h" + +namespace WiimoteReal +{ +class WiimoteDarwin final : public Wiimote +{ +public: + WiimoteDarwin(IOBluetoothDevice* device); + ~WiimoteDarwin() override; + + // These are not protected/private because ConnectBT needs them. + void DisconnectInternal() override; + IOBluetoothDevice* m_btd; + unsigned char* m_input; + int m_inputlen; + +protected: + bool ConnectInternal() override; + bool IsConnected() const override; + void IOWakeup() override; + int IORead(u8* buf) override; + int IOWrite(u8 const* buf, size_t len) override; + void EnablePowerAssertionInternal() override; + void DisablePowerAssertionInternal() override; + +private: + IOBluetoothL2CAPChannel* m_ichan; + IOBluetoothL2CAPChannel* m_cchan; + bool m_connected; + CFRunLoopRef m_wiimote_thread_run_loop; + IOPMAssertionID m_pm_assertion; +}; + +class WiimoteDarwinHid final : public Wiimote +{ +public: + WiimoteDarwinHid(IOHIDDeviceRef device); + ~WiimoteDarwinHid() override; + +protected: + bool ConnectInternal() override; + void DisconnectInternal() override; + bool IsConnected() const override; + void IOWakeup() override; + int IORead(u8* buf) override; + int IOWrite(u8 const* buf, size_t len) override; + +private: + static void ReportCallback(void* context, IOReturn result, void* sender, IOHIDReportType type, + u32 reportID, u8* report, CFIndex reportLength); + static void RemoveCallback(void* context, IOReturn result, void* sender); + void QueueBufferReport(int length); + IOHIDDeviceRef m_device; + bool m_connected; + std::atomic m_interrupted; + Report m_report_buffer; + Common::FifoQueue m_buffered_reports; +}; + +class WiimoteScannerDarwin final : public WiimoteScannerBackend +{ +public: + WiimoteScannerDarwin() = default; + ~WiimoteScannerDarwin() override = default; + bool IsReady() const override; + void FindWiimotes(std::vector&, Wiimote*&) override; + void Update() override{}; // not needed +}; +} + +#else +#include "Core/HW/WiimoteReal/IODummy.h" +namespace WiimoteReal +{ +using WiimoteScannerDarwin = WiimoteScannerDummy; +} +#endif diff --git a/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm index afc066e326..073b3f38e9 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/HW/WiimoteReal/IOdarwin.mm @@ -1,9 +1,9 @@ #define BLUETOOTH_VERSION_USE_CURRENT +#include "Core/HW/WiimoteReal/IOdarwin.h" #include "Common/Common.h" #include "Common/Logging/Log.h" #include "Core/HW/WiimoteEmu/WiimoteHid.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" @interface SearchBT : NSObject { @@ -20,74 +20,8 @@ namespace WiimoteReal { -class WiimoteDarwin final : public Wiimote -{ -public: - WiimoteDarwin(IOBluetoothDevice* device); - ~WiimoteDarwin() override; - - // These are not protected/private because ConnectBT needs them. - void DisconnectInternal() override; - IOBluetoothDevice* m_btd; - unsigned char* m_input; - int m_inputlen; - -protected: - bool ConnectInternal() override; - bool IsConnected() const override; - void IOWakeup() override; - int IORead(u8* buf) override; - int IOWrite(u8 const* buf, size_t len) override; - void EnablePowerAssertionInternal() override; - void DisablePowerAssertionInternal() override; - -private: - IOBluetoothL2CAPChannel* m_ichan; - IOBluetoothL2CAPChannel* m_cchan; - bool m_connected; - CFRunLoopRef m_wiimote_thread_run_loop; - IOPMAssertionID m_pm_assertion; -}; - -class WiimoteDarwinHid final : public Wiimote -{ -public: - WiimoteDarwinHid(IOHIDDeviceRef device); - ~WiimoteDarwinHid() override; - -protected: - bool ConnectInternal() override; - void DisconnectInternal() override; - bool IsConnected() const override; - void IOWakeup() override; - int IORead(u8* buf) override; - int IOWrite(u8 const* buf, size_t len) override; - -private: - static void ReportCallback(void* context, IOReturn result, void* sender, IOHIDReportType type, - u32 reportID, u8* report, CFIndex reportLength); - static void RemoveCallback(void* context, IOReturn result, void* sender); - void QueueBufferReport(int length); - IOHIDDeviceRef m_device; - bool m_connected; - std::atomic m_interrupted; - Report m_report_buffer; - Common::FifoQueue m_buffered_reports; -}; - -WiimoteScanner::WiimoteScanner() -{ -} - -WiimoteScanner::~WiimoteScanner() -{ -} - -void WiimoteScanner::Update() -{ -} - -void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote*& found_board) +void WiimoteScannerDarwin::FindWiimotes(std::vector& found_wiimotes, + Wiimote*& found_board) { // TODO: find the device in the constructor and save it for later IOBluetoothHostController* bth; @@ -199,7 +133,7 @@ void WiimoteScanner::FindWiimotes(std::vector& found_wiimotes, Wiimote } } -bool WiimoteScanner::IsReady() const +bool WiimoteScannerDarwin::IsReady() const { // TODO: only return true when a BT device is present return true; diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index af62ece6ba..d1ee896ca2 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -6,6 +6,8 @@ #include #include +#include "Core/HW/WiimoteReal/WiimoteReal.h" + #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/IniFile.h" @@ -15,7 +17,10 @@ #include "Core/Core.h" #include "Core/HW/WiimoteEmu/WiimoteEmu.h" #include "Core/HW/WiimoteEmu/WiimoteHid.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" +#include "Core/HW/WiimoteReal/IOAndroid.h" +#include "Core/HW/WiimoteReal/IONix.h" +#include "Core/HW/WiimoteReal/IOWin.h" +#include "Core/HW/WiimoteReal/IOdarwin.h" #include "Core/Host.h" #include "InputCommon/InputConfig.h" @@ -452,6 +457,17 @@ void WiimoteScanner::SetScanMode(WiimoteScanMode scan_mode) m_scan_mode_changed_event.Set(); } +bool WiimoteScanner::IsReady() const +{ + return std::any_of(m_scanner_backends.begin(), m_scanner_backends.end(), + [](const auto& backend) { return backend->IsReady(); }); +} + +void WiimoteScanner::AddScannerBackend(std::unique_ptr backend) +{ + m_scanner_backends.emplace_back(std::move(backend)); +} + static void CheckForDisconnectedWiimotes() { std::lock_guard lk(g_wiimotes_mutex); @@ -475,21 +491,24 @@ void WiimoteScanner::ThreadFunc() if (m_scan_mode.load() == WiimoteScanMode::DO_NOT_SCAN) continue; - if (CalculateWantedWiimotes() != 0 || CalculateWantedBB() != 0) + for (const auto& backend : m_scanner_backends) { - std::vector found_wiimotes; - Wiimote* found_board = nullptr; - FindWiimotes(found_wiimotes, found_board); + if (CalculateWantedWiimotes() != 0 || CalculateWantedBB() != 0) { - std::lock_guard lk(g_wiimotes_mutex); - std::for_each(found_wiimotes.begin(), found_wiimotes.end(), TryToConnectWiimote); - if (found_board) - TryToConnectBalanceBoard(found_board); + std::vector found_wiimotes; + Wiimote* found_board = nullptr; + backend->FindWiimotes(found_wiimotes, found_board); + { + std::lock_guard lk(g_wiimotes_mutex); + std::for_each(found_wiimotes.begin(), found_wiimotes.end(), TryToConnectWiimote); + if (found_board) + TryToConnectBalanceBoard(found_board); + } + } + else + { + backend->Update(); // Does stuff needed to detect disconnects on Windows } - } - else - { - Update(); // Does stuff needed to detect disconnects on Windows } if (m_scan_mode.load() == WiimoteScanMode::SCAN_ONCE) @@ -615,7 +634,13 @@ void LoadSettings() void Initialize(::Wiimote::InitializeMode init_mode) { if (!g_real_wiimotes_initialized) + { + g_wiimote_scanner.AddScannerBackend(std::make_unique()); + g_wiimote_scanner.AddScannerBackend(std::make_unique()); + g_wiimote_scanner.AddScannerBackend(std::make_unique()); + g_wiimote_scanner.AddScannerBackend(std::make_unique()); g_wiimote_scanner.StartThread(); + } if (SConfig::GetInstance().m_WiimoteContinuousScanning) g_wiimote_scanner.SetScanMode(WiimoteScanMode::CONTINUOUSLY_SCAN); diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index b576788157..36ef8ca3c0 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -114,6 +114,16 @@ private: Common::FifoQueue m_write_reports; }; +class WiimoteScannerBackend +{ +public: + virtual ~WiimoteScannerBackend() = default; + virtual bool IsReady() const = 0; + virtual void FindWiimotes(std::vector&, Wiimote*&) = 0; + // function called when not looking for more Wiimotes + virtual void Update() = 0; +}; + enum class WiimoteScanMode { DO_NOT_SCAN, @@ -124,36 +134,23 @@ enum class WiimoteScanMode class WiimoteScanner { public: - WiimoteScanner(); - ~WiimoteScanner(); - - bool IsReady() const; - + WiimoteScanner() = default; void StartThread(); void StopThread(); void SetScanMode(WiimoteScanMode scan_mode); - void FindWiimotes(std::vector&, Wiimote*&); - - // function called when not looking for more Wiimotes - void Update(); + void AddScannerBackend(std::unique_ptr backend); + bool IsReady() const; private: void ThreadFunc(); - std::thread m_scan_thread; + Common::Flag m_scan_thread_running; Common::Event m_scan_mode_changed_event; - Common::Flag m_scan_thread_running; std::atomic m_scan_mode{WiimoteScanMode::DO_NOT_SCAN}; -#if defined(_WIN32) - void CheckDeviceType(std::basic_string& devicepath, WinWriteMethod& write_method, - bool& real_wiimote, bool& is_bb); -#elif defined(__linux__) && HAVE_BLUEZ - int device_id; - int device_sock; -#endif + std::vector> m_scanner_backends; }; extern std::mutex g_wiimotes_mutex; diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteRealBase.h b/Source/Core/Core/HW/WiimoteReal/WiimoteRealBase.h index 092eda0504..1f34d36fe4 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteRealBase.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteRealBase.h @@ -4,23 +4,6 @@ #pragma once -#ifdef _WIN32 -#include -#elif defined(__APPLE__) -// Work around an Apple bug: for some reason, IOBluetooth.h errors on -// inclusion in Mavericks, but only in Objective-C++ C++11 mode. I filed -// this as ; in the meantime... -#import -#undef NS_ENUM_AVAILABLE -#define NS_ENUM_AVAILABLE(...) -// end hack -#import -#include -#include -#elif defined(__linux__) && HAVE_BLUEZ -#include -#endif - // Wiimote internal codes // Communication channels @@ -51,13 +34,3 @@ // It's 23. NOT 32! #define MAX_PAYLOAD 23 #define WIIMOTE_DEFAULT_TIMEOUT 1000 - -#ifdef _WIN32 -// Different methods to send data Wiimote on Windows depending on OS and Bluetooth Stack -enum WinWriteMethod -{ - WWM_WRITE_FILE_LARGEST_REPORT_SIZE, - WWM_WRITE_FILE_ACTUAL_REPORT_SIZE, - WWM_SET_OUTPUT_REPORT -}; -#endif