Merge pull request #4054 from leoetlino/wiimote-scanner
WiimoteReal: Change the scanner to support several backends
This commit is contained in:
commit
ad1c5a8e2e
|
@ -256,12 +256,10 @@ elseif(APPLE)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(SRCS ${SRCS} HW/BBA-TAP/TAP_Unix.cpp)
|
set(SRCS ${SRCS} HW/BBA-TAP/TAP_Unix.cpp)
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND BLUEZ_FOUND)
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND BLUEZ_FOUND)
|
||||||
set(SRCS ${SRCS} HW/WiimoteReal/IONix.cpp)
|
set(SRCS ${SRCS} HW/WiimoteReal/IOLinux.cpp)
|
||||||
set(LIBS ${LIBS} bluetooth)
|
set(LIBS ${LIBS} bluetooth)
|
||||||
elseif(ANDROID)
|
elseif(ANDROID)
|
||||||
set(SRCS ${SRCS} HW/WiimoteReal/IOAndroid.cpp)
|
set(SRCS ${SRCS} HW/WiimoteReal/IOAndroid.cpp)
|
||||||
else()
|
|
||||||
set(SRCS ${SRCS} HW/WiimoteReal/IODummy.cpp)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
#include "Common/Timer.h"
|
#include "Common/Timer.h"
|
||||||
|
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
#include "Core/HW/WiimoteReal/IOAndroid.h"
|
||||||
|
|
||||||
// Global java_vm class
|
// Global java_vm class
|
||||||
extern JavaVM* g_java_vm;
|
extern JavaVM* g_java_vm;
|
||||||
|
@ -22,45 +22,8 @@ namespace WiimoteReal
|
||||||
// Java classes
|
// Java classes
|
||||||
static jclass s_adapter_class;
|
static jclass s_adapter_class;
|
||||||
|
|
||||||
class WiimoteAndroid final : public Wiimote
|
void WiimoteScannerAndroid::FindWiimotes(std::vector<Wiimote*>& found_wiimotes,
|
||||||
{
|
Wiimote*& found_board)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
found_wiimotes.clear();
|
found_wiimotes.clear();
|
||||||
found_board = nullptr;
|
found_board = nullptr;
|
||||||
|
@ -87,11 +50,6 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote
|
||||||
g_java_vm->DetachCurrentThread();
|
g_java_vm->DetachCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiimoteScanner::IsReady() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index)
|
WiimoteAndroid::WiimoteAndroid(int index) : Wiimote(), m_mayflash_index(index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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 {}
|
||||||
|
};
|
||||||
|
}
|
|
@ -2,78 +2,57 @@
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
#include <bluetooth/hci.h>
|
#include <bluetooth/hci.h>
|
||||||
#include <bluetooth/hci_lib.h>
|
#include <bluetooth/hci_lib.h>
|
||||||
#include <bluetooth/l2cap.h>
|
#include <bluetooth/l2cap.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
#include "Core/HW/WiimoteReal/IOLinux.h"
|
||||||
|
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
class WiimoteLinux final : public Wiimote
|
// This is used to store the Bluetooth address of connected Wiimotes,
|
||||||
|
// so we can ignore Wiimotes that are already connected.
|
||||||
|
static std::vector<std::string> s_known_addrs;
|
||||||
|
static bool IsNewWiimote(const std::string& addr)
|
||||||
{
|
{
|
||||||
public:
|
return std::find(s_known_addrs.begin(), s_known_addrs.end(), addr) == s_known_addrs.end();
|
||||||
WiimoteLinux(bdaddr_t bdaddr);
|
}
|
||||||
~WiimoteLinux() override;
|
|
||||||
const bdaddr_t& Address() const;
|
|
||||||
|
|
||||||
protected:
|
WiimoteScannerLinux::WiimoteScannerLinux() : m_device_id(-1), m_device_sock(-1)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Get the id of the first Bluetooth device.
|
// Get the id of the first Bluetooth device.
|
||||||
device_id = hci_get_route(nullptr);
|
m_device_id = hci_get_route(nullptr);
|
||||||
if (device_id < 0)
|
if (m_device_id < 0)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(WIIMOTE, "Bluetooth not found.");
|
NOTICE_LOG(WIIMOTE, "Bluetooth not found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a socket to the device
|
// Create a socket to the device
|
||||||
device_sock = hci_open_dev(device_id);
|
m_device_sock = hci_open_dev(m_device_id);
|
||||||
if (device_sock < 0)
|
if (m_device_sock < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to open Bluetooth.");
|
ERROR_LOG(WIIMOTE, "Unable to open Bluetooth.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiimoteScanner::IsReady() const
|
WiimoteScannerLinux::~WiimoteScannerLinux()
|
||||||
{
|
|
||||||
return device_sock > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiimoteScanner::~WiimoteScanner()
|
|
||||||
{
|
{
|
||||||
if (IsReady())
|
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
|
// supposedly 1.28 seconds
|
||||||
int const wait_len = 1;
|
int const wait_len = 1;
|
||||||
|
@ -88,7 +67,7 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote
|
||||||
|
|
||||||
// Scan for Bluetooth devices
|
// Scan for Bluetooth devices
|
||||||
int const found_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)
|
if (found_devices < 0)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Error searching for Bluetooth devices.");
|
ERROR_LOG(WIIMOTE, "Error searching for Bluetooth devices.");
|
||||||
|
@ -104,46 +83,34 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*>& found_wiimotes, Wiimote
|
||||||
|
|
||||||
// BT names are a maximum of 248 bytes apparently
|
// BT names are a maximum of 248 bytes apparently
|
||||||
char name[255] = {};
|
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");
|
ERROR_LOG(WIIMOTE, "name request failed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ERROR_LOG(WIIMOTE, "device name %s", name);
|
ERROR_LOG(WIIMOTE, "device name %s", name);
|
||||||
if (IsValidBluetoothName(name))
|
if (!IsValidBluetoothName(name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char bdaddr_str[18] = {};
|
||||||
|
ba2str(&scan_infos[i].bdaddr, bdaddr_str);
|
||||||
|
|
||||||
|
if (!IsNewWiimote(bdaddr_str))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Found a new device
|
||||||
|
s_known_addrs.push_back(bdaddr_str);
|
||||||
|
Wiimote* wm = new WiimoteLinux(scan_infos[i].bdaddr);
|
||||||
|
if (IsBalanceBoardName(name))
|
||||||
{
|
{
|
||||||
bool new_wiimote = true;
|
found_board = wm;
|
||||||
|
NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str);
|
||||||
// Determine if this Wiimote has already been found.
|
}
|
||||||
for (int j = 0; j < MAX_BBMOTES && new_wiimote; ++j)
|
else
|
||||||
{
|
{
|
||||||
// compare this address with the stored addresses in our global array
|
found_wiimotes.push_back(wm);
|
||||||
// static_cast is OK here, since we're only ever going to have this subclass in g_wiimotes
|
NOTICE_LOG(WIIMOTE, "Found Wiimote (%s).", bdaddr_str);
|
||||||
// on Linux (and likewise, only WiimoteWindows on Windows, etc)
|
|
||||||
auto connected_wiimote = static_cast<WiimoteLinux*>(g_wiimotes[j]);
|
|
||||||
if (connected_wiimote && bacmp(&scan_infos[i].bdaddr, &connected_wiimote->Address()) == 0)
|
|
||||||
new_wiimote = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_wiimote)
|
|
||||||
{
|
|
||||||
// Found a new device
|
|
||||||
char bdaddr_str[18] = {};
|
|
||||||
ba2str(&scan_infos[i].bdaddr, bdaddr_str);
|
|
||||||
|
|
||||||
Wiimote* wm = new WiimoteLinux(scan_infos[i].bdaddr);
|
|
||||||
if (IsBalanceBoardName(name))
|
|
||||||
{
|
|
||||||
found_board = wm;
|
|
||||||
NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
found_wiimotes.push_back(wm);
|
|
||||||
NOTICE_LOG(WIIMOTE, "Found Wiimote (%s).", bdaddr_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,11 +139,6 @@ WiimoteLinux::~WiimoteLinux()
|
||||||
close(m_wakeup_pipe_r);
|
close(m_wakeup_pipe_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bdaddr_t& WiimoteLinux::Address() const
|
|
||||||
{
|
|
||||||
return m_bdaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to a Wiimote with a known address.
|
// Connect to a Wiimote with a known address.
|
||||||
bool WiimoteLinux::ConnectInternal()
|
bool WiimoteLinux::ConnectInternal()
|
||||||
{
|
{
|
||||||
|
@ -218,6 +180,10 @@ void WiimoteLinux::DisconnectInternal()
|
||||||
|
|
||||||
m_cmd_sock = -1;
|
m_cmd_sock = -1;
|
||||||
m_int_sock = -1;
|
m_int_sock = -1;
|
||||||
|
char bdaddr_str[18] = {};
|
||||||
|
ba2str(&m_bdaddr, bdaddr_str);
|
||||||
|
s_known_addrs.erase(std::remove(s_known_addrs.begin(), s_known_addrs.end(), bdaddr_str),
|
||||||
|
s_known_addrs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiimoteLinux::IsConnected() const
|
bool WiimoteLinux::IsConnected() const
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
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
|
|
@ -27,8 +27,7 @@
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Thread.h"
|
#include "Common/Thread.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
|
#include "Core/HW/WiimoteReal/IOWin.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
|
||||||
|
|
||||||
//#define AUTHENTICATE_WIIMOTES
|
//#define AUTHENTICATE_WIIMOTES
|
||||||
#define SHARE_WRITE_WIIMOTES
|
#define SHARE_WRITE_WIIMOTES
|
||||||
|
@ -192,28 +191,6 @@ inline void init_lib()
|
||||||
|
|
||||||
namespace WiimoteReal
|
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,
|
int IOWrite(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write, enum WinWriteMethod& stack,
|
||||||
const u8* buf, size_t len, DWORD* written);
|
const u8* buf, size_t len, DWORD* written);
|
||||||
int IORead(HANDLE& dev_handle, OVERLAPPED& hid_overlap_read, u8* buf, int index);
|
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&);
|
void RemoveWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
||||||
bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
bool ForgetWiimote(BLUETOOTH_DEVICE_INFO_STRUCT&);
|
||||||
|
|
||||||
WiimoteScanner::WiimoteScanner()
|
WiimoteScannerWindows::WiimoteScannerWindows()
|
||||||
{
|
{
|
||||||
init_lib();
|
init_lib();
|
||||||
}
|
}
|
||||||
|
|
||||||
WiimoteScanner::~WiimoteScanner()
|
WiimoteScannerWindows::~WiimoteScannerWindows()
|
||||||
{
|
{
|
||||||
// TODO: what do we want here?
|
// TODO: what do we want here?
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -241,7 +218,7 @@ WiimoteScanner::~WiimoteScanner()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiimoteScanner::Update()
|
void WiimoteScannerWindows::Update()
|
||||||
{
|
{
|
||||||
if (!s_loaded_ok)
|
if (!s_loaded_ok)
|
||||||
return;
|
return;
|
||||||
|
@ -371,7 +348,8 @@ static WinWriteMethod GetInitialWriteMethod(bool IsUsingToshibaStack)
|
||||||
// Does not replace already found Wiimotes even if they are disconnected.
|
// Does not replace already found Wiimotes even if they are disconnected.
|
||||||
// wm is an array of max_wiimotes Wiimotes
|
// wm is an array of max_wiimotes Wiimotes
|
||||||
// Returns the total number of found and connected 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)
|
if (!s_loaded_ok)
|
||||||
return;
|
return;
|
||||||
|
@ -480,8 +458,9 @@ int CheckDeviceType_Read(HANDLE& dev_handle, u8* buf, int attempts)
|
||||||
// Wiimote.
|
// Wiimote.
|
||||||
// Because nothing on Windows should be easy.
|
// Because nothing on Windows should be easy.
|
||||||
// (We can't seem to easily identify the Bluetooth device an HID device belongs to...)
|
// (We can't seem to easily identify the Bluetooth device an HID device belongs to...)
|
||||||
void WiimoteScanner::CheckDeviceType(std::basic_string<TCHAR>& devicepath,
|
void WiimoteScannerWindows::CheckDeviceType(std::basic_string<TCHAR>& devicepath,
|
||||||
WinWriteMethod& write_method, bool& real_wiimote, bool& is_bb)
|
WinWriteMethod& write_method, bool& real_wiimote,
|
||||||
|
bool& is_bb)
|
||||||
{
|
{
|
||||||
real_wiimote = false;
|
real_wiimote = false;
|
||||||
is_bb = false;
|
is_bb = false;
|
||||||
|
@ -606,7 +585,7 @@ void WiimoteScanner::CheckDeviceType(std::basic_string<TCHAR>& devicepath,
|
||||||
CloseHandle(dev_handle);
|
CloseHandle(dev_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiimoteScanner::IsReady() const
|
bool WiimoteScannerWindows::IsReady() const
|
||||||
{
|
{
|
||||||
if (!s_loaded_ok)
|
if (!s_loaded_ok)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,106 @@
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
|
||||||
|
class WiimoteScannerDarwinHID final : public WiimoteScannerBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WiimoteScannerDarwinHID() = default;
|
||||||
|
~WiimoteScannerDarwinHID() 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;
|
||||||
|
using WiimoteScannerDarwinHID = WiimoteScannerDummy;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -1,9 +1,9 @@
|
||||||
#define BLUETOOTH_VERSION_USE_CURRENT
|
#define BLUETOOTH_VERSION_USE_CURRENT
|
||||||
|
|
||||||
|
#include "Core/HW/WiimoteReal/IOdarwin.h"
|
||||||
#include "Common/Common.h"
|
#include "Common/Common.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
|
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
|
||||||
|
|
||||||
@interface SearchBT : NSObject
|
@interface SearchBT : NSObject
|
||||||
{
|
{
|
||||||
|
@ -20,188 +20,123 @@
|
||||||
|
|
||||||
namespace WiimoteReal
|
namespace WiimoteReal
|
||||||
{
|
{
|
||||||
class WiimoteDarwin final : public Wiimote
|
void WiimoteScannerDarwin::FindWiimotes(std::vector<Wiimote*>& found_wiimotes,
|
||||||
{
|
Wiimote*& found_board)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// TODO: find the device in the constructor and save it for later
|
// TODO: find the device in the constructor and save it for later
|
||||||
IOBluetoothHostController* bth;
|
IOBluetoothHostController* bth;
|
||||||
IOBluetoothDeviceInquiry* bti;
|
IOBluetoothDeviceInquiry* bti;
|
||||||
IOHIDManagerRef hid;
|
|
||||||
SearchBT* sbt;
|
|
||||||
NSEnumerator* en;
|
|
||||||
found_board = nullptr;
|
found_board = nullptr;
|
||||||
|
|
||||||
bool btFailed = false;
|
|
||||||
bool hidFailed = false;
|
|
||||||
|
|
||||||
bth = [[IOBluetoothHostController alloc] init];
|
bth = [[IOBluetoothHostController alloc] init];
|
||||||
btFailed = [bth addressAsString] == nil;
|
bool btFailed = [bth addressAsString] == nil;
|
||||||
if (btFailed)
|
if (btFailed)
|
||||||
WARN_LOG(WIIMOTE, "No Bluetooth host controller");
|
|
||||||
|
|
||||||
hid = IOHIDManagerCreate(NULL, kIOHIDOptionsTypeNone);
|
|
||||||
hidFailed = CFGetTypeID(hid) != IOHIDManagerGetTypeID();
|
|
||||||
if (hidFailed)
|
|
||||||
WARN_LOG(WIIMOTE, "No HID manager");
|
|
||||||
|
|
||||||
if (hidFailed && btFailed)
|
|
||||||
{
|
{
|
||||||
CFRelease(hid);
|
WARN_LOG(WIIMOTE, "No Bluetooth host controller");
|
||||||
[bth release];
|
[bth release];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!btFailed)
|
SearchBT* sbt = [[SearchBT alloc] init];
|
||||||
|
sbt->maxDevices = 32;
|
||||||
|
bti = [[IOBluetoothDeviceInquiry alloc] init];
|
||||||
|
[bti setDelegate:sbt];
|
||||||
|
[bti setInquiryLength:2];
|
||||||
|
|
||||||
|
if ([bti start] != kIOReturnSuccess)
|
||||||
{
|
{
|
||||||
sbt = [[SearchBT alloc] init];
|
ERROR_LOG(WIIMOTE, "Unable to do Bluetooth discovery");
|
||||||
sbt->maxDevices = 32;
|
[bth release];
|
||||||
bti = [[IOBluetoothDeviceInquiry alloc] init];
|
[sbt release];
|
||||||
[bti setDelegate:sbt];
|
btFailed = true;
|
||||||
[bti setInquiryLength:2];
|
}
|
||||||
|
|
||||||
if ([bti start] != kIOReturnSuccess)
|
do
|
||||||
|
{
|
||||||
|
CFRunLoopRun();
|
||||||
|
} while (!sbt->done);
|
||||||
|
|
||||||
|
int found_devices = [[bti foundDevices] count];
|
||||||
|
|
||||||
|
if (found_devices)
|
||||||
|
NOTICE_LOG(WIIMOTE, "Found %i Bluetooth devices", found_devices);
|
||||||
|
|
||||||
|
NSEnumerator* en = [[bti foundDevices] objectEnumerator];
|
||||||
|
for (int i = 0; i < found_devices; i++)
|
||||||
|
{
|
||||||
|
IOBluetoothDevice* dev = [en nextObject];
|
||||||
|
if (!IsValidBluetoothName([[dev name] UTF8String]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Wiimote* wm = new WiimoteDarwin([dev retain]);
|
||||||
|
|
||||||
|
if (IsBalanceBoardName([[dev name] UTF8String]))
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to do Bluetooth discovery");
|
found_board = wm;
|
||||||
[bth release];
|
|
||||||
[sbt release];
|
|
||||||
btFailed = true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
do
|
|
||||||
{
|
{
|
||||||
CFRunLoopRun();
|
found_wiimotes.push_back(wm);
|
||||||
} while (!sbt->done);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int found_devices = [[bti foundDevices] count];
|
[bth release];
|
||||||
|
[bti release];
|
||||||
|
[sbt release];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiimoteScannerDarwin::IsReady() const
|
||||||
|
{
|
||||||
|
// TODO: only return true when a BT device is present
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiimoteScannerDarwinHID::FindWiimotes(std::vector<Wiimote*>& found_wiimotes,
|
||||||
|
Wiimote*& found_board)
|
||||||
|
{
|
||||||
|
found_board = nullptr;
|
||||||
|
|
||||||
|
IOHIDManagerRef hid = IOHIDManagerCreate(NULL, kIOHIDOptionsTypeNone);
|
||||||
|
bool hidFailed = CFGetTypeID(hid) != IOHIDManagerGetTypeID();
|
||||||
|
if (hidFailed)
|
||||||
|
{
|
||||||
|
CFRelease(hid);
|
||||||
|
WARN_LOG(WIIMOTE, "No HID manager");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSArray* criteria = @[
|
||||||
|
@{ @kIOHIDVendorIDKey : @0x057e,
|
||||||
|
@kIOHIDProductIDKey : @0x0306 },
|
||||||
|
@{ @kIOHIDVendorIDKey : @0x057e,
|
||||||
|
@kIOHIDProductIDKey : @0x0330 },
|
||||||
|
];
|
||||||
|
IOHIDManagerSetDeviceMatchingMultiple(hid, (CFArrayRef)criteria);
|
||||||
|
if (IOHIDManagerOpen(hid, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
|
||||||
|
WARN_LOG(WIIMOTE, "Failed to open HID Manager");
|
||||||
|
CFSetRef devices = IOHIDManagerCopyDevices(hid);
|
||||||
|
if (devices)
|
||||||
|
{
|
||||||
|
int found_devices = CFSetGetCount(devices);
|
||||||
if (found_devices)
|
if (found_devices)
|
||||||
NOTICE_LOG(WIIMOTE, "Found %i Bluetooth devices", found_devices);
|
|
||||||
|
|
||||||
en = [[bti foundDevices] objectEnumerator];
|
|
||||||
for (int i = 0; i < found_devices; i++)
|
|
||||||
{
|
{
|
||||||
IOBluetoothDevice* dev = [en nextObject];
|
NOTICE_LOG(WIIMOTE, "Found %i HID devices", found_devices);
|
||||||
if (!IsValidBluetoothName([[dev name] UTF8String]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Wiimote* wm = new WiimoteDarwin([dev retain]);
|
IOHIDDeviceRef values[found_devices];
|
||||||
|
CFSetGetValues(devices, reinterpret_cast<const void**>(&values));
|
||||||
if (IsBalanceBoardName([[dev name] UTF8String]))
|
for (int i = 0; i < found_devices; i++)
|
||||||
{
|
|
||||||
found_board = wm;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
Wiimote* wm = new WiimoteDarwinHid(values[i]);
|
||||||
found_wiimotes.push_back(wm);
|
found_wiimotes.push_back(wm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[bth release];
|
|
||||||
[bti release];
|
|
||||||
[sbt release];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hidFailed)
|
|
||||||
{
|
|
||||||
NSArray* criteria = @[
|
|
||||||
@{ @kIOHIDVendorIDKey : @0x057e,
|
|
||||||
@kIOHIDProductIDKey : @0x0306 },
|
|
||||||
@{ @kIOHIDVendorIDKey : @0x057e,
|
|
||||||
@kIOHIDProductIDKey : @0x0330 },
|
|
||||||
];
|
|
||||||
IOHIDManagerSetDeviceMatchingMultiple(hid, (CFArrayRef)criteria);
|
|
||||||
if (IOHIDManagerOpen(hid, kIOHIDOptionsTypeNone) != kIOReturnSuccess)
|
|
||||||
WARN_LOG(WIIMOTE, "Failed to open HID Manager");
|
|
||||||
CFSetRef devices = IOHIDManagerCopyDevices(hid);
|
|
||||||
if (devices)
|
|
||||||
{
|
|
||||||
int found_devices = CFSetGetCount(devices);
|
|
||||||
if (found_devices)
|
|
||||||
{
|
|
||||||
NOTICE_LOG(WIIMOTE, "Found %i HID devices", found_devices);
|
|
||||||
|
|
||||||
IOHIDDeviceRef values[found_devices];
|
|
||||||
CFSetGetValues(devices, reinterpret_cast<const void**>(&values));
|
|
||||||
for (int i = 0; i < found_devices; i++)
|
|
||||||
{
|
|
||||||
Wiimote* wm = new WiimoteDarwinHid(values[i]);
|
|
||||||
found_wiimotes.push_back(wm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CFRelease(hid);
|
|
||||||
}
|
}
|
||||||
|
CFRelease(hid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiimoteScanner::IsReady() const
|
bool WiimoteScannerDarwinHID::IsReady() const
|
||||||
{
|
{
|
||||||
// TODO: only return true when a BT device is present
|
// TODO: only return true when !hidFailed
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||||
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
|
@ -15,7 +17,10 @@
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||||
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
|
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
#include "Core/HW/WiimoteReal/IOAndroid.h"
|
||||||
|
#include "Core/HW/WiimoteReal/IOLinux.h"
|
||||||
|
#include "Core/HW/WiimoteReal/IOWin.h"
|
||||||
|
#include "Core/HW/WiimoteReal/IOdarwin.h"
|
||||||
#include "Core/Host.h"
|
#include "Core/Host.h"
|
||||||
#include "InputCommon/InputConfig.h"
|
#include "InputCommon/InputConfig.h"
|
||||||
|
|
||||||
|
@ -452,6 +457,17 @@ void WiimoteScanner::SetScanMode(WiimoteScanMode scan_mode)
|
||||||
m_scan_mode_changed_event.Set();
|
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()
|
static void CheckForDisconnectedWiimotes()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(g_wiimotes_mutex);
|
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)
|
if (m_scan_mode.load() == WiimoteScanMode::DO_NOT_SCAN)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (CalculateWantedWiimotes() != 0 || CalculateWantedBB() != 0)
|
for (const auto& backend : m_scanner_backends)
|
||||||
{
|
{
|
||||||
std::vector<Wiimote*> found_wiimotes;
|
if (CalculateWantedWiimotes() != 0 || CalculateWantedBB() != 0)
|
||||||
Wiimote* found_board = nullptr;
|
|
||||||
FindWiimotes(found_wiimotes, found_board);
|
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(g_wiimotes_mutex);
|
std::vector<Wiimote*> found_wiimotes;
|
||||||
std::for_each(found_wiimotes.begin(), found_wiimotes.end(), TryToConnectWiimote);
|
Wiimote* found_board = nullptr;
|
||||||
if (found_board)
|
backend->FindWiimotes(found_wiimotes, found_board);
|
||||||
TryToConnectBalanceBoard(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)
|
if (m_scan_mode.load() == WiimoteScanMode::SCAN_ONCE)
|
||||||
|
@ -615,7 +634,14 @@ void LoadSettings()
|
||||||
void Initialize(::Wiimote::InitializeMode init_mode)
|
void Initialize(::Wiimote::InitializeMode init_mode)
|
||||||
{
|
{
|
||||||
if (!g_real_wiimotes_initialized)
|
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.AddScannerBackend(std::make_unique<WiimoteScannerDarwinHID>());
|
||||||
g_wiimote_scanner.StartThread();
|
g_wiimote_scanner.StartThread();
|
||||||
|
}
|
||||||
|
|
||||||
if (SConfig::GetInstance().m_WiimoteContinuousScanning)
|
if (SConfig::GetInstance().m_WiimoteContinuousScanning)
|
||||||
g_wiimote_scanner.SetScanMode(WiimoteScanMode::CONTINUOUSLY_SCAN);
|
g_wiimote_scanner.SetScanMode(WiimoteScanMode::CONTINUOUSLY_SCAN);
|
||||||
|
|
|
@ -114,6 +114,16 @@ private:
|
||||||
Common::FifoQueue<Report> m_write_reports;
|
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
|
enum class WiimoteScanMode
|
||||||
{
|
{
|
||||||
DO_NOT_SCAN,
|
DO_NOT_SCAN,
|
||||||
|
@ -124,36 +134,23 @@ enum class WiimoteScanMode
|
||||||
class WiimoteScanner
|
class WiimoteScanner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WiimoteScanner();
|
WiimoteScanner() = default;
|
||||||
~WiimoteScanner();
|
|
||||||
|
|
||||||
bool IsReady() const;
|
|
||||||
|
|
||||||
void StartThread();
|
void StartThread();
|
||||||
void StopThread();
|
void StopThread();
|
||||||
void SetScanMode(WiimoteScanMode scan_mode);
|
void SetScanMode(WiimoteScanMode scan_mode);
|
||||||
|
|
||||||
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&);
|
void AddScannerBackend(std::unique_ptr<WiimoteScannerBackend> backend);
|
||||||
|
bool IsReady() const;
|
||||||
// function called when not looking for more Wiimotes
|
|
||||||
void Update();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ThreadFunc();
|
void ThreadFunc();
|
||||||
|
|
||||||
std::thread m_scan_thread;
|
std::thread m_scan_thread;
|
||||||
|
Common::Flag m_scan_thread_running;
|
||||||
|
|
||||||
Common::Event m_scan_mode_changed_event;
|
Common::Event m_scan_mode_changed_event;
|
||||||
Common::Flag m_scan_thread_running;
|
|
||||||
std::atomic<WiimoteScanMode> m_scan_mode{WiimoteScanMode::DO_NOT_SCAN};
|
std::atomic<WiimoteScanMode> m_scan_mode{WiimoteScanMode::DO_NOT_SCAN};
|
||||||
|
|
||||||
#if defined(_WIN32)
|
std::vector<std::unique_ptr<WiimoteScannerBackend>> m_scanner_backends;
|
||||||
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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::mutex g_wiimotes_mutex;
|
extern std::mutex g_wiimotes_mutex;
|
||||||
|
|
|
@ -4,23 +4,6 @@
|
||||||
|
|
||||||
#pragma once
|
#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
|
// Wiimote internal codes
|
||||||
|
|
||||||
// Communication channels
|
// Communication channels
|
||||||
|
@ -51,13 +34,3 @@
|
||||||
// It's 23. NOT 32!
|
// It's 23. NOT 32!
|
||||||
#define MAX_PAYLOAD 23
|
#define MAX_PAYLOAD 23
|
||||||
#define WIIMOTE_DEFAULT_TIMEOUT 1000
|
#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
|
|
||||||
|
|
Loading…
Reference in New Issue