mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-08 13:43:33 +01:00
Merge branch '6584'
Fix for XP and lifetime issues on Mac. Fixes issue 6584.
This commit is contained in:
commit
9ee50a2730
@ -43,6 +43,12 @@ bool WiimoteScanner::IsReady() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wiimote::InitInternal()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Wiimote::TeardownInternal()
|
||||||
|
{}
|
||||||
|
|
||||||
bool Wiimote::ConnectInternal()
|
bool Wiimote::ConnectInternal()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -133,6 +133,28 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimot
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wiimote::InitInternal()
|
||||||
|
{
|
||||||
|
cmd_sock = -1;
|
||||||
|
int_sock = -1;
|
||||||
|
|
||||||
|
int fds[2];
|
||||||
|
if (pipe(fds))
|
||||||
|
{
|
||||||
|
ERROR_LOG(WIIMOTE, "pipe failed");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
wakeup_pipe_w = fds[1];
|
||||||
|
wakeup_pipe_r = fds[0];
|
||||||
|
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wiimote::TeardownInternal()
|
||||||
|
{
|
||||||
|
close(wakeup_pipe_w);
|
||||||
|
close(wakeup_pipe_r);
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to a wiimote with a known address.
|
// Connect to a wiimote with a known address.
|
||||||
bool Wiimote::ConnectInternal()
|
bool Wiimote::ConnectInternal()
|
||||||
{
|
{
|
||||||
|
@ -514,12 +514,6 @@ bool Wiimote::ConnectInternal()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hid_overlap_read = OVERLAPPED();
|
|
||||||
hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL);
|
|
||||||
|
|
||||||
hid_overlap_write = OVERLAPPED();
|
|
||||||
hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL);
|
|
||||||
|
|
||||||
// TODO: thread isn't started here now, do this elsewhere
|
// TODO: thread isn't started here now, do this elsewhere
|
||||||
// This isn't as drastic as it sounds, since the process in which the threads
|
// This isn't as drastic as it sounds, since the process in which the threads
|
||||||
// reside is normal priority. Needed for keeping audio reports at a decent rate
|
// reside is normal priority. Needed for keeping audio reports at a decent rate
|
||||||
@ -544,15 +538,30 @@ void Wiimote::DisconnectInternal()
|
|||||||
CloseHandle(dev_handle);
|
CloseHandle(dev_handle);
|
||||||
dev_handle = 0;
|
dev_handle = 0;
|
||||||
|
|
||||||
CloseHandle(hid_overlap_read.hEvent);
|
|
||||||
CloseHandle(hid_overlap_write.hEvent);
|
|
||||||
|
|
||||||
#ifdef SHARE_WRITE_WIIMOTES
|
#ifdef SHARE_WRITE_WIIMOTES
|
||||||
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
|
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
|
||||||
g_connected_wiimotes.erase(devicepath);
|
g_connected_wiimotes.erase(devicepath);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wiimote::InitInternal()
|
||||||
|
{
|
||||||
|
dev_handle = 0;
|
||||||
|
stack = MSBT_STACK_UNKNOWN;
|
||||||
|
|
||||||
|
hid_overlap_read = OVERLAPPED();
|
||||||
|
hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL);
|
||||||
|
|
||||||
|
hid_overlap_write = OVERLAPPED();
|
||||||
|
hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wiimote::TeardownInternal()
|
||||||
|
{
|
||||||
|
CloseHandle(hid_overlap_read.hEvent);
|
||||||
|
CloseHandle(hid_overlap_write.hEvent);
|
||||||
|
}
|
||||||
|
|
||||||
bool Wiimote::IsConnected() const
|
bool Wiimote::IsConnected() const
|
||||||
{
|
{
|
||||||
return dev_handle != 0;
|
return dev_handle != 0;
|
||||||
@ -560,7 +569,7 @@ bool Wiimote::IsConnected() const
|
|||||||
|
|
||||||
void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read)
|
void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read)
|
||||||
{
|
{
|
||||||
CancelIoEx(dev_handle, &hid_overlap_read);
|
SetEvent(hid_overlap_read.hEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// positive = read packet
|
// positive = read packet
|
||||||
@ -582,26 +591,22 @@ int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index
|
|||||||
if (ERROR_IO_PENDING == read_err)
|
if (ERROR_IO_PENDING == read_err)
|
||||||
{
|
{
|
||||||
auto const wait_result = WaitForSingleObject(hid_overlap_read.hEvent, INFINITE);
|
auto const wait_result = WaitForSingleObject(hid_overlap_read.hEvent, INFINITE);
|
||||||
if (WAIT_TIMEOUT == wait_result)
|
|
||||||
{
|
// In case the event was signalled by _IOWakeup before the read completed, cancel it.
|
||||||
CancelIo(dev_handle);
|
CancelIo(dev_handle);
|
||||||
}
|
|
||||||
else if (WAIT_FAILED == wait_result)
|
if (WAIT_FAILED == wait_result)
|
||||||
{
|
{
|
||||||
WARN_LOG(WIIMOTE, "A wait error occurred on reading from Wiimote %i.", index + 1);
|
WARN_LOG(WIIMOTE, "A wait error occurred on reading from Wiimote %i.", index + 1);
|
||||||
CancelIo(dev_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, TRUE))
|
if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, FALSE))
|
||||||
{
|
{
|
||||||
auto const overlapped_err = GetLastError();
|
auto const overlapped_err = GetLastError();
|
||||||
|
|
||||||
if (ERROR_OPERATION_ABORTED == overlapped_err)
|
if (ERROR_OPERATION_ABORTED == overlapped_err)
|
||||||
{
|
{
|
||||||
/*
|
// It was.
|
||||||
if (buf[1] != 0)
|
|
||||||
WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem.");
|
|
||||||
*/
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +188,25 @@ bool WiimoteScanner::IsReady() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wiimote::InitInternal()
|
||||||
|
{
|
||||||
|
inputlen = 0;
|
||||||
|
m_connected = false;
|
||||||
|
m_wiimote_thread_run_loop = NULL;
|
||||||
|
btd = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wiimote::TeardownInternal()
|
||||||
|
{
|
||||||
|
if (m_wiimote_thread_run_loop)
|
||||||
|
{
|
||||||
|
CFRelease(m_wiimote_thread_run_loop);
|
||||||
|
m_wiimote_thread_run_loop = NULL;
|
||||||
|
}
|
||||||
|
[btd release];
|
||||||
|
btd = nil;
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to a wiimote with a known address.
|
// Connect to a wiimote with a known address.
|
||||||
bool Wiimote::ConnectInternal()
|
bool Wiimote::ConnectInternal()
|
||||||
{
|
{
|
||||||
@ -198,35 +217,54 @@ bool Wiimote::ConnectInternal()
|
|||||||
|
|
||||||
cchan = ichan = nil;
|
cchan = ichan = nil;
|
||||||
|
|
||||||
[btd openL2CAPChannelSync: &cchan
|
IOReturn ret = [btd openConnection];
|
||||||
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
|
if (ret)
|
||||||
[btd openL2CAPChannelSync: &ichan
|
{
|
||||||
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
|
ERROR_LOG(WIIMOTE, "Unable to open Bluetooth connection to wiimote %i: %x",
|
||||||
|
index + 1, ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = [btd openL2CAPChannelSync: &cchan
|
||||||
|
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ERROR_LOG(WIIMOTE, "Unable to open control channel for wiimote %i: %x",
|
||||||
|
index + 1, ret);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
// Apple docs claim:
|
// Apple docs claim:
|
||||||
// "The L2CAP channel object is already retained when this function returns
|
// "The L2CAP channel object is already retained when this function returns
|
||||||
// success; the channel must be released when the caller is done with it."
|
// success; the channel must be released when the caller is done with it."
|
||||||
// But without this, the channels get over-autoreleased, even though the
|
// But without this, the channels get over-autoreleased, even though the
|
||||||
// refcounting behavior here is clearly correct.
|
// refcounting behavior here is clearly correct.
|
||||||
[ichan retain];
|
|
||||||
[cchan retain];
|
[cchan retain];
|
||||||
if (ichan == nil || cchan == nil)
|
|
||||||
|
ret = [btd openL2CAPChannelSync: &ichan
|
||||||
|
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
|
||||||
|
if (ret)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels "
|
WARN_LOG(WIIMOTE, "Unable to open interrupt channel for wiimote %i: %x",
|
||||||
"for wiimote %i", index + 1);
|
index + 1, ret);
|
||||||
DisconnectInternal();
|
goto bad;
|
||||||
[cbt release];
|
|
||||||
[ichan release];
|
|
||||||
[cchan release];
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
[ichan retain];
|
||||||
|
|
||||||
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
|
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
|
||||||
index + 1, [[btd addressString] UTF8String]);
|
index + 1, [[btd addressString] UTF8String]);
|
||||||
|
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
|
|
||||||
[cbt release];
|
[cbt release];
|
||||||
|
|
||||||
|
m_wiimote_thread_run_loop = (CFRunLoopRef) CFRetain(CFRunLoopGetCurrent());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
DisconnectInternal();
|
||||||
|
[cbt release];
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disconnect a wiimote.
|
// Disconnect a wiimote.
|
||||||
@ -234,15 +272,13 @@ void Wiimote::DisconnectInternal()
|
|||||||
{
|
{
|
||||||
[ichan closeChannel];
|
[ichan closeChannel];
|
||||||
[ichan release];
|
[ichan release];
|
||||||
ichan = NULL;
|
ichan = nil;
|
||||||
|
|
||||||
[cchan closeChannel];
|
[cchan closeChannel];
|
||||||
[cchan release];
|
[cchan release];
|
||||||
cchan = NULL;
|
cchan = nil;
|
||||||
|
|
||||||
[btd closeConnection];
|
[btd closeConnection];
|
||||||
[btd release];
|
|
||||||
btd = NULL;
|
|
||||||
|
|
||||||
if (!IsConnected())
|
if (!IsConnected())
|
||||||
return;
|
return;
|
||||||
@ -259,7 +295,10 @@ bool Wiimote::IsConnected() const
|
|||||||
|
|
||||||
void Wiimote::IOWakeup()
|
void Wiimote::IOWakeup()
|
||||||
{
|
{
|
||||||
CFRunLoopStop(m_wiimote_thread_run_loop);
|
if (m_wiimote_thread_run_loop)
|
||||||
|
{
|
||||||
|
CFRunLoopStop(m_wiimote_thread_run_loop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Wiimote::IORead(unsigned char *buf)
|
int Wiimote::IORead(unsigned char *buf)
|
||||||
|
@ -39,29 +39,12 @@ WiimoteScanner g_wiimote_scanner;
|
|||||||
|
|
||||||
Wiimote::Wiimote()
|
Wiimote::Wiimote()
|
||||||
: index()
|
: index()
|
||||||
#ifdef __APPLE__
|
|
||||||
, btd(), ichan(), cchan(), input(), inputlen(), m_connected()
|
|
||||||
#elif defined(__linux__) && HAVE_BLUEZ
|
|
||||||
, cmd_sock(-1), int_sock(-1)
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
, dev_handle(0), stack(MSBT_STACK_UNKNOWN)
|
|
||||||
#endif
|
|
||||||
, m_last_input_report()
|
, m_last_input_report()
|
||||||
, m_channel(0)
|
, m_channel(0)
|
||||||
, m_rumble_state()
|
, m_rumble_state()
|
||||||
, m_need_prepare()
|
, m_need_prepare()
|
||||||
{
|
{
|
||||||
#if defined(__linux__) && HAVE_BLUEZ
|
InitInternal();
|
||||||
int fds[2];
|
|
||||||
if (pipe(fds))
|
|
||||||
{
|
|
||||||
ERROR_LOG(WIIMOTE, "pipe failed");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
wakeup_pipe_w = fds[1];
|
|
||||||
wakeup_pipe_r = fds[0];
|
|
||||||
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Wiimote::~Wiimote()
|
Wiimote::~Wiimote()
|
||||||
@ -69,10 +52,7 @@ Wiimote::~Wiimote()
|
|||||||
StopThread();
|
StopThread();
|
||||||
ClearReadQueue();
|
ClearReadQueue();
|
||||||
m_write_reports.Clear();
|
m_write_reports.Clear();
|
||||||
#if defined(__linux__) && HAVE_BLUEZ
|
TeardownInternal();
|
||||||
close(wakeup_pipe_w);
|
|
||||||
close(wakeup_pipe_r);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called from CPU thread
|
// to be called from CPU thread
|
||||||
@ -514,8 +494,6 @@ void Wiimote::StopThread()
|
|||||||
if (m_wiimote_thread.joinable())
|
if (m_wiimote_thread.joinable())
|
||||||
m_wiimote_thread.join();
|
m_wiimote_thread.join();
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
CFRelease(m_wiimote_thread_run_loop);
|
|
||||||
m_wiimote_thread_run_loop = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -543,9 +521,6 @@ void Wiimote::WaitReady()
|
|||||||
void Wiimote::ThreadFunc()
|
void Wiimote::ThreadFunc()
|
||||||
{
|
{
|
||||||
Common::SetCurrentThreadName("Wiimote Device Thread");
|
Common::SetCurrentThreadName("Wiimote Device Thread");
|
||||||
#if defined(__APPLE__)
|
|
||||||
m_wiimote_thread_run_loop = (CFRunLoopRef) CFRetain(CFRunLoopGetCurrent());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool ok = ConnectInternal();
|
bool ok = ConnectInternal();
|
||||||
|
|
||||||
@ -565,7 +540,7 @@ void Wiimote::ThreadFunc()
|
|||||||
if (!PrepareOnThread())
|
if (!PrepareOnThread())
|
||||||
{
|
{
|
||||||
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.", index + 1);
|
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.", index + 1);
|
||||||
DisconnectInternal();
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write();
|
Write();
|
||||||
|
@ -56,6 +56,9 @@ public:
|
|||||||
bool ConnectInternal();
|
bool ConnectInternal();
|
||||||
void DisconnectInternal();
|
void DisconnectInternal();
|
||||||
|
|
||||||
|
void InitInternal();
|
||||||
|
void TeardownInternal();
|
||||||
|
|
||||||
bool Connect();
|
bool Connect();
|
||||||
|
|
||||||
// TODO: change to something like IsRelevant
|
// TODO: change to something like IsRelevant
|
||||||
|
Loading…
x
Reference in New Issue
Block a user