Merge pull request #4195 from leoetlino/direct-hci
Add ability to passthrough a Bluetooth adapter
This commit is contained in:
commit
6ec756980d
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -31,6 +31,7 @@ enum Hotkey
|
|||
HK_SCREENSHOT,
|
||||
HK_EXIT,
|
||||
|
||||
HK_TRIGGER_SYNC_BUTTON,
|
||||
HK_WIIMOTE1_CONNECT,
|
||||
HK_WIIMOTE2_CONNECT,
|
||||
HK_WIIMOTE3_CONNECT,
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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 "
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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; }
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -270,4 +270,4 @@
|
|||
<Message Text="Copy: @(BinaryFiles) -> $(BinaryOutputDir)" Importance="High" />
|
||||
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
|
||||
</Target>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue