Skip to content

Commit

Permalink
Merge branch '6584'
Browse files Browse the repository at this point in the history
Fix for XP and lifetime issues on Mac.  Fixes issue 6584.
  • Loading branch information
comex committed Sep 12, 2013
2 parents fde3815 + fe0a450 commit 9ee50a2
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 68 deletions.
6 changes: 6 additions & 0 deletions Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
Expand Up @@ -43,6 +43,12 @@ bool WiimoteScanner::IsReady() const
return false;
}

void Wiimote::InitInternal()
{}

void Wiimote::TeardownInternal()
{}

bool Wiimote::ConnectInternal()
{
return 0;
Expand Down
22 changes: 22 additions & 0 deletions Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
Expand Up @@ -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.
bool Wiimote::ConnectInternal()
{
Expand Down
47 changes: 26 additions & 21 deletions Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
Expand Up @@ -514,12 +514,6 @@ bool Wiimote::ConnectInternal()
}
#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
// 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
Expand All @@ -544,23 +538,38 @@ void Wiimote::DisconnectInternal()
CloseHandle(dev_handle);
dev_handle = 0;

CloseHandle(hid_overlap_read.hEvent);
CloseHandle(hid_overlap_write.hEvent);

#ifdef SHARE_WRITE_WIIMOTES
std::lock_guard<std::mutex> lk(g_connected_wiimotes_lock);
g_connected_wiimotes.erase(devicepath);
#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
{
return dev_handle != 0;
}

void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read)
{
CancelIoEx(dev_handle, &hid_overlap_read);
SetEvent(hid_overlap_read.hEvent);
}

// positive = read packet
Expand All @@ -582,26 +591,22 @@ int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index
if (ERROR_IO_PENDING == read_err)
{
auto const wait_result = WaitForSingleObject(hid_overlap_read.hEvent, INFINITE);
if (WAIT_TIMEOUT == wait_result)
{
CancelIo(dev_handle);
}
else if (WAIT_FAILED == wait_result)

// In case the event was signalled by _IOWakeup before the read completed, cancel it.
CancelIo(dev_handle);

if (WAIT_FAILED == wait_result)
{
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();

if (ERROR_OPERATION_ABORTED == overlapped_err)
{
/*
if (buf[1] != 0)
WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem.");
*/
// It was.
return -1;
}

Expand Down
77 changes: 58 additions & 19 deletions Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
Expand Up @@ -188,6 +188,25 @@ - (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
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.
bool Wiimote::ConnectInternal()
{
Expand All @@ -198,51 +217,68 @@ - (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel

cchan = ichan = nil;

[btd openL2CAPChannelSync: &cchan
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
[btd openL2CAPChannelSync: &ichan
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
IOReturn ret = [btd openConnection];
if (ret)
{
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:
// "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.
[ichan 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 "
"for wiimote %i", index + 1);
DisconnectInternal();
[cbt release];
[ichan release];
[cchan release];
return false;
WARN_LOG(WIIMOTE, "Unable to open interrupt channel for wiimote %i: %x",
index + 1, ret);
goto bad;
}
[ichan retain];

NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
index + 1, [[btd addressString] UTF8String]);
index + 1, [[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 Wiimote::DisconnectInternal()
{
[ichan closeChannel];
[ichan release];
ichan = NULL;
ichan = nil;

[cchan closeChannel];
[cchan release];
cchan = NULL;
cchan = nil;

[btd closeConnection];
[btd release];
btd = NULL;

if (!IsConnected())
return;
Expand All @@ -259,7 +295,10 @@ - (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel

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)
Expand Down
31 changes: 3 additions & 28 deletions Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
Expand Up @@ -39,40 +39,20 @@ WiimoteScanner g_wiimote_scanner;

Wiimote::Wiimote()
: 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_channel(0)
, m_rumble_state()
, m_need_prepare()
{
#if defined(__linux__) && HAVE_BLUEZ
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
InitInternal();
}

Wiimote::~Wiimote()
{
StopThread();
ClearReadQueue();
m_write_reports.Clear();
#if defined(__linux__) && HAVE_BLUEZ
close(wakeup_pipe_w);
close(wakeup_pipe_r);
#endif
TeardownInternal();
}

// to be called from CPU thread
Expand Down Expand Up @@ -514,8 +494,6 @@ void Wiimote::StopThread()
if (m_wiimote_thread.joinable())
m_wiimote_thread.join();
#if defined(__APPLE__)
CFRelease(m_wiimote_thread_run_loop);
m_wiimote_thread_run_loop = NULL;
#endif
}

Expand Down Expand Up @@ -543,9 +521,6 @@ void Wiimote::WaitReady()
void Wiimote::ThreadFunc()
{
Common::SetCurrentThreadName("Wiimote Device Thread");
#if defined(__APPLE__)
m_wiimote_thread_run_loop = (CFRunLoopRef) CFRetain(CFRunLoopGetCurrent());
#endif

bool ok = ConnectInternal();

Expand All @@ -565,7 +540,7 @@ void Wiimote::ThreadFunc()
if (!PrepareOnThread())
{
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.", index + 1);
DisconnectInternal();
break;
}
}
Write();
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
Expand Up @@ -56,6 +56,9 @@ friend class WiimoteEmu::Wiimote;
bool ConnectInternal();
void DisconnectInternal();

void InitInternal();
void TeardownInternal();

bool Connect();

// TODO: change to something like IsRelevant
Expand Down

0 comments on commit 9ee50a2

Please sign in to comment.