Merge pull request #4195 from leoetlino/direct-hci

Add ability to passthrough a Bluetooth adapter
This commit is contained in:
shuffle2 2016-10-03 14:22:47 -07:00 committed by GitHub
commit 6ec756980d
37 changed files with 1772 additions and 643 deletions

View File

@ -120,6 +120,7 @@
#define WII_STATE "state.dat"
#define WII_SDCARD "sd.raw"
#define WII_BTDINF_BACKUP "btdinf.bak"
#define WII_SETTING "setting.txt"

View File

@ -35,6 +35,7 @@
#include "Core/HW/Sram.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/Host.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
#include "VideoCommon/VideoBackendBase.h"
@ -399,6 +400,8 @@ bool BootCore(const std::string& _rFilename)
// TODO: remove this if and once Dolphin supports WC24 standby mode.
SConfig::GetInstance().m_SYSCONF->SetData<u8>("IPL.IDL", 0x00);
NOTICE_LOG(BOOT, "Disabling WC24 'standby' (shutdown to idle) to avoid hanging on shutdown");
RestoreBTInfoSection();
}
// Run the game

View File

@ -145,7 +145,9 @@ set(SRCS ActionReplay.cpp
IPC_HLE/WII_IPC_HLE_Device_net_ssl.cpp
IPC_HLE/WII_IPC_HLE_Device_stm.cpp
IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.cpp
IPC_HLE/WII_IPC_HLE_Device_usb.cpp
IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.cpp
IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.cpp
IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.cpp
IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp
IPC_HLE/WII_IPC_HLE_Device_usb_ven.cpp
IPC_HLE/WII_IPC_HLE_WiiMote.cpp
@ -243,7 +245,8 @@ set(LIBS
if(LIBUSB_FOUND)
# Using shared LibUSB
set(LIBS ${LIBS} ${LIBUSB_LIBRARIES})
set(SRCS ${SRCS} IPC_HLE/WII_IPC_HLE_Device_hid.cpp)
set(SRCS ${SRCS} IPC_HLE/WII_IPC_HLE_Device_hid.cpp
IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.cpp)
endif(LIBUSB_FOUND)
set(LIBS ${LIBS} ${MBEDTLS_LIBRARIES})

View File

@ -55,6 +55,7 @@ void SConfig::SaveSettings()
NOTICE_LOG(BOOT, "Saving settings to %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); // load first to not kill unknown stuff
m_SYSCONF->Reload();
SaveGeneralSettings(ini);
SaveInterfaceSettings(ini);
@ -67,6 +68,7 @@ void SConfig::SaveSettings()
SaveFifoPlayerSettings(ini);
SaveAnalyticsSettings(ini);
SaveNetworkSettings(ini);
SaveBluetoothPassthroughSettings(ini);
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
m_SYSCONF->Save();
@ -322,6 +324,16 @@ void SConfig::SaveAnalyticsSettings(IniFile& ini)
analytics->Set("PermissionAsked", m_analytics_permission_asked);
}
void SConfig::SaveBluetoothPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("BluetoothPassthrough");
section->Set("Enabled", m_bt_passthrough_enabled);
section->Set("VID", m_bt_passthrough_vid);
section->Set("PID", m_bt_passthrough_pid);
section->Set("LinkKeys", m_bt_passthrough_link_keys);
}
void SConfig::LoadSettings()
{
INFO_LOG(BOOT, "Loading Settings from %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
@ -339,6 +351,7 @@ void SConfig::LoadSettings()
LoadFifoPlayerSettings(ini);
LoadNetworkSettings(ini);
LoadAnalyticsSettings(ini);
LoadBluetoothPassthroughSettings(ini);
m_SYSCONF = new SysConf();
}
@ -604,6 +617,16 @@ void SConfig::LoadAnalyticsSettings(IniFile& ini)
analytics->Get("PermissionAsked", &m_analytics_permission_asked, false);
}
void SConfig::LoadBluetoothPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("BluetoothPassthrough");
section->Get("Enabled", &m_bt_passthrough_enabled, false);
section->Get("VID", &m_bt_passthrough_vid, -1);
section->Get("PID", &m_bt_passthrough_pid, -1);
section->Get("LinkKeys", &m_bt_passthrough_link_keys, "");
}
void SConfig::LoadDefaults()
{
bEnableDebugging = false;

View File

@ -143,6 +143,12 @@ struct SConfig : NonCopyable
bool m_analytics_enabled = false;
bool m_analytics_permission_asked = false;
// Bluetooth passthrough mode settings
bool m_bt_passthrough_enabled = false;
int m_bt_passthrough_pid = -1;
int m_bt_passthrough_vid = -1;
std::string m_bt_passthrough_link_keys;
// Fifo Player related settings
bool bLoopFifoReplay = true;
@ -325,6 +331,7 @@ private:
void SaveFifoPlayerSettings(IniFile& ini);
void SaveNetworkSettings(IniFile& ini);
void SaveAnalyticsSettings(IniFile& ini);
void SaveBluetoothPassthroughSettings(IniFile& ini);
void LoadGeneralSettings(IniFile& ini);
void LoadInterfaceSettings(IniFile& ini);
@ -337,6 +344,7 @@ private:
void LoadFifoPlayerSettings(IniFile& ini);
void LoadNetworkSettings(IniFile& ini);
void LoadAnalyticsSettings(IniFile& ini);
void LoadBluetoothPassthroughSettings(IniFile& ini);
static SConfig* m_Instance;
};

View File

@ -52,7 +52,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/Wiimote.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/IPC_HLE/WII_Socket.h"
#include "Core/Movie.h"
@ -297,7 +297,7 @@ void Stop() // - Hammertime!
g_video_backend->Video_ExitLoop();
}
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
GCAdapter::ResetRumble();
#endif
@ -528,7 +528,7 @@ void EmuThread()
}
// Load and Init Wiimotes - only if we are booting in Wii mode
if (core_parameter.bWii)
if (core_parameter.bWii && !SConfig::GetInstance().m_bt_passthrough_enabled)
{
if (init_controllers)
Wiimote::Initialize(s_window_handle, !s_state_filename.empty() ?
@ -698,7 +698,7 @@ void SetState(EState state)
// stopped (including the CPU).
CPU::EnableStepping(true); // Break
Wiimote::Pause();
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
GCAdapter::ResetRumble();
#endif
break;
@ -818,7 +818,7 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock)
// (s_efbAccessRequested).
Fifo::PauseAndLock(do_lock, false);
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
GCAdapter::ResetRumble();
#endif

View File

@ -185,7 +185,12 @@
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_net_ssl.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_stm.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_base.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_emu.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_real.cpp">
<DisableSpecificWarnings>4200;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_stub.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_kbd.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_WiiMote.cpp" />
@ -389,7 +394,10 @@
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_net_ssl.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_stm.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_sdio_slot0.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_base.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_emu.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_real.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_stub.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_kbd.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_WiiMote.h" />

View File

@ -591,7 +591,16 @@
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_hid.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
</ClCompile>
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb.cpp">
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_base.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClCompile>
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_emu.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClCompile>
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_real.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClCompile>
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_stub.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClCompile>
<ClCompile Include="IPC_HLE\WII_IPC_HLE_WiiMote.cpp">
@ -1148,7 +1157,16 @@
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_hid.h">
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
</ClInclude>
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb.h">
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_base.h">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClInclude>
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_emu.h">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClInclude>
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_real.h">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClInclude>
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_bt_stub.h">
<Filter>IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote</Filter>
</ClInclude>
<ClInclude Include="IPC_HLE\WII_IPC_HLE_WiiMote.h">

View File

@ -702,7 +702,8 @@ void Initialize(::Wiimote::InitializeMode init_mode)
g_wiimote_scanner.StartThread();
}
if (SConfig::GetInstance().m_WiimoteContinuousScanning)
if (SConfig::GetInstance().m_WiimoteContinuousScanning &&
!SConfig::GetInstance().m_bt_passthrough_enabled)
g_wiimote_scanner.SetScanMode(WiimoteScanMode::CONTINUOUSLY_SCAN);
else
g_wiimote_scanner.SetScanMode(WiimoteScanMode::DO_NOT_SCAN);

View File

@ -32,6 +32,7 @@ const std::string hotkey_labels[] = {
_trans("Take Screenshot"),
_trans("Exit"),
_trans("Press Sync Button"),
_trans("Connect Wiimote 1"),
_trans("Connect Wiimote 2"),
_trans("Connect Wiimote 3"),

View File

@ -31,6 +31,7 @@ enum Hotkey
HK_SCREENSHOT,
HK_EXIT,
HK_TRIGGER_SYNC_BUTTON,
HK_WIIMOTE1_CONNECT,
HK_WIIMOTE2_CONNECT,
HK_WIIMOTE3_CONNECT,

View File

@ -22,6 +22,7 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
#include <list>
#include <map>
#include <mutex>
#include <string>
#include <vector>
@ -50,11 +51,12 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
#include "Core/IPC_HLE/WII_IPC_HLE_Device_net_ssl.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_stm.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_ven.h"
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
#include "Core/IPC_HLE/WII_IPC_HLE_Device_hid.h"
#endif
@ -62,41 +64,41 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
namespace WII_IPC_HLE_Interface
{
typedef std::map<u32, std::shared_ptr<IWII_IPC_HLE_Device>> TDeviceMap;
static TDeviceMap g_DeviceMap;
static std::map<u32, std::shared_ptr<IWII_IPC_HLE_Device>> s_device_map;
static std::mutex s_device_map_mutex;
// STATE_TO_SAVE
#define IPC_MAX_FDS 0x18
#define ES_MAX_COUNT 2
static std::shared_ptr<IWII_IPC_HLE_Device> g_FdMap[IPC_MAX_FDS];
static bool es_inuse[ES_MAX_COUNT];
static std::shared_ptr<IWII_IPC_HLE_Device> es_handles[ES_MAX_COUNT];
static std::shared_ptr<IWII_IPC_HLE_Device> s_fdmap[IPC_MAX_FDS];
static bool s_es_inuse[ES_MAX_COUNT];
static std::shared_ptr<IWII_IPC_HLE_Device> s_es_handles[ES_MAX_COUNT];
typedef std::deque<u32> ipc_msg_queue;
static ipc_msg_queue request_queue; // ppc -> arm
static ipc_msg_queue reply_queue; // arm -> ppc
static ipc_msg_queue ack_queue; // arm -> ppc
using IPCMsgQueue = std::deque<u32>;
static IPCMsgQueue s_request_queue; // ppc -> arm
static IPCMsgQueue s_reply_queue; // arm -> ppc
static IPCMsgQueue s_ack_queue; // arm -> ppc
static CoreTiming::EventType* event_enqueue;
static CoreTiming::EventType* event_sdio_notify;
static CoreTiming::EventType* s_event_enqueue;
static CoreTiming::EventType* s_event_sdio_notify;
static u64 last_reply_time;
static u64 s_last_reply_time;
static const u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
static const u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
static constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
static constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
static void EnqueueEvent(u64 userdata, s64 cycles_late = 0)
{
if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG)
{
ack_queue.push_back((u32)userdata);
s_ack_queue.push_back(static_cast<u32>(userdata));
}
else if (userdata & ENQUEUE_REQUEST_FLAG)
{
request_queue.push_back((u32)userdata);
s_request_queue.push_back(static_cast<u32>(userdata));
}
else
{
reply_queue.push_back((u32)userdata);
s_reply_queue.push_back(static_cast<u32>(userdata));
}
Update();
}
@ -112,23 +114,28 @@ static void SDIO_EventNotify_CPUThread(u64 userdata, s64 cycles_late)
static u32 num_devices;
template <typename T>
std::shared_ptr<T> AddDevice(const char* deviceName)
std::shared_ptr<T> AddDevice(const char* device_name)
{
auto device = std::make_shared<T>(num_devices, deviceName);
g_DeviceMap[num_devices] = device;
auto device = std::make_shared<T>(num_devices, device_name);
s_device_map[num_devices] = device;
num_devices++;
return device;
}
void Reinit()
{
_assert_msg_(WII_IPC_HLE, g_DeviceMap.empty(), "Reinit called while already initialized");
std::lock_guard<std::mutex> lock(s_device_map_mutex);
_assert_msg_(WII_IPC_HLE, s_device_map.empty(), "Reinit called while already initialized");
CWII_IPC_HLE_Device_es::m_ContentFile = "";
num_devices = 0;
// Build hardware devices
AddDevice<CWII_IPC_HLE_Device_usb_oh1_57e_305>("/dev/usb/oh1/57e/305");
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
AddDevice<CWII_IPC_HLE_Device_usb_oh1_57e_305_emu>("/dev/usb/oh1/57e/305");
else
AddDevice<CWII_IPC_HLE_Device_usb_oh1_57e_305_real>("/dev/usb/oh1/57e/305");
AddDevice<CWII_IPC_HLE_Device_stm_immediate>("/dev/stm/immediate");
AddDevice<CWII_IPC_HLE_Device_stm_eventhook>("/dev/stm/eventhook");
AddDevice<CWII_IPC_HLE_Device_fs>("/dev/fs");
@ -136,8 +143,8 @@ void Reinit()
// IOS allows two ES devices at a time
for (u32 j = 0; j < ES_MAX_COUNT; j++)
{
es_handles[j] = AddDevice<CWII_IPC_HLE_Device_es>("/dev/es");
es_inuse[j] = false;
s_es_handles[j] = AddDevice<CWII_IPC_HLE_Device_es>("/dev/es");
s_es_inuse[j] = false;
}
AddDevice<CWII_IPC_HLE_Device_di>("/dev/di");
@ -151,7 +158,7 @@ void Reinit()
AddDevice<CWII_IPC_HLE_Device_usb_ven>("/dev/usb/ven");
AddDevice<CWII_IPC_HLE_Device_sdio_slot0>("/dev/sdio/slot0");
AddDevice<CWII_IPC_HLE_Device_stub>("/dev/sdio/slot1");
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
AddDevice<CWII_IPC_HLE_Device_hid>("/dev/usb/hid");
#else
AddDevice<CWII_IPC_HLE_Device_stub>("/dev/usb/hid");
@ -164,15 +171,15 @@ void Init()
{
Reinit();
event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEvent);
event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", SDIO_EventNotify_CPUThread);
s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEvent);
s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", SDIO_EventNotify_CPUThread);
}
void Reset(bool _bHard)
void Reset(bool hard)
{
CoreTiming::RemoveAllEvents(event_enqueue);
CoreTiming::RemoveAllEvents(s_event_enqueue);
for (auto& dev : g_FdMap)
for (auto& dev : s_fdmap)
{
if (dev && !dev->IsHardware())
{
@ -183,28 +190,30 @@ void Reset(bool _bHard)
dev.reset();
}
for (bool& in_use : es_inuse)
for (bool& in_use : s_es_inuse)
{
in_use = false;
}
for (const auto& entry : g_DeviceMap)
{
if (entry.second)
std::lock_guard<std::mutex> lock(s_device_map_mutex);
for (const auto& entry : s_device_map)
{
// Force close
entry.second->Close(0, true);
if (entry.second)
{
// Force close
entry.second->Close(0, true);
}
}
if (hard)
s_device_map.clear();
}
if (_bHard)
{
g_DeviceMap.clear();
}
request_queue.clear();
reply_queue.clear();
s_request_queue.clear();
s_reply_queue.clear();
last_reply_time = 0;
s_last_reply_time = 0;
}
void Shutdown()
@ -212,13 +221,14 @@ void Shutdown()
Reset(true);
}
void SetDefaultContentFile(const std::string& _rFilename)
void SetDefaultContentFile(const std::string& file_name)
{
for (const auto& entry : g_DeviceMap)
std::lock_guard<std::mutex> lock(s_device_map_mutex);
for (const auto& entry : s_device_map)
{
if (entry.second && entry.second->GetDeviceName().find("/dev/es") == 0)
{
static_cast<CWII_IPC_HLE_Device_es*>(entry.second.get())->LoadWAD(_rFilename);
static_cast<CWII_IPC_HLE_Device_es*>(entry.second.get())->LoadWAD(file_name);
}
}
}
@ -233,14 +243,14 @@ void SDIO_EventNotify()
// TODO: Potential race condition: If IsRunning() becomes false after
// it's checked, an event may be scheduled after CoreTiming shuts down.
if (SConfig::GetInstance().bWii && Core::IsRunning())
CoreTiming::ScheduleEvent(0, event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU);
CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU);
}
int getFreeDeviceId()
static int GetFreeDeviceID()
{
for (u32 i = 0; i < IPC_MAX_FDS; i++)
{
if (g_FdMap[i] == nullptr)
if (s_fdmap[i] == nullptr)
{
return i;
}
@ -249,11 +259,12 @@ int getFreeDeviceId()
return -1;
}
std::shared_ptr<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& _rDeviceName)
std::shared_ptr<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& device_name)
{
for (const auto& entry : g_DeviceMap)
std::lock_guard<std::mutex> lock(s_device_map_mutex);
for (const auto& entry : s_device_map)
{
if (entry.second && entry.second->GetDeviceName() == _rDeviceName)
if (entry.second && entry.second->GetDeviceName() == device_name)
{
return entry.second;
}
@ -262,39 +273,40 @@ std::shared_ptr<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& _rDevice
return nullptr;
}
std::shared_ptr<IWII_IPC_HLE_Device> AccessDeviceByID(u32 _ID)
std::shared_ptr<IWII_IPC_HLE_Device> AccessDeviceByID(u32 id)
{
if (g_DeviceMap.find(_ID) != g_DeviceMap.end())
std::lock_guard<std::mutex> lock(s_device_map_mutex);
if (s_device_map.find(id) != s_device_map.end())
{
return g_DeviceMap[_ID];
return s_device_map[id];
}
return nullptr;
}
// This is called from ExecuteCommand() COMMAND_OPEN_DEVICE
std::shared_ptr<IWII_IPC_HLE_Device> CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName)
std::shared_ptr<IWII_IPC_HLE_Device> CreateFileIO(u32 device_id, const std::string& device_name)
{
// scan device name and create the right one
INFO_LOG(WII_IPC_FILEIO, "IOP: Create FileIO %s", _rDeviceName.c_str());
return std::make_shared<CWII_IPC_HLE_Device_FileIO>(_DeviceID, _rDeviceName);
INFO_LOG(WII_IPC_FILEIO, "IOP: Create FileIO %s", device_name.c_str());
return std::make_shared<CWII_IPC_HLE_Device_FileIO>(device_id, device_name);
}
void DoState(PointerWrap& p)
{
p.Do(request_queue);
p.Do(reply_queue);
p.Do(last_reply_time);
p.Do(s_request_queue);
p.Do(s_reply_queue);
p.Do(s_last_reply_time);
// We need to make sure all file handles are closed so WII_IPC_Devices_fs::DoState can
// successfully save or re-create /tmp
for (auto& descriptor : g_FdMap)
for (auto& descriptor : s_fdmap)
{
if (descriptor)
descriptor->PrepareForState(p.GetMode());
}
for (const auto& entry : g_DeviceMap)
for (const auto& entry : s_device_map)
{
if (entry.second->IsHardware())
{
@ -316,28 +328,28 @@ void DoState(PointerWrap& p)
{
u32 hwId = 0;
p.Do(hwId);
g_FdMap[i] = AccessDeviceByID(hwId);
s_fdmap[i] = AccessDeviceByID(hwId);
}
else
{
g_FdMap[i] = std::make_shared<CWII_IPC_HLE_Device_FileIO>(i, "");
g_FdMap[i]->DoState(p);
s_fdmap[i] = std::make_shared<CWII_IPC_HLE_Device_FileIO>(i, "");
s_fdmap[i]->DoState(p);
}
}
}
for (u32 i = 0; i < ES_MAX_COUNT; i++)
{
p.Do(es_inuse[i]);
u32 handleID = es_handles[i]->GetDeviceID();
p.Do(s_es_inuse[i]);
u32 handleID = s_es_handles[i]->GetDeviceID();
p.Do(handleID);
es_handles[i] = AccessDeviceByID(handleID);
s_es_handles[i] = AccessDeviceByID(handleID);
}
}
else
{
for (auto& descriptor : g_FdMap)
for (auto& descriptor : s_fdmap)
{
u32 exists = descriptor ? 1 : 0;
p.Do(exists);
@ -359,203 +371,203 @@ void DoState(PointerWrap& p)
for (u32 i = 0; i < ES_MAX_COUNT; i++)
{
p.Do(es_inuse[i]);
u32 handleID = es_handles[i]->GetDeviceID();
p.Do(s_es_inuse[i]);
u32 handleID = s_es_handles[i]->GetDeviceID();
p.Do(handleID);
}
}
}
void ExecuteCommand(u32 _Address)
void ExecuteCommand(u32 address)
{
IPCCommandResult result = IWII_IPC_HLE_Device::GetNoReply();
IPCCommandType Command = static_cast<IPCCommandType>(Memory::Read_U32(_Address));
s32 DeviceID = Memory::Read_U32(_Address + 8);
IPCCommandType Command = static_cast<IPCCommandType>(Memory::Read_U32(address));
s32 DeviceID = Memory::Read_U32(address + 8);
std::shared_ptr<IWII_IPC_HLE_Device> pDevice =
(DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr;
std::shared_ptr<IWII_IPC_HLE_Device> device =
(DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? s_fdmap[DeviceID] : nullptr;
DEBUG_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", _Address,
Command, DeviceID, pDevice.get());
DEBUG_LOG(WII_IPC_HLE, "-->> Execute Command Address: 0x%08x (code: %x, device: %x) %p", address,
Command, DeviceID, device.get());
switch (Command)
{
case IPC_CMD_OPEN:
{
u32 Mode = Memory::Read_U32(_Address + 0x10);
DeviceID = getFreeDeviceId();
u32 Mode = Memory::Read_U32(address + 0x10);
DeviceID = GetFreeDeviceID();
std::string DeviceName = Memory::GetString(Memory::Read_U32(_Address + 0xC));
std::string device_name = Memory::GetString(Memory::Read_U32(address + 0xC));
INFO_LOG(WII_IPC_HLE, "Trying to open %s as %d", DeviceName.c_str(), DeviceID);
INFO_LOG(WII_IPC_HLE, "Trying to open %s as %d", device_name.c_str(), DeviceID);
if (DeviceID >= 0)
{
if (DeviceName.find("/dev/es") == 0)
if (device_name.find("/dev/es") == 0)
{
u32 j;
for (j = 0; j < ES_MAX_COUNT; j++)
{
if (!es_inuse[j])
if (!s_es_inuse[j])
{
es_inuse[j] = true;
g_FdMap[DeviceID] = es_handles[j];
result = es_handles[j]->Open(_Address, Mode);
Memory::Write_U32(DeviceID, _Address + 4);
s_es_inuse[j] = true;
s_fdmap[DeviceID] = s_es_handles[j];
result = s_es_handles[j]->Open(address, Mode);
Memory::Write_U32(DeviceID, address + 4);
break;
}
}
if (j == ES_MAX_COUNT)
{
Memory::Write_U32(FS_EESEXHAUSTED, _Address + 4);
Memory::Write_U32(FS_EESEXHAUSTED, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
}
else if (DeviceName.find("/dev/") == 0)
else if (device_name.find("/dev/") == 0)
{
pDevice = GetDeviceByName(DeviceName);
if (pDevice)
device = GetDeviceByName(device_name);
if (device)
{
g_FdMap[DeviceID] = pDevice;
result = pDevice->Open(_Address, Mode);
s_fdmap[DeviceID] = device;
result = device->Open(address, Mode);
DEBUG_LOG(WII_IPC_FILEIO, "IOP: ReOpen (Device=%s, DeviceID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
Memory::Write_U32(DeviceID, _Address + 4);
device->GetDeviceName().c_str(), DeviceID, Mode);
Memory::Write_U32(DeviceID, address + 4);
}
else
{
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", DeviceName.c_str());
Memory::Write_U32(FS_ENOENT, _Address + 4);
WARN_LOG(WII_IPC_HLE, "Unimplemented device: %s", device_name.c_str());
Memory::Write_U32(FS_ENOENT, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
}
else
{
pDevice = CreateFileIO(DeviceID, DeviceName);
result = pDevice->Open(_Address, Mode);
device = CreateFileIO(DeviceID, device_name);
result = device->Open(address, Mode);
DEBUG_LOG(WII_IPC_FILEIO, "IOP: Open File (Device=%s, ID=%08x, Mode=%i)",
pDevice->GetDeviceName().c_str(), DeviceID, Mode);
if (Memory::Read_U32(_Address + 4) == (u32)DeviceID)
device->GetDeviceName().c_str(), DeviceID, Mode);
if (Memory::Read_U32(address + 4) == (u32)DeviceID)
{
g_FdMap[DeviceID] = pDevice;
s_fdmap[DeviceID] = device;
}
}
}
else
{
Memory::Write_U32(FS_EFDEXHAUSTED, _Address + 4);
Memory::Write_U32(FS_EFDEXHAUSTED, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break;
}
case IPC_CMD_CLOSE:
{
if (pDevice)
if (device)
{
result = pDevice->Close(_Address);
result = device->Close(address);
for (u32 j = 0; j < ES_MAX_COUNT; j++)
{
if (es_handles[j] == g_FdMap[DeviceID])
if (s_es_handles[j] == s_fdmap[DeviceID])
{
es_inuse[j] = false;
s_es_inuse[j] = false;
}
}
g_FdMap[DeviceID].reset();
s_fdmap[DeviceID].reset();
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
Memory::Write_U32(FS_EINVAL, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break;
}
case IPC_CMD_READ:
{
if (pDevice)
if (device)
{
result = pDevice->Read(_Address);
result = device->Read(address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
Memory::Write_U32(FS_EINVAL, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break;
}
case IPC_CMD_WRITE:
{
if (pDevice)
if (device)
{
result = pDevice->Write(_Address);
result = device->Write(address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
Memory::Write_U32(FS_EINVAL, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break;
}
case IPC_CMD_SEEK:
{
if (pDevice)
if (device)
{
result = pDevice->Seek(_Address);
result = device->Seek(address);
}
else
{
Memory::Write_U32(FS_EINVAL, _Address + 4);
Memory::Write_U32(FS_EINVAL, address + 4);
result = IWII_IPC_HLE_Device::GetDefaultReply();
}
break;
}
case IPC_CMD_IOCTL:
{
if (pDevice)
if (device)
{
result = pDevice->IOCtl(_Address);
result = device->IOCtl(address);
}
break;
}
case IPC_CMD_IOCTLV:
{
if (pDevice)
if (device)
{
result = pDevice->IOCtlV(_Address);
result = device->IOCtlV(address);
}
break;
}
default:
{
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, _Address);
_dbg_assert_msg_(WII_IPC_HLE, 0, "Unknown IPC Command %i (0x%08x)", Command, address);
break;
}
}
// Ensure replies happen in order
const s64 ticks_until_last_reply = last_reply_time - CoreTiming::GetTicks();
const s64 ticks_until_last_reply = s_last_reply_time - CoreTiming::GetTicks();
if (ticks_until_last_reply > 0)
result.reply_delay_ticks += ticks_until_last_reply;
last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
s_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
if (result.send_reply)
{
// The original hardware overwrites the command type with the async reply type.
Memory::Write_U32(IPC_REP_ASYNC, _Address);
Memory::Write_U32(IPC_REP_ASYNC, address);
// IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(Command, _Address + 8);
Memory::Write_U32(Command, address + 8);
// Generate a reply to the IPC command
EnqueueReply(_Address, (int)result.reply_delay_ticks);
EnqueueReply(address, (int)result.reply_delay_ticks);
}
}
// Happens AS SOON AS IPC gets a new pointer!
void EnqueueRequest(u32 address)
{
CoreTiming::ScheduleEvent(1000, event_enqueue, address | ENQUEUE_REQUEST_FLAG);
CoreTiming::ScheduleEvent(1000, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG);
}
// Called when IOS module has some reply
@ -564,12 +576,12 @@ void EnqueueRequest(u32 address)
// Please search for examples of this being called elsewhere.
void EnqueueReply(u32 address, int cycles_in_future, CoreTiming::FromThread from)
{
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue, address, from);
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, address, from);
}
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
{
CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue,
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue,
address | ENQUEUE_ACKNOWLEDGEMENT_FLAG);
}
@ -580,29 +592,29 @@ void Update()
if (!WII_IPCInterface::IsReady())
return;
if (request_queue.size())
if (s_request_queue.size())
{
WII_IPCInterface::GenerateAck(request_queue.front());
DEBUG_LOG(WII_IPC_HLE, "||-- Acknowledge IPC Request @ 0x%08x", request_queue.front());
u32 command = request_queue.front();
request_queue.pop_front();
WII_IPCInterface::GenerateAck(s_request_queue.front());
DEBUG_LOG(WII_IPC_HLE, "||-- Acknowledge IPC Request @ 0x%08x", s_request_queue.front());
u32 command = s_request_queue.front();
s_request_queue.pop_front();
ExecuteCommand(command);
return;
}
if (reply_queue.size())
if (s_reply_queue.size())
{
WII_IPCInterface::GenerateReply(reply_queue.front());
DEBUG_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", reply_queue.front());
reply_queue.pop_front();
WII_IPCInterface::GenerateReply(s_reply_queue.front());
DEBUG_LOG(WII_IPC_HLE, "<<-- Reply to IPC Request @ 0x%08x", s_reply_queue.front());
s_reply_queue.pop_front();
return;
}
if (ack_queue.size())
if (s_ack_queue.size())
{
WII_IPCInterface::GenerateAck(ack_queue.front());
WARN_LOG(WII_IPC_HLE, "<<-- Double-ack to IPC Request @ 0x%08x", ack_queue.front());
ack_queue.pop_front();
WII_IPCInterface::GenerateAck(s_ack_queue.front());
WARN_LOG(WII_IPC_HLE, "<<-- Double-ack to IPC Request @ 0x%08x", s_ack_queue.front());
s_ack_queue.pop_front();
return;
}
}
@ -610,7 +622,7 @@ void Update()
void UpdateDevices()
{
// Check if a hardware device must be updated
for (const auto& entry : g_DeviceMap)
for (const auto& entry : s_device_map)
{
if (entry.second->IsOpened())
{

View File

@ -67,7 +67,6 @@ std::shared_ptr<IWII_IPC_HLE_Device> CreateFileIO(u32 _DeviceID, const std::stri
std::shared_ptr<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& _rDeviceName);
std::shared_ptr<IWII_IPC_HLE_Device> AccessDeviceByID(u32 _ID);
int getFreeDeviceId();
// Update
void Update();

View File

@ -47,7 +47,7 @@
#include "Core/ConfigManager.h"
#include "Core/HW/DVDInterface.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_es.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/Movie.h"
#include "Core/PowerPC/PowerPC.h"
@ -998,28 +998,33 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
}
else
{
CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer();
size_t size = s_Usb->m_WiiMotes.size();
bool* wiiMoteConnected = new bool[size];
for (unsigned int i = 0; i < size; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
bool* wiiMoteConnected = new bool[MAX_BBMOTES];
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
}
WII_IPC_HLE_Interface::Reset(true);
WII_IPC_HLE_Interface::Reinit();
s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < s_Usb->m_WiiMotes.size(); i++)
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
if (wiiMoteConnected[i])
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
if (wiiMoteConnected[i])
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
}
}
}
delete[] wiiMoteConnected;
WII_IPC_HLE_Interface::SetDefaultContentFile(tContentFile);
}

View File

@ -0,0 +1,90 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <string>
#include <vector>
#include "Common/Assert.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
constexpr u16 BT_INFO_SECTION_LENGTH = 0x460;
void BackUpBTInfoSection()
{
const std::string filename = File::GetUserPath(D_SESSION_WIIROOT_IDX) + DIR_SEP WII_BTDINF_BACKUP;
if (File::Exists(filename))
return;
File::IOFile backup(filename, "wb");
std::vector<u8> section(BT_INFO_SECTION_LENGTH);
if (!SConfig::GetInstance().m_SYSCONF->GetArrayData("BT.DINF", section.data(),
static_cast<u16>(section.size())))
{
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to read source BT.DINF section");
return;
}
if (!backup.WriteBytes(section.data(), section.size()))
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to back up BT.DINF section");
}
void RestoreBTInfoSection()
{
const std::string filename = File::GetUserPath(D_SESSION_WIIROOT_IDX) + DIR_SEP WII_BTDINF_BACKUP;
if (!File::Exists(filename))
return;
File::IOFile backup(filename, "rb");
std::vector<u8> section(BT_INFO_SECTION_LENGTH);
if (!backup.ReadBytes(section.data(), section.size()))
{
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to read backed up BT.DINF section");
return;
}
SConfig::GetInstance().m_SYSCONF->SetArrayData("BT.DINF", section.data(),
static_cast<u16>(section.size()));
SConfig::GetInstance().m_SYSCONF->Save();
File::Delete(filename);
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_base::IOCtl(u32 command_address)
{
// NeoGamma (homebrew) is known to use this path.
ERROR_LOG(WII_IPC_WIIMOTE, "Bad IOCtl to /dev/usb/oh1/57e/305");
Memory::Write_U32(FS_EINVAL, command_address + 4);
return GetDefaultReply();
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlMessage::CtrlMessage(const SIOCtlVBuffer& cmd_buffer)
{
request_type = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
request = Memory::Read_U8(cmd_buffer.InBuffer[1].m_Address);
value = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[2].m_Address));
index = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[3].m_Address));
length = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[4].m_Address));
payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
address = cmd_buffer.m_Address;
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::CtrlBuffer(const SIOCtlVBuffer& cmd_buffer,
const u32 command_address)
{
m_endpoint = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
m_length = Memory::Read_U16(cmd_buffer.InBuffer[1].m_Address);
m_payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
m_cmd_address = command_address;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8* src,
const size_t size) const
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, size <= m_length, "FillBuffer: size %li > payload length %i",
size, m_length);
Memory::CopyToEmu(m_payload_addr, src, size);
}

View File

@ -0,0 +1,83 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
void BackUpBTInfoSection();
void RestoreBTInfoSection();
class CWII_IPC_HLE_Device_usb_oh1_57e_305_base : public IWII_IPC_HLE_Device
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_base(u32 device_id, const std::string& device_name)
: IWII_IPC_HLE_Device(device_id, device_name)
{
}
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_base() override = default;
virtual IPCCommandResult Open(u32 command_address, u32 mode) override = 0;
virtual IPCCommandResult Close(u32 command_address, bool force) override = 0;
IPCCommandResult IOCtl(u32 command_address) override;
virtual IPCCommandResult IOCtlV(u32 command_address) override = 0;
virtual void DoState(PointerWrap& p) override = 0;
virtual u32 Update() override = 0;
virtual void UpdateSyncButtonState(bool is_held) {}
virtual void TriggerSyncButtonPressedEvent() {}
virtual void TriggerSyncButtonHeldEvent() {}
protected:
static constexpr int ACL_PKT_SIZE = 339;
static constexpr int ACL_PKT_NUM = 10;
static constexpr int SCO_PKT_SIZE = 64;
static constexpr int SCO_PKT_NUM = 0;
enum USBIOCtl
{
USBV0_IOCTL_CTRLMSG = 0,
USBV0_IOCTL_BLKMSG = 1,
USBV0_IOCTL_INTRMSG = 2,
};
enum USBEndpoint
{
HCI_CTRL = 0x00,
HCI_EVENT = 0x81,
ACL_DATA_IN = 0x82,
ACL_DATA_OUT = 0x02
};
struct CtrlMessage
{
CtrlMessage() = default;
CtrlMessage(const SIOCtlVBuffer& cmd_buffer);
u8 request_type;
u8 request;
u16 value;
u16 index;
u16 length;
u32 payload_addr;
u32 address;
};
class CtrlBuffer
{
public:
CtrlBuffer() = default;
CtrlBuffer(const SIOCtlVBuffer& cmd_buffer, u32 command_address);
void FillBuffer(const u8* src, size_t size) const;
void SetRetVal(const u32 retval) const { Memory::Write_U32(retval, m_cmd_address + 4); }
bool IsValid() const { return m_cmd_address != 0; }
void Invalidate() { m_cmd_address = m_payload_addr = 0; }
u8 m_endpoint;
u16 m_length;
u32 m_payload_addr;
u32 m_cmd_address;
};
};

View File

@ -12,12 +12,12 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/Movie.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::EnqueueReply(u32 CommandAddress)
{
// IOS seems to write back the command that was responded to in the FD field, this
// class does not overwrite the command so it is safe to read back.
@ -29,10 +29,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
}
// The device class
CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CWII_IPC_HLE_Device_usb_oh1_57e_305_emu(
u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName), m_ScanEnable(0), m_HCIEndpoint(0),
m_ACLEndpoint(0), m_last_ticks(0)
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(_DeviceID, _rDeviceName)
{
SysConf* sysconf;
std::unique_ptr<SysConf> owned_sysconf;
@ -47,6 +46,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(
else
{
sysconf = SConfig::GetInstance().m_SYSCONF;
BackUpBTInfoSection();
}
// Activate only first Wiimote by default
@ -63,24 +63,13 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(
u8 i = 0;
while (i < MAX_BBMOTES)
{
if (i < BT_DINF.num_registered)
{
tmpBD.b[5] = BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0];
tmpBD.b[4] = BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1];
tmpBD.b[3] = BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2];
tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3];
tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4];
tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5];
}
else
{
tmpBD.b[5] = BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = i;
tmpBD.b[4] = BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = 0;
tmpBD.b[3] = BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = 0x79;
tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = 0x19;
tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = 2;
tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = 0x11;
}
// Previous records can be safely overwritten, since they are backed up
tmpBD.b[5] = BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = i;
tmpBD.b[4] = BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = 0;
tmpBD.b[3] = BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = 0x79;
tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = 0x19;
tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = 2;
tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = 0x11;
const char* wmName;
if (i == WIIMOTE_BALANCE_BOARD)
@ -96,6 +85,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(
i++;
}
BT_DINF.num_registered = MAX_BBMOTES;
// save now so that when games load sysconf file it includes the new Wiimotes
// and the correct order for connected Wiimotes
if (!sysconf->SetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads)) || !sysconf->Save())
@ -115,14 +105,23 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(
Host_SetWiiMoteConnectionState(0);
}
CWII_IPC_HLE_Device_usb_oh1_57e_305::~CWII_IPC_HLE_Device_usb_oh1_57e_305()
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::~CWII_IPC_HLE_Device_usb_oh1_57e_305_emu()
{
m_WiiMotes.clear();
SetUsbPointer(nullptr);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap& p)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DoState(PointerWrap& p)
{
bool passthrough_bluetooth = false;
p.Do(passthrough_bluetooth);
if (passthrough_bluetooth && p.GetMode() == PointerWrap::MODE_READ)
{
Core::DisplayMessage("State needs Bluetooth passthrough to be enabled. Aborting load.", 4000);
p.SetMode(PointerWrap::MODE_VERIFY);
return;
}
p.Do(m_Active);
p.Do(m_ControllerBD);
p.Do(m_CtrlSetup);
@ -139,35 +138,35 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap& p)
m_WiiMotes[i].DoState(p);
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::RemoteDisconnect(u16 _connectionHandle)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::RemoteDisconnect(u16 _connectionHandle)
{
return SendEventDisconnect(_connectionHandle, 0x13);
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::Open(u32 _CommandAddress, u32 _Mode)
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Open(u32 _CommandAddress, u32 _Mode)
{
m_ScanEnable = 0;
m_last_ticks = 0;
memset(m_PacketCount, 0, sizeof(m_PacketCount));
m_HCIEndpoint.m_address = 0;
m_ACLEndpoint.m_address = 0;
m_HCIEndpoint.m_cmd_address = 0;
m_ACLEndpoint.m_cmd_address = 0;
Memory::Write_U32(GetDeviceID(), _CommandAddress + 4);
m_Active = true;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::Close(u32 _CommandAddress, bool _bForce)
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Close(u32 _CommandAddress, bool _bForce)
{
m_ScanEnable = 0;
m_last_ticks = 0;
memset(m_PacketCount, 0, sizeof(m_PacketCount));
m_HCIEndpoint.m_address = 0;
m_ACLEndpoint.m_address = 0;
m_HCIEndpoint.m_cmd_address = 0;
m_ACLEndpoint.m_cmd_address = 0;
if (!_bForce)
Memory::Write_U32(0, _CommandAddress + 4);
@ -175,7 +174,7 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::Close(u32 _CommandAddress,
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtl(u32 _CommandAddress)
{
// NeoGamma (homebrew) is known to use this path.
ERROR_LOG(WII_IPC_WIIMOTE, "Bad IOCtl in CWII_IPC_HLE_Device_usb_oh1_57e_305");
@ -183,7 +182,7 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtl(u32 _CommandAddress)
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(u32 _CommandAddress)
{
/*
Memory::Write_U8(255, 0x80149950); // BTM LOG // 3 logs L2Cap // 4 logs l2_csm$
@ -240,8 +239,8 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress
case USBV0_IOCTL_BLKMSG:
{
u8 Command = Memory::Read_U8(CommandBuffer.InBuffer[0].m_Address);
switch (Command)
const CtrlBuffer ctrl(CommandBuffer, _CommandAddress);
switch (ctrl.m_endpoint)
{
case ACL_DATA_OUT: // ACL data is received from the stack
{
@ -249,20 +248,15 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress
// Here we only need to record the command address in case we need to delay the reply
m_ACLSetup = CommandBuffer.m_Address;
#if defined(_DEBUG) || defined(DEBUGFAST)
DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer,
CommandBuffer.NumberPayloadBuffer);
#endif
const auto* acl_header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.m_payload_addr));
CtrlBuffer BulkBuffer(_CommandAddress);
hci_acldata_hdr_t* pACLHeader = (hci_acldata_hdr_t*)Memory::GetPointer(BulkBuffer.m_buffer);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_BC_FLAG(pACLHeader->con_handle) == HCI_POINT2POINT);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_PB_FLAG(pACLHeader->con_handle) == HCI_PACKET_START);
SendToDevice(HCI_CON_HANDLE(pACLHeader->con_handle),
Memory::GetPointer(BulkBuffer.m_buffer + sizeof(hci_acldata_hdr_t)),
pACLHeader->length);
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
Memory::GetPointer(ctrl.m_payload_addr + sizeof(hci_acldata_hdr_t)),
acl_header->length);
_SendReply = true;
}
@ -270,7 +264,7 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress
case ACL_DATA_IN: // We are given an ACL buffer to fill
{
CtrlBuffer temp(_CommandAddress);
CtrlBuffer temp(CommandBuffer, _CommandAddress);
m_ACLEndpoint = temp;
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL_DATA_IN: 0x%08x ", _CommandAddress);
@ -279,7 +273,7 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress
default:
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_BLKMSG: %x", Command);
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_BLKMSG: %x", ctrl.m_endpoint);
}
break;
}
@ -288,17 +282,17 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress
case USBV0_IOCTL_INTRMSG:
{
u8 Command = Memory::Read_U8(CommandBuffer.InBuffer[0].m_Address);
if (Command == HCI_EVENT) // We are given a HCI buffer to fill
const CtrlBuffer ctrl(CommandBuffer, _CommandAddress);
if (ctrl.m_endpoint == HCI_EVENT) // We are given a HCI buffer to fill
{
CtrlBuffer temp(_CommandAddress);
CtrlBuffer temp(CommandBuffer, _CommandAddress);
m_HCIEndpoint = temp;
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI_EVENT: 0x%08x ", _CommandAddress);
}
else
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_INTRMSG: %x", Command);
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_INTRMSG: %x", ctrl.m_endpoint);
}
}
break;
@ -329,7 +323,8 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305::IOCtlV(u32 _CommandAddress
}
// Here we handle the USBV0_IOCTL_BLKMSG Ioctlv
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendToDevice(u16 _ConnectionHandle, u8* _pData,
u32 _Size)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_ConnectionHandle);
if (pWiiMote == nullptr)
@ -340,7 +335,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
pWiiMote->ExecuteL2capCmd(_pData, _Size);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IncDataPacket(u16 _ConnectionHandle)
{
m_PacketCount[_ConnectionHandle & 0xff]++;
@ -357,18 +352,18 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
// Here we send ACL packets to CPU. They will consist of header + data.
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 connection_handle, const u8* data,
u32 size)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendACLPacket(u16 connection_handle, const u8* data,
u32 size)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", connection_handle);
if (m_ACLEndpoint.IsValid() && !m_HCIEndpoint.IsValid() && m_EventQueue.empty())
{
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint valid, sending packet to %08x",
m_ACLEndpoint.m_address);
m_ACLEndpoint.m_cmd_address);
hci_acldata_hdr_t* header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint.m_buffer));
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint.m_payload_addr));
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;
@ -376,7 +371,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 connection_handle, c
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
EnqueueReply(m_ACLEndpoint.m_address);
EnqueueReply(m_ACLEndpoint.m_cmd_address);
m_ACLEndpoint.Invalidate();
}
else
@ -391,7 +386,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 connection_handle, c
//
// Our WII_IPC_HLE is so efficient that we could fill the buffer immediately
// rather than enqueue it to some other memory and this will do good for StateSave
void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _event)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent& _event)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x completed...",
((hci_event_hdr_t*)_event.m_buffer)->event);
@ -401,11 +396,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
if (m_EventQueue.empty()) // fast path :)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint valid, sending packet to %08x",
m_HCIEndpoint.m_address);
m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.FillBuffer(_event.m_buffer, _event.m_size);
m_HCIEndpoint.SetRetVal(_event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint.m_address);
EnqueueReply(m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.Invalidate();
}
else // push new one, pop oldest
@ -417,11 +412,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x "
"being written from queue (%zu) to %08x...",
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
m_HCIEndpoint.m_address);
m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint.SetRetVal(event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint.m_address);
EnqueueReply(m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.Invalidate();
m_EventQueue.pop_front();
}
@ -434,7 +429,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
}
}
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
u32 CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
{
bool packet_transferred = false;
@ -445,11 +440,11 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
const SQueuedEvent& event = m_EventQueue.front();
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x being written from queue (%zu) to %08x...",
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
m_HCIEndpoint.m_address);
m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint.SetRetVal(event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint.m_address);
EnqueueReply(m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.Invalidate();
m_EventQueue.pop_front();
packet_transferred = true;
@ -507,8 +502,8 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
return packet_transferred;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u16 size,
const u16 conn_handle)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ACLPool::Store(const u8* data, const u16 size,
const u16 conn_handle)
{
if (m_queue.size() >= 100)
{
@ -517,7 +512,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u
return;
}
_dbg_assert_msg_(WII_IPC_WIIMOTE, size < m_acl_pkt_size, "ACL packet too large for pool");
_dbg_assert_msg_(WII_IPC_WIIMOTE, size < ACL_PKT_SIZE, "ACL packet too large for pool");
m_queue.push_back(Packet());
auto& packet = m_queue.back();
@ -527,7 +522,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u
packet.conn_handle = conn_handle;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
{
auto& packet = m_queue.front();
@ -537,9 +532,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& e
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
"queue to %08x",
endpoint.m_address);
endpoint.m_cmd_address);
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_buffer);
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_payload_addr);
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
pHeader->length = size;
@ -550,11 +545,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& e
m_queue.pop_front();
EnqueueReply(endpoint.m_address);
EnqueueReply(endpoint.m_cmd_address);
endpoint.Invalidate();
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventInquiryComplete()
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventInquiryComplete()
{
SQueuedEvent Event(sizeof(SHCIEventInquiryComplete), 0);
@ -570,7 +565,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventInquiryComplete()
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventInquiryResponse()
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventInquiryResponse()
{
if (m_WiiMotes.empty())
return false;
@ -620,7 +615,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventInquiryResponse()
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConnectionComplete(const bdaddr_t& _bd)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventConnectionComplete(const bdaddr_t& _bd)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_bd);
if (pWiiMote == nullptr)
@ -663,7 +658,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConnectionComplete(const bdad
}
// This is called from Update() after ScanEnable has been enabled.
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventRequestConnection(
CWII_IPC_HLE_WiiMote& _rWiiMote)
{
SQueuedEvent Event(sizeof(SHCIEventRequestConnection), 0);
@ -699,7 +694,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestConnection(
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventDisconnect(u16 _connectionHandle, u8 _Reason)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventDisconnect(u16 _connectionHandle, u8 _Reason)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -723,7 +718,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventDisconnect(u16 _connectionHan
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventAuthenticationCompleted(u16 _connectionHandle)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventAuthenticationCompleted(
u16 _connectionHandle)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -747,7 +743,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventAuthenticationCompleted(u16 _
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRemoteNameReq(const bdaddr_t& _bd)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventRemoteNameReq(const bdaddr_t& _bd)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_bd);
if (pWiiMote == nullptr)
@ -774,7 +770,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRemoteNameReq(const bdaddr_t&
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventReadRemoteFeatures(u16 _connectionHandle)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventReadRemoteFeatures(u16 _connectionHandle)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -810,7 +806,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventReadRemoteFeatures(u16 _conne
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventReadRemoteVerInfo(u16 _connectionHandle)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventReadRemoteVerInfo(u16 _connectionHandle)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -838,8 +834,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventReadRemoteVerInfo(u16 _connec
return true;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventCommandComplete(u16 opcode, const void* data,
u32 data_size)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventCommandComplete(u16 opcode, const void* data,
u32 data_size)
{
_dbg_assert_(WII_IPC_WIIMOTE, (sizeof(SHCIEventCommand) - 2 + data_size) < 256);
@ -863,7 +859,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventCommandComplete(u16 opcode, c
AddEventToQueue(event);
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventCommandStatus(u16 _Opcode)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventCommandStatus(u16 _Opcode)
{
SQueuedEvent Event(sizeof(SHCIEventStatus), 0);
@ -881,7 +877,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventCommandStatus(u16 _Opcode)
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRoleChange(bdaddr_t _bd, bool _master)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventRoleChange(bdaddr_t _bd, bool _master)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_bd);
if (pWiiMote == nullptr)
@ -908,7 +904,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRoleChange(bdaddr_t _bd, bool
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets()
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventNumberOfCompletedPackets()
{
SQueuedEvent Event((u32)(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) +
(sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size())),
@ -954,8 +950,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets()
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventModeChange(u16 _connectionHandle, u8 _mode,
u16 _value)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventModeChange(u16 _connectionHandle, u8 _mode,
u16 _value)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -980,7 +976,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventModeChange(u16 _connectionHan
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventLinkKeyNotification(const u8 num_to_send)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventLinkKeyNotification(const u8 num_to_send)
{
u8 payload_length = sizeof(hci_return_link_keys_ep) + sizeof(hci_link_key_rep_cp) * num_to_send;
SQueuedEvent Event(2 + payload_length, 0);
@ -1014,7 +1010,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventLinkKeyNotification(const u8
return true;
};
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestLinkKey(const bdaddr_t& _bd)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventRequestLinkKey(const bdaddr_t& _bd)
{
SQueuedEvent Event(sizeof(SHCIEventRequestLinkKey), 0);
@ -1035,7 +1031,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRequestLinkKey(const bdaddr_t
return true;
};
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventReadClockOffsetComplete(u16 _connectionHandle)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventReadClockOffsetComplete(
u16 _connectionHandle)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -1061,8 +1058,8 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventReadClockOffsetComplete(u16 _
return true;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConPacketTypeChange(u16 _connectionHandle,
u16 _packetType)
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventConPacketTypeChange(u16 _connectionHandle,
u16 _packetType)
{
CWII_IPC_HLE_WiiMote* pWiiMote = AccessWiiMote(_connectionHandle);
if (pWiiMote == nullptr)
@ -1089,7 +1086,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventConPacketTypeChange(u16 _conn
// Command dispatcher
// This is called from the USBV0_IOCTL_CTRLMSG Ioctlv
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
const SHCICommandMessage& _rHCICommandMessage)
{
u8* pInput = Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr + 3);
@ -1278,7 +1275,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(
// --- command helper
//
//
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiry(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandInquiry(const u8* input)
{
// Inquiry should not be called normally
const hci_inquiry_cp* inquiry = reinterpret_cast<const hci_inquiry_cp*>(input);
@ -1296,7 +1293,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiry(const u8* input)
SendEventInquiryComplete();
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiryCancel(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandInquiryCancel(const u8* input)
{
hci_inquiry_cancel_rp reply;
reply.status = 0x00;
@ -1306,7 +1303,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandInquiryCancel(const u8* input)
SendEventCommandComplete(HCI_CMD_INQUIRY_CANCEL, &reply, sizeof(hci_inquiry_cancel_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandCreateCon(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandCreateCon(const u8* input)
{
const hci_create_con_cp* create_connection = reinterpret_cast<const hci_create_con_cp*>(input);
@ -1327,7 +1324,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandCreateCon(const u8* input)
SendEventConnectionComplete(create_connection->bdaddr);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandDisconnect(const u8* input)
{
const hci_discon_cp* disconnect = reinterpret_cast<const hci_discon_cp*>(input);
@ -1346,7 +1343,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(const u8* input)
wiimote->EventDisconnect();
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAcceptCon(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandAcceptCon(const u8* input)
{
const hci_accept_con_cp* accept_connection = reinterpret_cast<const hci_accept_con_cp*>(input);
@ -1372,7 +1369,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAcceptCon(const u8* input)
SendEventConnectionComplete(accept_connection->bdaddr);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandLinkKeyRep(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandLinkKeyRep(const u8* input)
{
const hci_link_key_rep_cp* key_rep = reinterpret_cast<const hci_link_key_rep_cp*>(input);
@ -1389,7 +1386,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandLinkKeyRep(const u8* input)
SendEventCommandComplete(HCI_CMD_LINK_KEY_REP, &reply, sizeof(hci_link_key_rep_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandLinkKeyNegRep(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandLinkKeyNegRep(const u8* input)
{
const hci_link_key_neg_rep_cp* key_neg = reinterpret_cast<const hci_link_key_neg_rep_cp*>(input);
@ -1405,7 +1402,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandLinkKeyNegRep(const u8* input)
SendEventCommandComplete(HCI_CMD_LINK_KEY_NEG_REP, &reply, sizeof(hci_link_key_neg_rep_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandChangeConPacketType(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandChangeConPacketType(const u8* input)
{
const hci_change_con_pkt_type_cp* change_packet_type =
reinterpret_cast<const hci_change_con_pkt_type_cp*>(input);
@ -1421,7 +1418,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandChangeConPacketType(const u8* i
SendEventConPacketTypeChange(change_packet_type->con_handle, change_packet_type->pkt_type);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAuthenticationRequested(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandAuthenticationRequested(const u8* input)
{
const hci_auth_req_cp* auth_req = reinterpret_cast<const hci_auth_req_cp*>(input);
@ -1432,7 +1429,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAuthenticationRequested(const u
SendEventAuthenticationCompleted(auth_req->con_handle);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandRemoteNameReq(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandRemoteNameReq(const u8* input)
{
const hci_remote_name_req_cp* remote_name_req =
reinterpret_cast<const hci_remote_name_req_cp*>(input);
@ -1450,7 +1447,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandRemoteNameReq(const u8* input)
SendEventRemoteNameReq(remote_name_req->bdaddr);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteFeatures(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadRemoteFeatures(const u8* input)
{
const hci_read_remote_features_cp* read_remote_features =
reinterpret_cast<const hci_read_remote_features_cp*>(input);
@ -1462,7 +1459,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteFeatures(const u8* in
SendEventReadRemoteFeatures(read_remote_features->con_handle);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteVerInfo(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadRemoteVerInfo(const u8* input)
{
const hci_read_remote_ver_info_cp* read_remote_ver_info =
reinterpret_cast<const hci_read_remote_ver_info_cp*>(input);
@ -1474,7 +1471,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadRemoteVerInfo(const u8* inp
SendEventReadRemoteVerInfo(read_remote_ver_info->con_handle);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadClockOffset(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadClockOffset(const u8* input)
{
const hci_read_clock_offset_cp* read_clock_offset =
reinterpret_cast<const hci_read_clock_offset_cp*>(input);
@ -1486,7 +1483,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadClockOffset(const u8* input
SendEventReadClockOffsetComplete(read_clock_offset->con_handle);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSniffMode(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandSniffMode(const u8* input)
{
const hci_sniff_mode_cp* sniff_mode = reinterpret_cast<const hci_sniff_mode_cp*>(input);
@ -1501,7 +1498,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSniffMode(const u8* input)
SendEventModeChange(sniff_mode->con_handle, 0x02, sniff_mode->max_interval); // 0x02 - sniff mode
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkPolicy(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteLinkPolicy(const u8* input)
{
const hci_write_link_policy_settings_cp* link_policy =
reinterpret_cast<const hci_write_link_policy_settings_cp*>(input);
@ -1513,7 +1510,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkPolicy(const u8* input
SendEventCommandStatus(HCI_CMD_WRITE_LINK_POLICY_SETTINGS);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReset(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReset(const u8* input)
{
hci_status_rp reply;
reply.status = 0x00;
@ -1523,7 +1520,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReset(const u8* input)
SendEventCommandComplete(HCI_CMD_RESET, &reply, sizeof(hci_status_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSetEventFilter(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandSetEventFilter(const u8* input)
{
const hci_set_event_filter_cp* set_event_filter =
reinterpret_cast<const hci_set_event_filter_cp*>(input);
@ -1539,7 +1536,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSetEventFilter(const u8* input)
SendEventCommandComplete(HCI_CMD_SET_EVENT_FILTER, &reply, sizeof(hci_set_event_filter_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePinType(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWritePinType(const u8* input)
{
const hci_write_pin_type_cp* write_pin_type =
reinterpret_cast<const hci_write_pin_type_cp*>(input);
@ -1553,7 +1550,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePinType(const u8* input)
SendEventCommandComplete(HCI_CMD_WRITE_PIN_TYPE, &reply, sizeof(hci_write_pin_type_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadStoredLinkKey(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadStoredLinkKey(const u8* input)
{
const hci_read_stored_link_key_cp* read_stored_link_key =
reinterpret_cast<const hci_read_stored_link_key_cp*>(input);
@ -1588,7 +1585,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadStoredLinkKey(const u8* inp
sizeof(hci_read_stored_link_key_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDeleteStoredLinkKey(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandDeleteStoredLinkKey(const u8* input)
{
const hci_delete_stored_link_key_cp* delete_stored_link_key =
reinterpret_cast<const hci_delete_stored_link_key_cp*>(input);
@ -1615,7 +1612,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDeleteStoredLinkKey(const u8* i
"has failed. Could be a problem with loading the SCONF");
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLocalName(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteLocalName(const u8* input)
{
const hci_write_local_name_cp* write_local_name =
reinterpret_cast<const hci_write_local_name_cp*>(input);
@ -1631,7 +1628,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLocalName(const u8* input)
// Here we normally receive the timeout interval.
// But not from homebrew games that use lwbt. Why not?
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePageTimeOut(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWritePageTimeOut(const u8* input)
{
const hci_write_page_timeout_cp* write_page_timeout =
reinterpret_cast<const hci_write_page_timeout_cp*>(input);
@ -1646,7 +1643,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePageTimeOut(const u8* inpu
}
/* This will enable ScanEnable so that Update() can start the Wiimote. */
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteScanEnable(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteScanEnable(const u8* input)
{
const hci_write_scan_enable_cp* write_scan_enable =
reinterpret_cast<const hci_write_scan_enable_cp*>(input);
@ -1669,7 +1666,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteScanEnable(const u8* input
SendEventCommandComplete(HCI_CMD_WRITE_SCAN_ENABLE, &reply, sizeof(hci_write_scan_enable_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteUnitClass(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteUnitClass(const u8* input)
{
const hci_write_unit_class_cp* write_unit_class =
reinterpret_cast<const hci_write_unit_class_cp*>(input);
@ -1685,7 +1682,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteUnitClass(const u8* input)
SendEventCommandComplete(HCI_CMD_WRITE_UNIT_CLASS, &reply, sizeof(hci_write_unit_class_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandHostBufferSize(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandHostBufferSize(const u8* input)
{
const hci_host_buffer_size_cp* host_buffer_size =
reinterpret_cast<const hci_host_buffer_size_cp*>(input);
@ -1702,7 +1699,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandHostBufferSize(const u8* input)
SendEventCommandComplete(HCI_CMD_HOST_BUFFER_SIZE, &reply, sizeof(hci_host_buffer_size_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkSupervisionTimeout(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteLinkSupervisionTimeout(const u8* input)
{
const hci_write_link_supervision_timeout_cp* supervision =
reinterpret_cast<const hci_write_link_supervision_timeout_cp*>(input);
@ -1720,7 +1717,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkSupervisionTimeout(con
sizeof(hci_write_link_supervision_timeout_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryScanType(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteInquiryScanType(const u8* input)
{
const hci_write_inquiry_scan_type_cp* set_event_filter =
reinterpret_cast<const hci_write_inquiry_scan_type_cp*>(input);
@ -1735,7 +1732,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryScanType(const u8*
sizeof(hci_write_inquiry_scan_type_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryMode(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWriteInquiryMode(const u8* input)
{
const hci_write_inquiry_mode_cp* inquiry_mode =
reinterpret_cast<const hci_write_inquiry_mode_cp*>(input);
@ -1753,7 +1750,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteInquiryMode(const u8* inpu
SendEventCommandComplete(HCI_CMD_WRITE_INQUIRY_MODE, &reply, sizeof(hci_write_inquiry_mode_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePageScanType(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandWritePageScanType(const u8* input)
{
const hci_write_page_scan_type_cp* write_page_scan_type =
reinterpret_cast<const hci_write_page_scan_type_cp*>(input);
@ -1771,7 +1768,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWritePageScanType(const u8* inp
sizeof(hci_write_page_scan_type_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadLocalVer(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadLocalVer(const u8* input)
{
hci_read_local_ver_rp reply;
reply.status = 0x00;
@ -1792,7 +1789,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadLocalVer(const u8* input)
SendEventCommandComplete(HCI_CMD_READ_LOCAL_VER, &reply, sizeof(hci_read_local_ver_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadLocalFeatures(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadLocalFeatures(const u8* input)
{
hci_read_local_features_rp reply;
reply.status = 0x00;
@ -1814,17 +1811,17 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadLocalFeatures(const u8* inp
SendEventCommandComplete(HCI_CMD_READ_LOCAL_FEATURES, &reply, sizeof(hci_read_local_features_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBufferSize(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadBufferSize(const u8* input)
{
hci_read_buffer_size_rp reply;
reply.status = 0x00;
reply.max_acl_size = m_acl_pkt_size;
reply.max_acl_size = ACL_PKT_SIZE;
// Due to how the widcomm stack which Nintendo uses is coded, we must never
// let the stack think the controller is buffering more than 10 data packets
// - it will cause a u8 underflow and royally screw things up.
reply.num_acl_pkts = m_acl_pkts_num;
reply.max_sco_size = 64;
reply.num_sco_pkts = 0;
reply.num_acl_pkts = ACL_PKT_NUM;
reply.max_sco_size = SCO_PKT_SIZE;
reply.num_sco_pkts = SCO_PKT_NUM;
INFO_LOG(WII_IPC_WIIMOTE, "Command: HCI_CMD_READ_BUFFER_SIZE:");
DEBUG_LOG(WII_IPC_WIIMOTE, "return:");
@ -1836,7 +1833,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBufferSize(const u8* input)
SendEventCommandComplete(HCI_CMD_READ_BUFFER_SIZE, &reply, sizeof(hci_read_buffer_size_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBDAdrr(const u8* input)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandReadBDAdrr(const u8* input)
{
hci_read_bdaddr_rp reply;
reply.status = 0x00;
@ -1851,7 +1848,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBDAdrr(const u8* input)
SendEventCommandComplete(HCI_CMD_READ_BDADDR, &reply, sizeof(hci_read_bdaddr_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandVendorSpecific_FC4F(const u8* input, u32 size)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandVendorSpecific_FC4F(const u8* input, u32 size)
{
// callstack...
// BTM_VendorSpecificCommad()
@ -1871,7 +1868,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandVendorSpecific_FC4F(const u8* i
SendEventCommandComplete(0xFC4F, &reply, sizeof(hci_status_rp));
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandVendorSpecific_FC4C(const u8* input, u32 size)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CommandVendorSpecific_FC4C(const u8* input, u32 size)
{
hci_status_rp reply;
reply.status = 0x00;
@ -1888,7 +1885,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandVendorSpecific_FC4C(const u8* i
// --- helper
//
//
CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(const bdaddr_t& _rAddr)
CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AccessWiiMote(const bdaddr_t& _rAddr)
{
for (auto& wiimote : m_WiiMotes)
{
@ -1903,7 +1900,7 @@ CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(const b
return nullptr;
}
CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(u16 _ConnectionHandle)
CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AccessWiiMote(u16 _ConnectionHandle)
{
for (auto& wiimote : m_WiiMotes)
{
@ -1916,8 +1913,8 @@ CWII_IPC_HLE_WiiMote* CWII_IPC_HLE_Device_usb_oh1_57e_305::AccessWiiMote(u16 _Co
return nullptr;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::DisplayDisconnectMessage(const int wiimoteNumber,
const int reason)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DisplayDisconnectMessage(const int wiimoteNumber,
const int reason)
{
// TODO: If someone wants to be fancy we could also figure out what the values for pDiscon->reason
// mean
@ -1926,7 +1923,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DisplayDisconnectMessage(const int wii
StringFromFormat("Wiimote %i disconnected by emulated software", wiimoteNumber), 3000);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::LOG_LinkKey(const u8* _pLinkKey)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::LOG_LinkKey(const u8* _pLinkKey)
{
DEBUG_LOG(WII_IPC_WIIMOTE, " link key: "
"0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "

View File

@ -12,6 +12,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
#include "Core/IPC_HLE/hci.h"
class CWII_IPC_HLE_WiiMote;
@ -19,8 +20,8 @@ class CWII_IPC_HLE_WiiMote;
struct SQueuedEvent
{
u8 m_buffer[1024];
u32 m_size;
u16 m_connectionHandle;
u32 m_size = 0;
u16 m_connectionHandle = 0;
SQueuedEvent(u32 size, u16 connectionHandle) : m_size(size), m_connectionHandle(connectionHandle)
{
@ -32,19 +33,20 @@ struct SQueuedEvent
memset(m_buffer, 0, 1024);
}
SQueuedEvent() : m_size(0), m_connectionHandle(0) {}
SQueuedEvent() = default;
};
// Important to remember that this class is for /dev/usb/oh1/57e/305 ONLY
// /dev/usb/oh1 -> internal usb bus
// 57e/305 -> VendorID/ProductID of device on usb bus
// This device is ONLY the internal Bluetooth module (based on BCM2045 chip)
class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device
class CWII_IPC_HLE_Device_usb_oh1_57e_305_emu final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName);
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu(u32 _DeviceID, const std::string& _rDeviceName);
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305();
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_emu();
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
@ -61,8 +63,6 @@ public:
bool RemoteDisconnect(u16 _connectionHandle);
// hack for Wiimote plugin
public:
std::vector<CWII_IPC_HLE_WiiMote> m_WiiMotes;
CWII_IPC_HLE_WiiMote* AccessWiiMote(const bdaddr_t& _rAddr);
CWII_IPC_HLE_WiiMote* AccessWiiMote(u16 _ConnectionHandle);
@ -70,21 +70,6 @@ public:
void DoState(PointerWrap& p) override;
private:
enum USBIOCtl
{
USBV0_IOCTL_CTRLMSG = 0,
USBV0_IOCTL_BLKMSG = 1,
USBV0_IOCTL_INTRMSG = 2,
};
enum USBEndpoint
{
HCI_CTRL = 0x00,
HCI_EVENT = 0x81,
ACL_DATA_IN = 0x82,
ACL_DATA_OUT = 0x02
};
struct SHCICommandMessage
{
u8 bRequestType;
@ -98,36 +83,10 @@ private:
u32 m_Address;
};
// This is a lightweight/specialized version of SIOCtlVBuffer
struct CtrlBuffer
{
u32 m_address;
u32 m_buffer;
CtrlBuffer(u32 _Address) : m_address(_Address), m_buffer()
{
if (m_address)
{
u32 InBufferNum = Memory::Read_U32(m_address + 0x10);
u32 BufferVector = Memory::Read_U32(m_address + 0x18);
m_buffer = Memory::Read_U32(BufferVector + InBufferNum * sizeof(SIOCtlVBuffer::SBuffer));
}
}
inline void FillBuffer(const void* src, const size_t size) const
{
Memory::CopyToEmu(m_buffer, (u8*)src, size);
}
inline void SetRetVal(const u32 retval) const { Memory::Write_U32(retval, m_address + 4); }
inline bool IsValid() const { return m_address != 0; }
inline void Invalidate() { m_address = m_buffer = 0; }
};
bdaddr_t m_ControllerBD;
// this is used to trigger connecting via ACL
u8 m_ScanEnable;
u8 m_ScanEnable = 0;
SHCICommandMessage m_CtrlSetup;
CtrlBuffer m_HCIEndpoint;
@ -136,14 +95,11 @@ private:
u32 m_ACLSetup;
CtrlBuffer m_ACLEndpoint;
static const int m_acl_pkt_size = 339;
static const int m_acl_pkts_num = 10;
class ACLPool
{
struct Packet
{
u8 data[m_acl_pkt_size];
u8 data[ACL_PKT_SIZE];
u16 size;
u16 conn_handle;
};
@ -162,7 +118,7 @@ private:
} m_acl_pool;
u32 m_PacketCount[MAX_BBMOTES];
u64 m_last_ticks;
u64 m_last_ticks = 0;
// Send ACL data to a device (wiimote)
void IncDataPacket(u16 _ConnectionHandle);

View File

@ -0,0 +1,618 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <iomanip>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <libusb.h>
#include "Common/Network.h"
#include "Common/Thread.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h"
#include "Core/IPC_HLE/hci.h"
// This stores the address of paired devices and associated link keys.
// It is needed because some adapters forget all stored link keys when they are reset,
// which breaks pairings because the Wii relies on the Bluetooth module to remember them.
static std::map<btaddr_t, linkkey_t> s_link_keys;
static Common::Flag s_need_reset_keys;
// This flag is set when a libusb transfer failed (for reasons other than timing out)
// and we showed an OSD message about it.
static Common::Flag s_showed_failed_transfer;
static void EnqueueReply(const u32 command_address)
{
Memory::Write_U32(Memory::Read_U32(command_address), command_address + 8);
Memory::Write_U32(IPC_REP_ASYNC, command_address);
WII_IPC_HLE_Interface::EnqueueReply(command_address, 0, CoreTiming::FromThread::ANY);
}
static bool IsWantedDevice(libusb_device_descriptor& descriptor)
{
const int vid = SConfig::GetInstance().m_bt_passthrough_vid;
const int pid = SConfig::GetInstance().m_bt_passthrough_pid;
if (vid == -1 || pid == -1)
return true;
return descriptor.idVendor == vid && descriptor.idProduct == pid;
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_real::CWII_IPC_HLE_Device_usb_oh1_57e_305_real(
u32 device_id, const std::string& device_name)
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(device_id, device_name)
{
const int ret = libusb_init(&m_libusb_context);
_assert_msg_(WII_IPC_WIIMOTE, ret == 0, "Failed to init libusb.");
LoadLinkKeys();
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_real::~CWII_IPC_HLE_Device_usb_oh1_57e_305_real()
{
if (m_handle != nullptr)
{
SendHCIResetCommand();
WaitForHCICommandComplete(HCI_CMD_RESET);
libusb_release_interface(m_handle, 0);
// libusb_handle_events() may block the libusb thread indefinitely, so we need to
// call libusb_close() first then immediately stop the thread in StopTransferThread.
StopTransferThread();
libusb_unref_device(m_device);
}
libusb_exit(m_libusb_context);
SaveLinkKeys();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(u32 command_address, u32 mode)
{
libusb_device** list;
const ssize_t cnt = libusb_get_device_list(m_libusb_context, &list);
_dbg_assert_msg_(WII_IPC_HLE, cnt > 0, "Couldn't get device list");
for (ssize_t i = 0; i < cnt; ++i)
{
libusb_device* device = list[i];
libusb_device_descriptor device_descriptor;
libusb_config_descriptor* config_descriptor;
libusb_get_device_descriptor(device, &device_descriptor);
const int ret = libusb_get_active_config_descriptor(device, &config_descriptor);
if (ret != 0)
{
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to get config descriptor for device %04x:%04x: %s",
device_descriptor.idVendor, device_descriptor.idProduct, libusb_error_name(ret));
continue;
}
const libusb_interface& interface = config_descriptor->interface[INTERFACE];
const libusb_interface_descriptor& descriptor = interface.altsetting[0];
if (descriptor.bInterfaceClass == LIBUSB_CLASS_WIRELESS &&
descriptor.bInterfaceSubClass == SUBCLASS &&
descriptor.bInterfaceProtocol == PROTOCOL_BLUETOOTH && IsWantedDevice(device_descriptor) &&
OpenDevice(device))
{
unsigned char manufacturer[50] = {}, product[50] = {}, serial_number[50] = {};
libusb_get_string_descriptor_ascii(m_handle, device_descriptor.iManufacturer, manufacturer,
sizeof(manufacturer));
libusb_get_string_descriptor_ascii(m_handle, device_descriptor.iProduct, product,
sizeof(product));
libusb_get_string_descriptor_ascii(m_handle, device_descriptor.iSerialNumber, serial_number,
sizeof(serial_number));
NOTICE_LOG(WII_IPC_WIIMOTE, "Using device %04x:%04x (rev %x) for Bluetooth: %s %s %s",
device_descriptor.idVendor, device_descriptor.idProduct,
device_descriptor.bcdDevice, manufacturer, product, serial_number);
m_is_wii_bt_module =
device_descriptor.idVendor == 0x57e && device_descriptor.idProduct == 0x305;
libusb_free_config_descriptor(config_descriptor);
break;
}
libusb_free_config_descriptor(config_descriptor);
}
libusb_free_device_list(list, 1);
if (m_handle == nullptr)
{
PanicAlertT("Bluetooth passthrough mode is enabled, "
"but no usable Bluetooth USB device was found. Aborting.");
Core::QueueHostJob(Core::Stop);
return GetNoReply();
}
StartTransferThread();
Memory::Write_U32(GetDeviceID(), command_address + 4);
m_Active = true;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close(u32 command_address, bool force)
{
if (!force)
{
libusb_release_interface(m_handle, 0);
StopTransferThread();
libusb_unref_device(m_device);
m_handle = nullptr;
Memory::Write_U32(0, command_address + 4);
}
m_Active = false;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_address)
{
if (!m_is_wii_bt_module && s_need_reset_keys.TestAndClear())
{
// Do this now before transferring any more data, so that this is fully transparent to games
SendHCIDeleteLinkKeyCommand();
WaitForHCICommandComplete(HCI_CMD_DELETE_STORED_LINK_KEY);
if (SendHCIStoreLinkKeyCommand())
WaitForHCICommandComplete(HCI_CMD_WRITE_STORED_LINK_KEY);
}
const SIOCtlVBuffer cmd_buffer(command_address);
switch (cmd_buffer.Parameter)
{
// HCI commands to the Bluetooth adapter
case USBV0_IOCTL_CTRLMSG:
{
auto cmd = std::make_unique<CtrlMessage>(cmd_buffer);
const u16 opcode = *reinterpret_cast<u16*>(Memory::GetPointer(cmd->payload_addr));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
m_fake_read_buffer_size_reply.Set();
return GetNoReply();
}
if (!m_is_wii_bt_module && (opcode == 0xFC4C || opcode == 0xFC4F))
{
m_fake_vendor_command_reply.Set();
m_fake_vendor_command_reply_opcode = opcode;
return GetNoReply();
}
if (opcode == HCI_CMD_DELETE_STORED_LINK_KEY)
{
// Delete link key(s) from our own link key storage when the game tells the adapter to
const auto* delete_cmd =
reinterpret_cast<hci_delete_stored_link_key_cp*>(Memory::GetPointer(cmd->payload_addr));
if (delete_cmd->delete_all)
{
s_link_keys.clear();
}
else
{
btaddr_t addr;
std::copy(std::begin(delete_cmd->bdaddr.b), std::end(delete_cmd->bdaddr.b), addr.begin());
s_link_keys.erase(addr);
}
}
auto buffer = std::vector<u8>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(buffer.data(), cmd->request_type, cmd->request, cmd->value,
cmd->index, cmd->length);
Memory::CopyFromEmu(buffer.data() + LIBUSB_CONTROL_SETUP_SIZE, cmd->payload_addr, cmd->length);
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.data(), CommandCallback, cmd.release(),
0);
libusb_submit_transfer(transfer);
break;
}
// ACL data (incoming or outgoing) and incoming HCI events (respectively)
case USBV0_IOCTL_BLKMSG:
case USBV0_IOCTL_INTRMSG:
{
auto buffer = std::make_unique<CtrlBuffer>(cmd_buffer, command_address);
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
{
FakeReadBufferSizeReply(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
{
FakeVendorCommandReply(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
m_sync_button_state == SyncButtonState::Pressed)
{
Core::DisplayMessage("Scanning for Wiimotes", 2000);
FakeSyncButtonPressedEvent(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
m_sync_button_state == SyncButtonState::LongPressed)
{
Core::DisplayMessage("Reset saved Wiimote pairings", 2000);
FakeSyncButtonHeldEvent(*buffer);
return GetNoReply();
}
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->buffer = Memory::GetPointer(buffer->m_payload_addr);
transfer->callback = TransferCallback;
transfer->dev_handle = m_handle;
transfer->endpoint = buffer->m_endpoint;
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
transfer->length = buffer->m_length;
transfer->timeout = TIMEOUT;
transfer->type = cmd_buffer.Parameter == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
LIBUSB_TRANSFER_TYPE_INTERRUPT;
transfer->user_data = buffer.release();
libusb_submit_transfer(transfer);
break;
}
}
// Replies are generated inside of the message handlers (and asynchronously).
return GetNoReply();
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::DoState(PointerWrap& p)
{
bool passthrough_bluetooth = true;
p.Do(passthrough_bluetooth);
if (p.GetMode() == PointerWrap::MODE_READ)
PanicAlertT("Attempted to load a state. Bluetooth will likely be broken now.");
if (!passthrough_bluetooth && p.GetMode() == PointerWrap::MODE_READ)
{
Core::DisplayMessage("State needs Bluetooth passthrough to be disabled. Aborting load.", 4000);
p.SetMode(PointerWrap::MODE_VERIFY);
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::UpdateSyncButtonState(const bool is_held)
{
if (m_sync_button_state == SyncButtonState::Unpressed && is_held)
{
m_sync_button_held_timer.Update();
m_sync_button_state = SyncButtonState::Held;
}
if (m_sync_button_state == SyncButtonState::Held && is_held &&
m_sync_button_held_timer.GetTimeDifference() > SYNC_BUTTON_HOLD_MS_TO_RESET)
m_sync_button_state = SyncButtonState::LongPressed;
else if (m_sync_button_state == SyncButtonState::Held && !is_held)
m_sync_button_state = SyncButtonState::Pressed;
if (m_sync_button_state == SyncButtonState::Ignored && !is_held)
m_sync_button_state = SyncButtonState::Unpressed;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TriggerSyncButtonPressedEvent()
{
m_sync_button_state = SyncButtonState::Pressed;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TriggerSyncButtonHeldEvent()
{
m_sync_button_state = SyncButtonState::LongPressed;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::WaitForHCICommandComplete(const u16 opcode)
{
int actual_length;
std::vector<u8> buffer(1024);
// Only try 100 transfers at most, to avoid being stuck in an infinite loop
for (int tries = 0; tries < 100; ++tries)
{
if (libusb_interrupt_transfer(m_handle, HCI_EVENT, buffer.data(),
static_cast<int>(buffer.size()), &actual_length, 20) == 0 &&
reinterpret_cast<hci_event_hdr_t*>(buffer.data())->event == HCI_EVENT_COMMAND_COMPL &&
reinterpret_cast<SHCIEventCommand*>(buffer.data())->Opcode == opcode)
break;
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::SendHCIResetCommand()
{
const u8 type = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE;
u8 packet[3] = {};
const u16 payload[] = {HCI_CMD_RESET};
memcpy(packet, payload, sizeof(payload));
libusb_control_transfer(m_handle, type, 0, 0, 0, packet, sizeof(packet), TIMEOUT);
INFO_LOG(WII_IPC_WIIMOTE, "Sent a reset command to adapter");
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::SendHCIDeleteLinkKeyCommand()
{
const u8 type = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE;
std::vector<u8> packet(sizeof(hci_cmd_hdr_t) + sizeof(hci_delete_stored_link_key_cp));
auto* header = reinterpret_cast<hci_cmd_hdr_t*>(packet.data());
header->opcode = HCI_CMD_DELETE_STORED_LINK_KEY;
header->length = sizeof(hci_delete_stored_link_key_cp);
auto* cmd =
reinterpret_cast<hci_delete_stored_link_key_cp*>(packet.data() + sizeof(hci_cmd_hdr_t));
cmd->bdaddr = {};
cmd->delete_all = true;
libusb_control_transfer(m_handle, type, 0, 0, 0, packet.data(), static_cast<u16>(packet.size()),
TIMEOUT);
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_real::SendHCIStoreLinkKeyCommand()
{
if (s_link_keys.empty())
return false;
const u8 type = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE;
// The HCI command field is limited to uint8_t, and libusb to uint16_t.
const u8 payload_size =
static_cast<u8>(sizeof(hci_write_stored_link_key_cp)) +
(sizeof(btaddr_t) + sizeof(linkkey_t)) * static_cast<u8>(s_link_keys.size());
std::vector<u8> packet(sizeof(hci_cmd_hdr_t) + payload_size);
auto* header = reinterpret_cast<hci_cmd_hdr_t*>(packet.data());
header->opcode = HCI_CMD_WRITE_STORED_LINK_KEY;
header->length = payload_size;
auto* cmd =
reinterpret_cast<hci_write_stored_link_key_cp*>(packet.data() + sizeof(hci_cmd_hdr_t));
cmd->num_keys_write = static_cast<u8>(s_link_keys.size());
// This is really ugly, but necessary because of the HCI command structure:
// u8 num_keys;
// u8 bdaddr[6];
// u8 key[16];
// where the two last items are repeated num_keys times.
auto iterator = packet.begin() + sizeof(hci_cmd_hdr_t) + sizeof(hci_write_stored_link_key_cp);
for (const auto& entry : s_link_keys)
{
std::copy(entry.first.begin(), entry.first.end(), iterator);
iterator += entry.first.size();
std::copy(entry.second.begin(), entry.second.end(), iterator);
iterator += entry.second.size();
}
libusb_control_transfer(m_handle, type, 0, 0, 0, packet.data(), static_cast<u16>(packet.size()),
TIMEOUT);
return true;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const CtrlBuffer& ctrl)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event->PacketIndicator = 0x01;
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
ctrl.SetRetVal(sizeof(SHCIEventCommand));
EnqueueReply(ctrl.m_cmd_address);
}
// Due to how the widcomm stack which Nintendo uses is coded, we must never
// let the stack think the controller is buffering more than 10 data packets
// - it will cause a u8 underflow and royally screw things up.
// Therefore, the reply to this command has to be faked to avoid random, weird issues
// (including Wiimote disconnects and "event mismatch" warning messages).
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(const CtrlBuffer& ctrl)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
hci_event->PacketIndicator = 0x01;
hci_event->Opcode = HCI_CMD_READ_BUFFER_SIZE;
hci_read_buffer_size_rp reply;
reply.status = 0x00;
reply.max_acl_size = ACL_PKT_SIZE;
reply.num_acl_pkts = ACL_PKT_NUM;
reply.max_sco_size = SCO_PKT_SIZE;
reply.num_sco_pkts = SCO_PKT_NUM;
memcpy(packet + sizeof(SHCIEventCommand), &reply, sizeof(hci_read_buffer_size_rp));
ctrl.SetRetVal(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp));
EnqueueReply(ctrl.m_cmd_address);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(const CtrlBuffer& ctrl,
const u8* payload, const u8 size)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<hci_event_hdr_t*>(packet);
hci_event->event = HCI_EVENT_VENDOR;
hci_event->length = size;
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
ctrl.SetRetVal(sizeof(hci_event_hdr_t) + size);
EnqueueReply(ctrl.m_cmd_address);
}
// When the red sync button is pressed, a HCI event is generated:
// > HCI Event: Vendor (0xff) plen 1
// 08
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl)
{
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
const u8 payload[1] = {0x08};
FakeSyncButtonEvent(ctrl, payload, sizeof(payload));
m_sync_button_state = SyncButtonState::Ignored;
}
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl)
{
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
const u8 payload[1] = {0x09};
FakeSyncButtonEvent(ctrl, payload, sizeof(payload));
m_sync_button_state = SyncButtonState::Ignored;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::LoadLinkKeys()
{
const std::string& entries = SConfig::GetInstance().m_bt_passthrough_link_keys;
if (entries.empty())
return;
std::vector<std::string> pairs;
SplitString(entries, ',', pairs);
for (const auto& pair : pairs)
{
const auto index = pair.find('=');
if (index == std::string::npos)
continue;
btaddr_t address;
StringToMacAddress(pair.substr(0, index), address.data());
std::reverse(address.begin(), address.end());
const std::string& key_string = pair.substr(index + 1);
linkkey_t key;
size_t pos = 0;
for (size_t i = 0; i < key_string.length(); i = i + 2)
{
int value;
std::stringstream(key_string.substr(i, 2)) >> std::hex >> value;
key[pos++] = value;
}
s_link_keys[address] = key;
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::SaveLinkKeys()
{
std::ostringstream oss;
for (const auto& entry : s_link_keys)
{
btaddr_t address;
// Reverse the address so that it is stored in the correct order in the config file
std::reverse_copy(entry.first.begin(), entry.first.end(), address.begin());
oss << MacAddressToString(address.data());
oss << '=';
oss << std::hex;
for (const u16& data : entry.second)
oss << std::setfill('0') << std::setw(2) << data;
oss << std::dec << ',';
}
std::string config_string = oss.str();
if (!config_string.empty())
config_string.pop_back();
SConfig::GetInstance().m_bt_passthrough_link_keys = config_string;
SConfig::GetInstance().SaveSettings();
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_real::OpenDevice(libusb_device* device)
{
m_device = libusb_ref_device(device);
const int ret = libusb_open(m_device, &m_handle);
if (ret != 0)
{
PanicAlertT("Failed to open Bluetooth device: %s", libusb_error_name(ret));
return false;
}
const int result = libusb_detach_kernel_driver(m_handle, INTERFACE);
if (result < 0 && result != LIBUSB_ERROR_NOT_FOUND && result != LIBUSB_ERROR_NOT_SUPPORTED)
{
PanicAlertT("Failed to detach kernel driver for BT passthrough: %s", libusb_error_name(result));
return false;
}
if (libusb_claim_interface(m_handle, INTERFACE) < 0)
{
PanicAlertT("Failed to claim interface for BT passthrough");
return false;
}
return true;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::StartTransferThread()
{
if (m_thread_running.IsSet())
return;
m_thread_running.Set();
m_thread = std::thread(&CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferThread, this);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::StopTransferThread()
{
if (m_thread_running.TestAndClear())
{
libusb_close(m_handle);
m_thread.join();
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferThread()
{
Common::SetCurrentThreadName("BT USB Thread");
while (m_thread_running.IsSet())
{
libusb_handle_events_completed(m_libusb_context, nullptr);
}
}
// The callbacks are called from libusb code on a separate thread.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::CommandCallback(libusb_transfer* tr)
{
const std::unique_ptr<CtrlMessage> cmd(static_cast<CtrlMessage*>(tr->user_data));
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_NO_DEVICE)
{
ERROR_LOG(WII_IPC_WIIMOTE, "libusb command transfer failed, status: 0x%02x", tr->status);
if (!s_showed_failed_transfer.IsSet())
{
Core::DisplayMessage("Failed to send a command to the Bluetooth adapter.", 10000);
Core::DisplayMessage("It may not be compatible with passthrough mode.", 10000);
s_showed_failed_transfer.Set();
}
}
else
{
s_showed_failed_transfer.Clear();
}
EnqueueReply(cmd->address);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer* tr)
{
const std::unique_ptr<CtrlBuffer> ctrl(static_cast<CtrlBuffer*>(tr->user_data));
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_TIMED_OUT &&
tr->status != LIBUSB_TRANSFER_NO_DEVICE)
{
ERROR_LOG(WII_IPC_WIIMOTE, "libusb transfer failed, status: 0x%02x", tr->status);
if (!s_showed_failed_transfer.IsSet())
{
Core::DisplayMessage("Failed to transfer to or from to the Bluetooth adapter.", 10000);
Core::DisplayMessage("It may not be compatible with passthrough mode.", 10000);
s_showed_failed_transfer.Set();
}
}
else
{
s_showed_failed_transfer.Clear();
}
if (tr->status == LIBUSB_TRANSFER_COMPLETED && tr->endpoint == HCI_EVENT)
{
const auto* event = reinterpret_cast<hci_event_hdr_t*>(tr->buffer);
if (event->event == HCI_EVENT_LINK_KEY_NOTIFICATION)
{
const auto* notification =
reinterpret_cast<hci_link_key_notification_ep*>(tr->buffer + sizeof(hci_event_hdr_t));
btaddr_t addr;
std::copy(std::begin(notification->bdaddr.b), std::end(notification->bdaddr.b), addr.begin());
linkkey_t key;
std::copy(std::begin(notification->key), std::end(notification->key), std::begin(key));
s_link_keys[addr] = key;
}
else if (event->event == HCI_EVENT_COMMAND_COMPL &&
reinterpret_cast<hci_command_compl_ep*>(tr->buffer + sizeof(*event))->opcode ==
HCI_CMD_RESET)
{
s_need_reset_keys.Set();
}
}
ctrl->SetRetVal(tr->actual_length);
EnqueueReply(ctrl->m_cmd_address);
}

View File

@ -0,0 +1,102 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#if defined(__LIBUSB__)
#include <array>
#include <atomic>
#include <thread>
#include "Common/Flag.h"
#include "Common/Timer.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
struct libusb_device;
struct libusb_device_handle;
struct libusb_context;
struct libusb_transfer;
enum class SyncButtonState
{
Unpressed,
Held,
Pressed,
LongPressed,
// On a real Wii, after a long press, the button release is ignored and doesn't trigger a sync.
Ignored,
};
using btaddr_t = std::array<u8, 6>;
using linkkey_t = std::array<u8, 16>;
class CWII_IPC_HLE_Device_usb_oh1_57e_305_real final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_real(u32 device_id, const std::string& device_name);
~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() override;
IPCCommandResult Open(u32 command_address, u32 mode) override;
IPCCommandResult Close(u32 command_address, bool force) override;
IPCCommandResult IOCtlV(u32 command_address) override;
void DoState(PointerWrap& p) override;
u32 Update() override { return 0; }
void UpdateSyncButtonState(bool is_held) override;
void TriggerSyncButtonPressedEvent() override;
void TriggerSyncButtonHeldEvent() override;
private:
static constexpr u8 INTERFACE = 0x00;
static constexpr u8 SUBCLASS = 0x01;
static constexpr u8 PROTOCOL_BLUETOOTH = 0x01;
// Arbitrarily chosen value that allows emulated software to send commands often enough
// so that the sync button event is triggered at least every 200ms.
// Ideally this should be equal to 0, so we don't trigger unnecessary libusb transfers.
static constexpr int TIMEOUT = 200;
static constexpr int SYNC_BUTTON_HOLD_MS_TO_RESET = 10000;
std::atomic<SyncButtonState> m_sync_button_state{SyncButtonState::Unpressed};
Common::Timer m_sync_button_held_timer;
libusb_device* m_device = nullptr;
libusb_device_handle* m_handle = nullptr;
libusb_context* m_libusb_context = nullptr;
Common::Flag m_thread_running;
std::thread m_thread;
// Set when we received a command to which we need to fake a reply
Common::Flag m_fake_read_buffer_size_reply;
Common::Flag m_fake_vendor_command_reply;
u16 m_fake_vendor_command_reply_opcode;
bool m_is_wii_bt_module = false;
void WaitForHCICommandComplete(u16 opcode);
void SendHCIResetCommand();
void SendHCIDeleteLinkKeyCommand();
bool SendHCIStoreLinkKeyCommand();
void FakeVendorCommandReply(const CtrlBuffer& ctrl);
void FakeReadBufferSizeReply(const CtrlBuffer& ctrl);
void FakeSyncButtonEvent(const CtrlBuffer& ctrl, const u8* payload, u8 size);
void FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl);
void FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl);
void LoadLinkKeys();
void SaveLinkKeys();
bool OpenDevice(libusb_device* device);
void StartTransferThread();
void StopTransferThread();
void TransferThread();
static void CommandCallback(libusb_transfer* transfer);
static void TransferCallback(libusb_transfer* transfer);
};
#else
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.h"
using CWII_IPC_HLE_Device_usb_oh1_57e_305_real = CWII_IPC_HLE_Device_usb_oh1_57e_305_stub;
#endif

View File

@ -0,0 +1,24 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.h"
#include "Common/MsgHandler.h"
namespace Core
{
void DisplayMessage(const std::string& message, int time_in_ms);
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::Open(u32 command_address, u32 mode)
{
PanicAlertT("Bluetooth passthrough mode is enabled, but Dolphin was built without libusb."
" Passthrough mode cannot be used.");
return GetNoReply();
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::DoState(PointerWrap& p)
{
Core::DisplayMessage("The current IPC_HLE_Device_usb is a stub. Aborting load.", 4000);
p.SetMode(PointerWrap::MODE_VERIFY);
}

View File

@ -0,0 +1,24 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
class CWII_IPC_HLE_Device_usb_oh1_57e_305_stub final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_stub(u32 device_id, const std::string& device_name)
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(device_id, device_name)
{
}
~CWII_IPC_HLE_Device_usb_oh1_57e_305_stub() override {}
IPCCommandResult Open(u32 command_address, u32 mode) override;
IPCCommandResult Close(u32 command_address, bool force) override { return GetNoReply(); }
IPCCommandResult IOCtl(u32 command_address) override { return GetDefaultReply(); }
IPCCommandResult IOCtlV(u32 command_address) override { return GetNoReply(); }
void DoState(PointerWrap& p) override;
u32 Update() override { return 0; }
};

View File

@ -6,7 +6,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h" // Local core functions
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.h"
#ifdef _WIN32

View File

@ -10,25 +10,25 @@
#include "Core/Core.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/IPC_HLE/WiiMote_HID_Attr.h"
#include "Core/IPC_HLE/l2cap.h"
static CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = nullptr;
static CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* s_Usb = nullptr;
CWII_IPC_HLE_Device_usb_oh1_57e_305* GetUsbPointer()
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* GetUsbPointer()
{
return s_Usb;
}
void SetUsbPointer(CWII_IPC_HLE_Device_usb_oh1_57e_305* ptr)
void SetUsbPointer(CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* ptr)
{
s_Usb = ptr;
}
CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number,
bdaddr_t _BD, bool ready)
CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* _pHost,
int _Number, bdaddr_t _BD, bool ready)
: m_HIDControlChannel_Connected(false), m_HIDControlChannel_ConnectedWait(false),
m_HIDControlChannel_Config(false), m_HIDControlChannel_ConfigWait(false),
m_HIDInterruptChannel_Connected(false), m_HIDInterruptChannel_ConnectedWait(false),
@ -71,6 +71,16 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
void CWII_IPC_HLE_WiiMote::DoState(PointerWrap& p)
{
bool passthrough_bluetooth = false;
p.Do(passthrough_bluetooth);
if (passthrough_bluetooth && p.GetMode() == PointerWrap::MODE_READ)
{
Core::DisplayMessage("State needs Bluetooth passthrough to be enabled. Aborting load state.",
3000);
p.SetMode(PointerWrap::MODE_VERIFY);
return;
}
// this function is usually not called... see CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState
p.Do(m_ConnectionState);

View File

@ -11,11 +11,11 @@
#include "Common/CommonTypes.h"
#include "Core/IPC_HLE/hci.h"
class CWII_IPC_HLE_Device_usb_oh1_57e_305;
class CWII_IPC_HLE_Device_usb_oh1_57e_305_emu;
class PointerWrap;
CWII_IPC_HLE_Device_usb_oh1_57e_305* GetUsbPointer();
void SetUsbPointer(CWII_IPC_HLE_Device_usb_oh1_57e_305* ptr);
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* GetUsbPointer();
void SetUsbPointer(CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* ptr);
class CBigEndianBuffer
{
@ -35,7 +35,7 @@ private:
class CWII_IPC_HLE_WiiMote
{
public:
CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number, bdaddr_t _BD,
CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* _pHost, int _Number, bdaddr_t _BD,
bool ready = false);
virtual ~CWII_IPC_HLE_WiiMote() {}
@ -93,7 +93,7 @@ private:
u16 lmp_subversion;
u8 m_LinkKey[HCI_KEY_SIZE];
std::string m_Name;
CWII_IPC_HLE_Device_usb_oh1_57e_305* m_pHost;
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* m_pHost;
struct SChannel
{

View File

@ -29,7 +29,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
@ -570,7 +570,8 @@ void ChangeWiiPads(bool instantly)
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
}
}

View File

@ -22,7 +22,7 @@
#include "Core/HW/Sram.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/Movie.h"
#include "InputCommon/GCAdapter.h"
#include "VideoCommon/OnScreenDisplay.h"

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 61; // Last changed in PR 4216
static const u32 STATE_VERSION = 62; // Last changed in PR 4195
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,

View File

@ -6,6 +6,7 @@
#include <wx/choice.h>
#include <wx/gbsizer.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h>
#include "Core/ConfigManager.h"
@ -38,6 +39,9 @@ void WiiConfigPane::InitializeGUI()
m_system_language_strings.Add(_("Traditional Chinese"));
m_system_language_strings.Add(_("Korean"));
m_bt_sensor_bar_pos_strings.Add(_("Bottom"));
m_bt_sensor_bar_pos_strings.Add(_("Top"));
m_screensaver_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable Screen Saver"));
m_pal60_mode_checkbox = new wxCheckBox(this, wxID_ANY, _("Use PAL60 Mode (EuRGB60)"));
m_aspect_ratio_choice =
@ -46,6 +50,15 @@ void WiiConfigPane::InitializeGUI()
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_system_language_strings);
m_sd_card_checkbox = new wxCheckBox(this, wxID_ANY, _("Insert SD Card"));
m_connect_keyboard_checkbox = new wxCheckBox(this, wxID_ANY, _("Connect USB Keyboard"));
m_bt_sensor_bar_pos =
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_bt_sensor_bar_pos_strings);
m_bt_sensor_bar_sens = new wxSlider(this, wxID_ANY, 0, 0, 4);
m_bt_speaker_volume = new wxSlider(this, wxID_ANY, 0, 0, 127);
m_bt_wiimote_motor = new wxCheckBox(this, wxID_ANY, _("Wiimote Motor"));
// With some GTK themes, no minimum size will be applied - so do this manually here
m_bt_sensor_bar_sens->SetMinSize(wxSize(100, -1));
m_bt_speaker_volume->SetMinSize(wxSize(100, -1));
m_screensaver_checkbox->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnScreenSaverCheckBoxChanged, this);
m_pal60_mode_checkbox->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnPAL60CheckBoxChanged, this);
@ -54,6 +67,10 @@ void WiiConfigPane::InitializeGUI()
m_sd_card_checkbox->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnSDCardCheckBoxChanged, this);
m_connect_keyboard_checkbox->Bind(wxEVT_CHECKBOX,
&WiiConfigPane::OnConnectKeyboardCheckBoxChanged, this);
m_bt_sensor_bar_pos->Bind(wxEVT_CHOICE, &WiiConfigPane::OnSensorBarPosChanged, this);
m_bt_sensor_bar_sens->Bind(wxEVT_SLIDER, &WiiConfigPane::OnSensorBarSensChanged, this);
m_bt_speaker_volume->Bind(wxEVT_SLIDER, &WiiConfigPane::OnSpeakerVolumeChanged, this);
m_bt_wiimote_motor->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnWiimoteMotorChanged, this);
m_screensaver_checkbox->SetToolTip(_("Dims the screen after five minutes of inactivity."));
m_pal60_mode_checkbox->SetToolTip(_("Sets the Wii display mode to 60Hz (480i) instead of 50Hz "
@ -77,6 +94,35 @@ void WiiConfigPane::InitializeGUI()
misc_settings_grid_sizer->Add(m_system_language_choice, wxGBPosition(3, 1), wxDefaultSpan, wxALL,
5);
auto* const bt_sensor_bar_pos_sizer = new wxBoxSizer(wxHORIZONTAL);
bt_sensor_bar_pos_sizer->Add(new wxStaticText(this, wxID_ANY, _("Min")), 0,
wxALIGN_CENTER_VERTICAL);
bt_sensor_bar_pos_sizer->Add(m_bt_sensor_bar_sens);
bt_sensor_bar_pos_sizer->Add(new wxStaticText(this, wxID_ANY, _("Max")), 0,
wxALIGN_CENTER_VERTICAL);
auto* const bt_speaker_volume_sizer = new wxBoxSizer(wxHORIZONTAL);
bt_speaker_volume_sizer->Add(new wxStaticText(this, wxID_ANY, _("Min")), 0,
wxALIGN_CENTER_VERTICAL);
bt_speaker_volume_sizer->Add(m_bt_speaker_volume);
bt_speaker_volume_sizer->Add(new wxStaticText(this, wxID_ANY, _("Max")), 0,
wxALIGN_CENTER_VERTICAL);
wxGridBagSizer* const bt_settings_grid_sizer = new wxGridBagSizer();
bt_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Sensor Bar Position:")),
wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
5);
bt_settings_grid_sizer->Add(m_bt_sensor_bar_pos, wxGBPosition(0, 1), wxDefaultSpan, wxALL, 5);
bt_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("IR Sensitivity:")),
wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
5);
bt_settings_grid_sizer->Add(bt_sensor_bar_pos_sizer, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5);
bt_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Speaker Volume:")),
wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
5);
bt_settings_grid_sizer->Add(bt_speaker_volume_sizer, wxGBPosition(2, 1), wxDefaultSpan, wxALL, 5);
bt_settings_grid_sizer->Add(m_bt_wiimote_motor, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5);
wxStaticBoxSizer* const misc_settings_static_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("Misc Settings"));
misc_settings_static_sizer->Add(misc_settings_grid_sizer);
@ -86,9 +132,14 @@ void WiiConfigPane::InitializeGUI()
device_settings_sizer->Add(m_sd_card_checkbox, 0, wxALL, 5);
device_settings_sizer->Add(m_connect_keyboard_checkbox, 0, wxALL, 5);
auto* const bt_settings_static_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("Wii Remote Settings"));
bt_settings_static_sizer->Add(bt_settings_grid_sizer);
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(misc_settings_static_sizer, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(device_settings_sizer, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(bt_settings_static_sizer, 0, wxEXPAND | wxALL, 5);
SetSizer(main_sizer);
}
@ -102,6 +153,11 @@ void WiiConfigPane::LoadGUIValues()
m_sd_card_checkbox->SetValue(SConfig::GetInstance().m_WiiSDCard);
m_connect_keyboard_checkbox->SetValue(SConfig::GetInstance().m_WiiKeyboard);
m_bt_sensor_bar_pos->SetSelection(SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.BAR"));
m_bt_sensor_bar_sens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u32>("BT.SENS"));
m_bt_speaker_volume->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.SPKV"));
m_bt_wiimote_motor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<bool>("BT.MOT"));
}
void WiiConfigPane::RefreshGUI()
@ -112,6 +168,11 @@ void WiiConfigPane::RefreshGUI()
m_pal60_mode_checkbox->Disable();
m_aspect_ratio_choice->Disable();
m_system_language_choice->Disable();
m_bt_sensor_bar_pos->Disable();
m_bt_sensor_bar_sens->Disable();
m_bt_speaker_volume->Disable();
m_bt_wiimote_motor->Disable();
}
}
@ -153,6 +214,26 @@ void WiiConfigPane::OnAspectRatioChoiceChanged(wxCommandEvent& event)
SConfig::GetInstance().m_SYSCONF->SetData("IPL.AR", m_aspect_ratio_choice->GetSelection());
}
void WiiConfigPane::OnSensorBarPosChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.BAR", event.GetInt());
}
void WiiConfigPane::OnSensorBarSensChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.SENS", event.GetInt());
}
void WiiConfigPane::OnSpeakerVolumeChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.SPKV", event.GetInt());
}
void WiiConfigPane::OnWiimoteMotorChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.MOT", event.GetInt());
}
// Change from IPL.LNG value to IPL.SADR country code.
// http://wiibrew.org/wiki/Country_Codes
u8 WiiConfigPane::GetSADRCountryCode(DiscIO::Language language)

View File

@ -15,6 +15,7 @@ enum class Language;
class wxCheckBox;
class wxChoice;
class wxSlider;
class WiiConfigPane final : public wxPanel
{
@ -33,10 +34,16 @@ private:
void OnSystemLanguageChoiceChanged(wxCommandEvent&);
void OnAspectRatioChoiceChanged(wxCommandEvent&);
void OnSensorBarPosChanged(wxCommandEvent&);
void OnSensorBarSensChanged(wxCommandEvent&);
void OnSpeakerVolumeChanged(wxCommandEvent&);
void OnWiimoteMotorChanged(wxCommandEvent&);
static u8 GetSADRCountryCode(DiscIO::Language language);
wxArrayString m_system_language_strings;
wxArrayString m_aspect_ratio_strings;
wxArrayString m_bt_sensor_bar_pos_strings;
wxCheckBox* m_screensaver_checkbox;
wxCheckBox* m_pal60_mode_checkbox;
@ -44,4 +51,9 @@ private:
wxCheckBox* m_connect_keyboard_checkbox;
wxChoice* m_system_language_choice;
wxChoice* m_aspect_ratio_choice;
wxChoice* m_bt_sensor_bar_pos;
wxSlider* m_bt_sensor_bar_sens;
wxSlider* m_bt_speaker_volume;
wxCheckBox* m_bt_wiimote_motor;
};

View File

@ -2,14 +2,16 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <array>
#include <map>
#include <string>
#include <utility>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/dialog.h>
#include <wx/gbsizer.h>
#include <wx/msgdlg.h>
#include <wx/radiobut.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h>
@ -17,7 +19,6 @@
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Common/SysConf.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/GCKeyboard.h"
@ -26,6 +27,8 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/HotkeyManager.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
#include "DolphinWX/Config/GCAdapterConfigDiag.h"
@ -57,16 +60,83 @@ ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent)
Bind(wxEVT_CLOSE_WINDOW, &ControllerConfigDiag::OnClose, this);
Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnCloseButton, this, wxID_CLOSE);
UpdateUI();
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
SetSizerAndFit(main_sizer);
Center();
}
void ControllerConfigDiag::UpdateUI()
{
const bool enable_bt_passthrough_mode = SConfig::GetInstance().m_bt_passthrough_enabled;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
m_wiimote_labels[i]->Enable(!enable_bt_passthrough_mode);
m_wiimote_sources[i]->Enable(!enable_bt_passthrough_mode);
m_wiimote_configure_button[i]->Enable(!enable_bt_passthrough_mode);
m_wiimote_sources[i]->Select(g_wiimote_sources[i]);
const bool wii_game_started =
SConfig::GetInstance().bWii || Core::GetState() == Core::CORE_UNINITIALIZED;
if (Core::g_want_determinism || !wii_game_started)
m_wiimote_sources[i]->Disable();
if (!wii_game_started ||
(g_wiimote_sources[i] != WIIMOTE_SRC_EMU && g_wiimote_sources[i] != WIIMOTE_SRC_HYBRID))
m_wiimote_configure_button[i]->Disable();
}
m_passthrough_sync_text->Enable(enable_bt_passthrough_mode);
m_passthrough_sync_btn->Enable(enable_bt_passthrough_mode);
m_passthrough_reset_text->Enable(enable_bt_passthrough_mode);
m_passthrough_reset_btn->Enable(enable_bt_passthrough_mode);
m_balance_board_checkbox->Enable(!enable_bt_passthrough_mode);
m_enable_continuous_scanning->Enable(!enable_bt_passthrough_mode);
m_refresh_wm_button->Enable(!enable_bt_passthrough_mode);
m_unsupported_bt_text->Enable(!enable_bt_passthrough_mode);
m_enable_speaker_data->Enable(!enable_bt_passthrough_mode);
// Disable some controls when emulation is running
if (Core::IsRunning())
{
if (!SConfig::GetInstance().bWii || NetPlay::IsNetPlayRunning())
{
m_passthrough_sync_text->Disable();
m_passthrough_sync_btn->Disable();
m_passthrough_reset_text->Disable();
m_passthrough_reset_btn->Disable();
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
m_wiimote_labels[i]->Disable();
m_wiimote_sources[i]->Disable();
}
m_balance_board_checkbox->Disable();
}
m_passthrough_bt_radio->Disable();
m_emulated_bt_radio->Disable();
if (!SConfig::GetInstance().bWii)
{
m_enable_continuous_scanning->Disable();
m_refresh_wm_button->Disable();
m_unsupported_bt_text->Disable();
m_enable_speaker_data->Disable();
}
}
}
wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
{
wxStaticBoxSizer* const gamecube_static_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("GameCube Controllers"));
wxFlexGridSizer* const gamecube_flex_sizer = new wxFlexGridSizer(3, 5, 5);
gamecube_flex_sizer->AddGrowableCol(1);
wxStaticText* pad_labels[4];
wxChoice* pad_type_choices[4];
@ -79,7 +149,7 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
const wxWindowID button_id = wxWindow::NewControlId();
m_gc_port_from_config_id.emplace(button_id, i);
m_gc_port_configure_button[i] =
new wxButton(this, button_id, _("Configure"), wxDefaultPosition, wxSize(100, 25));
new wxButton(this, button_id, _("Configure"), wxDefaultPosition, wxSize(100, -1));
m_gc_port_configure_button[i]->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnGameCubeConfigButton,
this);
@ -129,11 +199,11 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
// Add to the sizer
gamecube_flex_sizer->Add(pad_labels[i], 0, wxALIGN_CENTER_VERTICAL);
gamecube_flex_sizer->Add(pad_type_choices[i], 0, wxALIGN_CENTER_VERTICAL);
gamecube_flex_sizer->Add(pad_type_choices[i], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND);
gamecube_flex_sizer->Add(m_gc_port_configure_button[i], 1, wxEXPAND);
}
gamecube_static_sizer->Add(gamecube_flex_sizer, 1, wxEXPAND, 5);
gamecube_static_sizer->Add(gamecube_flex_sizer, 0, wxEXPAND | wxALL, 5);
gamecube_static_sizer->AddSpacer(5);
return gamecube_static_sizer;
@ -141,16 +211,76 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer()
{
wxStaticText* wiimote_label[4];
wxChoice* wiimote_source_ch[4];
auto* const box = new wxStaticBoxSizer(wxVERTICAL, this, _("Wiimotes"));
m_passthrough_bt_radio = new wxRadioButton(this, wxID_ANY, _("Passthrough a Bluetooth adapter"),
wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
m_passthrough_bt_radio->Bind(wxEVT_RADIOBUTTON, &ControllerConfigDiag::OnBluetoothModeChanged,
this);
box->Add(m_passthrough_bt_radio, 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 5);
box->Add(CreatePassthroughBTConfigSizer(), 0, wxALL | wxEXPAND, 5);
box->AddSpacer(10);
m_emulated_bt_radio = new wxRadioButton(this, wxID_ANY, _("Emulate the Wii's Bluetooth adapter"));
m_emulated_bt_radio->Bind(wxEVT_RADIOBUTTON, &ControllerConfigDiag::OnBluetoothModeChanged, this);
box->Add(m_emulated_bt_radio, 0, wxALL | wxEXPAND, 5);
box->Add(CreateEmulatedBTConfigSizer(), 0, wxALL | wxEXPAND, 5);
box->AddSpacer(5);
if (SConfig::GetInstance().m_bt_passthrough_enabled)
m_passthrough_bt_radio->SetValue(true);
else
m_emulated_bt_radio->SetValue(true);
return box;
}
wxBoxSizer* ControllerConfigDiag::CreatePassthroughBTConfigSizer()
{
auto* const sizer = new wxBoxSizer(wxVERTICAL);
m_passthrough_sync_text = new wxStaticText(this, wxID_ANY, _("Sync real Wiimotes and pair them"));
m_passthrough_sync_btn =
new wxButton(this, wxID_ANY, _("Sync"), wxDefaultPosition, wxSize(100, -1));
m_passthrough_sync_btn->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnPassthroughScanButton, this);
m_passthrough_reset_text =
new wxStaticText(this, wxID_ANY, _("Reset all saved Wiimote pairings"));
m_passthrough_reset_btn =
new wxButton(this, wxID_ANY, _("Reset"), wxDefaultPosition, wxSize(100, -1));
m_passthrough_reset_btn->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnPassthroughResetButton,
this);
auto* const sync_sizer = new wxBoxSizer(wxHORIZONTAL);
sync_sizer->Add(m_passthrough_sync_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
sync_sizer->AddStretchSpacer();
sync_sizer->Add(m_passthrough_sync_btn, 0, wxEXPAND);
auto* const reset_sizer = new wxBoxSizer(wxHORIZONTAL);
reset_sizer->Add(m_passthrough_reset_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
reset_sizer->AddStretchSpacer();
reset_sizer->Add(m_passthrough_reset_btn, 0, wxEXPAND);
sizer->Add(sync_sizer, 0, wxEXPAND);
sizer->AddSpacer(5);
sizer->Add(reset_sizer, 0, wxEXPAND);
return sizer;
}
wxBoxSizer* ControllerConfigDiag::CreateEmulatedBTConfigSizer()
{
static const std::array<wxString, 4> src_choices = {
{_("None"), _("Emulated Wiimote"), _("Real Wiimote"), _("Hybrid Wiimote")}};
auto* const sizer = new wxBoxSizer(wxVERTICAL);
// Source selector grid
auto* const grid = new wxFlexGridSizer(3, 5, 5);
grid->AddGrowableCol(1);
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
wxString wiimote_str = wxString::Format(_("Wiimote %i"), i + 1);
static const std::array<wxString, 4> src_choices = {
{_("None"), _("Emulated Wiimote"), _("Real Wiimote"), _("Hybrid Wiimote")}};
// reserve four ids, so that we can calculate the index from the ids later on
// Stupid wx 2.8 doesn't support reserving sequential IDs, so we need to do that more
// complicated..
@ -160,200 +290,61 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer()
int config_bt_id = wxWindow::NewControlId();
m_wiimote_index_from_config_id.emplace(config_bt_id, i);
wiimote_label[i] = new wxStaticText(this, wxID_ANY, wiimote_str);
wiimote_source_ch[i] = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize,
m_wiimote_labels[i] =
new wxStaticText(this, wxID_ANY, wxString::Format(_("Wiimote %i"), i + 1));
m_wiimote_sources[i] = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize,
src_choices.size(), src_choices.data());
wiimote_source_ch[i]->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnWiimoteSourceChanged, this);
m_wiimote_sources[i]->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnWiimoteSourceChanged, this);
m_wiimote_configure_button[i] =
new wxButton(this, config_bt_id, _("Configure"), wxDefaultPosition, wxSize(80, 25));
new wxButton(this, config_bt_id, _("Configure"), wxDefaultPosition, wxSize(100, -1));
m_wiimote_configure_button[i]->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteConfigButton,
this);
// Disable controller type selection for certain circumstances.
bool wii_game_started =
SConfig::GetInstance().bWii || Core::GetState() == Core::CORE_UNINITIALIZED;
if (Core::g_want_determinism || !wii_game_started)
wiimote_source_ch[i]->Disable();
wiimote_source_ch[i]->Select(g_wiimote_sources[i]);
if (!wii_game_started ||
(g_wiimote_sources[i] != WIIMOTE_SRC_EMU && g_wiimote_sources[i] != WIIMOTE_SRC_HYBRID))
m_wiimote_configure_button[i]->Disable();
grid->Add(m_wiimote_labels[i], 0, wxALIGN_CENTER_VERTICAL);
grid->Add(m_wiimote_sources[i], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND);
grid->Add(m_wiimote_configure_button[i], 1, wxEXPAND);
}
// "Wiimotes" layout
wxStaticBoxSizer* const wiimote_group = new wxStaticBoxSizer(wxVERTICAL, this, _("Wiimotes"));
wxBoxSizer* const wiimote_control_section = new wxBoxSizer(wxHORIZONTAL);
wxFlexGridSizer* const wiimote_sizer = new wxFlexGridSizer(3, 5, 5);
for (unsigned int i = 0; i < 4; ++i)
{
wiimote_sizer->Add(wiimote_label[i], 0, wxALIGN_CENTER_VERTICAL);
wiimote_sizer->Add(wiimote_source_ch[i], 0, wxALIGN_CENTER_VERTICAL);
wiimote_sizer->Add(m_wiimote_configure_button[i]);
}
wiimote_control_section->Add(wiimote_sizer, 1, wxEXPAND, 5);
sizer->Add(grid, 0, wxEXPAND);
sizer->AddSpacer(5);
// Disable some controls when emulation is running
if (Core::GetState() != Core::CORE_UNINITIALIZED && NetPlay::IsNetPlayRunning())
{
for (int i = 0; i < 4; ++i)
{
wiimote_label[i]->Disable();
wiimote_source_ch[i]->Disable();
}
}
// Scanning controls
m_enable_continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning"));
m_enable_continuous_scanning->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnContinuousScanning,
this);
m_enable_continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning);
m_refresh_wm_button =
new wxButton(this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxSize(100, -1));
m_refresh_wm_button->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteRefreshButton, this);
wiimote_group->Add(wiimote_control_section, 0, wxEXPAND);
wiimote_group->AddSpacer(5);
wiimote_group->Add(CreateBalanceBoardSizer(), 0, wxEXPAND);
wiimote_group->AddSpacer(5);
wiimote_group->Add(CreateRealWiimoteSizer(), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM);
wiimote_group->AddSpacer(5);
wiimote_group->Add(CreateGeneralWiimoteSettingsSizer(), 0,
wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM);
m_unsupported_bt_text =
new wxStaticText(this, wxID_ANY, _("A supported Bluetooth device could not be found,\n"
"so you must connect Wiimotes manually."));
m_unsupported_bt_text->Show(!WiimoteReal::g_wiimote_scanner.IsReady());
sizer->Add(m_unsupported_bt_text, 0, wxALIGN_CENTER | wxALL, 5);
return wiimote_group;
}
auto* const scanning_sizer = new wxBoxSizer(wxHORIZONTAL);
scanning_sizer->Add(m_enable_continuous_scanning, 0, wxALIGN_CENTER_VERTICAL);
scanning_sizer->AddStretchSpacer();
scanning_sizer->Add(m_refresh_wm_button, 0, wxALL | wxEXPAND);
sizer->Add(scanning_sizer, 0, wxEXPAND);
wxStaticBoxSizer* ControllerConfigDiag::CreateBalanceBoardSizer()
{
wxStaticBoxSizer* const bb_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board"));
wxFlexGridSizer* const bb_sizer = new wxFlexGridSizer(1, 5, 5);
int source_ctrl_id = wxWindow::NewControlId();
// Balance Board
m_balance_board_checkbox = new wxCheckBox(this, wxID_ANY, _("Real Balance Board"));
m_balance_board_checkbox->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnBalanceBoardChanged,
this);
m_balance_board_checkbox->SetValue(g_wiimote_sources[WIIMOTE_BALANCE_BOARD] == WIIMOTE_SRC_REAL);
sizer->Add(m_balance_board_checkbox);
sizer->AddSpacer(5);
m_wiimote_index_from_choice_id.emplace(source_ctrl_id, WIIMOTE_BALANCE_BOARD);
// Speaker data
m_enable_speaker_data = new wxCheckBox(this, wxID_ANY, _("Enable Speaker Data"));
m_enable_speaker_data->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnEnableSpeaker, this);
m_enable_speaker_data->SetValue(SConfig::GetInstance().m_WiimoteEnableSpeaker);
sizer->Add(m_enable_speaker_data);
static const std::array<wxString, 2> src_choices = {{_("None"), _("Real Balance Board")}};
wxChoice* const bb_source = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize,
src_choices.size(), src_choices.data());
bb_source->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnWiimoteSourceChanged, this);
bb_source->Select(g_wiimote_sources[WIIMOTE_BALANCE_BOARD] ? 1 : 0);
bb_sizer->Add(bb_source, 0, wxALIGN_CENTER_VERTICAL);
bb_group->Add(bb_sizer, 1, wxEXPAND, 5);
// Disable when emulation is running.
if (Core::GetState() != Core::CORE_UNINITIALIZED)
bb_source->Disable();
return bb_group;
}
wxStaticBoxSizer* ControllerConfigDiag::CreateRealWiimoteSizer()
{
// "Real wiimotes" controls
wxButton* const refresh_btn = new wxButton(this, wxID_ANY, _("Refresh"));
refresh_btn->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteRefreshButton, this);
wxStaticBoxSizer* const real_wiimotes_group =
new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes"));
wxBoxSizer* const real_wiimotes_sizer = new wxBoxSizer(wxHORIZONTAL);
if (!WiimoteReal::g_wiimote_scanner.IsReady())
real_wiimotes_group->Add(
new wxStaticText(this, wxID_ANY, _("A supported Bluetooth device could not be found.\n"
"You must manually connect your Wiimotes.")),
0, wxALIGN_CENTER | wxALL, 5);
wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning"));
continuous_scanning->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnContinuousScanning, this);
continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning);
real_wiimotes_sizer->Add(continuous_scanning, 0, wxALIGN_CENTER_VERTICAL);
real_wiimotes_sizer->AddStretchSpacer();
real_wiimotes_sizer->Add(refresh_btn, 0, wxALL | wxALIGN_CENTER, 5);
real_wiimotes_group->Add(real_wiimotes_sizer, 0, wxEXPAND);
return real_wiimotes_group;
}
wxStaticBoxSizer* ControllerConfigDiag::CreateGeneralWiimoteSettingsSizer()
{
const wxString str[] = {_("Bottom"), _("Top")};
wxChoice* const WiiSensBarPos =
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 2, str);
wxSlider* const WiiSensBarSens = new wxSlider(this, wxID_ANY, 0, 0, 4);
wxSlider* const WiimoteSpkVolume = new wxSlider(this, wxID_ANY, 0, 0, 127);
wxCheckBox* const WiimoteMotor = new wxCheckBox(this, wxID_ANY, _("Wiimote Motor"));
auto wiimote_speaker = new wxCheckBox(this, wxID_ANY, _("Enable Speaker Data"));
wiimote_speaker->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnEnableSpeaker, this);
wiimote_speaker->SetValue(SConfig::GetInstance().m_WiimoteEnableSpeaker);
wxStaticText* const WiiSensBarPosText =
new wxStaticText(this, wxID_ANY, _("Sensor Bar Position:"));
wxStaticText* const WiiSensBarSensText = new wxStaticText(this, wxID_ANY, _("IR Sensitivity:"));
wxStaticText* const WiiSensBarSensMinText = new wxStaticText(this, wxID_ANY, _("Min"));
wxStaticText* const WiiSensBarSensMaxText = new wxStaticText(this, wxID_ANY, _("Max"));
wxStaticText* const WiimoteSpkVolumeText = new wxStaticText(this, wxID_ANY, _("Speaker Volume:"));
wxStaticText* const WiimoteSpkVolumeMinText = new wxStaticText(this, wxID_ANY, _("Min"));
wxStaticText* const WiimoteSpkVolumeMaxText = new wxStaticText(this, wxID_ANY, _("Max"));
// With some GTK themes, no minimum size will be applied - so do this manually here
WiiSensBarSens->SetMinSize(wxSize(100, -1));
WiimoteSpkVolume->SetMinSize(wxSize(100, -1));
// Disable some controls when emulation is running
if (Core::GetState() != Core::CORE_UNINITIALIZED)
{
WiiSensBarPos->Disable();
WiiSensBarSens->Disable();
WiimoteSpkVolume->Disable();
WiimoteMotor->Disable();
WiiSensBarPosText->Disable();
WiiSensBarSensText->Disable();
WiiSensBarSensMinText->Disable();
WiiSensBarSensMaxText->Disable();
WiimoteSpkVolumeText->Disable();
WiimoteSpkVolumeMinText->Disable();
WiimoteSpkVolumeMaxText->Disable();
}
// "General Settings" initialization
WiiSensBarPos->SetSelection(SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.BAR"));
WiiSensBarSens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u32>("BT.SENS"));
WiimoteSpkVolume->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.SPKV"));
WiimoteMotor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<bool>("BT.MOT"));
WiiSensBarPos->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnSensorBarPos, this);
WiiSensBarSens->Bind(wxEVT_SLIDER, &ControllerConfigDiag::OnSensorBarSensitivity, this);
WiimoteSpkVolume->Bind(wxEVT_SLIDER, &ControllerConfigDiag::OnSpeakerVolume, this);
WiimoteMotor->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnMotor, this);
// "General Settings" layout
wxStaticBoxSizer* const general_sizer =
new wxStaticBoxSizer(wxVERTICAL, this, _("General Settings"));
wxFlexGridSizer* const choice_sizer = new wxFlexGridSizer(2, 5, 5);
wxBoxSizer* const sensbarsens_sizer = new wxBoxSizer(wxHORIZONTAL);
sensbarsens_sizer->Add(WiiSensBarSensMinText, 0, wxALIGN_CENTER_VERTICAL);
sensbarsens_sizer->Add(WiiSensBarSens);
sensbarsens_sizer->Add(WiiSensBarSensMaxText, 0, wxALIGN_CENTER_VERTICAL);
wxBoxSizer* const spkvol_sizer = new wxBoxSizer(wxHORIZONTAL);
spkvol_sizer->Add(WiimoteSpkVolumeMinText, 0, wxALIGN_CENTER_VERTICAL);
spkvol_sizer->Add(WiimoteSpkVolume);
spkvol_sizer->Add(WiimoteSpkVolumeMaxText, 0, wxALIGN_CENTER_VERTICAL);
choice_sizer->Add(WiiSensBarPosText, 0, wxALIGN_CENTER_VERTICAL);
choice_sizer->Add(WiiSensBarPos);
choice_sizer->Add(WiiSensBarSensText, 0, wxALIGN_CENTER_VERTICAL);
choice_sizer->Add(sensbarsens_sizer);
choice_sizer->Add(WiimoteSpkVolumeText, 0, wxALIGN_CENTER_VERTICAL);
choice_sizer->Add(spkvol_sizer);
wxGridSizer* const general_wiimote_sizer = new wxGridSizer(1, 5, 5);
general_wiimote_sizer->Add(WiimoteMotor);
general_wiimote_sizer->Add(wiimote_speaker);
general_sizer->Add(choice_sizer);
general_sizer->Add(general_wiimote_sizer);
return general_sizer;
return sizer;
}
void ControllerConfigDiag::OnClose(wxCloseEvent& event)
@ -361,7 +352,6 @@ void ControllerConfigDiag::OnClose(wxCloseEvent& event)
// Save all settings
SConfig::GetInstance().SaveSettings();
SaveWiimoteSource();
EndModal(wxID_OK);
}
@ -493,11 +483,63 @@ void ControllerConfigDiag::OnWiimoteConfigButton(wxCommandEvent& ev)
HotkeyManagerEmu::Enable(true);
}
void ControllerConfigDiag::OnBluetoothModeChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_bt_passthrough_enabled = m_passthrough_bt_radio->GetValue();
WiimoteReal::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
UpdateUI();
}
void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event)
{
if (!Core::IsRunning())
{
wxMessageBox(_("A sync can only be triggered when a Wii game is running."), _("Sync Wiimotes"),
wxICON_WARNING);
return;
}
auto device = WII_IPC_HLE_Interface::GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<CWII_IPC_HLE_Device_usb_oh1_57e_305_base>(device)
->TriggerSyncButtonPressedEvent();
}
void ControllerConfigDiag::OnPassthroughResetButton(wxCommandEvent& event)
{
if (!Core::IsRunning())
{
wxMessageBox(_("Saved Wiimote pairings can only be reset when a Wii game is running."),
_("Reset Wiimote pairings"), wxICON_WARNING);
return;
}
auto device = WII_IPC_HLE_Interface::GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<CWII_IPC_HLE_Device_usb_oh1_57e_305_base>(device)
->TriggerSyncButtonHeldEvent();
}
void ControllerConfigDiag::OnBalanceBoardChanged(wxCommandEvent& event)
{
WiimoteReal::ChangeWiimoteSource(WIIMOTE_BALANCE_BOARD,
event.IsChecked() ? WIIMOTE_SRC_REAL : WIIMOTE_SRC_NONE);
}
void ControllerConfigDiag::OnContinuousScanning(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked();
WiimoteReal::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
}
void ControllerConfigDiag::OnWiimoteRefreshButton(wxCommandEvent&)
{
WiimoteReal::Refresh();
}
void ControllerConfigDiag::OnEnableSpeaker(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked();
}
void ControllerConfigDiag::SaveWiimoteSource()
{
std::string ini_filename = File::GetUserPath(D_CONFIG_IDX) + WIIMOTE_INI_NAME ".ini";

View File

@ -6,83 +6,74 @@
#include <array>
#include <map>
#include <wx/dialog.h>
#include "Common/SysConf.h"
#include "Core/ConfigManager.h"
#include "Core/HW/Wiimote.h"
#include "InputCommon/GCAdapter.h"
class InputConfig;
class wxButton;
class wxCheckBox;
class wxChoice;
class wxRadioButton;
class wxStaticBoxSizer;
class wxStaticText;
class ControllerConfigDiag : public wxDialog
class ControllerConfigDiag final : public wxDialog
{
public:
ControllerConfigDiag(wxWindow* const parent);
private:
void OnSensorBarPos(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.BAR", event.GetInt());
event.Skip();
}
void OnSensorBarSensitivity(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.SENS", event.GetInt());
event.Skip();
}
void OnSpeakerVolume(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.SPKV", event.GetInt());
event.Skip();
}
void OnMotor(wxCommandEvent& event)
{
SConfig::GetInstance().m_SYSCONF->SetData("BT.MOT", event.GetInt());
event.Skip();
}
void OnContinuousScanning(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked();
WiimoteReal::Initialize(Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
event.Skip();
}
void OnEnableSpeaker(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked();
event.Skip();
}
void UpdateUI();
wxStaticBoxSizer* CreateGamecubeSizer();
wxStaticBoxSizer* CreateWiimoteConfigSizer();
wxStaticBoxSizer* CreateBalanceBoardSizer();
wxStaticBoxSizer* CreateRealWiimoteSizer();
wxStaticBoxSizer* CreateGeneralWiimoteSettingsSizer();
wxBoxSizer* CreatePassthroughBTConfigSizer();
wxBoxSizer* CreateEmulatedBTConfigSizer();
void OnClose(wxCloseEvent& event);
void OnCloseButton(wxCommandEvent& event);
void OnGameCubePortChanged(wxCommandEvent& event);
void OnGameCubeConfigButton(wxCommandEvent& event);
void OnWiimoteSourceChanged(wxCommandEvent& event);
void OnWiimoteConfigButton(wxCommandEvent& event);
void OnWiimoteRefreshButton(wxCommandEvent& event);
void SaveWiimoteSource();
void OnGameCubePortChanged(wxCommandEvent& event);
void OnGameCubeConfigButton(wxCommandEvent& event);
void OnBluetoothModeChanged(wxCommandEvent& event);
void OnPassthroughScanButton(wxCommandEvent& event);
void OnPassthroughResetButton(wxCommandEvent& event);
void OnBalanceBoardChanged(wxCommandEvent& event);
void OnContinuousScanning(wxCommandEvent& event);
void OnEnableSpeaker(wxCommandEvent& event);
std::map<wxWindowID, unsigned int> m_gc_port_from_choice_id;
std::map<wxWindowID, unsigned int> m_gc_port_from_config_id;
std::array<wxButton*, 4> m_gc_port_configure_button;
std::array<wxString, 8> m_gc_pad_type_strs;
wxRadioButton* m_passthrough_bt_radio;
wxRadioButton* m_emulated_bt_radio;
wxStaticText* m_passthrough_sync_text;
wxButton* m_passthrough_sync_btn;
wxStaticText* m_passthrough_reset_text;
wxButton* m_passthrough_reset_btn;
std::map<wxWindowID, unsigned int> m_wiimote_index_from_choice_id;
std::map<wxWindowID, unsigned int> m_wiimote_index_from_config_id;
std::array<wxButton*, MAX_WIIMOTES> m_wiimote_configure_button;
std::array<wxStaticText*, MAX_WIIMOTES> m_wiimote_labels;
std::array<wxChoice*, MAX_WIIMOTES> m_wiimote_sources;
wxCheckBox* m_balance_board_checkbox;
wxCheckBox* m_enable_continuous_scanning;
wxButton* m_refresh_wm_button;
wxStaticText* m_unsupported_bt_text;
wxCheckBox* m_enable_speaker_data;
};

View File

@ -270,4 +270,4 @@
<Message Text="Copy: @(BinaryFiles) -&gt; $(BinaryOutputDir)" Importance="High" />
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
</Target>
</Project>
</Project>

View File

@ -43,6 +43,8 @@
#include "Core/HW/GCPad.h"
#include "Core/HW/Wiimote.h"
#include "Core/HotkeyManager.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
#include "Core/Movie.h"
#include "Core/State.h"
@ -1415,6 +1417,14 @@ void CFrame::ParseHotkeys()
if (IsHotkey(HK_VOLUME_TOGGLE_MUTE))
AudioCommon::ToggleMuteVolume();
if (SConfig::GetInstance().m_bt_passthrough_enabled)
{
auto device = WII_IPC_HLE_Interface::GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<CWII_IPC_HLE_Device_usb_oh1_57e_305_base>(device)
->UpdateSyncButtonState(IsHotkey(HK_TRIGGER_SYNC_BUTTON, true));
}
// Wiimote connect and disconnect hotkeys
int WiimoteId = -1;
if (IsHotkey(HK_WIIMOTE1_CONNECT))

View File

@ -41,7 +41,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/HotkeyManager.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/Movie.h"
#include "Core/PowerPC/PPCSymbolDB.h"
@ -1565,7 +1565,8 @@ void CFrame::OnFifoPlayer(wxCommandEvent& WXUNUSED(event))
void CFrame::ConnectWiimote(int wm_idx, bool connect)
{
if (Core::IsRunning() && SConfig::GetInstance().bWii)
if (Core::IsRunning() && SConfig::GetInstance().bWii &&
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
bool was_unpaused = Core::PauseAndLock(true);
GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
@ -1578,6 +1579,8 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
void CFrame::OnConnectWiimote(wxCommandEvent& event)
{
if (SConfig::GetInstance().m_bt_passthrough_enabled)
return;
bool was_unpaused = Core::PauseAndLock(true);
ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1,
!GetUsbPointer()
@ -1721,7 +1724,6 @@ void CFrame::UpdateGUI()
bool Running = Core::GetState() == Core::CORE_RUN;
bool Paused = Core::GetState() == Core::CORE_PAUSE;
bool Stopping = Core::GetState() == Core::CORE_STOPPING;
bool RunningWii = Initialized && SConfig::GetInstance().bWii;
// Make sure that we have a toolbar
if (m_ToolBar)
@ -1771,12 +1773,14 @@ void CFrame::UpdateGUI()
// Tools
GetMenuBar()->FindItem(IDM_CHEATS)->Enable(SConfig::GetInstance().bEnableCheats);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(RunningWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(RunningWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Enable(RunningWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Enable(RunningWii);
GetMenuBar()->FindItem(IDM_CONNECT_BALANCEBOARD)->Enable(RunningWii);
if (RunningWii)
bool ShouldEnableWiimotes = Initialized && SConfig::GetInstance().bWii &&
!SConfig::GetInstance().m_bt_passthrough_enabled;
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_BALANCEBOARD)->Enable(ShouldEnableWiimotes);
if (ShouldEnableWiimotes)
{
bool was_unpaused = Core::PauseAndLock(true);
GetMenuBar()

View File

@ -23,7 +23,7 @@
#include "Core/Core.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/State.h"
@ -139,7 +139,8 @@ bool Host_RendererIsFullscreen()
void Host_ConnectWiimote(int wm_idx, bool connect)
{
if (Core::IsRunning() && SConfig::GetInstance().bWii)
if (Core::IsRunning() && SConfig::GetInstance().bWii &&
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
Core::QueueHostJob([=] {
bool was_unpaused = Core::PauseAndLock(true);

View File

@ -51,7 +51,7 @@
<AdditionalIncludeDirectories>$(ExternalsDir)xxhash;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ExternalsDir)zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_UPNP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>USE_UPNP;__LIBUSB__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>PSAPI_VERSION=1;_M_X86=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>SFML_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>CURL_STATICLIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>