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.
This commit is contained in:
Léo Lam 2016-07-23 19:07:14 +02:00
parent 0e7b10064d
commit 9455e2bca4
14 changed files with 380 additions and 281 deletions

View File

@ -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()

View File

@ -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<Wiimote*>& found_wiimotes, Wiimote*& found_board)
void WiimoteScannerAndroid::FindWiimotes(std::vector<Wiimote*>& found_wiimotes,
Wiimote*& found_board)
{
found_wiimotes.clear();
found_board = nullptr;
@ -87,11 +50,6 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote
g_java_vm->DetachCurrentThread();
}
bool WiimoteScanner::IsReady() const
{
return true;
}
WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index)
{
}

View File

@ -0,0 +1,57 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#ifdef ANDROID
#include <jni.h>
#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*>&, Wiimote*&) override;
void Update() override {}
};
}
#else
#include "Core/HW/WiimoteReal/IODummy.h"
namespace WiimoteReal
{
using WiimoteScannerAndroid = WiimoteScannerDummy;
}
#endif

View File

@ -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<Wiimote*>& found_wiimotes, Wiimote*& found_board)
{
found_wiimotes.clear();
found_board = nullptr;
}
bool WiimoteScanner::IsReady() const
{
return false;
}
};

View File

@ -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*>&, Wiimote*&) override {}
void Update() override {}
};
}

View File

@ -2,78 +2,49 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#ifndef _WIN32
#include <unistd.h>
#endif
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/l2cap.h>
#include <unistd.h>
#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<Wiimote*>& found_wiimotes, Wiimote*& found_board)
void WiimoteScannerLinux::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote*& found_board)
{
// supposedly 1.28 seconds
int const wait_len = 1;
@ -88,7 +59,7 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& 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<Wiimote*>& 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;

View File

@ -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 <bluetooth/bluetooth.h>
#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*>&, 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

View File

@ -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<TCHAR>& 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<TCHAR> 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<Wiimote*>& found_wiimotes, Wiimote*& found_board)
void WiimoteScannerWindows::FindWiimotes(std::vector<Wiimote*>& 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<TCHAR>& devicepath,
WinWriteMethod& write_method, bool& real_wiimote, bool& is_bb)
void WiimoteScannerWindows::CheckDeviceType(std::basic_string<TCHAR>& 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<TCHAR>& devicepath,
CloseHandle(dev_handle);
}
bool WiimoteScanner::IsReady() const
bool WiimoteScannerWindows::IsReady() const
{
if (!s_loaded_ok)
{

View File

@ -0,0 +1,66 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#ifdef _WIN32
#include <windows.h>
#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<TCHAR>& 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<TCHAR> 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*>&, Wiimote*&) override;
void Update() override;
private:
void CheckDeviceType(std::basic_string<TCHAR>& devicepath, WinWriteMethod& write_method,
bool& real_wiimote, bool& is_bb);
};
}
#else
#include "Core/HW/WiimoteReal/IODummy.h"
namespace WiimoteReal
{
using WiimoteScannerWindows = WiimoteScannerDummy;
}
#endif

View File

@ -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 <rdar://15312520>; in the meantime...
#import <Foundation/Foundation.h>
#undef NS_ENUM_AVAILABLE
#define NS_ENUM_AVAILABLE(...)
// end hack
#import <IOBluetooth/IOBluetooth.h>
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#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<bool> m_interrupted;
Report m_report_buffer;
Common::FifoQueue<Report> m_buffered_reports;
};
class WiimoteScannerDarwin final : public WiimoteScannerBackend
{
public:
WiimoteScannerDarwin() = default;
~WiimoteScannerDarwin() override = default;
bool IsReady() const override;
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
void Update() override{}; // not needed
};
}
#else
#include "Core/HW/WiimoteReal/IODummy.h"
namespace WiimoteReal
{
using WiimoteScannerDarwin = WiimoteScannerDummy;
}
#endif

View File

@ -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<bool> m_interrupted;
Report m_report_buffer;
Common::FifoQueue<Report> m_buffered_reports;
};
WiimoteScanner::WiimoteScanner()
{
}
WiimoteScanner::~WiimoteScanner()
{
}
void WiimoteScanner::Update()
{
}
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote*& found_board)
void WiimoteScannerDarwin::FindWiimotes(std::vector<Wiimote*>& 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<Wiimote*>& found_wiimotes, Wiimote
}
}
bool WiimoteScanner::IsReady() const
bool WiimoteScannerDarwin::IsReady() const
{
// TODO: only return true when a BT device is present
return true;

View File

@ -6,6 +6,8 @@
#include <cstdlib>
#include <queue>
#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<WiimoteScannerBackend> backend)
{
m_scanner_backends.emplace_back(std::move(backend));
}
static void CheckForDisconnectedWiimotes()
{
std::lock_guard<std::mutex> 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<Wiimote*> found_wiimotes;
Wiimote* found_board = nullptr;
FindWiimotes(found_wiimotes, found_board);
if (CalculateWantedWiimotes() != 0 || CalculateWantedBB() != 0)
{
std::lock_guard<std::mutex> lk(g_wiimotes_mutex);
std::for_each(found_wiimotes.begin(), found_wiimotes.end(), TryToConnectWiimote);
if (found_board)
TryToConnectBalanceBoard(found_board);
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = nullptr;
backend->FindWiimotes(found_wiimotes, found_board);
{
std::lock_guard<std::mutex> 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<WiimoteScannerLinux>());
g_wiimote_scanner.AddScannerBackend(std::make_unique<WiimoteScannerAndroid>());
g_wiimote_scanner.AddScannerBackend(std::make_unique<WiimoteScannerWindows>());
g_wiimote_scanner.AddScannerBackend(std::make_unique<WiimoteScannerDarwin>());
g_wiimote_scanner.StartThread();
}
if (SConfig::GetInstance().m_WiimoteContinuousScanning)
g_wiimote_scanner.SetScanMode(WiimoteScanMode::CONTINUOUSLY_SCAN);

View File

@ -114,6 +114,16 @@ private:
Common::FifoQueue<Report> m_write_reports;
};
class WiimoteScannerBackend
{
public:
virtual ~WiimoteScannerBackend() = default;
virtual bool IsReady() const = 0;
virtual void FindWiimotes(std::vector<Wiimote*>&, 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*>&, Wiimote*&);
// function called when not looking for more Wiimotes
void Update();
void AddScannerBackend(std::unique_ptr<WiimoteScannerBackend> 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<WiimoteScanMode> m_scan_mode{WiimoteScanMode::DO_NOT_SCAN};
#if defined(_WIN32)
void CheckDeviceType(std::basic_string<TCHAR>& devicepath, WinWriteMethod& write_method,
bool& real_wiimote, bool& is_bb);
#elif defined(__linux__) && HAVE_BLUEZ
int device_id;
int device_sock;
#endif
std::vector<std::unique_ptr<WiimoteScannerBackend>> m_scanner_backends;
};
extern std::mutex g_wiimotes_mutex;

View File

@ -4,23 +4,6 @@
#pragma once
#ifdef _WIN32
#include <windows.h>
#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 <rdar://15312520>; in the meantime...
#import <Foundation/Foundation.h>
#undef NS_ENUM_AVAILABLE
#define NS_ENUM_AVAILABLE(...)
// end hack
#import <IOBluetooth/IOBluetooth.h>
#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#elif defined(__linux__) && HAVE_BLUEZ
#include <bluetooth/bluetooth.h>
#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