Futile attempts at fixing Windows.

This commit is contained in:
Jordan Woyak 2013-02-13 14:00:15 -06:00
parent 77381a1af2
commit e57ff06130
1 changed files with 50 additions and 59 deletions

View File

@ -19,7 +19,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <regex> #include <regex>
#include <algorithm> #include <algorithm>
#include <unordered_set> #include <unordered_map>
#include <ctime>
#include <windows.h> #include <windows.h>
#include <dbt.h> #include <dbt.h>
@ -75,8 +76,7 @@ HINSTANCE bthprops_lib = NULL;
static int initialized = 0; static int initialized = 0;
std::mutex g_connected_devices_lock; std::unordered_map<BTH_ADDR, std::time_t> g_connect_times;
static std::unordered_set<std::string> g_connected_devices;
inline void init_lib() inline void init_lib()
{ {
@ -173,60 +173,50 @@ void WiimoteScanner::Update()
// Returns the total number of found and connected wiimotes. // Returns the total number of found and connected wiimotes.
std::vector<Wiimote*> WiimoteScanner::FindWiimotes() std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
{ {
bool attached_some; ProcessWiimotes(true, [](HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
ProcessWiimotes(true, [&](HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{ {
ForgetWiimote(hRadio, btdi); ForgetWiimote(hRadio, btdi);
attached_some |= AttachWiimote(hRadio, btdi); AttachWiimote(hRadio, btdi);
}); });
// Hacks...
if (attached_some)
SLEEP(2000);
GUID device_id;
HDEVINFO device_info;
DWORD len;
SP_DEVICE_INTERFACE_DATA device_data;
PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
device_data.cbSize = sizeof(device_data);
// Get the device id // Get the device id
GUID device_id;
HidD_GetHidGuid(&device_id); HidD_GetHidGuid(&device_id);
// Get all hid devices connected // Get all hid devices connected
device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
std::vector<Wiimote*> wiimotes; std::vector<Wiimote*> wiimotes;
for (int index = 0; true; ++index)
SP_DEVICE_INTERFACE_DATA device_data;
device_data.cbSize = sizeof(device_data);
PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL;
for (int index = 0; SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data); ++index)
{ {
free(detail_data);
detail_data = NULL;
// Query the next hid device info
if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data))
break;
// Get the size of the data block required // Get the size of the data block required
DWORD len;
SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL);
detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len);
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// Query the data for this device // Query the data for this device
if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL))
continue; {
auto const wm = new Wiimote;
wm->devicepath = detail_data->DevicePath;
wiimotes.push_back(wm);
}
auto const wm = new Wiimote; free(detail_data);
wm->devicepath = detail_data->DevicePath;
wiimotes.push_back(wm);
} }
free(detail_data);
SetupDiDestroyDeviceInfoList(device_info); SetupDiDestroyDeviceInfoList(device_info);
// Don't mind me, just a random sleep to fix stuff on Windows
//if (!wiimotes.empty())
// SLEEP(2000);
return wiimotes; return wiimotes;
} }
@ -254,17 +244,14 @@ bool WiimoteScanner::IsReady() const
// Connect to a wiimote with a known device path. // Connect to a wiimote with a known device path.
bool Wiimote::Connect() bool Wiimote::Connect()
{ {
std::lock_guard<std::mutex> lk(g_connected_devices_lock); if (IsConnected())
// This is where we disallow connecting to the same device twice
if (g_connected_devices.count(devicepath))
return false; return false;
dev_handle = CreateFile(devicepath.c_str(), dev_handle = CreateFile(devicepath.c_str(),
(GENERIC_READ | GENERIC_WRITE), GENERIC_READ | GENERIC_WRITE,
// TODO: Just do FILE_SHARE_READ and remove "g_connected_devices"? // Having no FILE_SHARE_WRITE disallows us from connecting to the same wiimote twice.
// That is what "WiiYourself" does. // This is what "WiiYourself" does.
(FILE_SHARE_READ | FILE_SHARE_WRITE), FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (dev_handle == INVALID_HANDLE_VALUE) if (dev_handle == INVALID_HANDLE_VALUE)
@ -299,15 +286,13 @@ bool Wiimote::Connect()
ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority"); ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority");
} }
*/ */
g_connected_devices.insert(devicepath);
return true; return true;
} }
void Wiimote::Disconnect() void Wiimote::Disconnect()
{ {
std::lock_guard<std::mutex> lk(g_connected_devices_lock); if (!IsConnected())
g_connected_devices.erase(devicepath); return;
CloseHandle(dev_handle); CloseHandle(dev_handle);
dev_handle = 0; dev_handle = 0;
@ -385,7 +370,7 @@ int Wiimote::IORead(u8* buf)
if (bytes > 0) if (bytes > 0)
{ {
// Move the data over one, so we can add back in data report indicator byte (here, 0xa1) // Move the data over one, so we can add back in data report indicator byte (here, 0xa1)
memmove(buf + 1, buf, MAX_PAYLOAD - 1); std::copy_n(buf, MAX_PAYLOAD - 1, buf + 1);
buf[0] = 0xa1; buf[0] = 0xa1;
// TODO: is this really needed? // TODO: is this really needed?
@ -408,11 +393,7 @@ int Wiimote::IOWrite(const u8* buf, int len)
stack = MSBT_STACK_MS; stack = MSBT_STACK_MS;
if (IOWrite(buf, len)) if (IOWrite(buf, len))
{
// Don't mind me, just a random sleep to fix stuff on Windows
SLEEP(1000);
return 1; return 1;
}
stack = MSBT_STACK_UNKNOWN; stack = MSBT_STACK_UNKNOWN;
break; break;
@ -553,6 +534,8 @@ void RemoveWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{ {
// We don't want "remembered" devices.
// SetServiceState will just fail with them..
if (!btdi.fConnected && !btdi.fRemembered) if (!btdi.fConnected && !btdi.fRemembered)
{ {
NOTICE_LOG(WIIMOTE, "Found wiimote. Enabling HID service."); NOTICE_LOG(WIIMOTE, "Found wiimote. Enabling HID service.");
@ -561,6 +544,8 @@ bool AttachWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi, const DWORD hr = Bth_BluetoothSetServiceState(hRadio, &btdi,
&HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE); &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE);
g_connect_times[btdi.Address.ullLong] = std::time(nullptr);
if (FAILED(hr)) if (FAILED(hr))
ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr); ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr);
else else
@ -575,14 +560,20 @@ bool ForgetWiimote(HANDLE, BLUETOOTH_DEVICE_INFO_STRUCT& btdi)
{ {
if (!btdi.fConnected && btdi.fRemembered) if (!btdi.fConnected && btdi.fRemembered)
{ {
// We don't want "remembered" devices. // Time to avoid RemoveDevice after SetServiceState.
// SetServiceState seems to just fail with them. // Sometimes SetServiceState takes a while..
// Make Windows forget about them. auto const avoid_forget_seconds = 5.0;
// This is also required to detect a disconnect for some reason..
NOTICE_LOG(WIIMOTE, "Removing remembered wiimote.");
Bth_BluetoothRemoveDevice(&btdi.Address);
return true; auto pair_time = g_connect_times.find(btdi.Address.ullLong);
if (pair_time == g_connect_times.end()
|| std::difftime(time(nullptr), pair_time->second) >= avoid_forget_seconds)
{
// Make Windows forget about device so it will re-find it if visible.
// This is also required to detect a disconnect for some reason..
NOTICE_LOG(WIIMOTE, "Removing remembered wiimote.");
Bth_BluetoothRemoveDevice(&btdi.Address);
return true;
}
} }
return false; return false;