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..6e896658ef 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -67,6 +67,7 @@ void SConfig::SaveSettings() SaveFifoPlayerSettings(ini); SaveAnalyticsSettings(ini); SaveNetworkSettings(ini); + SaveBluetoothPassthroughSettings(ini); ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX)); m_SYSCONF->Save(); @@ -322,6 +323,15 @@ 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); +} + void SConfig::LoadSettings() { INFO_LOG(BOOT, "Loading Settings from %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str()); @@ -339,6 +349,7 @@ void SConfig::LoadSettings() LoadFifoPlayerSettings(ini); LoadNetworkSettings(ini); LoadAnalyticsSettings(ini); + LoadBluetoothPassthroughSettings(ini); m_SYSCONF = new SysConf(); } @@ -604,6 +615,15 @@ 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); +} + void SConfig::LoadDefaults() { bEnableDebugging = false; diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 001417cb1c..2bb649fcbc 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -143,6 +143,11 @@ 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; + // Fifo Player related settings bool bLoopFifoReplay = true; @@ -325,6 +330,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 +343,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 b8cd1e2733..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" @@ -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() ? 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 e52273f673..2cd0c130ac 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,7 +51,8 @@ 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" @@ -64,6 +66,7 @@ namespace WII_IPC_HLE_Interface { typedef std::map> TDeviceMap; static TDeviceMap g_DeviceMap; +static std::mutex g_device_map_mutex; // STATE_TO_SAVE #define IPC_MAX_FDS 0x18 @@ -122,13 +125,18 @@ std::shared_ptr AddDevice(const char* deviceName) void Reinit() { + std::lock_guard lock(g_device_map_mutex); _assert_msg_(WII_IPC_HLE, g_DeviceMap.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"); @@ -188,19 +196,21 @@ void Reset(bool _bHard) in_use = false; } - for (const auto& entry : g_DeviceMap) { - if (entry.second) + std::lock_guard lock(g_device_map_mutex); + for (const auto& entry : g_DeviceMap) { - // Force close - entry.second->Close(0, true); + if (entry.second) + { + // Force close + entry.second->Close(0, true); + } } + + if (_bHard) + g_DeviceMap.clear(); } - if (_bHard) - { - g_DeviceMap.clear(); - } request_queue.clear(); reply_queue.clear(); @@ -214,6 +224,7 @@ void Shutdown() void SetDefaultContentFile(const std::string& _rFilename) { + std::lock_guard lock(g_device_map_mutex); for (const auto& entry : g_DeviceMap) { if (entry.second && entry.second->GetDeviceName().find("/dev/es") == 0) @@ -251,6 +262,7 @@ int getFreeDeviceId() std::shared_ptr GetDeviceByName(const std::string& _rDeviceName) { + std::lock_guard lock(g_device_map_mutex); for (const auto& entry : g_DeviceMap) { if (entry.second && entry.second->GetDeviceName() == _rDeviceName) @@ -264,6 +276,7 @@ std::shared_ptr GetDeviceByName(const std::string& _rDevice std::shared_ptr AccessDeviceByID(u32 _ID) { + std::lock_guard lock(g_device_map_mutex); if (g_DeviceMap.find(_ID) != g_DeviceMap.end()) { return g_DeviceMap[_ID]; 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..85e2095fa3 --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.cpp @@ -0,0 +1,48 @@ +// 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_base.h" +#include "Common/Assert.h" +#include "Common/CommonFuncs.h" +#include "Common/CommonTypes.h" +#include "Common/Logging/Log.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/HW/Memmap.h" + +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..2b7b230e1c --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h @@ -0,0 +1,75 @@ +// 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" + +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: + 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 88% 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..46a3669f54 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; @@ -115,14 +114,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 +147,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 +183,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 +191,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 +248,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 +257,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 +273,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 +282,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 +291,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 +332,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 +344,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 +361,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 +380,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 +395,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 +405,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 +421,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 +438,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 +449,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 +511,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) { @@ -527,7 +531,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 +541,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 +554,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 +574,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 +624,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 +667,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 +703,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 +727,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 +752,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 +779,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 +815,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 +843,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 +868,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 +886,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 +913,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 +959,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 +985,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 +1019,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 +1040,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 +1067,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 +1095,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 +1284,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 +1302,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 +1312,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 +1333,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 +1352,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 +1378,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 +1395,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 +1411,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 +1427,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 +1438,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 +1456,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 +1468,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 +1480,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 +1492,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 +1507,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 +1519,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 +1529,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 +1545,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 +1559,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 +1594,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 +1621,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 +1637,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 +1652,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 +1675,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 +1691,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 +1708,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 +1726,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 +1741,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 +1759,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 +1777,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 +1798,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,7 +1820,7 @@ 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; @@ -1836,7 +1842,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 +1857,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 +1877,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 +1894,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 +1909,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 +1922,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 +1932,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 81% 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..bdf5404d74 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; @@ -162,7 +121,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..ff5dcf0af4 --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.cpp @@ -0,0 +1,370 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#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 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."); +} + +CWII_IPC_HLE_Device_usb_oh1_57e_305_real::~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() +{ + if (m_handle != nullptr) + { + SendHCIResetCommand(); + 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); +} + +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); + 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) +{ + 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); + 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_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::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::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; +} + +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(); + } + 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..87a005a2be --- /dev/null +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h @@ -0,0 +1,83 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#if defined(__LIBUSB__) +#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, +}; + +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; + + void SendHCIResetCommand(); + void FakeSyncButtonEvent(const CtrlBuffer& ctrl, const u8* payload, u8 size); + void FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl); + void FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl); + + 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/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index 92e0e79c5b..e05250f3d8 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -60,6 +60,7 @@ ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent) SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED); SetSizerAndFit(main_sizer); Center(); + UpdateUI(); } wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer() @@ -141,9 +142,6 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer() wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer() { - wxStaticText* wiimote_label[4]; - wxChoice* wiimote_source_ch[4]; - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) { wxString wiimote_str = wxString::Format(_("Wiimote %i"), i + 1); @@ -160,10 +158,10 @@ 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, wiimote_str); + 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)); m_wiimote_configure_button[i]->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteConfigButton, @@ -173,9 +171,9 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer() 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(); + m_wiimote_sources[i]->Disable(); - wiimote_source_ch[i]->Select(g_wiimote_sources[i]); + m_wiimote_sources[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(); @@ -187,8 +185,8 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer() 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_labels[i], 0, wxALIGN_CENTER_VERTICAL); + wiimote_sizer->Add(m_wiimote_sources[i], 0, wxALIGN_CENTER_VERTICAL); wiimote_sizer->Add(m_wiimote_configure_button[i]); } wiimote_control_section->Add(wiimote_sizer, 1, wxEXPAND, 5); @@ -198,8 +196,8 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer() { for (int i = 0; i < 4; ++i) { - wiimote_label[i]->Disable(); - wiimote_source_ch[i]->Disable(); + m_wiimote_labels[i]->Disable(); + m_wiimote_sources[i]->Disable(); } } @@ -209,15 +207,15 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer() 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_general_wm_settings = CreateGeneralWiimoteSettingsSizer(); + wiimote_group->Add(m_general_wm_settings, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM); return wiimote_group; } wxStaticBoxSizer* ControllerConfigDiag::CreateBalanceBoardSizer() { - wxStaticBoxSizer* const bb_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board")); + m_balance_board_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board")); wxFlexGridSizer* const bb_sizer = new wxFlexGridSizer(1, 5, 5); int source_ctrl_id = wxWindow::NewControlId(); @@ -233,40 +231,74 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateBalanceBoardSizer() bb_sizer->Add(bb_source, 0, wxALIGN_CENTER_VERTICAL); - bb_group->Add(bb_sizer, 1, wxEXPAND, 5); + m_balance_board_group->Add(bb_sizer, 1, wxEXPAND, 5); // Disable when emulation is running. if (Core::GetState() != Core::CORE_UNINITIALIZED) bb_source->Disable(); - return bb_group; + return m_balance_board_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); + auto* const real_wiimotes_group = new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes")); - wxStaticBoxSizer* const real_wiimotes_group = - new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes")); - wxBoxSizer* const real_wiimotes_sizer = new wxBoxSizer(wxHORIZONTAL); + m_unsupported_bt_text = + new wxStaticText(this, wxID_ANY, _("A supported Bluetooth device could not be found.\n" + "You must manually connect your Wiimotes.")); + real_wiimotes_group->Add(m_unsupported_bt_text, 0, wxALIGN_CENTER | wxALL, 5); + m_unsupported_bt_text->Show(!WiimoteReal::g_wiimote_scanner.IsReady()); - 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); + // Bluetooth adapter passthrough + m_bt_passthrough_text = new wxStaticText( + this, wxID_ANY, _("A Bluetooth adapter will be passed through to the game.\n" + "Only real Wiimotes will be usable.\n" + "Wiimotes can be synced to Dolphin with the sync hotkey.")); + real_wiimotes_group->Add(m_bt_passthrough_text, 0, wxALIGN_CENTER | wxALL, 5); - wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning")); + auto* const enable_passthrough = + new wxCheckBox(this, wxID_ANY, _("Enable Bluetooth Adapter Passthrough")); + enable_passthrough->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnPassthroughMode, this); + enable_passthrough->SetValue(SConfig::GetInstance().m_bt_passthrough_enabled); + + auto* const wm_bt_sync_button = new wxButton(this, wxID_ANY, _("Sync Wiimotes")); + wm_bt_sync_button->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnPassthroughScanButton, this); + auto* const wm_bt_reset_button = new wxButton(this, wxID_ANY, _("Reset pairings")); + wm_bt_reset_button->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnPassthroughResetButton, this); + + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + enable_passthrough->Disable(); + if (!SConfig::GetInstance().bWii) + m_bt_passthrough_text->Disable(); + } + + if (!SConfig::GetInstance().bWii || Core::GetState() == Core::CORE_UNINITIALIZED) + { + wm_bt_sync_button->Disable(); + wm_bt_reset_button->Disable(); + } + + m_bt_passthrough_sizer = new wxBoxSizer(wxHORIZONTAL); + m_bt_passthrough_sizer->Add(wm_bt_sync_button, 0, wxALIGN_CENTER_VERTICAL); + m_bt_passthrough_sizer->Add(wm_bt_reset_button, 0, wxALL | wxALIGN_CENTER, 5); + + // Regular real Wiimotes controls + auto* 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); + auto* const wm_refresh_button = new wxButton(this, wxID_ANY, _("Refresh")); + wm_refresh_button->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteRefreshButton, this); - 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); + m_real_wiimotes_sizer = new wxBoxSizer(wxHORIZONTAL); + m_real_wiimotes_sizer->Add(continuous_scanning, 0, wxALIGN_CENTER_VERTICAL); + m_real_wiimotes_sizer->AddStretchSpacer(); + m_real_wiimotes_sizer->Add(wm_refresh_button, 0, wxALL | wxALIGN_CENTER, 5); - real_wiimotes_group->Add(real_wiimotes_sizer, 0, wxEXPAND); + real_wiimotes_group->Add(enable_passthrough, 0); + real_wiimotes_group->Add(m_bt_passthrough_sizer, 0, wxEXPAND); + real_wiimotes_group->Add(m_real_wiimotes_sizer, 0, wxEXPAND); return real_wiimotes_group; } @@ -280,9 +312,9 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGeneralWiimoteSettingsSizer() 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); + 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); wxStaticText* const WiiSensBarPosText = new wxStaticText(this, wxID_ANY, _("Sensor Bar Position:")); @@ -348,7 +380,7 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGeneralWiimoteSettingsSizer() wxGridSizer* const general_wiimote_sizer = new wxGridSizer(1, 5, 5); general_wiimote_sizer->Add(WiimoteMotor); - general_wiimote_sizer->Add(wiimote_speaker); + general_wiimote_sizer->Add(m_enable_speaker_data); general_sizer->Add(choice_sizer); general_sizer->Add(general_wiimote_sizer); diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.h b/Source/Core/DolphinWX/ControllerConfigDiag.h index 18c1496b52..f8b4ef3a2c 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.h +++ b/Source/Core/DolphinWX/ControllerConfigDiag.h @@ -6,16 +6,22 @@ #include #include +#include +#include +#include #include +#include +#include +#include #include "Common/SysConf.h" #include "Core/ConfigManager.h" #include "Core/HW/Wiimote.h" +#include "Core/IPC_HLE/WII_IPC_HLE.h" +#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h" #include "InputCommon/GCAdapter.h" class InputConfig; -class wxButton; -class wxStaticBoxSizer; class ControllerConfigDiag : public wxDialog { @@ -54,12 +60,55 @@ private: event.Skip(); } + void OnPassthroughMode(wxCommandEvent& event) + { + SConfig::GetInstance().m_bt_passthrough_enabled = event.IsChecked(); + UpdateUI(); + } + + void OnPassthroughScanButton(wxCommandEvent& event) + { + auto device = WII_IPC_HLE_Interface::GetDeviceByName("/dev/usb/oh1/57e/305"); + if (device != nullptr) + std::static_pointer_cast(device) + ->TriggerSyncButtonPressedEvent(); + event.Skip(); + } + + void OnPassthroughResetButton(wxCommandEvent& event) + { + auto device = WII_IPC_HLE_Interface::GetDeviceByName("/dev/usb/oh1/57e/305"); + if (device != nullptr) + std::static_pointer_cast(device) + ->TriggerSyncButtonHeldEvent(); + event.Skip(); + } + void OnEnableSpeaker(wxCommandEvent& event) { SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked(); event.Skip(); } + void UpdateUI() + { + const bool enable_bt_passthrough_mode = SConfig::GetInstance().m_bt_passthrough_enabled; + m_real_wiimotes_sizer->ShowItems(!enable_bt_passthrough_mode); + m_bt_passthrough_sizer->ShowItems(enable_bt_passthrough_mode); + m_unsupported_bt_text->Show(!enable_bt_passthrough_mode); + m_bt_passthrough_text->Show(enable_bt_passthrough_mode); + m_balance_board_group->ShowItems(!enable_bt_passthrough_mode); + m_enable_speaker_data->Enable(!enable_bt_passthrough_mode); + for (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); + } + Layout(); + Fit(); + } + wxStaticBoxSizer* CreateGamecubeSizer(); wxStaticBoxSizer* CreateWiimoteConfigSizer(); wxStaticBoxSizer* CreateBalanceBoardSizer(); @@ -85,4 +134,14 @@ private: 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; + wxBoxSizer* m_real_wiimotes_sizer; + wxBoxSizer* m_bt_passthrough_sizer; + wxStaticText* m_unsupported_bt_text; + wxStaticText* m_bt_passthrough_text; + wxStaticBoxSizer* m_general_wm_settings; + wxStaticBoxSizer* m_balance_board_group; + 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);