summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp4
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp7
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp4
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm27
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp163
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h22
6 files changed, 128 insertions, 99 deletions
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
index 59025f9040..870d281326 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp
@@ -43,12 +43,12 @@ bool WiimoteScanner::IsReady() const
return false;
}
-bool Wiimote::Connect()
+bool Wiimote::ConnectInternal()
{
return 0;
}
-void Wiimote::Disconnect()
+void Wiimote::DisconnectInternal()
{
return;
}
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
index edd79f2bf6..014eadc9a8 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp
@@ -27,8 +27,7 @@ namespace WiimoteReal
{
WiimoteScanner::WiimoteScanner()
- : m_run_thread()
- , m_want_wiimotes()
+ : m_want_wiimotes()
, device_id(-1)
, device_sock(-1)
{
@@ -135,7 +134,7 @@ void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimot
}
// Connect to a wiimote with a known address.
-bool Wiimote::Connect()
+bool Wiimote::ConnectInternal()
{
sockaddr_l2 addr;
addr.l2_family = AF_BLUETOOTH;
@@ -168,7 +167,7 @@ bool Wiimote::Connect()
return true;
}
-void Wiimote::Disconnect()
+void Wiimote::DisconnectInternal()
{
close(cmd_sock);
close(int_sock);
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
index 5d4d26108f..866284b323 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
@@ -459,7 +459,7 @@ bool WiimoteScanner::IsReady() const
}
// Connect to a wiimote with a known device path.
-bool Wiimote::Connect()
+bool Wiimote::ConnectInternal()
{
if (IsConnected())
return false;
@@ -535,7 +535,7 @@ bool Wiimote::Connect()
return true;
}
-void Wiimote::Disconnect()
+void Wiimote::DisconnectInternal()
{
if (!IsConnected())
return;
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
index 8596b12080..17e867bc7a 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
@@ -64,7 +64,7 @@
return;
}
- if (wm->inputlen != 0) {
+ if (wm->inputlen != -1) {
WARN_LOG(WIIMOTE, "Dropping packet for wiimote %i, queue full",
wm->index + 1);
return;
@@ -73,9 +73,8 @@
memcpy(wm->input, data, length);
wm->inputlen = length;
- (void)wm->Read();
-
(void)UpdateSystemActivity(UsrActivity);
+ CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
@@ -100,7 +99,7 @@
WARN_LOG(WIIMOTE, "Lost channel to wiimote %i", wm->index + 1);
- wm->Disconnect();
+ wm->DisconnectInternal();
}
@end
@@ -189,7 +188,7 @@ bool WiimoteScanner::IsReady() const
}
// Connect to a wiimote with a known address.
-bool Wiimote::Connect()
+bool Wiimote::ConnectInternal()
{
if (IsConnected())
return false;
@@ -204,12 +203,12 @@ bool Wiimote::Connect()
{
ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels "
"for wiimote %i", index + 1);
- Disconnect();
+ DisconnectInternal();
[cbt release];
return false;
}
-
+
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i at %s",
index + 1, [[btd addressString] UTF8String]);
@@ -220,7 +219,7 @@ bool Wiimote::Connect()
}
// Disconnect a wiimote.
-void Wiimote::Disconnect()
+void Wiimote::DisconnectInternal()
{
if (ichan != NULL)
[ichan release];
@@ -250,16 +249,12 @@ bool Wiimote::IsConnected() const
int Wiimote::IORead(unsigned char *buf)
{
- int bytes;
-
- if (!IsConnected())
- return 0;
+ input = buf;
+ inputlen = -1;
- bytes = inputlen;
- memcpy(buf, input, bytes);
- inputlen = 0;
+ CFRunLoopRun();
- return bytes;
+ return inputlen;
}
int Wiimote::IOWrite(const unsigned char *buf, int len)
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
index d2e7e2f57a..aead9d60fa 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
@@ -40,7 +40,7 @@ WiimoteScanner g_wiimote_scanner;
Wiimote::Wiimote()
: index()
#ifdef __APPLE__
- , btd(), ichan(), cchan(), inputlen(), m_connected()
+ , btd(), ichan(), cchan(), input(), inputlen(), m_connected()
#elif defined(__linux__) && HAVE_BLUEZ
, cmd_sock(-1), int_sock(-1)
#elif defined(_WIN32)
@@ -49,7 +49,7 @@ Wiimote::Wiimote()
, m_last_input_report()
, m_channel(0)
, m_rumble_state()
- , m_run_thread(false)
+ , m_need_prepare()
{
#if defined(__linux__) && HAVE_BLUEZ
bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}};
@@ -60,9 +60,6 @@ Wiimote::~Wiimote()
{
StopThread();
- if (IsConnected())
- Disconnect();
-
ClearReadQueue();
m_write_reports.Clear();
}
@@ -225,8 +222,8 @@ bool Wiimote::Read()
}
else if (0 == result)
{
- WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting Wiimote %d.", index + 1);
- Disconnect();
+ ERROR_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting Wiimote %d.", index + 1);
+ DisconnectInternal();
}
return false;
@@ -308,27 +305,31 @@ void Wiimote::Update()
rpt.data(), rpt.size());
}
-bool Wiimote::Prepare(int _index)
+void Wiimote::Prepare(int _index)
{
index = _index;
+ m_need_prepare = true;
+}
+bool Wiimote::PrepareOnThread()
+{
// core buttons, no continuous reporting
- u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
+ u8 static const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};
// Set the active LEDs and turn on rumble.
- u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)};
+ u8 static const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)};
// Turn off rumble
- u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
+ u8 static const rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
// Request status report
- u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
+ u8 static const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0};
// TODO: check for sane response?
return (IOWrite(mode_report, sizeof(mode_report))
- && IOWrite(led_report, sizeof(led_report))
- && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report)))
- && IOWrite(req_status_report, sizeof(req_status_report)));
+ && IOWrite(led_report, sizeof(led_report))
+ && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report)))
+ && IOWrite(req_status_report, sizeof(req_status_report)));
}
void Wiimote::EmuStart()
@@ -480,35 +481,75 @@ void WiimoteScanner::ThreadFunc()
NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped.");
}
+bool Wiimote::Connect()
+{
+ m_thread_ready = false;
+ StartThread();
+ WaitReady();
+ return IsConnected();
+}
+
void Wiimote::StartThread()
{
- m_run_thread = true;
m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this);
}
void Wiimote::StopThread()
{
- m_run_thread = false;
if (m_wiimote_thread.joinable())
m_wiimote_thread.join();
}
+void Wiimote::SetReady()
+{
+ if (!m_thread_ready)
+ {
+ {
+ std::lock_guard<std::mutex> Guard(m_thread_ready_mutex);
+ m_thread_ready = true;
+ }
+ m_thread_ready_cond.notify_all();
+ }
+}
+
+void Wiimote::WaitReady()
+{
+ std::unique_lock<std::mutex> lock(m_thread_ready_mutex);
+ while (!m_thread_ready)
+ {
+ m_thread_ready_cond.wait(lock);
+ }
+}
+
void Wiimote::ThreadFunc()
{
Common::SetCurrentThreadName("Wiimote Device Thread");
+ bool ok = ConnectInternal();
+
+ SetReady();
+
+ if (!ok)
+ {
+ return;
+ }
// main loop
- while (m_run_thread && IsConnected())
+ while (IsConnected())
{
-#ifdef __APPLE__
- // Reading happens elsewhere on OSX
- bool const did_something = Write();
-#else
- bool const did_something = Write() || Read();
-#endif
- if (!did_something)
- Common::SleepCurrentThread(1);
+ if (m_need_prepare)
+ {
+ m_need_prepare = false;
+ if (!PrepareOnThread())
+ {
+ ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.", index + 1);
+ DisconnectInternal();
+ }
+ }
+ Write();
+ Read();
}
+
+ DisconnectInternal();
}
void LoadSettings()
@@ -629,24 +670,32 @@ void ChangeWiimoteSource(unsigned int index, int source)
Host_ConnectWiimote(index, true);
}
+static bool TryToConnectWiimoteN(Wiimote* wm, unsigned int i)
+{
+ if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
+ && !g_wiimotes[i])
+ {
+ if (wm->Connect())
+ {
+ wm->Prepare(i);
+ NOTICE_LOG(WIIMOTE, "Connected to Wiimote %i.", i + 1);
+ g_wiimotes[i] = wm;
+ Host_ConnectWiimote(i, true);
+ }
+ return true;
+ }
+ return false;
+}
+
void TryToConnectWiimote(Wiimote* wm)
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
- if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
- && !g_wiimotes[i])
+ if (TryToConnectWiimoteN(wm, i))
{
- if (wm->Connect() && wm->Prepare(i))
- {
- NOTICE_LOG(WIIMOTE, "Connected to Wiimote %i.", i + 1);
-
- std::swap(g_wiimotes[i], wm);
- g_wiimotes[i]->StartThread();
-
- Host_ConnectWiimote(i, true);
- }
+ wm = NULL;
break;
}
}
@@ -661,19 +710,10 @@ void TryToConnectWiimote(Wiimote* wm)
void TryToConnectBalanceBoard(Wiimote* wm)
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
-
- if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD]
- && !g_wiimotes[WIIMOTE_BALANCE_BOARD])
+
+ if (TryToConnectWiimoteN(wm, WIIMOTE_BALANCE_BOARD))
{
- if (wm->Connect() && wm->Prepare(WIIMOTE_BALANCE_BOARD))
- {
- NOTICE_LOG(WIIMOTE, "Connected to Balance Board %i.", WIIMOTE_BALANCE_BOARD + 1);
-
- std::swap(g_wiimotes[WIIMOTE_BALANCE_BOARD], wm);
- g_wiimotes[WIIMOTE_BALANCE_BOARD]->StartThread();
-
- Host_ConnectWiimote(WIIMOTE_BALANCE_BOARD, true);
- }
+ wm = NULL;
}
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
@@ -687,26 +727,13 @@ void DoneWithWiimote(int index)
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
- if (g_wiimotes[index])
+ Wiimote* wm = g_wiimotes[index];
+
+ if (wm)
{
- g_wiimotes[index]->StopThread();
-
+ g_wiimotes[index] = NULL;
// First see if we can use this real Wiimote in another slot.
- for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
- {
- if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
- && !g_wiimotes[i])
- {
- if (g_wiimotes[index]->Prepare(i))
- {
- std::swap(g_wiimotes[i], g_wiimotes[index]);
- g_wiimotes[i]->StartThread();
-
- Host_ConnectWiimote(i, true);
- }
- break;
- }
- }
+ TryToConnectWiimote(wm);
}
// else, just disconnect the Wiimote
@@ -763,9 +790,7 @@ void Refresh()
{
if (g_wiimotes[i])
{
- g_wiimotes[i]->StopThread();
g_wiimotes[i]->Prepare(i);
- g_wiimotes[i]->StartThread();
}
}
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
index 2ab4e435e2..e48567acbb 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
@@ -52,13 +52,17 @@ public:
// connecting and disconnecting from physical devices
// (using address inserted by FindWiimotes)
+ // these are called from the wiimote's thread.
+ bool ConnectInternal();
+ void DisconnectInternal();
+
bool Connect();
- void Disconnect();
// TODO: change to something like IsRelevant
bool IsConnected() const;
- bool Prepare(int index);
+ void Prepare(int index);
+ bool PrepareOnThread();
void DisableDataReporting();
void EnableDataReporting(u8 mode);
@@ -72,9 +76,10 @@ public:
IOBluetoothDevice *btd;
IOBluetoothL2CAPChannel *ichan;
IOBluetoothL2CAPChannel *cchan;
- char input[MAX_PAYLOAD];
+ unsigned char* input;
int inputlen;
bool m_connected;
+ CFRunLoopRef m_wiimote_thread_run_loop;
#elif defined(__linux__) && HAVE_BLUEZ
bdaddr_t bdaddr; // Bluetooth address
int cmd_sock; // Command socket
@@ -100,12 +105,17 @@ private:
int IOWrite(u8 const* buf, int len);
void ThreadFunc();
+ void SetReady();
+ void WaitReady();
bool m_rumble_state;
- bool m_run_thread;
- std::thread m_wiimote_thread;
-
+ std::thread m_wiimote_thread;
+ volatile bool m_thread_ready;
+ volatile bool m_need_prepare;
+ std::mutex m_thread_ready_mutex;
+ std::condition_variable m_thread_ready_cond;
+
Common::FifoQueue<Report> m_read_reports;
Common::FifoQueue<Report> m_write_reports;