WiimoteReal: Remove WiimoteScannerDarwin
For several reasons: - It pegs the CPU at 95% for scanning even when Dolphin is idle - WiimoteScannerHidapi works fine on macOS - Less macOS code to maintain
This commit is contained in:
parent
942545b7fc
commit
e9a11cdbfd
|
@ -649,9 +649,6 @@ elseif(APPLE)
|
||||||
HW/EXI/BBA/TAP_Apple.cpp
|
HW/EXI/BBA/TAP_Apple.cpp
|
||||||
HW/EXI/BBA/TAPServer_Apple.cpp
|
HW/EXI/BBA/TAPServer_Apple.cpp
|
||||||
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
HW/EXI/BBA/XLINK_KAI_BBA.cpp
|
||||||
HW/WiimoteReal/IOdarwin.h
|
|
||||||
HW/WiimoteReal/IOdarwin_private.h
|
|
||||||
HW/WiimoteReal/IOdarwin.mm
|
|
||||||
)
|
)
|
||||||
target_link_libraries(core PUBLIC ${IOB_LIBRARY})
|
target_link_libraries(core PUBLIC ${IOB_LIBRARY})
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
// Copyright 2016 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
|
||||||
|
|
||||||
#ifdef __OBJC__
|
|
||||||
#import <IOBluetooth/IOBluetooth.h>
|
|
||||||
#else
|
|
||||||
// IOBluetooth's types won't be defined in pure C++ mode.
|
|
||||||
typedef void IOBluetoothHostController;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WiimoteReal
|
|
||||||
{
|
|
||||||
class WiimoteScannerDarwin final : public WiimoteScannerBackend
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WiimoteScannerDarwin();
|
|
||||||
~WiimoteScannerDarwin() override;
|
|
||||||
bool IsReady() const override;
|
|
||||||
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
|
|
||||||
void Update() override {} // not needed
|
|
||||||
void RequestStopSearching() override { m_stop_scanning = true; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
IOBluetoothHostController* m_host_controller;
|
|
||||||
bool m_stop_scanning = false;
|
|
||||||
};
|
|
||||||
} // namespace WiimoteReal
|
|
||||||
|
|
||||||
#else
|
|
||||||
#include "Core/HW/WiimoteReal/IODummy.h"
|
|
||||||
namespace WiimoteReal
|
|
||||||
{
|
|
||||||
using WiimoteScannerDarwin = WiimoteScannerDummy;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,361 +0,0 @@
|
||||||
#define BLUETOOTH_VERSION_USE_CURRENT
|
|
||||||
|
|
||||||
#include "Core/HW/WiimoteReal/IOdarwin.h"
|
|
||||||
#include "Common/Common.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
|
||||||
#include "Core/HW/WiimoteCommon/WiimoteHid.h"
|
|
||||||
#include "Core/HW/WiimoteReal/IOdarwin_private.h"
|
|
||||||
|
|
||||||
@interface SearchBT : NSObject
|
|
||||||
{
|
|
||||||
@public
|
|
||||||
unsigned int maxDevices;
|
|
||||||
bool done;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface ConnectBT : NSObject
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace WiimoteReal
|
|
||||||
{
|
|
||||||
WiimoteScannerDarwin::WiimoteScannerDarwin()
|
|
||||||
{
|
|
||||||
m_host_controller = [IOBluetoothHostController defaultController];
|
|
||||||
if (![m_host_controller addressAsString])
|
|
||||||
{
|
|
||||||
WARN_LOG_FMT(WIIMOTE, "No Bluetooth host controller");
|
|
||||||
|
|
||||||
[m_host_controller release];
|
|
||||||
m_host_controller = nil;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
[m_host_controller retain];
|
|
||||||
}
|
|
||||||
|
|
||||||
WiimoteScannerDarwin::~WiimoteScannerDarwin()
|
|
||||||
{
|
|
||||||
[m_host_controller release];
|
|
||||||
m_host_controller = nil;
|
|
||||||
|
|
||||||
m_stop_scanning = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WiimoteScannerDarwin::FindWiimotes(std::vector<Wiimote*>& found_wiimotes,
|
|
||||||
Wiimote*& found_board)
|
|
||||||
{
|
|
||||||
if (!m_host_controller)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IOBluetoothDeviceInquiry* bti;
|
|
||||||
found_board = nullptr;
|
|
||||||
|
|
||||||
SearchBT* sbt = [[SearchBT alloc] init];
|
|
||||||
sbt->maxDevices = 32;
|
|
||||||
bti = [[IOBluetoothDeviceInquiry alloc] init];
|
|
||||||
[bti setDelegate:sbt];
|
|
||||||
[bti setInquiryLength:2];
|
|
||||||
|
|
||||||
if ([bti start] != kIOReturnSuccess)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Unable to do Bluetooth discovery");
|
|
||||||
[sbt release];
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
|
|
||||||
} while (!sbt->done && !m_stop_scanning);
|
|
||||||
|
|
||||||
int found_devices = [[bti foundDevices] count];
|
|
||||||
|
|
||||||
if (found_devices)
|
|
||||||
NOTICE_LOG_FMT(WIIMOTE, "Found {} Bluetooth devices", found_devices);
|
|
||||||
|
|
||||||
NSEnumerator* en = [[bti foundDevices] objectEnumerator];
|
|
||||||
for (int i = 0; i < found_devices; i++)
|
|
||||||
{
|
|
||||||
IOBluetoothDevice* dev = [en nextObject];
|
|
||||||
if (!IsValidDeviceName([[dev name] UTF8String]))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Wiimote* wm = new WiimoteDarwin([dev retain]);
|
|
||||||
|
|
||||||
if (IsBalanceBoardName([[dev name] UTF8String]))
|
|
||||||
{
|
|
||||||
found_board = wm;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
found_wiimotes.push_back(wm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[bti release];
|
|
||||||
[sbt release];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WiimoteScannerDarwin::IsReady() const
|
|
||||||
{
|
|
||||||
return m_host_controller != nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiimoteDarwin::WiimoteDarwin(IOBluetoothDevice* device) : m_btd(device)
|
|
||||||
{
|
|
||||||
m_inputlen = 0;
|
|
||||||
m_connected = false;
|
|
||||||
m_wiimote_thread_run_loop = nullptr;
|
|
||||||
m_pm_assertion = kIOPMNullAssertionID;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiimoteDarwin::~WiimoteDarwin()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
if (m_wiimote_thread_run_loop)
|
|
||||||
{
|
|
||||||
CFRelease(m_wiimote_thread_run_loop);
|
|
||||||
m_wiimote_thread_run_loop = nullptr;
|
|
||||||
}
|
|
||||||
[m_btd release];
|
|
||||||
m_btd = nil;
|
|
||||||
DisablePowerAssertionInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to a Wiimote with a known address.
|
|
||||||
bool WiimoteDarwin::ConnectInternal()
|
|
||||||
{
|
|
||||||
if (IsConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ConnectBT* cbt = [[ConnectBT alloc] init];
|
|
||||||
|
|
||||||
m_cchan = m_ichan = nil;
|
|
||||||
|
|
||||||
IOReturn ret = [m_btd openConnection];
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Unable to open Bluetooth connection to Wiimote {}: {:x}", m_index + 1,
|
|
||||||
ret);
|
|
||||||
[cbt release];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = [m_btd openL2CAPChannelSync:&m_cchan withPSM:kBluetoothL2CAPPSMHIDControl delegate:cbt];
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Unable to open control channel for Wiimote {}: {:x}", m_index + 1, ret);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
// Apple docs claim:
|
|
||||||
// "The L2CAP channel object is already retained when this function returns
|
|
||||||
// success; the channel must be released when the caller is done with it."
|
|
||||||
// But without this, the channels get over-autoreleased, even though the
|
|
||||||
// refcounting behavior here is clearly correct.
|
|
||||||
[m_cchan retain];
|
|
||||||
|
|
||||||
ret = [m_btd openL2CAPChannelSync:&m_ichan withPSM:kBluetoothL2CAPPSMHIDInterrupt delegate:cbt];
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
WARN_LOG_FMT(WIIMOTE, "Unable to open interrupt channel for Wiimote {}: {:x}", m_index + 1,
|
|
||||||
ret);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
[m_ichan retain];
|
|
||||||
|
|
||||||
NOTICE_LOG_FMT(WIIMOTE, "Connected to Wiimote {} at {}", m_index + 1,
|
|
||||||
[[m_btd addressString] UTF8String]);
|
|
||||||
|
|
||||||
m_connected = true;
|
|
||||||
|
|
||||||
[cbt release];
|
|
||||||
|
|
||||||
m_wiimote_thread_run_loop = (CFRunLoopRef)CFRetain(CFRunLoopGetCurrent());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
DisconnectInternal();
|
|
||||||
[cbt release];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disconnect a Wiimote.
|
|
||||||
void WiimoteDarwin::DisconnectInternal()
|
|
||||||
{
|
|
||||||
[m_ichan closeChannel];
|
|
||||||
[m_ichan release];
|
|
||||||
m_ichan = nil;
|
|
||||||
|
|
||||||
[m_cchan closeChannel];
|
|
||||||
[m_cchan release];
|
|
||||||
m_cchan = nil;
|
|
||||||
|
|
||||||
[m_btd closeConnection];
|
|
||||||
|
|
||||||
if (!IsConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
NOTICE_LOG_FMT(WIIMOTE, "Disconnecting Wiimote {}", m_index + 1);
|
|
||||||
|
|
||||||
m_connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WiimoteDarwin::IsConnected() const
|
|
||||||
{
|
|
||||||
return m_connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WiimoteDarwin::IOWakeup()
|
|
||||||
{
|
|
||||||
if (m_wiimote_thread_run_loop)
|
|
||||||
{
|
|
||||||
CFRunLoopStop(m_wiimote_thread_run_loop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiimoteDarwin::IORead(unsigned char* buf)
|
|
||||||
{
|
|
||||||
m_input = buf;
|
|
||||||
m_inputlen = -1;
|
|
||||||
|
|
||||||
CFRunLoopRun();
|
|
||||||
|
|
||||||
return m_inputlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WiimoteDarwin::IOWrite(const unsigned char* buf, size_t len)
|
|
||||||
{
|
|
||||||
IOReturn ret;
|
|
||||||
|
|
||||||
if (!IsConnected())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = [m_ichan writeAsync:const_cast<void*>((void*)buf) length:(int)len refcon:nil];
|
|
||||||
|
|
||||||
if (ret == kIOReturnSuccess)
|
|
||||||
return len;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WiimoteDarwin::EnablePowerAssertionInternal()
|
|
||||||
{
|
|
||||||
if (m_pm_assertion == kIOPMNullAssertionID)
|
|
||||||
{
|
|
||||||
if (IOReturn ret = IOPMAssertionCreateWithName(
|
|
||||||
kIOPMAssertPreventUserIdleDisplaySleep, kIOPMAssertionLevelOn,
|
|
||||||
CFSTR("Dolphin Wiimote activity"), &m_pm_assertion))
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Could not create power management assertion: {:08x}", ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WiimoteDarwin::DisablePowerAssertionInternal()
|
|
||||||
{
|
|
||||||
if (m_pm_assertion != kIOPMNullAssertionID)
|
|
||||||
{
|
|
||||||
if (IOReturn ret = IOPMAssertionRelease(m_pm_assertion))
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Could not release power management assertion: {:08x}", ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
@implementation SearchBT
|
|
||||||
- (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender
|
|
||||||
error:(IOReturn)error
|
|
||||||
aborted:(BOOL)aborted
|
|
||||||
{
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender device:(IOBluetoothDevice*)device
|
|
||||||
{
|
|
||||||
NOTICE_LOG_FMT(WIIMOTE, "Discovered Bluetooth device at {}: {}",
|
|
||||||
[[device addressString] UTF8String], [[device name] UTF8String]);
|
|
||||||
|
|
||||||
if ([[sender foundDevices] count] == maxDevices)
|
|
||||||
[sender stop];
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ConnectBT
|
|
||||||
- (void)l2capChannelData:(IOBluetoothL2CAPChannel*)l2capChannel
|
|
||||||
data:(unsigned char*)data
|
|
||||||
length:(NSUInteger)length
|
|
||||||
{
|
|
||||||
IOBluetoothDevice* device = [l2capChannel device];
|
|
||||||
WiimoteReal::WiimoteDarwin* wm = nullptr;
|
|
||||||
|
|
||||||
std::lock_guard lk(WiimoteReal::g_wiimotes_mutex);
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
|
||||||
{
|
|
||||||
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i].get());
|
|
||||||
if (!wm)
|
|
||||||
continue;
|
|
||||||
if ([device isEqual:wm->m_btd])
|
|
||||||
break;
|
|
||||||
wm = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wm == nullptr)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Received packet for unknown Wiimote");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length > WiimoteCommon::MAX_PAYLOAD)
|
|
||||||
{
|
|
||||||
WARN_LOG_FMT(WIIMOTE, "Dropping packet for Wiimote {}, too large", wm->GetIndex() + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wm->m_inputlen != -1)
|
|
||||||
{
|
|
||||||
WARN_LOG_FMT(WIIMOTE, "Dropping packet for Wiimote {}, queue full", wm->GetIndex() + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(wm->m_input, data, length);
|
|
||||||
wm->m_inputlen = length;
|
|
||||||
|
|
||||||
CFRunLoopStop(CFRunLoopGetCurrent());
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)l2capChannelClosed:(IOBluetoothL2CAPChannel*)l2capChannel
|
|
||||||
{
|
|
||||||
IOBluetoothDevice* device = [l2capChannel device];
|
|
||||||
WiimoteReal::WiimoteDarwin* wm = nullptr;
|
|
||||||
|
|
||||||
std::lock_guard lk(WiimoteReal::g_wiimotes_mutex);
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_WIIMOTES; i++)
|
|
||||||
{
|
|
||||||
wm = static_cast<WiimoteReal::WiimoteDarwin*>(WiimoteReal::g_wiimotes[i].get());
|
|
||||||
if (!wm)
|
|
||||||
continue;
|
|
||||||
if ([device isEqual:wm->m_btd])
|
|
||||||
break;
|
|
||||||
wm = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wm == nullptr)
|
|
||||||
{
|
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Channel for unknown Wiimote was closed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WARN_LOG_FMT(WIIMOTE, "Lost channel to Wiimote {}", wm->GetIndex() + 1);
|
|
||||||
|
|
||||||
wm->DisconnectInternal();
|
|
||||||
}
|
|
||||||
@end
|
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2016 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#import <IOBluetooth/IOBluetooth.h>
|
|
||||||
#include <IOKit/pwr_mgt/IOPMLib.h>
|
|
||||||
|
|
||||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
|
||||||
|
|
||||||
namespace WiimoteReal
|
|
||||||
{
|
|
||||||
class WiimoteDarwin final : public Wiimote
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WiimoteDarwin(IOBluetoothDevice* device);
|
|
||||||
~WiimoteDarwin() override;
|
|
||||||
std::string GetId() const override { return [[m_btd addressString] UTF8String]; }
|
|
||||||
// These are not protected/private because ConnectBT needs them.
|
|
||||||
void DisconnectInternal() override;
|
|
||||||
IOBluetoothDevice* m_btd;
|
|
||||||
unsigned char* m_input;
|
|
||||||
int m_inputlen;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool ConnectInternal() override;
|
|
||||||
bool IsConnected() const override;
|
|
||||||
void IOWakeup() override;
|
|
||||||
int IORead(u8* buf) override;
|
|
||||||
int IOWrite(u8 const* buf, size_t len) override;
|
|
||||||
void EnablePowerAssertionInternal() override;
|
|
||||||
void DisablePowerAssertionInternal() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
IOBluetoothL2CAPChannel* m_ichan;
|
|
||||||
IOBluetoothL2CAPChannel* m_cchan;
|
|
||||||
bool m_connected;
|
|
||||||
CFRunLoopRef m_wiimote_thread_run_loop;
|
|
||||||
IOPMAssertionID m_pm_assertion;
|
|
||||||
};
|
|
||||||
} // namespace WiimoteReal
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "Core/HW/WiimoteReal/IOAndroid.h"
|
#include "Core/HW/WiimoteReal/IOAndroid.h"
|
||||||
#include "Core/HW/WiimoteReal/IOLinux.h"
|
#include "Core/HW/WiimoteReal/IOLinux.h"
|
||||||
#include "Core/HW/WiimoteReal/IOWin.h"
|
#include "Core/HW/WiimoteReal/IOWin.h"
|
||||||
#include "Core/HW/WiimoteReal/IOdarwin.h"
|
|
||||||
#include "Core/HW/WiimoteReal/IOhidapi.h"
|
#include "Core/HW/WiimoteReal/IOhidapi.h"
|
||||||
#include "InputCommon/ControllerInterface/Wiimote/WiimoteController.h"
|
#include "InputCommon/ControllerInterface/Wiimote/WiimoteController.h"
|
||||||
#include "InputCommon/InputConfig.h"
|
#include "InputCommon/InputConfig.h"
|
||||||
|
@ -653,7 +652,6 @@ void WiimoteScanner::ThreadFunc()
|
||||||
m_backends.emplace_back(std::make_unique<WiimoteScannerLinux>());
|
m_backends.emplace_back(std::make_unique<WiimoteScannerLinux>());
|
||||||
m_backends.emplace_back(std::make_unique<WiimoteScannerAndroid>());
|
m_backends.emplace_back(std::make_unique<WiimoteScannerAndroid>());
|
||||||
m_backends.emplace_back(std::make_unique<WiimoteScannerWindows>());
|
m_backends.emplace_back(std::make_unique<WiimoteScannerWindows>());
|
||||||
m_backends.emplace_back(std::make_unique<WiimoteScannerDarwin>());
|
|
||||||
m_backends.emplace_back(std::make_unique<WiimoteScannerHidapi>());
|
m_backends.emplace_back(std::make_unique<WiimoteScannerHidapi>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue