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/TAPServer_Apple.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})
|
||||
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/IOLinux.h"
|
||||
#include "Core/HW/WiimoteReal/IOWin.h"
|
||||
#include "Core/HW/WiimoteReal/IOdarwin.h"
|
||||
#include "Core/HW/WiimoteReal/IOhidapi.h"
|
||||
#include "InputCommon/ControllerInterface/Wiimote/WiimoteController.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<WiimoteScannerAndroid>());
|
||||
m_backends.emplace_back(std::make_unique<WiimoteScannerWindows>());
|
||||
m_backends.emplace_back(std::make_unique<WiimoteScannerDarwin>());
|
||||
m_backends.emplace_back(std::make_unique<WiimoteScannerHidapi>());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue