Merge pull request #4195 from leoetlino/direct-hci

Add ability to passthrough a Bluetooth adapter
This commit is contained in:
shuffle2
2016-10-03 14:22:47 -07:00
committed by GitHub
37 changed files with 1772 additions and 643 deletions
+1
View File
@@ -120,6 +120,7 @@
#define WII_STATE "state.dat"
#define WII_SDCARD "sd.raw"
#define WII_BTDINF_BACKUP "btdinf.bak"
#define WII_SETTING "setting.txt"
+3
View File
@@ -35,6 +35,7 @@
#include "Core/HW/Sram.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/Host.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
#include "VideoCommon/VideoBackendBase.h"
@@ -399,6 +400,8 @@ bool BootCore(const std::string& _rFilename)
// TODO: remove this if and once Dolphin supports WC24 standby mode.
SConfig::GetInstance().m_SYSCONF->SetData<u8>("IPL.IDL", 0x00);
NOTICE_LOG(BOOT, "Disabling WC24 'standby' (shutdown to idle) to avoid hanging on shutdown");
RestoreBTInfoSection();
}
// Run the game
+5 -2
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})
+23
View File
@@ -55,6 +55,7 @@ void SConfig::SaveSettings()
NOTICE_LOG(BOOT, "Saving settings to %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); // load first to not kill unknown stuff
m_SYSCONF->Reload();
SaveGeneralSettings(ini);
SaveInterfaceSettings(ini);
@@ -67,6 +68,7 @@ void SConfig::SaveSettings()
SaveFifoPlayerSettings(ini);
SaveAnalyticsSettings(ini);
SaveNetworkSettings(ini);
SaveBluetoothPassthroughSettings(ini);
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
m_SYSCONF->Save();
@@ -322,6 +324,16 @@ void SConfig::SaveAnalyticsSettings(IniFile& ini)
analytics->Set("PermissionAsked", m_analytics_permission_asked);
}
void SConfig::SaveBluetoothPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("BluetoothPassthrough");
section->Set("Enabled", m_bt_passthrough_enabled);
section->Set("VID", m_bt_passthrough_vid);
section->Set("PID", m_bt_passthrough_pid);
section->Set("LinkKeys", m_bt_passthrough_link_keys);
}
void SConfig::LoadSettings()
{
INFO_LOG(BOOT, "Loading Settings from %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
@@ -339,6 +351,7 @@ void SConfig::LoadSettings()
LoadFifoPlayerSettings(ini);
LoadNetworkSettings(ini);
LoadAnalyticsSettings(ini);
LoadBluetoothPassthroughSettings(ini);
m_SYSCONF = new SysConf();
}
@@ -604,6 +617,16 @@ void SConfig::LoadAnalyticsSettings(IniFile& ini)
analytics->Get("PermissionAsked", &m_analytics_permission_asked, false);
}
void SConfig::LoadBluetoothPassthroughSettings(IniFile& ini)
{
IniFile::Section* section = ini.GetOrCreateSection("BluetoothPassthrough");
section->Get("Enabled", &m_bt_passthrough_enabled, false);
section->Get("VID", &m_bt_passthrough_vid, -1);
section->Get("PID", &m_bt_passthrough_pid, -1);
section->Get("LinkKeys", &m_bt_passthrough_link_keys, "");
}
void SConfig::LoadDefaults()
{
bEnableDebugging = false;
+8
View File
@@ -143,6 +143,12 @@ struct SConfig : NonCopyable
bool m_analytics_enabled = false;
bool m_analytics_permission_asked = false;
// Bluetooth passthrough mode settings
bool m_bt_passthrough_enabled = false;
int m_bt_passthrough_pid = -1;
int m_bt_passthrough_vid = -1;
std::string m_bt_passthrough_link_keys;
// Fifo Player related settings
bool bLoopFifoReplay = true;
@@ -325,6 +331,7 @@ private:
void SaveFifoPlayerSettings(IniFile& ini);
void SaveNetworkSettings(IniFile& ini);
void SaveAnalyticsSettings(IniFile& ini);
void SaveBluetoothPassthroughSettings(IniFile& ini);
void LoadGeneralSettings(IniFile& ini);
void LoadInterfaceSettings(IniFile& ini);
@@ -337,6 +344,7 @@ private:
void LoadFifoPlayerSettings(IniFile& ini);
void LoadNetworkSettings(IniFile& ini);
void LoadAnalyticsSettings(IniFile& ini);
void LoadBluetoothPassthroughSettings(IniFile& ini);
static SConfig* m_Instance;
};
+5 -5
View File
@@ -52,7 +52,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/Wiimote.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/IPC_HLE/WII_Socket.h"
#include "Core/Movie.h"
@@ -297,7 +297,7 @@ void Stop() // - Hammertime!
g_video_backend->Video_ExitLoop();
}
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
GCAdapter::ResetRumble();
#endif
@@ -528,7 +528,7 @@ void EmuThread()
}
// Load and Init Wiimotes - only if we are booting in Wii mode
if (core_parameter.bWii)
if (core_parameter.bWii && !SConfig::GetInstance().m_bt_passthrough_enabled)
{
if (init_controllers)
Wiimote::Initialize(s_window_handle, !s_state_filename.empty() ?
@@ -698,7 +698,7 @@ void SetState(EState state)
// stopped (including the CPU).
CPU::EnableStepping(true); // Break
Wiimote::Pause();
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
GCAdapter::ResetRumble();
#endif
break;
@@ -818,7 +818,7 @@ bool PauseAndLock(bool do_lock, bool unpause_on_unlock)
// (s_efbAccessRequested).
Fifo::PauseAndLock(do_lock, false);
#if defined(__LIBUSB__) || defined(_WIN32)
#if defined(__LIBUSB__)
GCAdapter::ResetRumble();
#endif
+10 -2
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" />
+20 -2
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">
@@ -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);
+1
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"),
+1
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,
File diff suppressed because it is too large Load Diff
-1
View File
@@ -67,7 +67,6 @@ std::shared_ptr<IWII_IPC_HLE_Device> CreateFileIO(u32 _DeviceID, const std::stri
std::shared_ptr<IWII_IPC_HLE_Device> GetDeviceByName(const std::string& _rDeviceName);
std::shared_ptr<IWII_IPC_HLE_Device> AccessDeviceByID(u32 _ID);
int getFreeDeviceId();
// Update
void Update();
@@ -47,7 +47,7 @@
#include "Core/ConfigManager.h"
#include "Core/HW/DVDInterface.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_es.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_emu.h"
#include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h"
#include "Core/Movie.h"
#include "Core/PowerPC/PowerPC.h"
@@ -998,28 +998,33 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
}
else
{
CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer();
size_t size = s_Usb->m_WiiMotes.size();
bool* wiiMoteConnected = new bool[size];
for (unsigned int i = 0; i < size; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
bool* wiiMoteConnected = new bool[MAX_BBMOTES];
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
}
WII_IPC_HLE_Interface::Reset(true);
WII_IPC_HLE_Interface::Reinit();
s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < s_Usb->m_WiiMotes.size(); i++)
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
{
if (wiiMoteConnected[i])
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu* s_Usb = GetUsbPointer();
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
if (wiiMoteConnected[i])
{
s_Usb->m_WiiMotes[i].Activate(false);
s_Usb->m_WiiMotes[i].Activate(true);
}
else
{
s_Usb->m_WiiMotes[i].Activate(false);
}
}
}
delete[] wiiMoteConnected;
WII_IPC_HLE_Interface::SetDefaultContentFile(tContentFile);
}
@@ -0,0 +1,90 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <string>
#include <vector>
#include "Common/Assert.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
constexpr u16 BT_INFO_SECTION_LENGTH = 0x460;
void BackUpBTInfoSection()
{
const std::string filename = File::GetUserPath(D_SESSION_WIIROOT_IDX) + DIR_SEP WII_BTDINF_BACKUP;
if (File::Exists(filename))
return;
File::IOFile backup(filename, "wb");
std::vector<u8> section(BT_INFO_SECTION_LENGTH);
if (!SConfig::GetInstance().m_SYSCONF->GetArrayData("BT.DINF", section.data(),
static_cast<u16>(section.size())))
{
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to read source BT.DINF section");
return;
}
if (!backup.WriteBytes(section.data(), section.size()))
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to back up BT.DINF section");
}
void RestoreBTInfoSection()
{
const std::string filename = File::GetUserPath(D_SESSION_WIIROOT_IDX) + DIR_SEP WII_BTDINF_BACKUP;
if (!File::Exists(filename))
return;
File::IOFile backup(filename, "rb");
std::vector<u8> section(BT_INFO_SECTION_LENGTH);
if (!backup.ReadBytes(section.data(), section.size()))
{
ERROR_LOG(WII_IPC_WIIMOTE, "Failed to read backed up BT.DINF section");
return;
}
SConfig::GetInstance().m_SYSCONF->SetArrayData("BT.DINF", section.data(),
static_cast<u16>(section.size()));
SConfig::GetInstance().m_SYSCONF->Save();
File::Delete(filename);
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_base::IOCtl(u32 command_address)
{
// NeoGamma (homebrew) is known to use this path.
ERROR_LOG(WII_IPC_WIIMOTE, "Bad IOCtl to /dev/usb/oh1/57e/305");
Memory::Write_U32(FS_EINVAL, command_address + 4);
return GetDefaultReply();
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlMessage::CtrlMessage(const SIOCtlVBuffer& cmd_buffer)
{
request_type = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
request = Memory::Read_U8(cmd_buffer.InBuffer[1].m_Address);
value = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[2].m_Address));
index = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[3].m_Address));
length = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[4].m_Address));
payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
address = cmd_buffer.m_Address;
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::CtrlBuffer(const SIOCtlVBuffer& cmd_buffer,
const u32 command_address)
{
m_endpoint = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
m_length = Memory::Read_U16(cmd_buffer.InBuffer[1].m_Address);
m_payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
m_cmd_address = command_address;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8* src,
const size_t size) const
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, size <= m_length, "FillBuffer: size %li > payload length %i",
size, m_length);
Memory::CopyToEmu(m_payload_addr, src, size);
}
@@ -0,0 +1,83 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
void BackUpBTInfoSection();
void RestoreBTInfoSection();
class CWII_IPC_HLE_Device_usb_oh1_57e_305_base : public IWII_IPC_HLE_Device
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_base(u32 device_id, const std::string& device_name)
: IWII_IPC_HLE_Device(device_id, device_name)
{
}
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_base() override = default;
virtual IPCCommandResult Open(u32 command_address, u32 mode) override = 0;
virtual IPCCommandResult Close(u32 command_address, bool force) override = 0;
IPCCommandResult IOCtl(u32 command_address) override;
virtual IPCCommandResult IOCtlV(u32 command_address) override = 0;
virtual void DoState(PointerWrap& p) override = 0;
virtual u32 Update() override = 0;
virtual void UpdateSyncButtonState(bool is_held) {}
virtual void TriggerSyncButtonPressedEvent() {}
virtual void TriggerSyncButtonHeldEvent() {}
protected:
static constexpr int ACL_PKT_SIZE = 339;
static constexpr int ACL_PKT_NUM = 10;
static constexpr int SCO_PKT_SIZE = 64;
static constexpr int SCO_PKT_NUM = 0;
enum USBIOCtl
{
USBV0_IOCTL_CTRLMSG = 0,
USBV0_IOCTL_BLKMSG = 1,
USBV0_IOCTL_INTRMSG = 2,
};
enum USBEndpoint
{
HCI_CTRL = 0x00,
HCI_EVENT = 0x81,
ACL_DATA_IN = 0x82,
ACL_DATA_OUT = 0x02
};
struct CtrlMessage
{
CtrlMessage() = default;
CtrlMessage(const SIOCtlVBuffer& cmd_buffer);
u8 request_type;
u8 request;
u16 value;
u16 index;
u16 length;
u32 payload_addr;
u32 address;
};
class CtrlBuffer
{
public:
CtrlBuffer() = default;
CtrlBuffer(const SIOCtlVBuffer& cmd_buffer, u32 command_address);
void FillBuffer(const u8* src, size_t size) const;
void SetRetVal(const u32 retval) const { Memory::Write_U32(retval, m_cmd_address + 4); }
bool IsValid() const { return m_cmd_address != 0; }
void Invalidate() { m_cmd_address = m_payload_addr = 0; }
u8 m_endpoint;
u16 m_length;
u32 m_payload_addr;
u32 m_cmd_address;
};
};
@@ -12,6 +12,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
#include "Core/IPC_HLE/hci.h"
class CWII_IPC_HLE_WiiMote;
@@ -19,8 +20,8 @@ class CWII_IPC_HLE_WiiMote;
struct SQueuedEvent
{
u8 m_buffer[1024];
u32 m_size;
u16 m_connectionHandle;
u32 m_size = 0;
u16 m_connectionHandle = 0;
SQueuedEvent(u32 size, u16 connectionHandle) : m_size(size), m_connectionHandle(connectionHandle)
{
@@ -32,19 +33,20 @@ struct SQueuedEvent
memset(m_buffer, 0, 1024);
}
SQueuedEvent() : m_size(0), m_connectionHandle(0) {}
SQueuedEvent() = default;
};
// Important to remember that this class is for /dev/usb/oh1/57e/305 ONLY
// /dev/usb/oh1 -> internal usb bus
// 57e/305 -> VendorID/ProductID of device on usb bus
// This device is ONLY the internal Bluetooth module (based on BCM2045 chip)
class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device
class CWII_IPC_HLE_Device_usb_oh1_57e_305_emu final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName);
CWII_IPC_HLE_Device_usb_oh1_57e_305_emu(u32 _DeviceID, const std::string& _rDeviceName);
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305();
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_emu();
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
@@ -61,8 +63,6 @@ public:
bool RemoteDisconnect(u16 _connectionHandle);
// hack for Wiimote plugin
public:
std::vector<CWII_IPC_HLE_WiiMote> m_WiiMotes;
CWII_IPC_HLE_WiiMote* AccessWiiMote(const bdaddr_t& _rAddr);
CWII_IPC_HLE_WiiMote* AccessWiiMote(u16 _ConnectionHandle);
@@ -70,21 +70,6 @@ public:
void DoState(PointerWrap& p) override;
private:
enum USBIOCtl
{
USBV0_IOCTL_CTRLMSG = 0,
USBV0_IOCTL_BLKMSG = 1,
USBV0_IOCTL_INTRMSG = 2,
};
enum USBEndpoint
{
HCI_CTRL = 0x00,
HCI_EVENT = 0x81,
ACL_DATA_IN = 0x82,
ACL_DATA_OUT = 0x02
};
struct SHCICommandMessage
{
u8 bRequestType;
@@ -98,36 +83,10 @@ private:
u32 m_Address;
};
// This is a lightweight/specialized version of SIOCtlVBuffer
struct CtrlBuffer
{
u32 m_address;
u32 m_buffer;
CtrlBuffer(u32 _Address) : m_address(_Address), m_buffer()
{
if (m_address)
{
u32 InBufferNum = Memory::Read_U32(m_address + 0x10);
u32 BufferVector = Memory::Read_U32(m_address + 0x18);
m_buffer = Memory::Read_U32(BufferVector + InBufferNum * sizeof(SIOCtlVBuffer::SBuffer));
}
}
inline void FillBuffer(const void* src, const size_t size) const
{
Memory::CopyToEmu(m_buffer, (u8*)src, size);
}
inline void SetRetVal(const u32 retval) const { Memory::Write_U32(retval, m_address + 4); }
inline bool IsValid() const { return m_address != 0; }
inline void Invalidate() { m_address = m_buffer = 0; }
};
bdaddr_t m_ControllerBD;
// this is used to trigger connecting via ACL
u8 m_ScanEnable;
u8 m_ScanEnable = 0;
SHCICommandMessage m_CtrlSetup;
CtrlBuffer m_HCIEndpoint;
@@ -136,14 +95,11 @@ private:
u32 m_ACLSetup;
CtrlBuffer m_ACLEndpoint;
static const int m_acl_pkt_size = 339;
static const int m_acl_pkts_num = 10;
class ACLPool
{
struct Packet
{
u8 data[m_acl_pkt_size];
u8 data[ACL_PKT_SIZE];
u16 size;
u16 conn_handle;
};
@@ -162,7 +118,7 @@ private:
} m_acl_pool;
u32 m_PacketCount[MAX_BBMOTES];
u64 m_last_ticks;
u64 m_last_ticks = 0;
// Send ACL data to a device (wiimote)
void IncDataPacket(u16 _ConnectionHandle);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,102 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#if defined(__LIBUSB__)
#include <array>
#include <atomic>
#include <thread>
#include "Common/Flag.h"
#include "Common/Timer.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_base.h"
struct libusb_device;
struct libusb_device_handle;
struct libusb_context;
struct libusb_transfer;
enum class SyncButtonState
{
Unpressed,
Held,
Pressed,
LongPressed,
// On a real Wii, after a long press, the button release is ignored and doesn't trigger a sync.
Ignored,
};
using btaddr_t = std::array<u8, 6>;
using linkkey_t = std::array<u8, 16>;
class CWII_IPC_HLE_Device_usb_oh1_57e_305_real final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_real(u32 device_id, const std::string& device_name);
~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() override;
IPCCommandResult Open(u32 command_address, u32 mode) override;
IPCCommandResult Close(u32 command_address, bool force) override;
IPCCommandResult IOCtlV(u32 command_address) override;
void DoState(PointerWrap& p) override;
u32 Update() override { return 0; }
void UpdateSyncButtonState(bool is_held) override;
void TriggerSyncButtonPressedEvent() override;
void TriggerSyncButtonHeldEvent() override;
private:
static constexpr u8 INTERFACE = 0x00;
static constexpr u8 SUBCLASS = 0x01;
static constexpr u8 PROTOCOL_BLUETOOTH = 0x01;
// Arbitrarily chosen value that allows emulated software to send commands often enough
// so that the sync button event is triggered at least every 200ms.
// Ideally this should be equal to 0, so we don't trigger unnecessary libusb transfers.
static constexpr int TIMEOUT = 200;
static constexpr int SYNC_BUTTON_HOLD_MS_TO_RESET = 10000;
std::atomic<SyncButtonState> m_sync_button_state{SyncButtonState::Unpressed};
Common::Timer m_sync_button_held_timer;
libusb_device* m_device = nullptr;
libusb_device_handle* m_handle = nullptr;
libusb_context* m_libusb_context = nullptr;
Common::Flag m_thread_running;
std::thread m_thread;
// Set when we received a command to which we need to fake a reply
Common::Flag m_fake_read_buffer_size_reply;
Common::Flag m_fake_vendor_command_reply;
u16 m_fake_vendor_command_reply_opcode;
bool m_is_wii_bt_module = false;
void WaitForHCICommandComplete(u16 opcode);
void SendHCIResetCommand();
void SendHCIDeleteLinkKeyCommand();
bool SendHCIStoreLinkKeyCommand();
void FakeVendorCommandReply(const CtrlBuffer& ctrl);
void FakeReadBufferSizeReply(const CtrlBuffer& ctrl);
void FakeSyncButtonEvent(const CtrlBuffer& ctrl, const u8* payload, u8 size);
void FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl);
void FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl);
void LoadLinkKeys();
void SaveLinkKeys();
bool OpenDevice(libusb_device* device);
void StartTransferThread();
void StopTransferThread();
void TransferThread();
static void CommandCallback(libusb_transfer* transfer);
static void TransferCallback(libusb_transfer* transfer);
};
#else
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_stub.h"
using CWII_IPC_HLE_Device_usb_oh1_57e_305_real = CWII_IPC_HLE_Device_usb_oh1_57e_305_stub;
#endif

Some files were not shown because too many files have changed in this diff Show More