Add ability to passthrough a Bluetooth adapter

This adds the ability to passthrough a whole Bluetooth adapter and skip
the majority of the Bluetooth emulation code. We use libusb to send HCI
commands, receive HCI events and transfer ACL data directly to the
first adapter that is found or to a specific adapter (if configured to)

This is possible because the Wii's Bluetooth module is actually just
a pretty standard Bluetooth adapter…

…except for two vendor-specific commands, for which replies are faked,
and also for the sync button. This adds a hotkey that works in the
exact same way as the sync button would on a Wii: it triggers an HCI
event, which emulated software interpret as a command to perform
a BT inquiry.

This commit also changes the UI code to expose passthrough mode
and WII_IPC_HLE to be a bit more thread safe (for the device map).
This commit is contained in:
Léo Lam 2016-08-23 16:19:30 +02:00
parent 59a17db6c4
commit 4b47997cf8
31 changed files with 1055 additions and 272 deletions

View File

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

View File

@ -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;

View File

@ -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;
};

View File

@ -52,7 +52,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/Wiimote.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/IPC_HLE/WII_Socket.h"
#include "Core/Movie.h"
@ -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() ?

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,6 +22,7 @@ They will also generate a true or false return for UpdateInterrupts() in WII_IPC
#include <list>
#include <map>
#include <mutex>
#include <string>
#include <vector>
@ -50,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<u32, std::shared_ptr<IWII_IPC_HLE_Device>> 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<T> AddDevice(const char* deviceName)
void Reinit()
{
std::lock_guard<std::mutex> 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<CWII_IPC_HLE_Device_usb_oh1_57e_305>("/dev/usb/oh1/57e/305");
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
AddDevice<CWII_IPC_HLE_Device_usb_oh1_57e_305_emu>("/dev/usb/oh1/57e/305");
else
AddDevice<CWII_IPC_HLE_Device_usb_oh1_57e_305_real>("/dev/usb/oh1/57e/305");
AddDevice<CWII_IPC_HLE_Device_stm_immediate>("/dev/stm/immediate");
AddDevice<CWII_IPC_HLE_Device_stm_eventhook>("/dev/stm/eventhook");
AddDevice<CWII_IPC_HLE_Device_fs>("/dev/fs");
@ -188,19 +196,21 @@ void Reset(bool _bHard)
in_use = false;
}
for (const auto& entry : g_DeviceMap)
{
if (entry.second)
std::lock_guard<std::mutex> 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<std::mutex> 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<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& _rDeviceName)
{
std::lock_guard<std::mutex> 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<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& _rDevice
std::shared_ptr<IWII_IPC_HLE_Device> AccessDeviceByID(u32 _ID)
{
std::lock_guard<std::mutex> lock(g_device_map_mutex);
if (g_DeviceMap.find(_ID) != g_DeviceMap.end())
{
return g_DeviceMap[_ID];

View File

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

View File

@ -0,0 +1,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);
}

View File

@ -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;
};
};

View File

@ -12,12 +12,12 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/Movie.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::EnqueueReply(u32 CommandAddress)
{
// IOS seems to write back the command that was responded to in the FD field, this
// class does not overwrite the command so it is safe to read back.
@ -29,10 +29,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
}
// The device class
CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CWII_IPC_HLE_Device_usb_oh1_57e_305_emu(
u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName), m_ScanEnable(0), m_HCIEndpoint(0),
m_ACLEndpoint(0), m_last_ticks(0)
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(_DeviceID, _rDeviceName)
{
SysConf* sysconf;
std::unique_ptr<SysConf> owned_sysconf;
@ -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<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.m_payload_addr));
CtrlBuffer BulkBuffer(_CommandAddress);
hci_acldata_hdr_t* pACLHeader = (hci_acldata_hdr_t*)Memory::GetPointer(BulkBuffer.m_buffer);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_BC_FLAG(pACLHeader->con_handle) == HCI_POINT2POINT);
_dbg_assert_(WII_IPC_WIIMOTE, HCI_PB_FLAG(pACLHeader->con_handle) == HCI_PACKET_START);
SendToDevice(HCI_CON_HANDLE(pACLHeader->con_handle),
Memory::GetPointer(BulkBuffer.m_buffer + sizeof(hci_acldata_hdr_t)),
pACLHeader->length);
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
Memory::GetPointer(ctrl.m_payload_addr + sizeof(hci_acldata_hdr_t)),
acl_header->length);
_SendReply = true;
}
@ -270,7 +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<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint.m_buffer));
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint.m_payload_addr));
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;
@ -376,7 +380,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 connection_handle, c
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
EnqueueReply(m_ACLEndpoint.m_address);
EnqueueReply(m_ACLEndpoint.m_cmd_address);
m_ACLEndpoint.Invalidate();
}
else
@ -391,7 +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<const hci_inquiry_cp*>(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<const hci_create_con_cp*>(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<const hci_discon_cp*>(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<const hci_accept_con_cp*>(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<const hci_link_key_rep_cp*>(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<const hci_link_key_neg_rep_cp*>(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<const hci_change_con_pkt_type_cp*>(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<const hci_auth_req_cp*>(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<const hci_remote_name_req_cp*>(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<const hci_read_remote_features_cp*>(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<const hci_read_remote_ver_info_cp*>(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<const hci_read_clock_offset_cp*>(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<const hci_sniff_mode_cp*>(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<const hci_write_link_policy_settings_cp*>(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<const hci_set_event_filter_cp*>(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<const hci_write_pin_type_cp*>(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<const hci_read_stored_link_key_cp*>(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<const hci_delete_stored_link_key_cp*>(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<const hci_write_local_name_cp*>(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<const hci_write_page_timeout_cp*>(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<const hci_write_scan_enable_cp*>(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<const hci_write_unit_class_cp*>(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<const hci_host_buffer_size_cp*>(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<const hci_write_link_supervision_timeout_cp*>(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<const hci_write_inquiry_scan_type_cp*>(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<const hci_write_inquiry_mode_cp*>(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<const hci_write_page_scan_type_cp*>(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 "

View File

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

View File

@ -0,0 +1,370 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <memory>
#include <string>
#include <libusb.h>
#include "Common/Network.h"
#include "Common/Thread.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h"
#include "Core/IPC_HLE/hci.h"
// This 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<CtrlMessage>(cmd_buffer);
auto buffer = std::vector<u8>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(buffer.data(), cmd->request_type, cmd->request, cmd->value,
cmd->index, cmd->length);
Memory::CopyFromEmu(buffer.data() + LIBUSB_CONTROL_SETUP_SIZE, cmd->payload_addr, cmd->length);
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.data(), CommandCallback, cmd.release(),
0);
libusb_submit_transfer(transfer);
break;
}
// ACL data (incoming or outgoing) and incoming HCI events (respectively)
case USBV0_IOCTL_BLKMSG:
case USBV0_IOCTL_INTRMSG:
{
auto buffer = std::make_unique<CtrlBuffer>(cmd_buffer, command_address);
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
m_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<hci_event_hdr_t*>(packet);
hci_event->event = HCI_EVENT_VENDOR;
hci_event->length = size;
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
ctrl.SetRetVal(sizeof(hci_event_hdr_t) + size);
EnqueueReply(ctrl.m_cmd_address);
}
// When the red sync button is pressed, a HCI event is generated:
// > HCI Event: Vendor (0xff) plen 1
// 08
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl)
{
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
const u8 payload[1] = {0x08};
FakeSyncButtonEvent(ctrl, payload, sizeof(payload));
m_sync_button_state = SyncButtonState::Ignored;
}
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl)
{
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
const u8 payload[1] = {0x09};
FakeSyncButtonEvent(ctrl, payload, sizeof(payload));
m_sync_button_state = SyncButtonState::Ignored;
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_real::OpenDevice(libusb_device* device)
{
m_device = libusb_ref_device(device);
const int ret = libusb_open(m_device, &m_handle);
if (ret != 0)
{
PanicAlertT("Failed to open Bluetooth device: %s", libusb_error_name(ret));
return false;
}
const int result = libusb_detach_kernel_driver(m_handle, INTERFACE);
if (result < 0 && result != LIBUSB_ERROR_NOT_FOUND && result != LIBUSB_ERROR_NOT_SUPPORTED)
{
PanicAlertT("Failed to detach kernel driver for BT passthrough: %s", libusb_error_name(result));
return false;
}
if (libusb_claim_interface(m_handle, INTERFACE) < 0)
{
PanicAlertT("Failed to claim interface for BT passthrough");
return false;
}
return true;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::StartTransferThread()
{
if (m_thread_running.IsSet())
return;
m_thread_running.Set();
m_thread = std::thread(&CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferThread, this);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::StopTransferThread()
{
if (m_thread_running.TestAndClear())
{
libusb_close(m_handle);
m_thread.join();
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferThread()
{
Common::SetCurrentThreadName("BT USB Thread");
while (m_thread_running.IsSet())
{
libusb_handle_events_completed(m_libusb_context, nullptr);
}
}
// The callbacks are called from libusb code on a separate thread.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::CommandCallback(libusb_transfer* tr)
{
const std::unique_ptr<CtrlMessage> cmd(static_cast<CtrlMessage*>(tr->user_data));
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_NO_DEVICE)
{
ERROR_LOG(WII_IPC_WIIMOTE, "libusb command transfer failed, status: 0x%02x", tr->status);
if (!s_showed_failed_transfer.IsSet())
{
Core::DisplayMessage("Failed to send a command to the Bluetooth adapter.", 10000);
Core::DisplayMessage("It may not be compatible with passthrough mode.", 10000);
s_showed_failed_transfer.Set();
}
}
else
{
s_showed_failed_transfer.Clear();
}
EnqueueReply(cmd->address);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer* tr)
{
const std::unique_ptr<CtrlBuffer> ctrl(static_cast<CtrlBuffer*>(tr->user_data));
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_TIMED_OUT &&
tr->status != LIBUSB_TRANSFER_NO_DEVICE)
{
ERROR_LOG(WII_IPC_WIIMOTE, "libusb transfer failed, status: 0x%02x", tr->status);
if (!s_showed_failed_transfer.IsSet())
{
Core::DisplayMessage("Failed to transfer to or from to the Bluetooth adapter.", 10000);
Core::DisplayMessage("It may not be compatible with passthrough mode.", 10000);
s_showed_failed_transfer.Set();
}
}
else
{
s_showed_failed_transfer.Clear();
}
ctrl->SetRetVal(tr->actual_length);
EnqueueReply(ctrl->m_cmd_address);
}

View File

@ -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 <atomic>
#include <thread>
#include "Common/Flag.h"
#include "Common/Timer.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
struct libusb_device;
struct libusb_device_handle;
struct libusb_context;
struct libusb_transfer;
enum class SyncButtonState
{
Unpressed,
Held,
Pressed,
LongPressed,
// On a real Wii, after a long press, the button release is ignored and doesn't trigger a sync.
Ignored,
};
class CWII_IPC_HLE_Device_usb_oh1_57e_305_real final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_real(u32 device_id, const std::string& device_name);
~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() override;
IPCCommandResult Open(u32 command_address, u32 mode) override;
IPCCommandResult Close(u32 command_address, bool force) override;
IPCCommandResult IOCtlV(u32 command_address) override;
void DoState(PointerWrap& p) override;
u32 Update() override { return 0; }
void UpdateSyncButtonState(bool is_held) override;
void TriggerSyncButtonPressedEvent() override;
void TriggerSyncButtonHeldEvent() override;
private:
static constexpr u8 INTERFACE = 0x00;
static constexpr u8 SUBCLASS = 0x01;
static constexpr u8 PROTOCOL_BLUETOOTH = 0x01;
// Arbitrarily chosen value that allows emulated software to send commands often enough
// so that the sync button event is triggered at least every 200ms.
// Ideally this should be equal to 0, so we don't trigger unnecessary libusb transfers.
static constexpr int TIMEOUT = 200;
static constexpr int SYNC_BUTTON_HOLD_MS_TO_RESET = 10000;
std::atomic<SyncButtonState> m_sync_button_state{SyncButtonState::Unpressed};
Common::Timer m_sync_button_held_timer;
libusb_device* m_device = nullptr;
libusb_device_handle* m_handle = nullptr;
libusb_context* m_libusb_context = nullptr;
Common::Flag m_thread_running;
std::thread m_thread;
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);

View File

@ -6,16 +6,22 @@
#include <array>
#include <map>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/stattext.h>
#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<CWII_IPC_HLE_Device_usb_oh1_57e_305_base>(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<CWII_IPC_HLE_Device_usb_oh1_57e_305_base>(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<wxWindowID, unsigned int> m_wiimote_index_from_choice_id;
std::map<wxWindowID, unsigned int> m_wiimote_index_from_config_id;
std::array<wxButton*, MAX_WIIMOTES> m_wiimote_configure_button;
std::array<wxStaticText*, 4> m_wiimote_labels;
std::array<wxChoice*, 4> 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;
};

View File

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

View File

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

View File

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

View File

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