mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
WiimoteReal: Send periodic writes to test for disconnect.
This commit is contained in:
parent
94ecf4df39
commit
e8d22923c6
@ -168,8 +168,6 @@ void Wiimote::Shutdown()
|
|||||||
|
|
||||||
StopThread();
|
StopThread();
|
||||||
ClearReadQueue();
|
ClearReadQueue();
|
||||||
|
|
||||||
NOTICE_LOG_FMT(WIIMOTE, "Disconnected real wiimote.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called from CPU thread
|
// to be called from CPU thread
|
||||||
@ -209,8 +207,8 @@ void Wiimote::WriteReport(Report rpt)
|
|||||||
const auto report_time =
|
const auto report_time =
|
||||||
Core::IsCPUThread() ? core_timing.GetTargetHostTime(core_timing.GetTicks()) : Clock::now();
|
Core::IsCPUThread() ? core_timing.GetTargetHostTime(core_timing.GetTicks()) : Clock::now();
|
||||||
|
|
||||||
m_write_thread.EmplaceItem(report_time, std::move(rpt));
|
m_write_reports.Emplace(report_time, std::move(rpt));
|
||||||
IOWakeup();
|
m_write_event.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called from CPU thread
|
// to be called from CPU thread
|
||||||
@ -512,11 +510,13 @@ void Wiimote::Prepare()
|
|||||||
// Set reporting mode to non-continuous core buttons and turn on rumble.
|
// Set reporting mode to non-continuous core buttons and turn on rumble.
|
||||||
Report mode_report = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::ReportMode), 1,
|
Report mode_report = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::ReportMode), 1,
|
||||||
u8(InputReportID::ReportCore)};
|
u8(InputReportID::ReportCore)};
|
||||||
m_write_thread.EmplaceItem(now, std::move(mode_report));
|
m_write_reports.Emplace(now, std::move(mode_report));
|
||||||
|
|
||||||
// Request status and turn off rumble.
|
// Request status and turn off rumble.
|
||||||
Report req_status_report = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RequestStatus), 0};
|
Report req_status_report = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::RequestStatus), 0};
|
||||||
m_write_thread.EmplaceItem(now + std::chrono::milliseconds{200}, std::move(req_status_report));
|
m_write_reports.Emplace(now + std::chrono::milliseconds{200}, std::move(req_status_report));
|
||||||
|
|
||||||
|
m_write_event.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::EmuStop()
|
void Wiimote::EmuStop()
|
||||||
@ -764,38 +764,54 @@ void WiimoteScanner::ThreadFunc()
|
|||||||
bool Wiimote::Connect(int index)
|
bool Wiimote::Connect(int index)
|
||||||
{
|
{
|
||||||
m_index = index;
|
m_index = index;
|
||||||
|
StartThread();
|
||||||
if (!m_run_thread.IsSet())
|
|
||||||
{
|
|
||||||
m_run_thread.Set();
|
|
||||||
StartThread();
|
|
||||||
m_thread_ready_event.Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
return IsConnected();
|
return IsConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::StartThread()
|
void Wiimote::StartThread()
|
||||||
{
|
{
|
||||||
// Note that the read thread starts the writing worker thread.
|
if (m_write_thread.joinable())
|
||||||
m_read_thread = std::thread(&Wiimote::ReadThreadFunc, this);
|
return;
|
||||||
|
|
||||||
|
m_run_thread.Set();
|
||||||
|
// Note that the write thread starts the read thread.
|
||||||
|
m_write_thread = std::thread(&Wiimote::WriteThreadFunc, this);
|
||||||
|
|
||||||
|
m_thread_ready_event.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::StopThread()
|
void Wiimote::StopThread()
|
||||||
{
|
{
|
||||||
if (!m_run_thread.TestAndClear())
|
if (!m_write_thread.joinable())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IOWakeup();
|
m_run_thread.Clear();
|
||||||
|
m_write_event.Set();
|
||||||
|
|
||||||
// Note that the read thread stops the writing worker thread.
|
// Note that the write thread stops the read thread.
|
||||||
m_read_thread.join();
|
m_write_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wiimote::ReadThreadFunc()
|
void Wiimote::ReadThreadFunc()
|
||||||
{
|
{
|
||||||
Common::SetCurrentThreadName("Wiimote Read Thread");
|
Common::SetCurrentThreadName("Wiimote Read Thread");
|
||||||
|
|
||||||
|
while (m_run_thread.IsSet())
|
||||||
|
{
|
||||||
|
if (!Read())
|
||||||
|
{
|
||||||
|
WARN_LOG_FMT(WIIMOTE, "Wiimote::Read failed on Wiimote {}.", m_index + 1);
|
||||||
|
m_run_thread.Clear();
|
||||||
|
m_write_event.Set();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wiimote::WriteThreadFunc()
|
||||||
|
{
|
||||||
|
Common::SetCurrentThreadName("Wiimote Write Thread");
|
||||||
|
|
||||||
bool ok = ConnectInternal();
|
bool ok = ConnectInternal();
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
@ -812,19 +828,55 @@ void Wiimote::ReadThreadFunc()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_write_thread.Reset("Wiimote Write Thread", std::bind_front(&Wiimote::Write, this));
|
std::thread read_thread{&Wiimote::ReadThreadFunc, this};
|
||||||
|
|
||||||
|
// Windows and also the DolphinBar require performing a write
|
||||||
|
// to detect disconnections in a timely manner
|
||||||
|
// If we haven't written a report in some time, attempt a rumble-off report.
|
||||||
|
// This also has a minor benefit of preventing rumble from being stuck on.
|
||||||
|
constexpr auto WRITE_TEST_INTERVAL = std::chrono::milliseconds{1000};
|
||||||
|
|
||||||
|
TimePoint last_write_time = Clock::now();
|
||||||
|
|
||||||
while (m_run_thread.IsSet())
|
while (m_run_thread.IsSet())
|
||||||
{
|
{
|
||||||
if (!Read())
|
bool write_success = false;
|
||||||
|
|
||||||
|
if (!m_write_reports.Empty())
|
||||||
{
|
{
|
||||||
ERROR_LOG_FMT(WIIMOTE, "Wiimote::Read failed. Disconnecting Wiimote {}.", m_index + 1);
|
// Send a normal report.
|
||||||
|
write_success = Write(m_write_reports.Front());
|
||||||
|
m_write_reports.Pop();
|
||||||
|
}
|
||||||
|
else if (Clock::now() - last_write_time >= WRITE_TEST_INTERVAL)
|
||||||
|
{
|
||||||
|
// We haven't written in a while, test a write so we can check for a disconnect.
|
||||||
|
DEBUG_LOG_FMT(WIIMOTE, "Sending periodic write test for Wiimote {}.", m_index + 1);
|
||||||
|
const u8 rumble_off[] = {WR_SET_REPORT | BT_OUTPUT, u8(OutputReportID::Rumble), 0x00};
|
||||||
|
|
||||||
|
write_success = IOWrite(std::data(rumble_off), std::size(rumble_off)) > 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Nothing to do. Wait a while for a kick.
|
||||||
|
m_write_event.WaitFor(WRITE_TEST_INTERVAL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_write_time = Clock::now();
|
||||||
|
|
||||||
|
if (!write_success)
|
||||||
|
{
|
||||||
|
WARN_LOG_FMT(WIIMOTE, "Wiimote::Write failed on Wiimote {}.", m_index + 1);
|
||||||
|
m_run_thread.Clear();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_write_thread.StopAndCancel();
|
IOWakeup();
|
||||||
|
read_thread.join();
|
||||||
|
|
||||||
|
NOTICE_LOG_FMT(WIIMOTE, "Disconnecting Wiimote {}.", m_index + 1);
|
||||||
DisconnectInternal();
|
DisconnectInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -146,6 +146,7 @@ private:
|
|||||||
virtual void IOWakeup() = 0;
|
virtual void IOWakeup() = 0;
|
||||||
|
|
||||||
void ReadThreadFunc();
|
void ReadThreadFunc();
|
||||||
|
void WriteThreadFunc();
|
||||||
|
|
||||||
void RefreshConfig();
|
void RefreshConfig();
|
||||||
|
|
||||||
@ -158,14 +159,16 @@ private:
|
|||||||
// And we track the rumble state to drop unnecessary rumble reports.
|
// And we track the rumble state to drop unnecessary rumble reports.
|
||||||
bool m_rumble_state = false;
|
bool m_rumble_state = false;
|
||||||
|
|
||||||
std::thread m_read_thread;
|
std::thread m_write_thread;
|
||||||
// Whether to keep running the thread.
|
// Whether to keep running the thread.
|
||||||
Common::Flag m_run_thread;
|
Common::Flag m_run_thread;
|
||||||
// Triggered when the thread has finished ConnectInternal.
|
// Triggered when the thread has finished ConnectInternal.
|
||||||
Common::Event m_thread_ready_event;
|
Common::Event m_thread_ready_event;
|
||||||
|
|
||||||
Common::SPSCQueue<Report> m_read_reports;
|
Common::SPSCQueue<Report> m_read_reports;
|
||||||
Common::WorkQueueThreadSP<TimedReport> m_write_thread;
|
Common::SPSCQueue<TimedReport> m_write_reports;
|
||||||
|
// Kick the write thread.
|
||||||
|
Common::Event m_write_event;
|
||||||
|
|
||||||
bool m_speaker_enabled_in_dolphin_config = false;
|
bool m_speaker_enabled_in_dolphin_config = false;
|
||||||
int m_balance_board_dump_port = 0;
|
int m_balance_board_dump_port = 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user