diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h index 24152773df..c6cc3e2acf 100644 --- a/Source/Core/Common/CommonPaths.h +++ b/Source/Core/Common/CommonPaths.h @@ -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" diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 6758c25b48..732955cf5e 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -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("IPL.IDL", 0x00); NOTICE_LOG(BOOT, "Disabling WC24 'standby' (shutdown to idle) to avoid hanging on shutdown"); + + RestoreBTInfoSection(); } // Run the game diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 5250837e6f..8d62fc0668 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -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}) diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index ec198b2837..b6b74e5160 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -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; diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 001417cb1c..f2275bb4c4 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -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; }; diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 73b4079a80..071302e17f 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -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 diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index f0a54a74f3..62f953c2fe 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -185,7 +185,12 @@ - + + + + 4200;%(DisableSpecificWarnings) + + @@ -389,7 +394,10 @@ - + + + + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 082b302901..5479aee662 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -591,7 +591,16 @@ IPC HLE %28IOS/Starlet%29\USB - + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote + + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote + + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote @@ -1148,7 +1157,16 @@ IPC HLE %28IOS/Starlet%29\USB - + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote + + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote + + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote + + IPC HLE %28IOS/Starlet%29\USB/BT/Wiimote diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index e455047a66..1e780d5c56 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -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); diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp index 8e757384ab..a97c87ae25 100644 --- a/Source/Core/Core/HotkeyManager.cpp +++ b/Source/Core/Core/HotkeyManager.cpp @@ -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"), diff --git a/Source/Core/Core/HotkeyManager.h b/Source/Core/Core/HotkeyManager.h index b8934dd79d..45dfc6474f 100644 --- a/Source/Core/Core/HotkeyManager.h +++ b/Source/Core/Core/HotkeyManager.h @@ -31,6 +31,7 @@ enum Hotkey HK_SCREENSHOT, HK_EXIT, + HK_TRIGGER_SYNC_BUTTON, HK_WIIMOTE1_CONNECT, HK_WIIMOTE2_CONNECT, HK_WIIMOTE3_CONNECT, diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index d7f655c105..3799113178 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -22,6 +22,7 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC #include #include +#include #include #include @@ -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> TDeviceMap; -static TDeviceMap g_DeviceMap; +static std::map> 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 g_FdMap[IPC_MAX_FDS]; -static bool es_inuse[ES_MAX_COUNT]; -static std::shared_ptr es_handles[ES_MAX_COUNT]; +static std::shared_ptr s_fdmap[IPC_MAX_FDS]; +static bool s_es_inuse[ES_MAX_COUNT]; +static std::shared_ptr s_es_handles[ES_MAX_COUNT]; -typedef std::deque 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; +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(userdata)); } else if (userdata & ENQUEUE_REQUEST_FLAG) { - request_queue.push_back((u32)userdata); + s_request_queue.push_back(static_cast(userdata)); } else { - reply_queue.push_back((u32)userdata); + s_reply_queue.push_back(static_cast(userdata)); } Update(); } @@ -112,23 +114,28 @@ static void SDIO_EventNotify_CPUThread(u64 userdata, s64 cycles_late) static u32 num_devices; template -std::shared_ptr AddDevice(const char* deviceName) +std::shared_ptr AddDevice(const char* device_name) { - auto device = std::make_shared(num_devices, deviceName); - g_DeviceMap[num_devices] = device; + auto device = std::make_shared(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 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("/dev/usb/oh1/57e/305"); + if (!SConfig::GetInstance().m_bt_passthrough_enabled) + AddDevice("/dev/usb/oh1/57e/305"); + else + AddDevice("/dev/usb/oh1/57e/305"); + AddDevice("/dev/stm/immediate"); AddDevice("/dev/stm/eventhook"); AddDevice("/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("/dev/es"); - es_inuse[j] = false; + s_es_handles[j] = AddDevice("/dev/es"); + s_es_inuse[j] = false; } AddDevice("/dev/di"); @@ -151,7 +158,7 @@ void Reinit() AddDevice("/dev/usb/ven"); AddDevice("/dev/sdio/slot0"); AddDevice("/dev/sdio/slot1"); -#if defined(__LIBUSB__) || defined(_WIN32) +#if defined(__LIBUSB__) AddDevice("/dev/usb/hid"); #else AddDevice("/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 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 lock(s_device_map_mutex); + for (const auto& entry : s_device_map) { if (entry.second && entry.second->GetDeviceName().find("/dev/es") == 0) { - static_cast(entry.second.get())->LoadWAD(_rFilename); + static_cast(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 GetDeviceByName(const std::string& _rDeviceName) +std::shared_ptr GetDeviceByName(const std::string& device_name) { - for (const auto& entry : g_DeviceMap) + std::lock_guard 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 GetDeviceByName(const std::string& _rDevice return nullptr; } -std::shared_ptr AccessDeviceByID(u32 _ID) +std::shared_ptr AccessDeviceByID(u32 id) { - if (g_DeviceMap.find(_ID) != g_DeviceMap.end()) + std::lock_guard 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 CreateFileIO(u32 _DeviceID, const std::string& _rDeviceName) +std::shared_ptr 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(_DeviceID, _rDeviceName); + INFO_LOG(WII_IPC_FILEIO, "IOP: Create FileIO %s", device_name.c_str()); + return std::make_shared(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(i, ""); - g_FdMap[i]->DoState(p); + s_fdmap[i] = std::make_shared(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(Memory::Read_U32(_Address)); - s32 DeviceID = Memory::Read_U32(_Address + 8); + IPCCommandType Command = static_cast(Memory::Read_U32(address)); + s32 DeviceID = Memory::Read_U32(address + 8); - std::shared_ptr pDevice = - (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr; + std::shared_ptr 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()) { diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h index 4ec90fac6f..d0a274349b 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h @@ -67,7 +67,6 @@ std::shared_ptr CreateFileIO(u32 _DeviceID, const std::stri std::shared_ptr GetDeviceByName(const std::string& _rDeviceName); std::shared_ptr AccessDeviceByID(u32 _ID); -int getFreeDeviceId(); // Update void Update(); diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 8ffaffccc9..12a48e41b0 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -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); } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.cpp new file mode 100644 index 0000000000..67884c7b8d --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.cpp @@ -0,0 +1,90 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#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 section(BT_INFO_SECTION_LENGTH); + if (!SConfig::GetInstance().m_SYSCONF->GetArrayData("BT.DINF", section.data(), + static_cast(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 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(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); +} diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h new file mode 100644 index 0000000000..ea28ad17b9 --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h @@ -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; + }; +}; diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.cpp similarity index 86% rename from Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp rename to Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.cpp index 17cf062ec4..d672464cf4 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.cpp @@ -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 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(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(Memory::GetPointer(m_ACLEndpoint.m_buffer)); + reinterpret_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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 " diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h similarity index 80% rename from Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.h rename to Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h index 3cdda8d61f..48b56820c5 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h @@ -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 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); diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.cpp new file mode 100644 index 0000000000..27bddc8361 --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.cpp @@ -0,0 +1,618 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include + +#include + +#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 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(cmd_buffer); + const u16 opcode = *reinterpret_cast(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(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(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(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 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(buffer.size()), &actual_length, 20) == 0 && + reinterpret_cast(buffer.data())->event == HCI_EVENT_COMMAND_COMPL && + reinterpret_cast(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 packet(sizeof(hci_cmd_hdr_t) + sizeof(hci_delete_stored_link_key_cp)); + + auto* header = reinterpret_cast(packet.data()); + header->opcode = HCI_CMD_DELETE_STORED_LINK_KEY; + header->length = sizeof(hci_delete_stored_link_key_cp); + auto* cmd = + reinterpret_cast(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(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(sizeof(hci_write_stored_link_key_cp)) + + (sizeof(btaddr_t) + sizeof(linkkey_t)) * static_cast(s_link_keys.size()); + std::vector packet(sizeof(hci_cmd_hdr_t) + payload_size); + + auto* header = reinterpret_cast(packet.data()); + header->opcode = HCI_CMD_WRITE_STORED_LINK_KEY; + header->length = payload_size; + + auto* cmd = + reinterpret_cast(packet.data() + sizeof(hci_cmd_hdr_t)); + cmd->num_keys_write = static_cast(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(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(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(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(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 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 cmd(static_cast(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 ctrl(static_cast(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(tr->buffer); + if (event->event == HCI_EVENT_LINK_KEY_NOTIFICATION) + { + const auto* notification = + reinterpret_cast(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(tr->buffer + sizeof(*event))->opcode == + HCI_CMD_RESET) + { + s_need_reset_keys.Set(); + } + } + + ctrl->SetRetVal(tr->actual_length); + EnqueueReply(ctrl->m_cmd_address); +} diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h new file mode 100644 index 0000000000..3bab9db86b --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h @@ -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 +#include +#include + +#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; +using linkkey_t = std::array; + +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 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 diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.cpp new file mode 100644 index 0000000000..1677699fe6 --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.cpp @@ -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); +} diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.h new file mode 100644 index 0000000000..2e0ed16691 --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.h @@ -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; } +}; diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp index 1ae285fc44..847aa21060 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_kbd.cpp @@ -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 diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 563deb4eb3..d48d6abb6a 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -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); diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.h index b9cf483234..fdb2b02cb9 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_WiiMote.h @@ -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 { diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 6bd3f72f0a..702fe58e54 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -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)); } } diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 6180b3e13d..30c7e56424 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -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" diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 89bd1d7211..c1efa7d2d9 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -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, diff --git a/Source/Core/DolphinWX/Config/WiiConfigPane.cpp b/Source/Core/DolphinWX/Config/WiiConfigPane.cpp index dfbd600470..559bee6051 100644 --- a/Source/Core/DolphinWX/Config/WiiConfigPane.cpp +++ b/Source/Core/DolphinWX/Config/WiiConfigPane.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #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("BT.BAR")); + m_bt_sensor_bar_sens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("BT.SENS")); + m_bt_speaker_volume->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("BT.SPKV")); + m_bt_wiimote_motor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("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) diff --git a/Source/Core/DolphinWX/Config/WiiConfigPane.h b/Source/Core/DolphinWX/Config/WiiConfigPane.h index 9d875aa0e4..ac482277fd 100644 --- a/Source/Core/DolphinWX/Config/WiiConfigPane.h +++ b/Source/Core/DolphinWX/Config/WiiConfigPane.h @@ -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; }; diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index 92e0e79c5b..58ddcbaf8a 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -2,14 +2,16 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. -#include -#include #include #include + #include #include #include #include +#include +#include +#include #include #include #include @@ -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 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 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 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("BT.BAR")); - WiiSensBarSens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("BT.SENS")); - WiimoteSpkVolume->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("BT.SPKV")); - WiimoteMotor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("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(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(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"; diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.h b/Source/Core/DolphinWX/ControllerConfigDiag.h index 18c1496b52..48a8e4b9fe 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.h +++ b/Source/Core/DolphinWX/ControllerConfigDiag.h @@ -6,83 +6,74 @@ #include #include + #include -#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 m_gc_port_from_choice_id; std::map m_gc_port_from_config_id; std::array m_gc_port_configure_button; std::array 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 m_wiimote_index_from_choice_id; std::map m_wiimote_index_from_config_id; std::array m_wiimote_configure_button; + std::array m_wiimote_labels; + std::array 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; }; diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj index 1cf24890aa..31dc2180be 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj @@ -270,4 +270,4 @@ - \ No newline at end of file + diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 18be3f9712..422867e904 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -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(device) + ->UpdateSyncButtonState(IsHotkey(HK_TRIGGER_SYNC_BUTTON, true)); + } + // Wiimote connect and disconnect hotkeys int WiimoteId = -1; if (IsHotkey(HK_WIIMOTE1_CONNECT)) diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 2ab6b9b45c..29b8bca723 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -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() diff --git a/Source/Core/DolphinWX/MainNoGUI.cpp b/Source/Core/DolphinWX/MainNoGUI.cpp index c954539e79..8e8512c07d 100644 --- a/Source/Core/DolphinWX/MainNoGUI.cpp +++ b/Source/Core/DolphinWX/MainNoGUI.cpp @@ -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); diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 4d4c080c3e..66013cc4a9 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -51,7 +51,7 @@ $(ExternalsDir)xxhash;%(AdditionalIncludeDirectories) $(ExternalsDir)zlib;%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - USE_UPNP;%(PreprocessorDefinitions) + USE_UPNP;__LIBUSB__;%(PreprocessorDefinitions) PSAPI_VERSION=1;_M_X86=1;%(PreprocessorDefinitions) SFML_STATIC;%(PreprocessorDefinitions) CURL_STATICLIB;%(PreprocessorDefinitions)