Fix minor issue with real wiimote data report handling.
This commit is contained in:
parent
a2ebb2b324
commit
99da297951
|
@ -707,10 +707,10 @@ void Wiimote::Update()
|
|||
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
|
||||
if (g_wiimotes[m_index])
|
||||
{
|
||||
Report rpt = g_wiimotes[m_index]->ProcessReadQueue();
|
||||
const u8 *real_data = rpt.first;
|
||||
if (real_data)
|
||||
const Report& rpt = g_wiimotes[m_index]->ProcessReadQueue();
|
||||
if (!rpt.empty())
|
||||
{
|
||||
const u8 *real_data = rpt.data();
|
||||
switch (real_data[1])
|
||||
{
|
||||
// use data reports
|
||||
|
@ -770,13 +770,9 @@ void Wiimote::Update()
|
|||
// copy over report from real-wiimote
|
||||
if (-1 == rptf_size)
|
||||
{
|
||||
memcpy(data, real_data, rpt.second);
|
||||
rptf_size = rpt.second;
|
||||
std::copy(rpt.begin(), rpt.end(), data);
|
||||
rptf_size = rpt.size();
|
||||
}
|
||||
|
||||
if (real_data != g_wiimotes[m_index]->\
|
||||
m_last_data_report.first)
|
||||
delete[] real_data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,8 @@ Wiimote::Wiimote()
|
|||
#elif defined(_WIN32)
|
||||
, dev_handle(0), stack(MSBT_STACK_UNKNOWN)
|
||||
#endif
|
||||
, m_last_data_report(Report((u8 *)NULL, 0))
|
||||
, m_last_data_report()
|
||||
, m_current_report()
|
||||
, m_channel(0), m_run_thread(false)
|
||||
{
|
||||
#if defined(__linux__) && HAVE_BLUEZ
|
||||
|
@ -73,11 +74,7 @@ Wiimote::~Wiimote()
|
|||
Disconnect();
|
||||
|
||||
ClearReadQueue();
|
||||
|
||||
// clear write queue
|
||||
Report rpt;
|
||||
while (m_write_reports.Pop(rpt))
|
||||
delete[] rpt.first;
|
||||
m_write_reports.Clear();
|
||||
}
|
||||
|
||||
// to be called from CPU thread
|
||||
|
@ -85,12 +82,10 @@ void Wiimote::QueueReport(u8 rpt_id, const void* _data, unsigned int size)
|
|||
{
|
||||
auto const data = static_cast<const u8*>(_data);
|
||||
|
||||
Report rpt;
|
||||
rpt.second = size + 2;
|
||||
rpt.first = new u8[rpt.second];
|
||||
rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
|
||||
rpt.first[1] = rpt_id;
|
||||
std::copy(data, data + size, rpt.first + 2);
|
||||
Report rpt(size + 2);
|
||||
rpt[0] = WM_SET_REPORT | WM_BT_OUTPUT;
|
||||
rpt[1] = rpt_id;
|
||||
std::copy_n(data, size, rpt.begin() + 2);
|
||||
m_write_reports.Push(rpt);
|
||||
}
|
||||
|
||||
|
@ -107,15 +102,10 @@ void Wiimote::DisableDataReporting()
|
|||
void Wiimote::ClearReadQueue()
|
||||
{
|
||||
Report rpt;
|
||||
|
||||
if (m_last_data_report.first)
|
||||
{
|
||||
delete[] m_last_data_report.first;
|
||||
m_last_data_report.first = NULL;
|
||||
}
|
||||
|
||||
|
||||
// The "Clear" function isn't thread-safe :/
|
||||
while (m_read_reports.Pop(rpt))
|
||||
delete[] rpt.first;
|
||||
{}
|
||||
}
|
||||
|
||||
void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size)
|
||||
|
@ -148,39 +138,35 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const
|
|||
}
|
||||
|
||||
auto const data = static_cast<const u8*>(_data);
|
||||
|
||||
Report rpt;
|
||||
rpt.first = new u8[size];
|
||||
rpt.second = (u8)size;
|
||||
std::copy(data, data + size, rpt.first);
|
||||
Report rpt(data, data + size);
|
||||
|
||||
// Convert output DATA packets to SET_REPORT packets.
|
||||
// Nintendo Wiimotes work without this translation, but 3rd
|
||||
// party ones don't.
|
||||
if (rpt.first[0] == 0xa2)
|
||||
if (rpt[0] == 0xa2)
|
||||
{
|
||||
rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT;
|
||||
rpt[0] = WM_SET_REPORT | WM_BT_OUTPUT;
|
||||
}
|
||||
|
||||
// Disallow games from turning off all of the LEDs.
|
||||
// It makes Wiimote connection status confusing.
|
||||
if (rpt.first[1] == WM_LEDS)
|
||||
if (rpt[1] == WM_LEDS)
|
||||
{
|
||||
auto& leds_rpt = *reinterpret_cast<wm_leds*>(&rpt.first[2]);
|
||||
auto& leds_rpt = *reinterpret_cast<wm_leds*>(&rpt[2]);
|
||||
if (0 == leds_rpt.leds)
|
||||
{
|
||||
// Turn on ALL of the LEDs.
|
||||
leds_rpt.leds = 0xf;
|
||||
}
|
||||
}
|
||||
else if (rpt.first[1] == WM_WRITE_SPEAKER_DATA
|
||||
else if (rpt[1] == WM_WRITE_SPEAKER_DATA
|
||||
&& !SConfig::GetInstance().m_WiimoteEnableSpeaker)
|
||||
{
|
||||
// Translate speaker data reports into rumble reports.
|
||||
rpt.first[1] = WM_CMD_RUMBLE;
|
||||
rpt[1] = WM_CMD_RUMBLE;
|
||||
// Keep only the rumble bit.
|
||||
rpt.first[2] &= 0x1;
|
||||
rpt.second = 3;
|
||||
rpt[2] &= 0x1;
|
||||
rpt.resize(3);
|
||||
}
|
||||
|
||||
m_write_reports.Push(rpt);
|
||||
|
@ -188,25 +174,22 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const
|
|||
|
||||
bool Wiimote::Read()
|
||||
{
|
||||
Report rpt;
|
||||
|
||||
rpt.first = new unsigned char[MAX_PAYLOAD];
|
||||
rpt.second = IORead(rpt.first);
|
||||
Report rpt(MAX_PAYLOAD);
|
||||
auto const result = IORead(rpt.data());
|
||||
|
||||
if (0 == rpt.second)
|
||||
if (result > 0 && m_channel > 0)
|
||||
{
|
||||
// Add it to queue
|
||||
rpt.resize(result);
|
||||
m_read_reports.Push(std::move(rpt));
|
||||
return true;
|
||||
}
|
||||
else if (0 == result)
|
||||
{
|
||||
WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting Wiimote %d.", index + 1);
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
if (rpt.second > 0 && m_channel > 0)
|
||||
{
|
||||
// Add it to queue
|
||||
m_read_reports.Push(rpt);
|
||||
return true;
|
||||
}
|
||||
|
||||
delete[] rpt.first;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -216,16 +199,15 @@ bool Wiimote::Write()
|
|||
{
|
||||
Report const& rpt = m_write_reports.Front();
|
||||
|
||||
bool const is_speaker_data = rpt.first[1] == WM_WRITE_SPEAKER_DATA;
|
||||
bool const is_speaker_data = rpt[1] == WM_WRITE_SPEAKER_DATA;
|
||||
|
||||
if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5)
|
||||
{
|
||||
IOWrite(rpt.first, rpt.second);
|
||||
IOWrite(rpt.data(), rpt.size());
|
||||
|
||||
if (is_speaker_data)
|
||||
m_last_audio_report.Update();
|
||||
|
||||
delete[] rpt.first;
|
||||
m_write_reports.Pop();
|
||||
return true;
|
||||
}
|
||||
|
@ -235,22 +217,38 @@ bool Wiimote::Write()
|
|||
}
|
||||
|
||||
// Returns the next report that should be sent
|
||||
Report Wiimote::ProcessReadQueue()
|
||||
const Report& Wiimote::ProcessReadQueue()
|
||||
{
|
||||
// Pop through the queued reports
|
||||
Report rpt = m_last_data_report;
|
||||
while (m_read_reports.Pop(rpt))
|
||||
while (m_read_reports.Pop(m_current_report))
|
||||
{
|
||||
if (rpt.first[1] >= WM_REPORT_CORE)
|
||||
if (m_current_report[1] >= WM_REPORT_CORE)
|
||||
{
|
||||
// A data report
|
||||
m_last_data_report = rpt;
|
||||
m_last_data_report.swap(m_current_report);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some other kind of report
|
||||
return rpt;
|
||||
|
||||
// If this input report is an "ack" for setting the data reporting mode,
|
||||
// then drop m_last_data_report as it may be of the wrong type
|
||||
if (WM_ACK_DATA == m_current_report[1] && WM_REPORT_MODE == m_current_report[4])
|
||||
{
|
||||
m_last_data_report.clear();
|
||||
}
|
||||
|
||||
// Copy button data (which is included in every input report except WM_REPORT_EXT21)
|
||||
// needed to prevent rare spurious presses/releases.
|
||||
if (m_last_data_report.size() >= 4 && m_last_data_report[1] != WM_REPORT_EXT21)
|
||||
std::copy_n(m_current_report.begin() + 2, 2, m_last_data_report.begin() + 2);
|
||||
|
||||
return m_current_report;
|
||||
}
|
||||
}
|
||||
|
||||
// The queue was empty, or there were only data reports
|
||||
return rpt;
|
||||
return m_last_data_report;
|
||||
}
|
||||
|
||||
void Wiimote::Update()
|
||||
|
@ -262,16 +260,12 @@ void Wiimote::Update()
|
|||
}
|
||||
|
||||
// Pop through the queued reports
|
||||
Report const rpt = ProcessReadQueue();
|
||||
const Report& rpt = ProcessReadQueue();
|
||||
|
||||
// Send the report
|
||||
if (rpt.first != NULL && m_channel > 0)
|
||||
if (!rpt.empty() && m_channel > 0)
|
||||
Core::Callback_WiimoteInterruptChannel(index, m_channel,
|
||||
rpt.first, rpt.second);
|
||||
|
||||
// Delete the data if it isn't also the last data rpt
|
||||
if (rpt != m_last_data_report)
|
||||
delete[] rpt.first;
|
||||
rpt.data(), rpt.size());
|
||||
}
|
||||
|
||||
bool Wiimote::Prepare(int _index)
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
|
||||
#include "../../InputCommon/Src/InputConfig.h"
|
||||
|
||||
// Pointer to data, and size of data
|
||||
typedef std::pair<u8*,u8> Report;
|
||||
typedef std::vector<u8> Report;
|
||||
|
||||
namespace WiimoteReal
|
||||
{
|
||||
|
@ -50,7 +49,7 @@ public:
|
|||
void InterruptChannel(const u16 channel, const void* const data, const u32 size);
|
||||
void Update();
|
||||
|
||||
Report ProcessReadQueue();
|
||||
const Report& ProcessReadQueue();
|
||||
|
||||
bool Read();
|
||||
bool Write();
|
||||
|
@ -99,7 +98,8 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
Report m_last_data_report;
|
||||
Report m_last_data_report;
|
||||
Report m_current_report;
|
||||
u16 m_channel;
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue