Make real wiimotes not so crappy on Windows hopefully.

This commit is contained in:
Jordan Woyak 2013-02-11 03:39:09 -06:00
parent 50c83d614c
commit 05ec90488b
7 changed files with 259 additions and 197 deletions

View File

@ -29,7 +29,10 @@ WiimoteScanner::WiimoteScanner()
WiimoteScanner::~WiimoteScanner()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
void WiimoteScanner::Update()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{
return std::vector<Wiimote*>();
}

View File

@ -60,11 +60,10 @@ WiimoteScanner::~WiimoteScanner()
close(device_sock);
}
// Find wiimotes.
// Does not replace already found wiimotes even if they are disconnected.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found wiimotes.
std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
void WiimoteScanner::Update()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{
std::vector<Wiimote*> found_wiimotes;
@ -86,7 +85,7 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices);
// Display discovered devices
for (int i = 0; (i < found_devices) && (found_wiimotes.size() < max_wiimotes); ++i)
for (int i = 0; i < found_devices; ++i)
{
ERROR_LOG(WIIMOTE, "found a device...");

View File

@ -18,6 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <regex>
#include <unordered_set>
#include <windows.h>
#include <dbt.h>
@ -73,6 +74,8 @@ HINSTANCE bthprops_lib = NULL;
static int initialized = 0;
static std::unordered_set<std::string> g_connected_devices;
inline void init_lib()
{
if (!initialized)
@ -127,7 +130,12 @@ inline void init_lib()
namespace WiimoteReal
{
int PairUp(bool unpair = false);
template <typename T>
void ProcessWiimotes(bool new_scan, T& callback);
bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi);
void RemoveWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi);
bool ForgetWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi);
WiimoteScanner::WiimoteScanner()
{
@ -137,24 +145,47 @@ WiimoteScanner::WiimoteScanner()
WiimoteScanner::~WiimoteScanner()
{
// TODO: what do we want here?
//PairUp(true);
ProcessWiimotes(false, RemoveWiimote);
}
void WiimoteScanner::Update()
{
bool forgot_some = false;
ProcessWiimotes(false, [&](HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
forgot_some |= ForgetWiimote(hRadio, btdi);
});
// Some hacks that allows disconnects to be detected before connections are handled
// workaround for wiimote 1 moving to slot 2 on temporary disconnect
if (forgot_some)
SLEEP(100);
}
// Find and connect wiimotes.
// Does not replace already found wiimotes even if they are disconnected.
// wm is an array of max_wiimotes wiimotes
// Returns the total number of found and connected wiimotes.
std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{
PairUp();
bool attached_some;
ProcessWiimotes(true, [&](HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
ForgetWiimote(hRadio, btdi);
attached_some |= AttachWiimote(hRadio, btdi);
});
// Hacks...
if (attached_some)
SLEEP(1000);
GUID device_id;
HANDLE dev;
HDEVINFO device_info;
DWORD len;
SP_DEVICE_INTERFACE_DATA device_data;
PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
HIDD_ATTRIBUTES attr;
device_data.cbSize = sizeof(device_data);
@ -165,7 +196,7 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
std::vector<Wiimote*> wiimotes;
for (int index = 0; wiimotes.size() < max_wiimotes; ++index)
for (int index = 0; true; ++index)
{
free(detail_data);
detail_data = NULL;
@ -184,24 +215,7 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
continue;
auto const wm = new Wiimote;
// Open new device
#if 0
dev = CreateFile(detail_data->DevicePath,
(GENERIC_READ | GENERIC_WRITE),
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (dev == INVALID_HANDLE_VALUE)
continue;
// Get device attributes
attr.Size = sizeof(attr);
HidD_GetAttributes(dev, &attr);
wm->dev_handle = dev;
#endif
wm->devicepath = detail_data->DevicePath;
wiimotes.push_back(wm);
}
@ -236,9 +250,15 @@ bool WiimoteScanner::IsReady() const
// Connect to a wiimote with a known device path.
bool Wiimote::Connect()
{
// This is where we disallow connecting to the same device twice
if (g_connected_devices.count(devicepath))
return false;
dev_handle = CreateFile(devicepath.c_str(),
(GENERIC_READ | GENERIC_WRITE),
/*(FILE_SHARE_READ | FILE_SHARE_WRITE)*/ 0,
// TODO: Just do FILE_SHARE_READ and remove "g_connected_devices"?
// That is what "WiiYourself" does.
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (dev_handle == INVALID_HANDLE_VALUE)
@ -247,11 +267,12 @@ bool Wiimote::Connect()
return false;
}
hid_overlap = OVERLAPPED();
hid_overlap.hEvent = CreateEvent(NULL, 1, 1, _T(""));
hid_overlap.Offset = 0;
hid_overlap.OffsetHigh = 0;
// TODO: 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
// reside is normal priority. Needed for keeping audio reports at a decent rate
/*
@ -261,15 +282,17 @@ bool Wiimote::Connect()
}
*/
g_connected_devices.insert(devicepath);
return true;
}
void Wiimote::Disconnect()
{
g_connected_devices.erase(devicepath);
CloseHandle(dev_handle);
dev_handle = 0;
//ResetEvent(&hid_overlap);
CloseHandle(hid_overlap.hEvent);
}
@ -283,50 +306,73 @@ bool Wiimote::IsConnected() const
// zero = error
int Wiimote::IORead(unsigned char* buf)
{
// used below for a warning
*buf = 0;
DWORD b;
if (!ReadFile(dev_handle, buf, MAX_PAYLOAD, &b, &hid_overlap))
DWORD bytes;
ResetEvent(hid_overlap.hEvent);
if (!ReadFile(dev_handle, buf, MAX_PAYLOAD - 1, &bytes, &hid_overlap))
{
// Partial read
b = GetLastError();
if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED))
auto const err = GetLastError();
if (ERROR_IO_PENDING == err)
{
auto const r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
if (WAIT_TIMEOUT == r)
{
// Timeout - cancel and continue
if (*buf)
WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).",
WIIMOTE_DEFAULT_TIMEOUT);
CancelIo(dev_handle);
bytes = -1;
}
else if (WAIT_FAILED == r)
{
WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1);
bytes = 0;
}
else if (WAIT_OBJECT_0 == r)
{
if (!GetOverlappedResult(dev_handle, &hid_overlap, &bytes, TRUE))
{
WARN_LOG(WIIMOTE, "GetOverlappedResult failed on wiimote %i.", index + 1);
bytes = 0;
}
}
else
{
bytes = 0;
}
}
else if (ERROR_HANDLE_EOF == err)
{
// Remote disconnect
return 0;
bytes = 0;
}
auto const r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
if (r == WAIT_TIMEOUT)
else if (ERROR_DEVICE_NOT_CONNECTED == err)
{
// Timeout - cancel and continue
if (*buf)
WARN_LOG(WIIMOTE, "Packet ignored. This may indicate a problem (timeout is %i ms).",
WIIMOTE_DEFAULT_TIMEOUT);
CancelIo(dev_handle);
ResetEvent(hid_overlap.hEvent);
return -1;
// Remote disconnect
bytes = 0;
}
else if (r == WAIT_FAILED)
else
{
WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1);
return -1;
}
if (!GetOverlappedResult(dev_handle, &hid_overlap, &b, 0))
{
return -1;
bytes = 0;
}
}
// This needs to be done even if ReadFile fails, essential during init
// Move the data over one, so we can add back in data report indicator byte (here, 0xa1)
memmove(buf + 1, buf, MAX_PAYLOAD - 1);
buf[0] = 0xa1;
if (bytes > 0)
{
// Move the data over one, so we can add back in data report indicator byte (here, 0xa1)
memmove(buf + 1, buf, MAX_PAYLOAD - 1);
buf[0] = 0xa1;
ResetEvent(hid_overlap.hEvent);
return MAX_PAYLOAD; // XXX
// TODO: is this really needed?
bytes = MAX_PAYLOAD;
}
return bytes;
}
int Wiimote::IOWrite(const u8* buf, int len)
@ -392,14 +438,12 @@ int Wiimote::IOWrite(const u8* buf, int len)
return 0;
}
// WiiMote Pair-Up, function will return amount of either new paired or unpaired devices
// negative number on failure
int PairUp(bool unpair)
// invokes callback for each found wiimote bluetooth device
template <typename T>
void ProcessWiimotes(bool new_scan, T& callback)
{
// match strings like "Nintendo RVL-WBC-01", "Nintendo RVL-CNT-01", "Nintendo RVL-CNT-01-TR"
const std::wregex wiimote_device_name(L"Nintendo RVL-\\w{3}-\\d{2}(-\\w{2})?");
int nPaired = 0;
const std::wregex wiimote_device_name(L"Nintendo RVL-.*");
BLUETOOTH_DEVICE_SEARCH_PARAMS srch;
srch.dwSize = sizeof(srch);
@ -409,7 +453,7 @@ int PairUp(bool unpair)
// fConnected BT Devices
srch.fReturnConnected = true;
srch.fReturnUnknown = true;
srch.fIssueInquiry = true;
srch.fIssueInquiry = new_scan;
// multiple of 1.28 seconds
srch.cTimeoutMultiplier = 1;
@ -418,14 +462,10 @@ int PairUp(bool unpair)
HANDLE hRadio;
// TODO: save radio(s) in the WiimoteScanner constructor
// TODO: save radio(s) in the WiimoteScanner constructor?
// Enumerate BT radios
HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio);
if (NULL == hFindRadio)
return -1;
while (hFindRadio)
{
BLUETOOTH_RADIO_INFO radioInfo;
@ -449,40 +489,7 @@ int PairUp(bool unpair)
if (std::regex_match(btdi.szName, wiimote_device_name))
{
if (unpair)
{
if (SUCCEEDED(Bth_BluetoothRemoveDevice(&btdi.Address)))
{
NOTICE_LOG(WIIMOTE,
"Pair-Up: Automatically removed BT Device on shutdown: %08x",
GetLastError());
++nPaired;
}
}
else
{
if (false == btdi.fConnected)
{
// TODO: improve the read of the BT driver, esp. when batteries
// of the wiimote are removed while being fConnected
if (btdi.fRemembered)
{
// Make Windows forget old expired pairing. We can pretty
// much ignore the return value here. It either worked
// (ERROR_SUCCESS), or the device did not exist
// (ERROR_NOT_FOUND). In both cases, there is nothing left.
Bth_BluetoothRemoveDevice(&btdi.Address);
}
// Activate service
const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi,
&HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
if (SUCCEEDED(hr))
++nPaired;
else
ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr);
}
}
callback(hRadio, btdi);
}
if (false == Bth_BluetoothFindNextDevice(hFindDevice, &btdi))
@ -498,8 +505,53 @@ int PairUp(bool unpair)
hFindRadio = NULL;
}
}
}
return nPaired;
void RemoveWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
//if (btdi.fConnected)
{
if (SUCCEEDED(Bth_BluetoothRemoveDevice(&btdi.Address)))
{
NOTICE_LOG(WIIMOTE, "Removed BT Device", GetLastError());
}
}
}
bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
if (!btdi.fConnected && !btdi.fRemembered)
{
NOTICE_LOG(WIIMOTE, "Found wiimote. Enabling HID service.");
// Activate service
const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi,
&HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
if (FAILED(hr))
ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr);
else
return true;
}
return false;
}
// Removes remembered non-connected devices
bool ForgetWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{
if (!btdi.fConnected && btdi.fRemembered)
{
// We don't want "remembered" devices.
// SetServiceState seems to just fail with them.
// Make Windows forget about them.
NOTICE_LOG(WIIMOTE, "Removing remembered wiimote.");
Bth_BluetoothRemoveDevice(&btdi.Address);
return true;
}
return false;
}
};

View File

@ -111,7 +111,10 @@ WiimoteScanner::WiimoteScanner()
WiimoteScanner::~WiimoteScanner()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
void WiimoteScanner::Update()
{}
std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{
// TODO: find the device in the constructor and save it for later
@ -130,7 +133,7 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
}
sbt = [[SearchBT alloc] init];
sbt->maxDevices = max_wiimotes;
sbt->maxDevices = 32;
bti = [[IOBluetoothDeviceInquiry alloc] init];
[bti setDelegate: sbt];
[bti setInquiryLength: 2];
@ -157,9 +160,6 @@ std::vector<Wiimote*> WiimoteScanner::FindWiimotes(size_t max_wiimotes)
Wiimote *wm = new Wiimote();
wm->btd = dev;
wiimotes.push_back(wm);
if(wiimotes.size() >= max_wiimotes)
break;
}
[bth release];

View File

@ -35,7 +35,7 @@ namespace WiimoteReal
{
void HandleFoundWiimotes(const std::vector<Wiimote*>&);
void HandleWiimoteConnect(Wiimote*);
void TryToConnectWiimote(Wiimote*);
void HandleWiimoteDisconnect(int index);
bool g_real_wiimotes_initialized = false;
@ -171,7 +171,10 @@ bool Wiimote::Read()
rpt.second = IORead(rpt.first);
if (0 == rpt.second)
{
WARN_LOG(WIIMOTE, "Wiimote::IORead failed. Disconnecting wiimote %d.", index + 1);
Disconnect();
}
if (rpt.second > 0 && m_channel > 0)
{
@ -192,12 +195,12 @@ bool Wiimote::Write()
bool const is_speaker_data = rpt.first[1] == WM_WRITE_SPEAKER_DATA;
if (!is_speaker_data || last_audio_report.GetTimeDifference() > 5)
if (!is_speaker_data || m_last_audio_report.GetTimeDifference() > 5)
{
IOWrite(rpt.first, rpt.second);
if (is_speaker_data)
last_audio_report.Update();
m_last_audio_report.Update();
delete[] rpt.first;
m_write_reports.Pop();
@ -242,27 +245,24 @@ void Wiimote::Update()
delete[] rpt.first;
}
// Rumble briefly
void Wiimote::RumbleBriefly()
bool Wiimote::Prepare(int _index)
{
unsigned char buffer = 0x01;
DEBUG_LOG(WIIMOTE, "Starting rumble...");
QueueReport(WM_CMD_RUMBLE, &buffer, sizeof(buffer));
index = _index;
SLEEP(200);
// Set the active LEDs.
u8 const led_report[] = {HID_TYPE_SET_REPORT, WM_CMD_LED, WIIMOTE_LED_1 << index};
DEBUG_LOG(WIIMOTE, "Stopping rumble...");
buffer = 0x00;
QueueReport(WM_CMD_RUMBLE, &buffer, sizeof(buffer));
}
// Rumble briefly
u8 rumble_report[] = {HID_TYPE_SET_REPORT, WM_CMD_RUMBLE, 1};
// Set the active LEDs.
// leds is a bitwise OR of WIIMOTE_LED_1 through WIIMOTE_LED_4.
void Wiimote::SetLEDs(int new_leds)
{
// Remove the lower 4 bits because they control rumble
u8 const buffer = (new_leds & 0xF0);
QueueReport(WM_CMD_LED, &buffer, sizeof(buffer));
// don't really care what is read, just that reading works
u8 input_buf[MAX_PAYLOAD];
// TODO: request status and check for sane response?
return (IOWrite(led_report, sizeof(led_report))
&& IOWrite(rumble_report, sizeof(rumble_report))
&& (rumble_report[2] = 0, SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report))));
}
void Wiimote::EmuStart()
@ -290,48 +290,66 @@ unsigned int CalculateWantedWiimotes()
return wanted_wiimotes;
}
void WiimoteScanner::WantWiimotes(size_t count)
void WiimoteScanner::WantWiimotes(bool do_want)
{
want_wiimotes = count;
m_want_wiimotes = do_want;
}
void WiimoteScanner::StartScanning()
{
run_thread = true;
m_run_thread = true;
if (IsReady())
{
scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this);
m_scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this);
}
}
void WiimoteScanner::StopScanning()
{
run_thread = false;
if (scan_thread.joinable())
m_run_thread = false;
if (m_scan_thread.joinable())
{
scan_thread.join();
m_scan_thread.join();
}
}
void CheckForDisconnectedWiimotes()
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected())
HandleWiimoteDisconnect(i);
}
void WiimoteScanner::ThreadFunc()
{
Common::SetCurrentThreadName("Wiimote Scanning Thread");
NOTICE_LOG(WIIMOTE, "Wiimote scanning has started");
while (run_thread)
while (m_run_thread)
{
auto const found_wiimotes = FindWiimotes(want_wiimotes);
HandleFoundWiimotes(found_wiimotes);
#if 1
std::vector<Wiimote*> found_wiimotes;
//NOTICE_LOG(WIIMOTE, "in loop");
if (m_want_wiimotes)
found_wiimotes = FindWiimotes();
else
{
// TODO: this code here is ugly
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected())
HandleWiimoteDisconnect(i);
// Does stuff needed to detect disconnects on Windows
Update();
}
#endif
//NOTICE_LOG(WIIMOTE, "after update");
// TODO: this is a fairly lame place for this
CheckForDisconnectedWiimotes();
HandleFoundWiimotes(found_wiimotes);
//std::this_thread::yield();
Common::SleepCurrentThread(500);
}
@ -396,8 +414,7 @@ void Initialize()
if (g_real_wiimotes_initialized)
return;
auto const wanted_wiimotes = CalculateWantedWiimotes();
g_wiimote_scanner.WantWiimotes(wanted_wiimotes);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.StartScanning();
@ -431,26 +448,23 @@ void ChangeWiimoteSource(unsigned int index, int source)
if (!(WIIMOTE_SRC_REAL & g_wiimote_sources[index]))
HandleWiimoteDisconnect(index);
auto const wanted_wiimotes = CalculateWantedWiimotes();
g_wiimote_scanner.WantWiimotes(wanted_wiimotes);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
}
void HandleWiimoteConnect(Wiimote* wm)
void TryToConnectWiimote(Wiimote* wm)
{
std::lock_guard<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 (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i]
&& wm->Connect()
&& wm->Prepare(i))
{
g_wiimotes[i] = wm;
wm->index = i;
wm->StartThread();
wm->DisableDataReporting();
wm->SetLEDs(WIIMOTE_LED_1 << i);
wm->RumbleBriefly();
Host_ConnectWiimote(i, true);
@ -463,14 +477,12 @@ void HandleWiimoteConnect(Wiimote* wm)
delete wm;
auto const want_wiimotes = CalculateWantedWiimotes();
g_wiimote_scanner.WantWiimotes(want_wiimotes);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
}
void HandleWiimoteDisconnect(int index)
{
// locked above
//std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
Host_ConnectWiimote(index, false);
@ -482,19 +494,12 @@ void HandleWiimoteDisconnect(int index)
NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1);
}
auto const want_wiimotes = CalculateWantedWiimotes();
g_wiimote_scanner.WantWiimotes(want_wiimotes);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
}
void HandleFoundWiimotes(const std::vector<Wiimote*>& wiimotes)
{
std::for_each(wiimotes.begin(), wiimotes.end(), [](Wiimote* const wm)
{
if (wm->Connect())
HandleWiimoteConnect(wm);
else
delete wm;
});
std::for_each(wiimotes.begin(), wiimotes.end(), TryToConnectWiimote);
}
// This is called from the GUI thread
@ -504,14 +509,13 @@ void Refresh()
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
CheckForDisconnectedWiimotes();
auto wanted_wiimotes = CalculateWantedWiimotes();
auto const found_wiimotes = g_wiimote_scanner.FindWiimotes(wanted_wiimotes);
HandleFoundWiimotes(found_wiimotes);
wanted_wiimotes = CalculateWantedWiimotes();
g_wiimote_scanner.WantWiimotes(wanted_wiimotes);
if (0 != CalculateWantedWiimotes())
{
HandleFoundWiimotes(g_wiimote_scanner.FindWiimotes());
}
}
g_wiimote_scanner.StartScanning();

View File

@ -63,14 +63,16 @@ public:
void EmuStop();
// connecting and disconnecting from physical devices
// (using address inserted by FindWiimotes)
// FYI, Connect/Disconnect are not thread safe even between unique objects (on windows)
bool Connect();
void Disconnect();
// TODO: change to something like IsRelevant
bool IsConnected() const;
void SetLEDs(int leds);
void RumbleBriefly();
bool Prepare(int index);
void DisableDataReporting();
@ -116,7 +118,7 @@ private:
Common::FifoQueue<Report> m_read_reports;
Common::FifoQueue<Report> m_write_reports;
Common::Timer last_audio_report;
Common::Timer m_last_audio_report;
};
class WiimoteScanner
@ -127,22 +129,23 @@ public:
bool IsReady() const;
void WantWiimotes(size_t count);
void WantWiimotes(bool do_want);
void StartScanning();
void StopScanning();
std::vector<Wiimote*> FindWiimotes(size_t max_wiimotes);
std::vector<Wiimote*> FindWiimotes();
// function called when not looking for more wiimotes
void Update();
private:
void ThreadFunc();
std::thread scan_thread;
std::thread m_scan_thread;
volatile bool run_thread;
// TODO: this should probably be atomic
volatile size_t want_wiimotes;
volatile bool m_run_thread;
volatile bool m_want_wiimotes;
#if defined(_WIN32)

View File

@ -66,8 +66,9 @@
// End Wiimote internal codes
#define MAX_PAYLOAD 32
#define WIIMOTE_DEFAULT_TIMEOUT 30
// It's 23. NOT 32!
#define MAX_PAYLOAD 23
#define WIIMOTE_DEFAULT_TIMEOUT 1000
#ifdef _WIN32
// Available bluetooth stacks for Windows.