summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2013-02-11 15:21:58 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2013-02-11 15:21:58 -0600
commitc2d2fb8c7c84ab2abf439f1ccdafd44d71b41b64 (patch)
treed0b6a4380c9645ae0298a0f643a1f5a79178990f /Source
parentb8fd5c0c307aa45f846b4ec412e05608d0e93e41 (diff)
Try to improve real wiimotes on Windows.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp124
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp56
-rw-r--r--Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h2
3 files changed, 111 insertions, 71 deletions
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
index d9b6a665ef..d6bc5dd28b 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
@@ -270,10 +270,22 @@ bool Wiimote::Connect()
return false;
}
- hid_overlap = OVERLAPPED();
- hid_overlap.hEvent = CreateEvent(NULL, 1, 1, _T(""));
- hid_overlap.Offset = 0;
- hid_overlap.OffsetHigh = 0;
+#if 0
+ HIDD_ATTRIBUTES attr;
+ attr.Size = sizeof(attr);
+ if (!HidD_GetAttributes(dev_handle, &attr))
+ {
+ CloseHandle(dev_handle);
+ dev_handle = 0;
+ return false;
+ }
+#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
@@ -296,7 +308,8 @@ void Wiimote::Disconnect()
CloseHandle(dev_handle);
dev_handle = 0;
- CloseHandle(hid_overlap.hEvent);
+ CloseHandle(hid_overlap_read.hEvent);
+ CloseHandle(hid_overlap_write.hEvent);
}
bool Wiimote::IsConnected() const
@@ -307,20 +320,20 @@ bool Wiimote::IsConnected() const
// positive = read packet
// negative = didn't read packet
// zero = error
-int Wiimote::IORead(unsigned char* buf)
+int Wiimote::IORead(u8* buf)
{
// used below for a warning
*buf = 0;
DWORD bytes;
- ResetEvent(hid_overlap.hEvent);
- if (!ReadFile(dev_handle, buf, MAX_PAYLOAD - 1, &bytes, &hid_overlap))
+ ResetEvent(hid_overlap_read.hEvent);
+ if (!ReadFile(dev_handle, buf, MAX_PAYLOAD - 1, &bytes, &hid_overlap_read))
{
auto const err = GetLastError();
if (ERROR_IO_PENDING == err)
{
- auto const r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
+ auto const r = WaitForSingleObject(hid_overlap_read.hEvent, WIIMOTE_DEFAULT_TIMEOUT);
if (WAIT_TIMEOUT == r)
{
// Timeout - cancel and continue
@@ -338,7 +351,7 @@ int Wiimote::IORead(unsigned char* buf)
}
else if (WAIT_OBJECT_0 == r)
{
- if (!GetOverlappedResult(dev_handle, &hid_overlap, &bytes, TRUE))
+ if (!GetOverlappedResult(dev_handle, &hid_overlap_read, &bytes, TRUE))
{
WARN_LOG(WIIMOTE, "GetOverlappedResult failed on wiimote %i.", index + 1);
bytes = 0;
@@ -380,70 +393,76 @@ int Wiimote::IORead(unsigned char* buf)
int Wiimote::IOWrite(const u8* buf, int len)
{
- u8 big_buf[MAX_PAYLOAD];
- if (len < MAX_PAYLOAD)
- {
- std::copy(buf, buf + len, big_buf);
- std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
- buf = big_buf;
- }
-
- DWORD bytes = 0;
switch (stack)
{
case MSBT_STACK_UNKNOWN:
{
// Try to auto-detect the stack type
-
- auto i = WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap);
- if (i)
- {
- // Bluesoleil will always return 1 here, even if it's not connected
- stack = MSBT_STACK_BLUESOLEIL;
- return i;
- }
+ stack = MSBT_STACK_BLUESOLEIL;
+ if (IOWrite(buf, len))
+ return 1;
- i = HidD_SetOutputReport(dev_handle, (unsigned char*) buf + 1, len - 1);
- if (i)
+ stack = MSBT_STACK_MS;
+ if (IOWrite(buf, len))
{
- stack = MSBT_STACK_MS;
- return i;
+ // Don't mind me, just a random sleep to fix stuff on Windows
+ SLEEP(1000);
+ return 1;
}
- auto const dw = GetLastError();
- // Checking for 121 = timeout on semaphore/device off/disconnected to
- // avoid trouble with other stacks toshiba/widcomm
- if (dw == 121)
- {
- NOTICE_LOG(WIIMOTE, "IOWrite[MSBT_STACK_UNKNOWN]: Timeout");
- return 0;
- }
- else
- {
- ERROR_LOG(WIIMOTE, "IOWrite[MSBT_STACK_UNKNOWN]: ERROR: %08x", dw);
- return 0;
- }
+ stack = MSBT_STACK_UNKNOWN;
break;
}
case MSBT_STACK_MS:
{
- auto i = HidD_SetOutputReport(dev_handle, (unsigned char*) buf + 1, len - 1);
- auto dw = GetLastError();
+ auto result = HidD_SetOutputReport(dev_handle, const_cast<u8*>(buf) + 1, len - 1);
+ //FlushFileBuffers(dev_handle);
- if (dw == 121)
+ if (!result)
{
- // Semaphore timeout
- NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote");
- return 0;
+ auto err = GetLastError();
+ if (err == 121)
+ {
+ // Semaphore timeout
+ NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote");
+ }
+ else
+ {
+ ERROR_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err);
+ }
}
- return i;
+ return result;
break;
}
case MSBT_STACK_BLUESOLEIL:
- return WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap);
+ {
+ u8 big_buf[MAX_PAYLOAD];
+ if (len < MAX_PAYLOAD)
+ {
+ std::copy(buf, buf + len, big_buf);
+ std::fill(big_buf + len, big_buf + MAX_PAYLOAD, 0);
+ buf = big_buf;
+ }
+
+ ResetEvent(hid_overlap_write.hEvent);
+ DWORD bytes = 0;
+ if (WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap_write))
+ {
+ // WriteFile always returns true with bluesoleil.
+ return 1;
+ }
+ else
+ {
+ auto const err = GetLastError();
+ if (ERROR_IO_PENDING == err)
+ {
+ CancelIo(dev_handle);
+ }
+ }
break;
}
+ }
return 0;
}
@@ -555,6 +574,7 @@ bool ForgetWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
// We don't want "remembered" devices.
// SetServiceState seems to just fail with them.
// Make Windows forget about them.
+ // This is also required to detect a disconnect for some reason..
NOTICE_LOG(WIIMOTE, "Removing remembered wiimote.");
Bth_BluetoothRemoveDevice(&btdi.Address);
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
index e006ec1f69..6e9a72eb00 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
@@ -232,6 +232,12 @@ Report Wiimote::ProcessReadQueue()
void Wiimote::Update()
{
+ if (!IsConnected())
+ {
+ HandleWiimoteDisconnect(index);
+ return;
+ }
+
// Pop through the queued reports
Report const rpt = ProcessReadQueue();
@@ -252,18 +258,17 @@ bool Wiimote::Prepare(int _index)
// core buttons, no continuous reporting
u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_REPORT_TYPE, 0, 0x30};
- // Set the active LEDs.
- u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index)};
+ // Set the active LEDs and turn on rumble.
+ u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index) | 0x1};
- // Rumble briefly
- u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 1};
+ // Turn off rumble
+ u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 0};
// TODO: request status and check for sane response?
return (IOWrite(mode_report, sizeof(mode_report))
&& IOWrite(led_report, sizeof(led_report))
- && IOWrite(rumble_report, sizeof(rumble_report))
- && (rumble_report[2] = 0, SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report))));
+ && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report))));
}
void Wiimote::EmuStart()
@@ -375,6 +380,8 @@ void Wiimote::ThreadFunc()
{
Common::SetCurrentThreadName("Wiimote Device Thread");
+ Host_ConnectWiimote(index, true);
+
// main loop
while (m_run_thread && IsConnected())
{
@@ -408,13 +415,13 @@ void LoadSettings()
void Initialize()
{
- NOTICE_LOG(WIIMOTE, "WiimoteReal::Initialize");
-
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
if (g_real_wiimotes_initialized)
return;
+ NOTICE_LOG(WIIMOTE, "WiimoteReal::Initialize");
+
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.StartScanning();
@@ -423,9 +430,7 @@ void Initialize()
}
void Shutdown(void)
-{
- NOTICE_LOG(WIIMOTE, "WiimoteReal::Shutdown");
-
+{
g_wiimote_scanner.StopScanning();
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
@@ -433,6 +438,8 @@ void Shutdown(void)
if (!g_real_wiimotes_initialized)
return;
+ NOTICE_LOG(WIIMOTE, "WiimoteReal::Shutdown");
+
g_real_wiimotes_initialized = false;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
@@ -466,8 +473,6 @@ void TryToConnectWiimote(Wiimote* wm)
g_wiimotes[i] = wm;
wm->StartThread();
-
- Host_ConnectWiimote(i, true);
NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1);
@@ -485,8 +490,6 @@ void HandleWiimoteDisconnect(int index)
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
- Host_ConnectWiimote(index, false);
-
if (g_wiimotes[index])
{
delete g_wiimotes[index];
@@ -511,12 +514,24 @@ void Refresh()
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
- CheckForDisconnectedWiimotes();
+ std::vector<Wiimote*> found_wiimotes;
if (0 != CalculateWantedWiimotes())
{
- HandleFoundWiimotes(g_wiimote_scanner.FindWiimotes());
+ found_wiimotes = g_wiimote_scanner.FindWiimotes();
+ }
+
+ CheckForDisconnectedWiimotes();
+
+ // Brief rumble for already connected wiimotes.
+ for (int i = 0; i != MAX_WIIMOTES; ++i)
+ {
+ // kinda sloppy
+ if (g_wiimotes[i])
+ g_wiimotes[i]->Prepare(i);
}
+
+ HandleFoundWiimotes(found_wiimotes);
}
g_wiimote_scanner.StartScanning();
@@ -546,8 +561,13 @@ void Update(int _WiimoteNumber)
if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->Update();
- else
+
+ // Wiimote::Update() may remove the wiimote if it was disconnected.
+ if (!g_wiimotes[_WiimoteNumber])
+ {
+ NOTICE_LOG(WIIMOTE, "Emulating disconnect of wiimote %d.", _WiimoteNumber + 1);
Host_ConnectWiimote(_WiimoteNumber, false);
+ }
}
void StateChange(EMUSTATE_CHANGE newState)
diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
index 4b8f4365d3..55fc552abd 100644
--- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
+++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
@@ -96,7 +96,7 @@ public:
std::string devicepath; // Unique wiimote reference
//ULONGLONG btaddr; // Bluetooth address
HANDLE dev_handle; // HID handle
- OVERLAPPED hid_overlap; // Overlap handle
+ OVERLAPPED hid_overlap_read, hid_overlap_write; // Overlap handle
enum win_bt_stack_t stack; // Type of bluetooth stack to use
#endif