From b2acae44b780ecf86ffb88cd32861edb25642e20 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 15 Jan 2013 21:15:54 -0600 Subject: [PATCH 01/37] Real wiimote continuous scanning working on Linux. Windows and OS X totally broken from various refactoring. --- Source/Core/Core/Src/HW/Wiimote.h | 2 +- .../Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp | 2 +- .../Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp | 2 +- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 229 ++++++------- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 312 ++++++++++++------ .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 73 +++- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 16 +- 7 files changed, 370 insertions(+), 266 deletions(-) diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h index 5e0ab8d05e..d514cf9909 100644 --- a/Source/Core/Core/Src/HW/Wiimote.h +++ b/Source/Core/Core/Src/HW/Wiimote.h @@ -38,7 +38,7 @@ void Update(int _number); namespace WiimoteReal { -unsigned int Initialize(); +void Initialize(); void Shutdown(); void Refresh(); diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 5c34fff9ac..cfb81bb768 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -248,7 +248,7 @@ void Wiimote::RequestStatus(const wm_request_status* const rs) { using namespace WiimoteReal; - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[m_index]) { diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index b7652e973a..30fad4b458 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -685,7 +685,7 @@ void Wiimote::Update() { using namespace WiimoteReal; - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[m_index]) { Report rpt = g_wiimotes[m_index]->ProcessReadQueue(); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index ec838d9313..82630aaebb 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -15,16 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include -#include - -#include -#include -#include -#include -#include -#include - #include #include #include @@ -32,114 +22,117 @@ #include "Common.h" #include "WiimoteReal.h" -#include "Host.h" namespace WiimoteReal { +WiimoteScanner::WiimoteScanner() + : run_thread() + , want_wiimotes() + , device_id(-1) + , device_sock(-1) +{ + // Get the id of the first bluetooth device. + device_id = hci_get_route(NULL); + if (device_id < 0) + { + NOTICE_LOG(WIIMOTE, "Bluetooth not found."); + return; + } + + // Create a socket to the device + device_sock = hci_open_dev(device_id); + if (device_sock < 0) + { + ERROR_LOG(WIIMOTE, "Unable to open bluetooth."); + return; + } +} + +bool WiimoteScanner::IsReady() const +{ + return device_sock > 0; +} + +WiimoteScanner::~WiimoteScanner() +{ + if (IsReady()) + 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. -int FindWiimotes(Wiimote** wm, int max_wiimotes) +std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) { - int device_id; - int device_sock; - int found_devices; - int found_wiimotes = 0; - int i; + std::vector found_wiimotes; - // Count the number of already found wiimotes - for (i = 0; i < MAX_WIIMOTES; ++i) - { - if (wm[i]) - found_wiimotes++; - } + // supposedly 1.28 seconds + int const wait_len = 1; - // Get the id of the first bluetooth device. - if ((device_id = hci_get_route(NULL)) < 0) + int const max_infos = 255; + inquiry_info scan_infos[max_infos] = {}; + auto* scan_infos_ptr = scan_infos; + + // Scan for bluetooth devices + int const found_devices = hci_inquiry(device_id, wait_len, max_infos, NULL, &scan_infos_ptr, IREQ_CACHE_FLUSH); + if (found_devices < 0) { - NOTICE_LOG(WIIMOTE, "Bluetooth not found."); + ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices."); return found_wiimotes; } - // Create a socket to the device - if ((device_sock = hci_open_dev(device_id)) < 0) - { - ERROR_LOG(WIIMOTE, "Unable to open bluetooth."); - return found_wiimotes; - } + DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); - int try_num = 0; - while ((try_num < 5) && (found_wiimotes < max_wiimotes)) + // Display discovered devices + for (int i = 0; (i < found_devices) && (found_wiimotes.size() < max_wiimotes); ++i) { - inquiry_info scan_info_arr[128]; - inquiry_info* scan_info = scan_info_arr; - memset(&scan_info_arr, 0, sizeof(scan_info_arr)); - - // Scan for bluetooth devices for approximately one second - found_devices = hci_inquiry(device_id, 1, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); - if (found_devices < 0) + ERROR_LOG(WIIMOTE, "found a device..."); + + // BT names are a maximum of 248 bytes apparently + char name[255] = {}; + if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 0) < 0) { - ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices."); - return found_wiimotes; + ERROR_LOG(WIIMOTE, "name request failed"); + continue; } - DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); - - // Display discovered devices - for (i = 0; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) + ERROR_LOG(WIIMOTE, "device name %s", name); + if (IsValidBluetoothName(name)) { - char name[1000]; - memset(name, 0, sizeof(name)); - ERROR_LOG(WIIMOTE, "found a device..."); - if (hci_read_remote_name(device_sock, &scan_info[i].bdaddr, sizeof(name), name, 0) < 0) { - ERROR_LOG(WIIMOTE, "name request failed"); - continue; - } - ERROR_LOG(WIIMOTE, "device name %s", name); - if (IsValidBluetoothName(name)) + bool new_wiimote = true; + + // TODO: do this + + // Determine if this wiimote has already been found. + //for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j) + //{ + // if (wm[j] && bacmp(&scan_infos[i].bdaddr,&wm[j]->bdaddr) == 0) + // new_wiimote = false; + //} + + if (new_wiimote) { - bool new_wiimote = true; - // Determine if this wiimote has already been found. - for (int j = 0; j < MAX_WIIMOTES && new_wiimote; ++j) - { - if (wm[j] && bacmp(&scan_info[i].bdaddr,&wm[j]->bdaddr) == 0) - new_wiimote = false; - } + // Found a new device + char bdaddr_str[18] = {}; + ba2str(&scan_infos[i].bdaddr, bdaddr_str); - if (new_wiimote) - { - // Find an unused slot - unsigned int k = 0; - for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k); - wm[k] = new Wiimote(k); - - // Found a new device - char bdaddr_str[18]; - ba2str(&scan_info[i].bdaddr, bdaddr_str); - - NOTICE_LOG(WIIMOTE, "Found wiimote %i, (%s).", - wm[k]->index + 1, bdaddr_str); - - wm[k]->bdaddr = scan_info[i].bdaddr; - ++found_wiimotes; - } + auto* const wm = new Wiimote; + wm->bdaddr = scan_infos[i].bdaddr; + found_wiimotes.push_back(wm); + + NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str); } } - try_num++; } - close(device_sock); return found_wiimotes; } // Connect to a wiimote with a known address. -bool Wiimote::Connect() +bool Wiimote::Open() { - if (IsConnected()) - return false; - sockaddr_l2 addr; addr.l2_family = AF_BLUETOOTH; addr.l2_bdaddr = bdaddr; @@ -148,7 +141,7 @@ bool Wiimote::Connect() // Output channel addr.l2_psm = htobs(WM_OUTPUT_CHANNEL); if ((cmd_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 || - connect(cmd_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + connect(cmd_sock, (sockaddr*)&addr, sizeof(addr)) < 0) { DEBUG_LOG(WIIMOTE, "Unable to open output socket to wiimote."); close(cmd_sock); @@ -159,7 +152,7 @@ bool Wiimote::Connect() // Input channel addr.l2_psm = htobs(WM_INPUT_CHANNEL); if ((int_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) == -1 || - connect(int_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) + connect(int_sock, (sockaddr*)&addr, sizeof(addr)) < 0) { DEBUG_LOG(WIIMOTE, "Unable to open input socket from wiimote."); close(int_sock); @@ -168,57 +161,37 @@ bool Wiimote::Connect() return false; } - NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); - - m_connected = true; - - // Do the handshake - Handshake(); - - // Set LEDs - SetLEDs(WIIMOTE_LED_1 << index); - - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); - return true; } -// Disconnect a wiimote. -void Wiimote::RealDisconnect() +void Wiimote::StartThread() { - if (!IsConnected()) - return; - - NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i.", index + 1); - - m_connected = false; + m_run_thread = true; + m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); +} +void Wiimote::StopThread() +{ + m_run_thread = false; if (m_wiimote_thread.joinable()) m_wiimote_thread.join(); - - Close(); } void Wiimote::Close() { - if (IsOpen()) - { - Host_ConnectWiimote(index, false); + close(cmd_sock); + close(int_sock); - close(cmd_sock); - close(int_sock); - - cmd_sock = -1; - int_sock = -1; - } + cmd_sock = -1; + int_sock = -1; } bool Wiimote::IsOpen() const { - return IsConnected() && cmd_sock != -1 && int_sock != -1; + return cmd_sock != -1;// && int_sock != -1; } -int Wiimote::IORead(unsigned char *buf) +int Wiimote::IORead(u8* buf) { // Block select for 1/2000th of a second timeval tv; @@ -232,11 +205,11 @@ int Wiimote::IORead(unsigned char *buf) if (select(int_sock + 1, &fds, NULL, NULL, &tv) == -1) { ERROR_LOG(WIIMOTE, "Unable to select wiimote %i input socket.", index + 1); - return 0; + return -1; } if (!FD_ISSET(int_sock, &fds)) - return 0; + return -1; // Read the pending message into the buffer int r = read(int_sock, buf, MAX_PAYLOAD); @@ -250,21 +223,15 @@ int Wiimote::IORead(unsigned char *buf) // This can happen if the bluetooth dongle is disconnected ERROR_LOG(WIIMOTE, "Bluetooth appears to be disconnected. " "Wiimote %i will be disconnected.", index + 1); - Close(); } - return 0; - } - else if (!r) - { - // Disconnect - Close(); + r = 0; } return r; } -int Wiimote::IOWrite(unsigned char* buf, int len) +int Wiimote::IOWrite(u8 const* buf, int len) { return write(int_sock, buf, len); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 2381793f30..2735c1a312 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -23,6 +23,7 @@ #include "IniFile.h" #include "StringUtil.h" #include "Timer.h" +#include "Host.h" #include "WiimoteReal.h" @@ -33,15 +34,20 @@ unsigned int g_wiimote_sources[MAX_WIIMOTES]; namespace WiimoteReal { +void HandleFoundWiimotes(const std::vector&); +void HandleWiimoteConnect(Wiimote*); +void HandleWiimoteDisconnect(int index); + bool g_real_wiimotes_initialized = false; -unsigned int g_wiimotes_found = 0; -std::mutex g_refresh_lock; +std::recursive_mutex g_refresh_lock; -Wiimote *g_wiimotes[MAX_WIIMOTES]; +Wiimote* g_wiimotes[MAX_WIIMOTES]; -Wiimote::Wiimote(const unsigned int _index) - : index(_index) +WiimoteScanner g_wiimote_scanner; + +Wiimote::Wiimote() + : index() #ifdef __APPLE__ , inputlen(0) #elif defined(__linux__) && HAVE_BLUEZ @@ -49,8 +55,8 @@ Wiimote::Wiimote(const unsigned int _index) #elif defined(_WIN32) , dev_handle(0), stack(MSBT_STACK_UNKNOWN) #endif - , leds(0), m_last_data_report(Report((u8 *)NULL, 0)) - , m_channel(0), m_connected(false) + , m_last_data_report(Report((u8 *)NULL, 0)) + , m_channel(0), m_run_thread(false) { #if defined(__linux__) && HAVE_BLUEZ bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}}; @@ -61,8 +67,11 @@ Wiimote::Wiimote(const unsigned int _index) Wiimote::~Wiimote() { - RealDisconnect(); + StopThread(); + if (IsOpen()) + Close(); + ClearReadQueue(); // clear write queue @@ -111,7 +120,7 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3 { // Check for custom communication if (99 == channel) - Disconnect(); + EmuStop(); else { InterruptChannel(channel, data, size); @@ -168,6 +177,9 @@ bool Wiimote::Read() rpt.first = new unsigned char[MAX_PAYLOAD]; rpt.second = IORead(rpt.first); + if (0 == rpt.second) + Close(); + if (rpt.second > 0 && m_channel > 0) { // Add it to queue m_read_reports.Push(rpt); @@ -234,24 +246,18 @@ void Wiimote::Update() delete[] rpt.first; } -void Wiimote::Disconnect() +void Wiimote::EmuStop() { m_channel = 0; DisableDataReporting(); -} -bool Wiimote::IsConnected() const -{ - return m_connected; + NOTICE_LOG(WIIMOTE, "Stopping wiimote data reporting"); } // Rumble briefly void Wiimote::Rumble() { - if (!IsConnected()) - return; - unsigned char buffer = 0x01; DEBUG_LOG(WIIMOTE, "Starting rumble..."); SendRequest(WM_CMD_RUMBLE, &buffer, 1); @@ -264,37 +270,29 @@ void Wiimote::Rumble() } // Set the active LEDs. -// leds is a bitwise or of WIIMOTE_LED_1 through WIIMOTE_LED_4. +// leds is a bitwise OR of WIIMOTE_LED_1 through WIIMOTE_LED_4. void Wiimote::SetLEDs(int new_leds) { - unsigned char buffer; - - if (!IsConnected()) - return; - // Remove the lower 4 bits because they control rumble - buffer = leds = (new_leds & 0xF0); - + u8 const buffer = (new_leds & 0xF0); SendRequest(WM_CMD_LED, &buffer, 1); } -// Send a handshake -bool Wiimote::Handshake() +bool Wiimote::EmuStart() { + // Send a handshake + // Set buffer[0] to 0x04 for continuous reporting - unsigned char buffer[2] = {0x04, 0x30}; + u8 const buffer[2] = {0x04, 0x30}; - if (!IsConnected()) - return 0; - - DEBUG_LOG(WIIMOTE, "Sending handshake to wiimote"); + NOTICE_LOG(WIIMOTE, "Sending handshake to wiimote"); return SendRequest(WM_CMD_REPORT_TYPE, buffer, 2); } // Send a packet to the wiimote. // report_type should be one of WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc. -bool Wiimote::SendRequest(unsigned char report_type, unsigned char* data, int length) +bool Wiimote::SendRequest(u8 report_type, u8 const* data, int length) { unsigned char buffer[32] = {WM_SET_REPORT | WM_BT_OUTPUT, report_type}; @@ -303,59 +301,99 @@ bool Wiimote::SendRequest(unsigned char report_type, unsigned char* data, int le return (IOWrite(buffer, length + 2) != 0); } +unsigned int CalculateWantedWiimotes() +{ + // Figure out how many real wiimotes are required + unsigned int wanted_wiimotes = 0; + for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i]) + ++wanted_wiimotes; + + return wanted_wiimotes; +} + +void WiimoteScanner::WantWiimotes(size_t count) +{ + want_wiimotes = count; +} + +void WiimoteScanner::StartScanning() +{ + run_thread = true; + scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this); +} + +void WiimoteScanner::StopScanning() +{ + run_thread = false; + if (scan_thread.joinable()) + { + scan_thread.join(); + NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped"); + } +} + +void WiimoteScanner::ThreadFunc() +{ + Common::SetCurrentThreadName("Wiimote Scanning Thread"); + + NOTICE_LOG(WIIMOTE, "Wiimote scanning has started"); + + while (run_thread) + { + auto const found_wiimotes = FindWiimotes(want_wiimotes); + HandleFoundWiimotes(found_wiimotes); +#if 1 + { + // TODO: this code here is ugly + std::lock_guard lk(g_refresh_lock); + for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + if (g_wiimotes[i] && !g_wiimotes[i]->IsOpen()) + HandleWiimoteDisconnect(i); + } +#endif + //std::this_thread::yield(); + Common::SleepCurrentThread(500); + } +} + void Wiimote::ThreadFunc() { - char thname[] = "Wiimote # Thread"; - thname[8] = (char)('1' + index); - Common::SetCurrentThreadName(thname); + Common::SetCurrentThreadName("Wiimote Device Thread"); // rumble briefly Rumble(); // main loop - while (IsOpen()) + while (m_run_thread && IsOpen()) { #ifdef __APPLE__ while (Write()) {} Common::SleepCurrentThread(1); #else - bool read = false; - while (Write() || (read = true, IsOpen() && Read())) + // TODO: this is all a mess + while (m_run_thread && IsOpen()) { - if (m_audio_reports.Size() && !read) - Read(); - Common::SleepCurrentThread(m_audio_reports.Size() ? 5 : 2); - read = false; + bool const did_write = Write(); + + if (did_write) + break; + else + if (!Read()) + break; + + // TODO: what is this doing? + //if (m_audio_reports.Size() && did_write) + // Read(); + + // TODO: make work well + //Common::SleepCurrentThread(m_audio_reports.Size() ? 5 : 2); + Common::SleepCurrentThread(2); } #endif } } -#ifndef _WIN32 -// Connect all discovered wiimotes -// Return the number of wiimotes that successfully connected. -static int ConnectWiimotes(Wiimote** wm) -{ - int connected = 0; - - for (int i = 0; i < MAX_WIIMOTES; ++i) - { - if (!wm[i] || wm[i]->IsConnected()) - continue; - - if (wm[i]->Connect()) - ++connected; - else - { - delete wm[i]; - wm[i] = NULL; - } - } - - return connected; -} -#endif - void LoadSettings() { std::string ini_filename = File::GetUserPath(D_CONFIG_IDX) + WIIMOTE_INI_NAME ".ini"; @@ -373,71 +411,124 @@ void LoadSettings() } } -unsigned int Initialize() +void Initialize() { - // Return if already initialized + NOTICE_LOG(WIIMOTE, "WiimoteReal::Initialize"); + + std::lock_guard lk(g_refresh_lock); + if (g_real_wiimotes_initialized) - return g_wiimotes_found; + return; - memset(g_wiimotes, 0, sizeof(g_wiimotes)); + auto const wanted_wiimotes = CalculateWantedWiimotes(); + g_wiimote_scanner.WantWiimotes(wanted_wiimotes); - // Only call FindWiimotes with the number of slots configured for real wiimotes - unsigned int wanted_wiimotes = 0; - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) - ++wanted_wiimotes; + //if (wanted_wiimotes > 0) + g_wiimote_scanner.StartScanning(); - // Don't bother initializing if we don't want any real wiimotes - if (0 == wanted_wiimotes) - { - g_wiimotes_found = 0; - return 0; - } - - // Initialized g_real_wiimotes_initialized = true; - - g_wiimotes_found = FindWiimotes(g_wiimotes, wanted_wiimotes); - - DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", - g_wiimotes_found, wanted_wiimotes); - -#ifndef _WIN32 - atexit(WiimoteReal::Shutdown); - g_wiimotes_found = ConnectWiimotes(g_wiimotes); -#endif - - DEBUG_LOG(WIIMOTE, "Connected to %i Real Wiimotes", g_wiimotes_found); - - return g_wiimotes_found; } void Shutdown(void) { - if (false == g_real_wiimotes_initialized) + NOTICE_LOG(WIIMOTE, "WiimoteReal::Shutdown"); + + g_wiimote_scanner.StopScanning(); + + std::lock_guard lk(g_refresh_lock); + + if (!g_real_wiimotes_initialized) return; - // Uninitialized g_real_wiimotes_initialized = false; - // Delete wiimotes for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (g_wiimotes[i]) + HandleWiimoteDisconnect(i); +} + +void ChangeWiimoteSource(unsigned int index, int source) +{ + std::lock_guard lk(g_refresh_lock); + + g_wiimote_sources[index] = source; + + // source is emulated, kill any real connection + if (!(WIIMOTE_SRC_REAL & g_wiimote_sources[index])) + HandleWiimoteDisconnect(index); + + auto const wanted_wiimotes = CalculateWantedWiimotes(); + g_wiimote_scanner.WantWiimotes(wanted_wiimotes); +} + +void HandleWiimoteConnect(Wiimote* wm) +{ + std::lock_guard lk(g_refresh_lock); + + for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + { + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i]) { - delete g_wiimotes[i]; - g_wiimotes[i] = NULL; + g_wiimotes[i] = wm; + + wm->index = i; + wm->StartThread(); + wm->SetLEDs(WIIMOTE_LED_1 << i); + + Host_ConnectWiimote(i, true); + + NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1); + + wm = NULL; + break; } + } + + delete wm; + + auto const want_wiimotes = CalculateWantedWiimotes(); + g_wiimote_scanner.WantWiimotes(want_wiimotes); +} + +void HandleWiimoteDisconnect(int index) +{ + // locked above + //std::lock_guard lk(g_refresh_lock); + + Host_ConnectWiimote(index, false); + + if (g_wiimotes[index]) + { + delete g_wiimotes[index]; + g_wiimotes[index] = NULL; + + NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1); + } + + auto const want_wiimotes = CalculateWantedWiimotes(); + g_wiimote_scanner.WantWiimotes(want_wiimotes); +} + +void HandleFoundWiimotes(const std::vector& wiimotes) +{ + std::for_each(wiimotes.begin(), wiimotes.end(), [](Wiimote* const wm) + { + if (wm->Open()) + HandleWiimoteConnect(wm); + else + delete wm; + }); } // This is called from the GUI thread void Refresh() { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); #ifdef _WIN32 Shutdown(); Initialize(); #else +/* // Make sure real wiimotes have been initialized if (!g_real_wiimotes_initialized) { @@ -477,12 +568,13 @@ void Refresh() g_wiimotes_found = num_wiimotes; } +*/ #endif } void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); @@ -490,7 +582,7 @@ void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u3 void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); @@ -500,7 +592,7 @@ void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 // Read the Wiimote once void Update(int _WiimoteNumber) { - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->Update(); @@ -508,7 +600,7 @@ void Update(int _WiimoteNumber) void StateChange(EMUSTATE_CHANGE newState) { - //std::lock_guard lk(g_refresh_lock); + //std::lock_guard lk(g_refresh_lock); // TODO: disable/enable auto reporting, maybe } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 9fdb305a56..5f8206bf14 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -20,6 +20,7 @@ #define WIIMOTE_REAL_H #include +#include #include "WiimoteRealBase.h" #include "ChunkFile.h" @@ -41,7 +42,7 @@ class Wiimote : NonCopyable { friend class WiimoteEmu::Wiimote; public: - Wiimote(const unsigned int _index); + Wiimote(); ~Wiimote(); void ControlChannel(const u16 channel, const void* const data, const u32 size); @@ -52,16 +53,28 @@ public: bool Read(); bool Write(); - bool Connect(); - bool IsConnected() const; + + void StartThread(); + void StopThread(); + + // "handshake" / stop packets + bool EmuStart(); + void EmuStop(); + + // connecting and disconnecting from physical devices + bool Open(); + void Close(); + + // TODO: change to something like IsRelevant bool IsOpen() const; - void Disconnect(); + + void SetLEDs(int leds); + void DisableDataReporting(); void Rumble(); void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size); - void RealDisconnect(); - const unsigned int index; + int index; #if defined(__APPLE__) IOBluetoothDevice *btd; @@ -74,8 +87,6 @@ public: int cmd_sock; // Command socket int int_sock; // Interrupt socket - void Close(); - #elif defined(_WIN32) char devicepath[255]; // Unique wiimote reference //ULONGLONG btaddr; // Bluetooth address @@ -83,7 +94,6 @@ public: OVERLAPPED hid_overlap; // Overlap handle enum win_bt_stack_t stack; // Type of bluetooth stack to use #endif - unsigned char leds; // Currently lit leds protected: Report m_last_data_report; @@ -91,21 +101,51 @@ protected: private: void ClearReadQueue(); - bool SendRequest(unsigned char report_type, unsigned char* data, int length); - bool Handshake(); - void SetLEDs(int leds); - int IORead(unsigned char* buf); - int IOWrite(unsigned char* buf, int len); + bool SendRequest(u8 report_type, u8 const* data, int length); + + int IORead(u8* buf); + int IOWrite(u8 const* buf, int len); + void ThreadFunc(); - bool m_connected; + bool m_run_thread; std::thread m_wiimote_thread; + Common::FifoQueue m_read_reports; Common::FifoQueue m_write_reports; Common::FifoQueue m_audio_reports; }; -extern std::mutex g_refresh_lock; +class WiimoteScanner +{ +public: + WiimoteScanner(); + ~WiimoteScanner(); + + bool IsReady() const; + + void WantWiimotes(size_t count); + + void StartScanning(); + void StopScanning(); + + std::vector FindWiimotes(size_t max_wiimotes); + +private: + void ThreadFunc(); + + std::thread scan_thread; + + volatile bool run_thread; + + // TODO: this should probably be atomic + volatile size_t want_wiimotes; + + int device_id; + int device_sock; +}; + +extern std::recursive_mutex g_refresh_lock; extern Wiimote *g_wiimotes[4]; void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); @@ -116,6 +156,7 @@ void DoState(PointerWrap &p); void StateChange(EMUSTATE_CHANGE newState); int FindWiimotes(Wiimote** wm, int max_wiimotes); +void ChangeWiimoteSource(unsigned int index, int source); bool IsValidBluetoothName(const std::string& name); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index ea23e532e7..ba2186d17a 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -4,11 +4,12 @@ #include "HW/WiimoteReal/WiimoteReal.h" #include "Frame.h" -const wxString& ConnectedWiimotesString() +wxString ConnectedWiimotesString() { - static wxString str; - str.Printf(_("%i connected"), WiimoteReal::Initialize()); - return str; + //static wxString str; + //str.Printf(_("%i connected"), WiimoteReal::Initialize()); + //return str; + return "TODO: this text"; } WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin) @@ -222,13 +223,16 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) // This needs to be changed now in order for refresh to work right. // Revert if the dialog is canceled. int index = m_wiimote_index_from_ctrl_id[event.GetId()]; - g_wiimote_sources[index] = event.GetInt(); + + WiimoteReal::ChangeWiimoteSource(index, event.GetInt()); + if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID) wiimote_configure_bt[index]->Disable(); else wiimote_configure_bt[index]->Enable(); } +// TODO: race conditiions void WiimoteConfigDiag::UpdateWiimoteStatus() { for (int index = 0; index < 4; ++index) @@ -241,7 +245,7 @@ void WiimoteConfigDiag::UpdateWiimoteStatus() if (WIIMOTE_SRC_EMU & g_wiimote_sources[index]) CFrame::ConnectWiimote(index, true); else if (WIIMOTE_SRC_REAL & g_wiimote_sources[index] && WiimoteReal::g_wiimotes[index]) - CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsConnected()); + CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsOpen()); } } } From 54497be653dfdf2de558426cf460a8b8a96bd524 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 15 Jan 2013 22:57:25 -0600 Subject: [PATCH 02/37] Untested Windows buildfix attempt. --- .../Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 16 +- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 6 +- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 213 ++++++++---------- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 19 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 14 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 13 +- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 2 +- 7 files changed, 139 insertions(+), 144 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index 49afee8ad1..b22f1c7795 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -21,9 +21,19 @@ namespace WiimoteReal { -int FindWiimotes(Wiimote **wm, int max_wiimotes) +WiimoteScanner::WiimoteScanner() { - return 0; + return; +} + +std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) +{ + return std::vector() +} + +bool WiimoteScanner::IsReady() const +{ + return false; } bool Wiimote::Connect() @@ -31,7 +41,7 @@ bool Wiimote::Connect() return 0; } -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { return; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 82630aaebb..24e25e9a2b 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -131,7 +131,7 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) } // Connect to a wiimote with a known address. -bool Wiimote::Open() +bool Wiimote::Connect() { sockaddr_l2 addr; addr.l2_family = AF_BLUETOOTH; @@ -177,7 +177,7 @@ void Wiimote::StopThread() m_wiimote_thread.join(); } -void Wiimote::Close() +void Wiimote::Disconnect() { close(cmd_sock); close(int_sock); @@ -186,7 +186,7 @@ void Wiimote::Close() int_sock = -1; } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { return cmd_sock != -1;// && int_sock != -1; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index cc05bc10e1..f862193ff9 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -127,12 +127,21 @@ inline void init_lib() namespace WiimoteReal { +WiimoteScanner::WiimoteScanner() +{ + init_lib(); +} + // 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. -int FindWiimotes(Wiimote** wm, int max_wiimotes) +std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) { + PairUp(); + + std::vector wiimotes; + GUID device_id; HANDLE dev; HDEVINFO device_info; @@ -142,8 +151,6 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes) PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; HIDD_ATTRIBUTES attr; - init_lib(); - // Count the number of already found wiimotes for (int i = 0; i < MAX_WIIMOTES; ++i) { @@ -207,22 +214,11 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes) // Find an unused slot unsigned int k = 0; - for (; k < MAX_WIIMOTES && !(WIIMOTE_SRC_REAL & g_wiimote_sources[k] && !wm[k]); ++k); - wm[k] = new Wiimote(k); - wm[k]->dev_handle = dev; - memcpy(wm[k]->devicepath, detail_data->DevicePath, 197); + auto const wm = new Wiimote; + wm->dev_handle = dev; + memcpy(wm->devicepath, detail_data->DevicePath, 197); - if (!wm[k]->Connect()) - { - ERROR_LOG(WIIMOTE, "Unable to connect to wiimote %i.", wm[k]->index + 1); - delete wm[k]; - wm[k] = NULL; - CloseHandle(dev); - } - else - { - ++found_wiimotes; - } + found_wiimotes.push_back(wm); } if (detail_data) @@ -233,87 +229,64 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes) return found_wiimotes; } +bool WiimoteScanner::IsReady() const +{ + // TODO: impl + return true; +} + // Connect to a wiimote with a known device path. bool Wiimote::Connect() { - if (IsConnected()) return false; + dev_handle = CreateFile(devicepath, + (GENERIC_READ | GENERIC_WRITE), + (FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (!dev_handle) + if (dev_handle == INVALID_HANDLE_VALUE) { - dev_handle = CreateFile(devicepath, - (GENERIC_READ | GENERIC_WRITE), - (FILE_SHARE_READ | FILE_SHARE_WRITE), - NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (dev_handle == INVALID_HANDLE_VALUE) - return false; + dev_handle = 0; + return false; } hid_overlap.hEvent = CreateEvent(NULL, 1, 1, _T("")); hid_overlap.Offset = 0; hid_overlap.OffsetHigh = 0; - m_connected = true; - - // Try a handshake to see if the device is actually connected - if (!Handshake()) - { - m_connected = false; - return false; - } - - // Set LEDs - SetLEDs(WIIMOTE_LED_1 << index); - - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); - + // TODO: 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 +/* if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL)) { ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority"); } - - NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); +*/ return true; } -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { - if (!IsConnected()) - return; - - m_connected = false; - - if (m_wiimote_thread.joinable()) - m_wiimote_thread.join(); - CloseHandle(dev_handle); dev_handle = 0; - ResetEvent(&hid_overlap); + //ResetEvent(&hid_overlap); + CloseHandle(hid_overlap.hEvent); } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { - return IsConnected(); + return dev_handle != 0; } int Wiimote::IORead(unsigned char* buf) { - DWORD b, r; - - init_lib(); - - if (!IsConnected()) - return 0; - - *buf = 0; + //*buf = 0; if (!ReadFile(dev_handle, buf, MAX_PAYLOAD, &b, &hid_overlap)) { // Partial read - b = GetLastError(); - + auto const b = GetLastError(); if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) { // Remote disconnect @@ -321,7 +294,7 @@ int Wiimote::IORead(unsigned char* buf) return 0; } - r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT); + auto const r = WaitForSingleObject(hid_overlap.hEvent, WIIMOTE_DEFAULT_TIMEOUT); if (r == WAIT_TIMEOUT) { // Timeout - cancel and continue @@ -357,77 +330,71 @@ int Wiimote::IORead(unsigned char* buf) int Wiimote::IOWrite(unsigned char* buf, int len) { - DWORD bytes, dw; - int i; - - init_lib(); - - if (!IsConnected()) - return 0; - switch (stack) { - case MSBT_STACK_UNKNOWN: - { - // Try to auto-detect the stack type - if (i = WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap)) - { - // Bluesoleil will always return 1 here, even if it's not connected - stack = MSBT_STACK_BLUESOLEIL; - return i; - } - - if (i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1)) - { - stack = MSBT_STACK_MS; - return i; - } - - 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"); - RealDisconnect(); - } - else ERROR_LOG(WIIMOTE, - "IOWrite[MSBT_STACK_UNKNOWN]: ERROR: %08x", dw); - return 0; - } - - case MSBT_STACK_MS: - i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1); - dw = GetLastError(); - - if (dw == 121) - { - // Semaphore timeout - NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote"); - RealDisconnect(); - return 0; - } + case MSBT_STACK_UNKNOWN: + { + // Try to auto-detect the stack type + DWORD bytes = 0; + auto i = WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); + if (i) + { + // Bluesoleil will always return 1 here, even if it's not connected + stack = MSBT_STACK_BLUESOLEIL; return i; + } - case MSBT_STACK_BLUESOLEIL: - return WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); + i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1); + if (i) + { + stack = MSBT_STACK_MS; + return i; + } + + 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); + // Correct? + return -1 + } + break; + } + case MSBT_STACK_MS: + { + i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1); + dw = GetLastError(); + + if (dw == 121) + { + // Semaphore timeout + NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote"); + RealDisconnect(); + return 0; + } + + return i; + break; + } + case MSBT_STACK_BLUESOLEIL: + return WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); + break; } return 0; } -int UnPair() -{ - // TODO: - return 0; -} - // WiiMote Pair-Up, function will return amount of either new paired or unpaired devices // negative number on failure int PairUp(bool unpair) { - init_lib(); - // 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})?"); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 64de880180..95068fe650 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -10,6 +10,19 @@ } @end +WiimoteScanner::WiimoteScanner() +{} + +std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) +{ + return std::vector(); +} + +bool WiimoteScanner::IsReady() const +{ + return false; +} + @implementation SearchBT - (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender error: (IOReturn) error @@ -92,7 +105,7 @@ WARN_LOG(WIIMOTE, "Lost channel to wiimote %i", wm->index + 1); - wm->RealDisconnect(); + wm->Disconnect(); } @end @@ -182,7 +195,7 @@ bool Wiimote::Connect() if (ichan == NULL || cchan == NULL) { ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels " "for wiimote %i", index + 1); - RealDisconnect(); + Disconnect(); return false; } @@ -207,7 +220,7 @@ bool Wiimote::Connect() } // Disconnect a wiimote. -void Wiimote::RealDisconnect() +void Wiimote::Disconnect() { if (!IsConnected()) return; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 2735c1a312..d25a78490d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -69,8 +69,8 @@ Wiimote::~Wiimote() { StopThread(); - if (IsOpen()) - Close(); + if (IsConnected()) + Disconnect(); ClearReadQueue(); @@ -178,7 +178,7 @@ bool Wiimote::Read() rpt.second = IORead(rpt.first); if (0 == rpt.second) - Close(); + Disconnect(); if (rpt.second > 0 && m_channel > 0) { // Add it to queue @@ -348,7 +348,7 @@ void WiimoteScanner::ThreadFunc() // TODO: this code here is ugly std::lock_guard lk(g_refresh_lock); for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) - if (g_wiimotes[i] && !g_wiimotes[i]->IsOpen()) + if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected()) HandleWiimoteDisconnect(i); } #endif @@ -365,14 +365,14 @@ void Wiimote::ThreadFunc() Rumble(); // main loop - while (m_run_thread && IsOpen()) + while (m_run_thread && IsConnected()) { #ifdef __APPLE__ while (Write()) {} Common::SleepCurrentThread(1); #else // TODO: this is all a mess - while (m_run_thread && IsOpen()) + while (m_run_thread && IsConnected()) { bool const did_write = Write(); @@ -512,7 +512,7 @@ void HandleFoundWiimotes(const std::vector& wiimotes) { std::for_each(wiimotes.begin(), wiimotes.end(), [](Wiimote* const wm) { - if (wm->Open()) + if (wm->Connect()) HandleWiimoteConnect(wm); else delete wm; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 5f8206bf14..4c65768666 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -62,11 +62,11 @@ public: void EmuStop(); // connecting and disconnecting from physical devices - bool Open(); - void Close(); + bool Connect(); + void Disconnect(); // TODO: change to something like IsRelevant - bool IsOpen() const; + bool IsConnected() const; void SetLEDs(int leds); @@ -141,8 +141,13 @@ private: // TODO: this should probably be atomic volatile size_t want_wiimotes; +#if defined(_WIN32) + + +#elif defined(__linux__) && HAVE_BLUEZ int device_id; - int device_sock; + int device_sock; +#endif }; extern std::recursive_mutex g_refresh_lock; diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index ba2186d17a..b259cde2b9 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -245,7 +245,7 @@ void WiimoteConfigDiag::UpdateWiimoteStatus() if (WIIMOTE_SRC_EMU & g_wiimote_sources[index]) CFrame::ConnectWiimote(index, true); else if (WIIMOTE_SRC_REAL & g_wiimote_sources[index] && WiimoteReal::g_wiimotes[index]) - CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsOpen()); + CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsConnected()); } } } From 62f56eb731fa66f8613438777d13941626be3fa5 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 15 Jan 2013 23:05:30 -0600 Subject: [PATCH 03/37] Sloppily fix wiimotes not being connected after boot. --- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index d25a78490d..516fa3a51e 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -596,6 +596,8 @@ void Update(int _WiimoteNumber) if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->Update(); + else + Host_ConnectWiimote(_WiimoteNumber, false); } void StateChange(EMUSTATE_CHANGE newState) From 246b11791bb415060eba52ee415c116ea64322ff Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 16 Jan 2013 16:14:23 -0600 Subject: [PATCH 04/37] More attempts at a Windows buildfix. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 43 ++++++++++--------- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 24 ++--------- Source/Core/DolphinWX/Src/WiimoteConfigDiag.h | 3 -- 3 files changed, 25 insertions(+), 45 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index f862193ff9..e285a33729 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -151,13 +151,6 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; HIDD_ATTRIBUTES attr; - // Count the number of already found wiimotes - for (int i = 0; i < MAX_WIIMOTES; ++i) - { - if (wm[i]) - found_wiimotes++; - } - device_data.cbSize = sizeof(device_data); // Get the device id @@ -187,19 +180,6 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) continue; - // Determine if this wiimote has already been found. - bool found = false; - for(int i = 0; i < MAX_WIIMOTES; i++) - { - if(wm[i] && strcmp(wm[i]->devicepath, detail_data->DevicePath) == 0) - { - found = true; - break; - } - } - if (found) - continue; - // Open new device dev = CreateFile(detail_data->DevicePath, (GENERIC_READ | GENERIC_WRITE), @@ -391,6 +371,26 @@ int Wiimote::IOWrite(unsigned char* buf, int len) return 0; } +// return true if a device using MS BT stack is available +bool CanPairUp() +{ + BLUETOOTH_FIND_RADIO_PARAMS radioParam; + radioParam.dwSize = sizeof(radioParam); + + HANDLE hRadio; + HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio); + + if (NULL != hFindRadio) + { + Bth_BluetoothFindRadioClose(hFindRadio); + return true; + } + else + { + return false; + } +} + // WiiMote Pair-Up, function will return amount of either new paired or unpaired devices // negative number on failure int PairUp(bool unpair) @@ -409,7 +409,8 @@ int PairUp(bool unpair) srch.fReturnConnected = true; srch.fReturnUnknown = true; srch.fIssueInquiry = true; - srch.cTimeoutMultiplier = 2; // == (2 * 1.28) seconds + // multiple of 1.28 seconds + srch.cTimeoutMultiplier = 1; BLUETOOTH_FIND_RADIO_PARAMS radioParam; radioParam.dwSize = sizeof(radioParam); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index b259cde2b9..d38eadb0e1 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -71,11 +71,11 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this); #ifdef _WIN32 - wxButton* const pairup_btn = new wxButton(this, -1, _("Pair Up"), wxDefaultPosition); - pairup_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::PairUpRealWiimotes, this); + //wxButton* const pairup_btn = new wxButton(this, -1, _("Pair Up"), wxDefaultPosition); + //pairup_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::PairUpRealWiimotes, this); + // TODO: text if can't Pair #endif - // "Real wiimotes" layout wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Real Wiimotes")); wxFlexGridSizer* const real_wiimotes_sizer = new wxFlexGridSizer(3, 5, 5); @@ -194,24 +194,6 @@ void WiimoteConfigDiag::UpdateGUI() connected_wiimotes_txt->SetLabel(ConnectedWiimotesString()); } -#ifdef _WIN32 -void WiimoteConfigDiag::PairUpRealWiimotes(wxCommandEvent&) -{ - const int paired = WiimoteReal::PairUp(); - - if (paired > 0) - { - // TODO: Maybe add a label of newly paired up wiimotes? - WiimoteReal::Refresh(); - UpdateGUI(); - } - else if (paired < 0) - PanicAlertT("A supported bluetooth device could not be found!\n" - "If you are not using Microsoft's bluetooth stack " - "you must manually pair your wiimotes and use only the \"Refresh\" button."); -} -#endif - void WiimoteConfigDiag::RefreshRealWiimotes(wxCommandEvent&) { WiimoteReal::Refresh(); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index 2b2e60de4a..fbd715bd40 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -24,9 +24,6 @@ class WiimoteConfigDiag : public wxDialog public: WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin); -#ifdef _WIN32 - void PairUpRealWiimotes(wxCommandEvent& event); -#endif void RefreshRealWiimotes(wxCommandEvent& event); From 8f5fb7e6f98b3283b5f3688e15cdab30fe842eef Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 14:15:47 -0600 Subject: [PATCH 05/37] Hopefully buildfix Windows. (thanks for the patch, RachelB) --- Source/Core/Core/Src/HW/Wiimote.h | 5 ---- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 13 -------- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 30 +++++++++++-------- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 13 ++++++++ Source/Core/DolphinWX/Src/Main.cpp | 4 --- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 2 +- 6 files changed, 32 insertions(+), 35 deletions(-) diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h index d514cf9909..dd0e6df389 100644 --- a/Source/Core/Core/Src/HW/Wiimote.h +++ b/Source/Core/Core/Src/HW/Wiimote.h @@ -44,11 +44,6 @@ void Refresh(); void LoadSettings(); -#ifdef _WIN32 -int PairUp(bool unpair = false); -int UnPair(); -#endif - } #endif diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 24e25e9a2b..2d3ed01e6d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -164,19 +164,6 @@ bool Wiimote::Connect() return true; } -void Wiimote::StartThread() -{ - m_run_thread = true; - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); -} - -void Wiimote::StopThread() -{ - m_run_thread = false; - if (m_wiimote_thread.joinable()) - m_wiimote_thread.join(); -} - void Wiimote::Disconnect() { close(cmd_sock); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index e285a33729..77555bae86 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -73,6 +73,8 @@ HINSTANCE bthprops_lib = NULL; static int initialized = 0; +int PairUp(bool unpair); + inline void init_lib() { if (!initialized) @@ -132,6 +134,9 @@ WiimoteScanner::WiimoteScanner() init_lib(); } +WiimoteScanner::~WiimoteScanner() +{} + // Find and connect wiimotes. // Does not replace already found wiimotes even if they are disconnected. // wm is an array of max_wiimotes wiimotes @@ -198,7 +203,7 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) wm->dev_handle = dev; memcpy(wm->devicepath, detail_data->DevicePath, 197); - found_wiimotes.push_back(wm); + wiimotes.push_back(wm); } if (detail_data) @@ -206,7 +211,7 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) SetupDiDestroyDeviceInfoList(device_info); - return found_wiimotes; + return wiimotes; } bool WiimoteScanner::IsReady() const @@ -262,15 +267,15 @@ bool Wiimote::IsConnected() const int Wiimote::IORead(unsigned char* buf) { - //*buf = 0; + DWORD b; if (!ReadFile(dev_handle, buf, MAX_PAYLOAD, &b, &hid_overlap)) { // Partial read - auto const b = GetLastError(); + b = GetLastError(); if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) { // Remote disconnect - RealDisconnect(); + Disconnect(); return 0; } @@ -308,14 +313,15 @@ int Wiimote::IORead(unsigned char* buf) return MAX_PAYLOAD; // XXX } -int Wiimote::IOWrite(unsigned char* buf, int len) +int Wiimote::IOWrite(const u8* buf, int len) { + DWORD bytes = 0; switch (stack) { case MSBT_STACK_UNKNOWN: { // Try to auto-detect the stack type - DWORD bytes = 0; + auto i = WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); if (i) { @@ -324,7 +330,7 @@ int Wiimote::IOWrite(unsigned char* buf, int len) return i; } - i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1); + i = HidD_SetOutputReport(dev_handle, (unsigned char*) buf + 1, len - 1); if (i) { stack = MSBT_STACK_MS; @@ -343,20 +349,20 @@ int Wiimote::IOWrite(unsigned char* buf, int len) { ERROR_LOG(WIIMOTE, "IOWrite[MSBT_STACK_UNKNOWN]: ERROR: %08x", dw); // Correct? - return -1 + return -1; } break; } case MSBT_STACK_MS: { - i = HidD_SetOutputReport(dev_handle, buf + 1, len - 1); - dw = GetLastError(); + auto i = HidD_SetOutputReport(dev_handle, (unsigned char*) buf + 1, len - 1); + auto dw = GetLastError(); if (dw == 121) { // Semaphore timeout NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote"); - RealDisconnect(); + Disconnect(); return 0; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 516fa3a51e..eb4856d2f9 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -357,6 +357,19 @@ void WiimoteScanner::ThreadFunc() } } +void Wiimote::StartThread() +{ + m_run_thread = true; + m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); +} + +void Wiimote::StopThread() +{ + m_run_thread = false; + if (m_wiimote_thread.joinable()) + m_wiimote_thread.join(); +} + void Wiimote::ThreadFunc() { Common::SetCurrentThreadName("Wiimote Device Thread"); diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp index 338ed59547..d9d1908de3 100644 --- a/Source/Core/DolphinWX/Src/Main.cpp +++ b/Source/Core/DolphinWX/Src/Main.cpp @@ -390,10 +390,6 @@ void DolphinApp::InitLanguageSupport() int DolphinApp::OnExit() { WiimoteReal::Shutdown(); -#ifdef _WIN32 - if (SConfig::GetInstance().m_WiiAutoUnpair) - WiimoteReal::UnPair(); -#endif VideoBackend::ClearList(); SConfig::Shutdown(); LogManager::Shutdown(); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index d38eadb0e1..b50ec9bc5d 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -81,7 +81,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin wxFlexGridSizer* const real_wiimotes_sizer = new wxFlexGridSizer(3, 5, 5); real_wiimotes_sizer->Add(connected_wiimotes_txt, 0, wxALIGN_CENTER_VERTICAL); #ifdef _WIN32 - real_wiimotes_sizer->Add(pairup_btn); + //real_wiimotes_sizer->Add(pairup_btn); #endif real_wiimotes_sizer->Add(refresh_btn); real_wiimotes_group->Add(real_wiimotes_sizer, 1, wxALL, 5); From 85f25ded4c210b633411fd373a775de5f1792a1f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 14:22:21 -0600 Subject: [PATCH 06/37] Buildfix! Programming for Windows on Linux is hard, OK? --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 77555bae86..1d82a19e1a 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -73,7 +73,7 @@ HINSTANCE bthprops_lib = NULL; static int initialized = 0; -int PairUp(bool unpair); +int PairUp(bool unpair = false); inline void init_lib() { From 9ecfb5e75d5f636a1c29c38bf67700dba6090d53 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 14:42:50 -0600 Subject: [PATCH 07/37] Buildfix for real! --- Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 13 ++++++++----- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index b22f1c7795..114feebeb7 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -26,9 +26,12 @@ WiimoteScanner::WiimoteScanner() return; } +WiimoteScanner::~WiimoteScanner() +{} + std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) { - return std::vector() + return std::vector(); } bool WiimoteScanner::IsReady() const @@ -46,17 +49,17 @@ void Wiimote::Disconnect() return; } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { - return IsConnected(); + return false; } -int Wiimote::IORead(unsigned char* buf) +int Wiimote::Read(const u8* buf) { return 0; } -int Wiimote::IOWrite(unsigned char* buf, int len) +int Wiimote::Write(const u8* buf, int len) { return 0; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 1d82a19e1a..407e3b6f4f 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -73,8 +73,6 @@ HINSTANCE bthprops_lib = NULL; static int initialized = 0; -int PairUp(bool unpair = false); - inline void init_lib() { if (!initialized) @@ -129,6 +127,8 @@ inline void init_lib() namespace WiimoteReal { +int PairUp(bool unpair = false); + WiimoteScanner::WiimoteScanner() { init_lib(); From 57ea09dcc2b2d51193e7f3c07cbd38ea9a7f85bd Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 14:46:01 -0600 Subject: [PATCH 08/37] Fix BT-less! --- Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index 114feebeb7..c696cc8012 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -54,12 +54,12 @@ bool Wiimote::IsConnected() const return false; } -int Wiimote::Read(const u8* buf) +int Wiimote::IORead(const u8* buf) { return 0; } -int Wiimote::Write(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, int len) { return 0; } From a2ca76ebd9c3300735c438b5ddc7bc726001b41a Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 15:16:41 -0600 Subject: [PATCH 09/37] Buildfix. --- Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index c696cc8012..6af169f5ee 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -54,7 +54,7 @@ bool Wiimote::IsConnected() const return false; } -int Wiimote::IORead(const u8* buf) +int Wiimote::IORead(u8* buf) { return 0; } From 3063942dd05d432fe0b750770e5159252b4ae199 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 21:53:09 -0600 Subject: [PATCH 10/37] some cleanup --- .../Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp | 5 +- .../Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h | 4 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 128 +++++------------- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 6 +- 4 files changed, 41 insertions(+), 102 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index cfb81bb768..5c2a28b57a 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -252,9 +252,8 @@ void Wiimote::RequestStatus(const wm_request_status* const rs) if (g_wiimotes[m_index]) { - wm_request_status rpt; - rpt.rumble = 0; - g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + wm_request_status rpt = {}; + g_wiimotes[m_index]->QueueReport(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); } return; diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h index fd7c549e8d..9d1a2092a0 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteHid.h @@ -201,6 +201,7 @@ struct wm_report #define WM_LEDS 0x11 struct wm_leds { u8 rumble : 1; + // real wii also sets bit 0x2 (unknown purpose) u8 : 3; u8 leds : 4; }; @@ -208,8 +209,9 @@ struct wm_leds { #define WM_REPORT_MODE 0x12 struct wm_report_mode { u8 rumble : 1; - u8 continuous : 1; // these 2 seem to be named wrong + // unsure what "all_the_time" actually is, the real wii does set it (bit 0x2) u8 all_the_time : 1; + u8 continuous : 1; u8 : 5; u8 mode; }; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index a7963ec4e0..dda9e32b5f 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -61,13 +61,11 @@ Wiimote::Wiimote() #if defined(__linux__) && HAVE_BLUEZ bdaddr = (bdaddr_t){{0, 0, 0, 0, 0, 0}}; #endif - - DisableDataReporting(); } Wiimote::~Wiimote() { - StopThread(); + StopThread(); if (IsConnected()) Disconnect(); @@ -80,26 +78,28 @@ Wiimote::~Wiimote() delete[] rpt.first; } -// Silly, copying data n stuff, o well, don't use this too often -void Wiimote::SendPacket(const u8 rpt_id, const void* const data, const unsigned int size) +// to be called from CPU thread +void Wiimote::QueueReport(u8 rpt_id, const void* _data, unsigned int size) { + auto const data = static_cast(_data); + Report rpt; rpt.second = size + 2; rpt.first = new u8[rpt.second]; - rpt.first[0] = 0xA1; + rpt.first[0] = WM_SET_REPORT | WM_BT_OUTPUT; rpt.first[1] = rpt_id; - memcpy(rpt.first + 2, data, size); + std::copy(data, data + size, rpt.first + 2); m_write_reports.Push(rpt); } void Wiimote::DisableDataReporting() { - wm_report_mode rpt; + wm_report_mode rpt = {}; rpt.mode = WM_REPORT_CORE; rpt.all_the_time = 0; rpt.continuous = 0; rpt.rumble = 0; - SendPacket(WM_REPORT_MODE, &rpt, sizeof(rpt)); + QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt)); } void Wiimote::ClearReadQueue() @@ -133,24 +133,24 @@ void Wiimote::ControlChannel(const u16 channel, const void* const data, const u3 } } -void Wiimote::InterruptChannel(const u16 channel, const void* const data, const u32 size) +void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const u32 size) { - if (0 == m_channel) // first interrupt/control channel sent + // first interrupt/control channel sent + if (channel != m_channel) { + m_channel = channel; + ClearReadQueue(); - // request status - wm_request_status rpt; - rpt.rumble = 0; - SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + EmuStart(); } - - m_channel = channel; // this right? + + auto const data = static_cast(_data); Report rpt; rpt.first = new u8[size]; rpt.second = (u8)size; - memcpy(rpt.first, (u8*)data, size); + std::copy(data, data + size, rpt.first); // Convert output DATA packets to SET_REPORT packets. // Nintendo Wiimotes work without this translation, but 3rd @@ -173,7 +173,8 @@ bool Wiimote::Read() if (0 == rpt.second) Disconnect(); - if (rpt.second > 0 && m_channel > 0) { + if (rpt.second > 0 && m_channel > 0) + { // Add it to queue m_read_reports.Push(rpt); return true; @@ -241,27 +242,18 @@ void Wiimote::Update() delete[] rpt.first; } -void Wiimote::EmuStop() -{ - m_channel = 0; - - DisableDataReporting(); - - NOTICE_LOG(WIIMOTE, "Stopping wiimote data reporting"); -} - // Rumble briefly -void Wiimote::Rumble() +void Wiimote::RumbleBriefly() { unsigned char buffer = 0x01; DEBUG_LOG(WIIMOTE, "Starting rumble..."); - SendRequest(WM_CMD_RUMBLE, &buffer, 1); + QueueReport(WM_CMD_RUMBLE, &buffer, sizeof(buffer)); SLEEP(200); DEBUG_LOG(WIIMOTE, "Stopping rumble..."); buffer = 0x00; - SendRequest(WM_CMD_RUMBLE, &buffer, 1); + QueueReport(WM_CMD_RUMBLE, &buffer, sizeof(buffer)); } // Set the active LEDs. @@ -270,30 +262,21 @@ void Wiimote::SetLEDs(int new_leds) { // Remove the lower 4 bits because they control rumble u8 const buffer = (new_leds & 0xF0); - SendRequest(WM_CMD_LED, &buffer, 1); + QueueReport(WM_CMD_LED, &buffer, sizeof(buffer)); } bool Wiimote::EmuStart() { - // Send a handshake - - // Set buffer[0] to 0x04 for continuous reporting - u8 const buffer[2] = {0x04, 0x30}; - - NOTICE_LOG(WIIMOTE, "Sending handshake to wiimote"); - - return SendRequest(WM_CMD_REPORT_TYPE, buffer, 2); + DisableDataReporting(); } -// Send a packet to the wiimote. -// report_type should be one of WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc. -bool Wiimote::SendRequest(u8 report_type, u8 const* data, int length) +void Wiimote::EmuStop() { - unsigned char buffer[32] = {WM_SET_REPORT | WM_BT_OUTPUT, report_type}; + m_channel = 0; - memcpy(buffer + 2, data, length); + DisableDataReporting(); - return (IOWrite(buffer, length + 2) != 0); + NOTICE_LOG(WIIMOTE, "Stopping wiimote data reporting"); } unsigned int CalculateWantedWiimotes() @@ -369,9 +352,6 @@ void Wiimote::ThreadFunc() { Common::SetCurrentThreadName("Wiimote Device Thread"); - // rumble briefly - Rumble(); - // main loop while (m_run_thread && IsConnected()) { @@ -464,7 +444,10 @@ void HandleWiimoteConnect(Wiimote* wm) wm->index = i; wm->StartThread(); + + wm->DisableDataReporting(); wm->SetLEDs(WIIMOTE_LED_1 << i); + wm->RumbleBriefly(); Host_ConnectWiimote(i, true); @@ -516,52 +499,7 @@ void Refresh() { std::lock_guard lk(g_refresh_lock); -#ifdef _WIN32 - Shutdown(); - Initialize(); -#else -/* - // Make sure real wiimotes have been initialized - if (!g_real_wiimotes_initialized) - { - Initialize(); - return; - } - - // Find the number of slots configured for real wiimotes - unsigned int wanted_wiimotes = 0; - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) - ++wanted_wiimotes; - - // Remove wiimotes that are paired with slots no longer configured for a - // real wiimote or that are disconnected - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) || - !g_wiimotes[i]->IsConnected())) - { - delete g_wiimotes[i]; - g_wiimotes[i] = NULL; - --g_wiimotes_found; - } - - // Scan for wiimotes if we want more - if (wanted_wiimotes > g_wiimotes_found) - { - // Scan for wiimotes - unsigned int num_wiimotes = FindWiimotes(g_wiimotes, wanted_wiimotes); - - DEBUG_LOG(WIIMOTE, "Found %i Real Wiimotes, %i wanted", num_wiimotes, wanted_wiimotes); - - // Connect newly found wiimotes. - int num_new_wiimotes = ConnectWiimotes(g_wiimotes); - - DEBUG_LOG(WIIMOTE, "Connected to %i additional Real Wiimotes", num_new_wiimotes); - - g_wiimotes_found = num_wiimotes; - } -*/ -#endif + // TODO: stuff, maybe } void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index d61967b4f1..0dee443597 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -70,10 +70,11 @@ public: bool IsConnected() const; void SetLEDs(int leds); + void RumbleBriefly(); void DisableDataReporting(); - void Rumble(); - void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size); + + void QueueReport(u8 rpt_id, const void* data, unsigned int size); int index; @@ -102,7 +103,6 @@ protected: private: void ClearReadQueue(); - bool SendRequest(u8 report_type, u8 const* data, int length); int IORead(u8* buf); int IOWrite(u8 const* buf, int len); From 026793fa4abfd7e2d1b6f443022e621b81bddac9 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 23:17:51 -0600 Subject: [PATCH 11/37] Fixup real wiimote GUI. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 42 +++++++------- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 29 +++++++--- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 3 +- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 57 +++---------------- Source/Core/DolphinWX/Src/WiimoteConfigDiag.h | 6 -- 5 files changed, 50 insertions(+), 87 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 1ac7ed03f4..25a83531dc 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -135,7 +135,10 @@ WiimoteScanner::WiimoteScanner() } WiimoteScanner::~WiimoteScanner() -{} +{ + // TODO: what do we want here? + //PairUp(true); +} // Find and connect wiimotes. // Does not replace already found wiimotes even if they are disconnected. @@ -216,8 +219,21 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) bool WiimoteScanner::IsReady() const { - // TODO: impl - return true; + BLUETOOTH_FIND_RADIO_PARAMS radioParam; + radioParam.dwSize = sizeof(radioParam); + + HANDLE hRadio; + HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio); + + if (NULL != hFindRadio) + { + Bth_BluetoothFindRadioClose(hFindRadio); + return true; + } + else + { + return false; + } } // Connect to a wiimote with a known device path. @@ -377,26 +393,6 @@ int Wiimote::IOWrite(const u8* buf, int len) return 0; } -// return true if a device using MS BT stack is available -bool CanPairUp() -{ - BLUETOOTH_FIND_RADIO_PARAMS radioParam; - radioParam.dwSize = sizeof(radioParam); - - HANDLE hRadio; - HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio); - - if (NULL != hFindRadio) - { - Bth_BluetoothFindRadioClose(hFindRadio); - return true; - } - else - { - return false; - } -} - // WiiMote Pair-Up, function will return amount of either new paired or unpaired devices // negative number on failure int PairUp(bool unpair) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index dda9e32b5f..5b8ee72f16 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -265,7 +265,7 @@ void Wiimote::SetLEDs(int new_leds) QueueReport(WM_CMD_LED, &buffer, sizeof(buffer)); } -bool Wiimote::EmuStart() +void Wiimote::EmuStart() { DisableDataReporting(); } @@ -298,7 +298,10 @@ void WiimoteScanner::WantWiimotes(size_t count) void WiimoteScanner::StartScanning() { run_thread = true; - scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this); + if (IsReady()) + { + scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this); + } } void WiimoteScanner::StopScanning() @@ -307,7 +310,6 @@ void WiimoteScanner::StopScanning() if (scan_thread.joinable()) { scan_thread.join(); - NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped"); } } @@ -333,6 +335,8 @@ void WiimoteScanner::ThreadFunc() //std::this_thread::yield(); Common::SleepCurrentThread(500); } + + NOTICE_LOG(WIIMOTE, "Wiimote scanning has stopped"); } void Wiimote::StartThread() @@ -395,8 +399,7 @@ void Initialize() auto const wanted_wiimotes = CalculateWantedWiimotes(); g_wiimote_scanner.WantWiimotes(wanted_wiimotes); - //if (wanted_wiimotes > 0) - g_wiimote_scanner.StartScanning(); + g_wiimote_scanner.StartScanning(); g_real_wiimotes_initialized = true; } @@ -497,9 +500,21 @@ void HandleFoundWiimotes(const std::vector& wiimotes) // This is called from the GUI thread void Refresh() { + g_wiimote_scanner.StopScanning(); + + { std::lock_guard lk(g_refresh_lock); - - // TODO: stuff, maybe + + 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); + } + + g_wiimote_scanner.StartScanning(); } void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 0dee443597..23631765ed 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -59,7 +59,7 @@ public: void StopThread(); // "handshake" / stop packets - bool EmuStart(); + void EmuStart(); void EmuStop(); // connecting and disconnecting from physical devices @@ -153,6 +153,7 @@ private: }; extern std::recursive_mutex g_refresh_lock; +extern WiimoteScanner g_wiimote_scanner; extern Wiimote *g_wiimotes[4]; void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index b50ec9bc5d..a4af2d5d9a 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -4,14 +4,6 @@ #include "HW/WiimoteReal/WiimoteReal.h" #include "Frame.h" -wxString ConnectedWiimotesString() -{ - //static wxString str; - //str.Printf(_("%i connected"), WiimoteReal::Initialize()); - //return str; - return "TODO: this text"; -} - WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin) : wxDialog(parent, -1, _("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize) , m_plugin(plugin) @@ -65,27 +57,17 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin // "Real wiimotes" controls - connected_wiimotes_txt = new wxStaticText(this, -1, ConnectedWiimotesString()); - wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition); refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this); -#ifdef _WIN32 - //wxButton* const pairup_btn = new wxButton(this, -1, _("Pair Up"), wxDefaultPosition); - //pairup_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::PairUpRealWiimotes, this); - // TODO: text if can't Pair -#endif - // "Real wiimotes" layout - wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Real Wiimotes")); - wxFlexGridSizer* const real_wiimotes_sizer = new wxFlexGridSizer(3, 5, 5); - real_wiimotes_sizer->Add(connected_wiimotes_txt, 0, wxALIGN_CENTER_VERTICAL); -#ifdef _WIN32 - //real_wiimotes_sizer->Add(pairup_btn); -#endif - real_wiimotes_sizer->Add(refresh_btn); - real_wiimotes_group->Add(real_wiimotes_sizer, 1, wxALL, 5); - + wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes")); + + if (!WiimoteReal::g_wiimote_scanner.IsReady()) + real_wiimotes_group->Add(new wxStaticText(this, -1, _("A supported bluetooth device could not be found.\n" + "You must manually pair your wiimotes.")), 0, wxALIGN_CENTER | wxALL, 5); + + real_wiimotes_group->Add(refresh_btn, 0, wxALIGN_CENTER); // "General Settings" controls const wxString str[] = { _("Bottom"), _("Top") }; @@ -189,15 +171,9 @@ void WiimoteConfigDiag::ConfigEmulatedWiimote(wxCommandEvent& ev) m_emu_config_diag->Destroy(); } -void WiimoteConfigDiag::UpdateGUI() -{ - connected_wiimotes_txt->SetLabel(ConnectedWiimotesString()); -} - void WiimoteConfigDiag::RefreshRealWiimotes(wxCommandEvent&) { WiimoteReal::Refresh(); - UpdateGUI(); } void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) @@ -214,24 +190,6 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) wiimote_configure_bt[index]->Enable(); } -// TODO: race conditiions -void WiimoteConfigDiag::UpdateWiimoteStatus() -{ - for (int index = 0; index < 4; ++index) - { - if (m_orig_wiimote_sources[index] != g_wiimote_sources[index]) - { - // Disconnect first, otherwise the new source doesn't seem to work - CFrame::ConnectWiimote(index, false); - // Connect wiimotes - if (WIIMOTE_SRC_EMU & g_wiimote_sources[index]) - CFrame::ConnectWiimote(index, true); - else if (WIIMOTE_SRC_REAL & g_wiimote_sources[index] && WiimoteReal::g_wiimotes[index]) - CFrame::ConnectWiimote(index, WiimoteReal::g_wiimotes[index]->IsConnected()); - } - } -} - void WiimoteConfigDiag::RevertSource() { for (int i = 0; i < 4; ++i) @@ -253,7 +211,6 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event) sec.Set("Source", (int)g_wiimote_sources[i]); } - UpdateWiimoteStatus(); inifile.Save(ini_filename); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index fbd715bd40..316d0d48bf 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -26,15 +26,11 @@ public: void RefreshRealWiimotes(wxCommandEvent& event); - void SelectSource(wxCommandEvent& event); - void UpdateWiimoteStatus(); void RevertSource(); - void ConfigEmulatedWiimote(wxCommandEvent& event); void Save(wxCommandEvent& event); - void UpdateGUI(); void OnSensorBarPos(wxCommandEvent& event) { @@ -73,8 +69,6 @@ private: wxButton* wiimote_configure_bt[4]; std::map m_wiimote_index_from_conf_bt_id; - - wxStaticText* connected_wiimotes_txt; }; From 87bbdbf5428b94520b44a97df53a5f7ee1e9945d Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 23:23:32 -0600 Subject: [PATCH 12/37] Remove settings stuff that was not actually used anywhere. --- Source/Core/Core/Src/ConfigManager.cpp | 20 +------------------- Source/Core/Core/Src/ConfigManager.h | 5 ----- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index f6194c1bb7..978eadace1 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -100,9 +100,6 @@ SConfig::SConfig() { // Make sure we have log manager LoadSettings(); - //Make sure we load any extra settings - LoadSettingsWii(); - } void SConfig::Init() @@ -427,19 +424,4 @@ void SConfig::LoadSettings() } m_SYSCONF = new SysConf(); -} -void SConfig::LoadSettingsWii() -{ - IniFile ini; - //Wiimote configs - ini.Load((File::GetUserPath(D_CONFIG_IDX) + "Dolphin.ini")); - for (int i = 0; i < 4; i++) - { - char SectionName[32]; - sprintf(SectionName, "Wiimote%i", i + 1); - ini.Get(SectionName, "AutoReconnectRealWiimote", &m_WiiAutoReconnect[i], false); - } - ini.Load((File::GetUserPath(D_CONFIG_IDX) + "wiimote.ini")); - ini.Get("Real", "Unpair", &m_WiiAutoUnpair, false); - -} +} \ No newline at end of file diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index e92d29ee65..e3ad7b42a9 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -41,8 +41,6 @@ struct SConfig : NonCopyable // Wii Devices bool m_WiiSDCard; bool m_WiiKeyboard; - bool m_WiiAutoReconnect[4]; - bool m_WiiAutoUnpair; bool m_WiimoteReconnectOnLoad; // name of the last used filename @@ -107,9 +105,6 @@ struct SConfig : NonCopyable // load settings void LoadSettings(); - //Special load settings - void LoadSettingsWii(); - // Return the permanent and somewhat globally used instance of this struct static SConfig& GetInstance() {return(*m_Instance);} From 8ce58759e33202342b79a611f4ebdd0a5b1a2bf5 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 7 Feb 2013 23:52:50 -0600 Subject: [PATCH 13/37] Remove some old nonsense. --- Source/Core/Common/Src/Common.h | 1 - .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp | 3 +- Source/Core/DolphinWX/Src/Frame.cpp | 31 ------------------- Source/Core/VideoCommon/Src/EmuWindow.cpp | 4 --- 4 files changed, 1 insertion(+), 38 deletions(-) diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index c3cab37dd8..0132915a5c 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -155,7 +155,6 @@ enum HOST_COMM WM_USER_CREATE, WM_USER_SETCURSOR, WM_USER_KEYDOWN, - WIIMOTE_DISCONNECT // Disconnect Wiimote }; // Used for notification on emulation state diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp index 6e06f60dd6..b3449ec059 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp @@ -211,8 +211,7 @@ void CWII_IPC_HLE_WiiMote::EventConnectionAccepted() void CWII_IPC_HLE_WiiMote::EventDisconnect() { // Send disconnect message to plugin - u8 Message = WIIMOTE_DISCONNECT; - Wiimote::ControlChannel(m_ConnectionHandle & 0xFF, 99, &Message, 0); + Wiimote::ControlChannel(m_ConnectionHandle & 0xFF, 99, NULL, 0); m_ConnectionState = CONN_INACTIVE; // Clear channel flags diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index d390b8afcd..46b3a1e8e5 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -100,37 +100,6 @@ CPanel::CPanel( else SetCursor(wxNullCursor); break; - - case WIIMOTE_DISCONNECT: - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) - { - const int wiimote_idx = lParam; - const int wiimote_num = wiimote_idx + 1; - - //Auto reconnect if option is turned on. - //TODO: Make this only auto reconnect wiimotes that have the option activated. - SConfig::GetInstance().LoadSettingsWii();//Make sure we are using the newest settings. - if (SConfig::GetInstance().m_WiiAutoReconnect[wiimote_idx]) - { - GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true); - NOTICE_LOG(WIIMOTE, "Wiimote %i has been auto-reconnected...", wiimote_num); - } - else - { - // The Wiimote has been disconnected, we offer reconnect here. - wxMessageDialog *dlg = new wxMessageDialog( - this, - wxString::Format(_("Wiimote %i has been disconnected by system.\nMaybe this game doesn't support multi-wiimote,\nor maybe it is due to idle time out or other reason.\nDo you want to reconnect immediately?"), wiimote_num), - _("Reconnect Wiimote Confirm"), - wxYES_NO | wxSTAY_ON_TOP | wxICON_INFORMATION, //wxICON_QUESTION, - wxDefaultPosition); - - if (dlg->ShowModal() == wxID_YES) - GetUsbPointer()->AccessWiiMote(wiimote_idx | 0x100)->Activate(true); - - dlg->Destroy(); - } - } } break; diff --git a/Source/Core/VideoCommon/Src/EmuWindow.cpp b/Source/Core/VideoCommon/Src/EmuWindow.cpp index cbb0bc31ac..81227ba0ca 100644 --- a/Source/Core/VideoCommon/Src/EmuWindow.cpp +++ b/Source/Core/VideoCommon/Src/EmuWindow.cpp @@ -205,10 +205,6 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam ) OnKeyDown(lParam); FreeLookInput((u32)wParam, lParam); } - else if (wParam == WIIMOTE_DISCONNECT) - { - PostMessage(m_hParent, WM_USER, wParam, lParam); - } break; // Called when a screensaver wants to show up while this window is active From 1998da867b57a7f6cee3320059e9c259abee64bd Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 8 Feb 2013 12:14:45 -0600 Subject: [PATCH 14/37] OSX fix maybe. (based on jchadwick's patch) --- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 87 ++++++++----------- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 1 + 2 files changed, 38 insertions(+), 50 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 95068fe650..2e53daca36 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -10,19 +10,6 @@ } @end -WiimoteScanner::WiimoteScanner() -{} - -std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) -{ - return std::vector(); -} - -bool WiimoteScanner::IsReady() const -{ - return false; -} - @implementation SearchBT - (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender error: (IOReturn) error @@ -112,34 +99,35 @@ bool WiimoteScanner::IsReady() const namespace WiimoteReal { -// Find wiimotes. -// wm is an array of max_wiimotes wiimotes -// Returns the total number of found wiimotes. -int FindWiimotes(Wiimote **wm, int max_wiimotes) +WiimoteScanner::WiimoteScanner() +{} + +WiimoteScanner::~WiimoteScanner() +{} + +std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) { + // TODO: find the device in the constructor and save it for later + + std::vector wiimotes; IOBluetoothHostController *bth; IOBluetoothDeviceInquiry *bti; SearchBT *sbt; NSEnumerator *en; - int found_devices = 0, found_wiimotes = 0; - - // Count the number of already found wiimotes - for (int i = 0; i < MAX_WIIMOTES; ++i) - if (wm[i]) - found_wiimotes++; bth = [[IOBluetoothHostController alloc] init]; - if ([bth addressAsString] == nil) { + if ([bth addressAsString] == nil) + { WARN_LOG(WIIMOTE, "No bluetooth host controller"); [bth release]; - return found_wiimotes; + return wiimotes; } sbt = [[SearchBT alloc] init]; - sbt->maxDevices = max_wiimotes - found_wiimotes; + sbt->maxDevices = max_wiimotes; bti = [[IOBluetoothDeviceInquiry alloc] init]; [bti setDelegate: sbt]; - [bti setInquiryLength: 5]; + [bti setInquiryLength: 2]; if ([bti start] == kIOReturnSuccess) [bti retain]; @@ -149,10 +137,9 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes) CFRunLoopRun(); [bti stop]; - found_devices = [[bti foundDevices] count]; + int found_devices = [[bti foundDevices] count]; - NOTICE_LOG(WIIMOTE, "Found %i bluetooth device%c", found_devices, - found_devices == 1 ? '\0' : 's'); + NOTICE_LOG(WIIMOTE, "Found %i bluetooth devices", found_devices); en = [[bti foundDevices] objectEnumerator]; for (int i = 0; i < found_devices; i++) @@ -160,24 +147,26 @@ int FindWiimotes(Wiimote **wm, int max_wiimotes) IOBluetoothDevice *dev = [en nextObject]; if (!IsValidBluetoothName([[dev name] UTF8String])) continue; - // Find an unused slot - for (int k = 0; k < MAX_WIIMOTES; k++) { - if (wm[k] != NULL || - !(g_wiimote_sources[k] & WIIMOTE_SRC_REAL)) - continue; - wm[k] = new Wiimote(k); - wm[k]->btd = dev; - found_wiimotes++; + Wiimote *wm = new Wiimote(); + wm->btd = dev; + wiimotes.push_back(wm); + + if(wiimotes.size() >= max_wiimotes) break; - } } [bth release]; [bti release]; [sbt release]; - return found_wiimotes; + return wiimotes; +} + +bool WiimoteScanner::IsReady() const +{ + // TODO: only return true when a BT device is present + return true; } // Connect to a wiimote with a known address. @@ -192,7 +181,8 @@ bool Wiimote::Connect() withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt]; [btd openL2CAPChannelSync: &ichan withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt]; - if (ichan == NULL || cchan == NULL) { + if (ichan == NULL || cchan == NULL) + { ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels " "for wiimote %i", index + 1); Disconnect(); @@ -209,11 +199,6 @@ bool Wiimote::Connect() m_connected = true; - Handshake(); - SetLEDs(WIIMOTE_LED_1 << index); - - m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); - [cbt release]; return true; @@ -240,9 +225,9 @@ void Wiimote::Disconnect() ichan = NULL; } -bool Wiimote::IsOpen() const +bool Wiimote::IsConnected() const { - return IsConnected(); + return m_connected; } int Wiimote::IORead(unsigned char *buf) @@ -251,6 +236,8 @@ int Wiimote::IORead(unsigned char *buf) if (!IsConnected()) return 0; + + // TODO: race conditions here, yo bytes = inputlen; memcpy(buf, input, bytes); @@ -259,14 +246,14 @@ int Wiimote::IORead(unsigned char *buf) return bytes; } -int Wiimote::IOWrite(unsigned char *buf, int len) +int Wiimote::IOWrite(const unsigned char *buf, int len) { IOReturn ret; if (!IsConnected()) return 0; - ret = [ichan writeAsync: buf length: len refcon: nil]; + ret = [ichan writeAsync: const_cast((void *)buf) length: len refcon: nil]; if (ret == kIOReturnSuccess) return len; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 23631765ed..139d59ce99 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -84,6 +84,7 @@ public: IOBluetoothL2CAPChannel *cchan; char input[MAX_PAYLOAD]; int inputlen; + bool m_connected; #elif defined(__linux__) && HAVE_BLUEZ bdaddr_t bdaddr; // Bluetooth address int cmd_sock; // Command socket From 1f1b4a6992553d132de3fc8b097fdfbba78ff556 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 8 Feb 2013 16:54:48 -0600 Subject: [PATCH 15/37] Hopefully make real wiimotes on OSX less crashy. --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 12 ++++++++---- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 2e53daca36..030daa0973 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -40,8 +40,11 @@ { IOBluetoothDevice *device = [l2capChannel getDevice]; WiimoteReal::Wiimote *wm = NULL; + + std::lock_guard lk(g_refresh_lock); - for (int i = 0; i < MAX_WIIMOTES; i++) { + for (int i = 0; i < MAX_WIIMOTES; i++) + { if (WiimoteReal::g_wiimotes[i] == NULL) continue; if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE) @@ -77,8 +80,11 @@ { IOBluetoothDevice *device = [l2capChannel getDevice]; WiimoteReal::Wiimote *wm = NULL; + + std::lock_guard lk(g_refresh_lock); - for (int i = 0; i < MAX_WIIMOTES; i++) { + for (int i = 0; i < MAX_WIIMOTES; i++) + { if (WiimoteReal::g_wiimotes[i] == NULL) continue; if ([device isEqual: WiimoteReal::g_wiimotes[i]->btd] == TRUE) @@ -236,8 +242,6 @@ int Wiimote::IORead(unsigned char *buf) if (!IsConnected()) return 0; - - // TODO: race conditions here, yo bytes = inputlen; memcpy(buf, input, bytes); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 5b8ee72f16..7ae1a9a961 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -360,13 +360,13 @@ void Wiimote::ThreadFunc() while (m_run_thread && IsConnected()) { #ifdef __APPLE__ - while (Write()) {} - Common::SleepCurrentThread(1); + // Reading happens elsewhere on OSX + bool const did_something = Write(); #else bool const did_something = Write() || Read(); +#endif if (!did_something) Common::SleepCurrentThread(1); -#endif } } From 9bb9286cd3b1dca212d9e5ebd95960f102ea79bc Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 8 Feb 2013 16:59:59 -0600 Subject: [PATCH 16/37] OSX buildfix! --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 030daa0973..02f3941fc8 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -41,7 +41,7 @@ IOBluetoothDevice *device = [l2capChannel getDevice]; WiimoteReal::Wiimote *wm = NULL; - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(WiimoteReal::g_refresh_lock); for (int i = 0; i < MAX_WIIMOTES; i++) { @@ -81,7 +81,7 @@ IOBluetoothDevice *device = [l2capChannel getDevice]; WiimoteReal::Wiimote *wm = NULL; - std::lock_guard lk(g_refresh_lock); + std::lock_guard lk(WiimoteReal::g_refresh_lock); for (int i = 0; i < MAX_WIIMOTES; i++) { From 50c83d614cba54f2720b889be3dd3bd8fea4840c Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 8 Feb 2013 21:20:54 -0600 Subject: [PATCH 17/37] More attempts at fixing Windows and OS X. --- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 3 ++ Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 45 ++++++++++--------- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 6 --- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 2d3ed01e6d..e926d44ec0 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -178,6 +178,9 @@ bool Wiimote::IsConnected() const return cmd_sock != -1;// && int_sock != -1; } +// positive = read packet +// negative = didn't read packet +// zero = error int Wiimote::IORead(u8* buf) { // Block select for 1/2000th of a second diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 25a83531dc..8226c784e8 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -148,12 +148,9 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) { PairUp(); - std::vector wiimotes; - GUID device_id; HANDLE dev; HDEVINFO device_info; - int found_wiimotes = 0; DWORD len; SP_DEVICE_INTERFACE_DATA device_data; PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; @@ -167,13 +164,11 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) // Get all hid devices connected device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); - for (int index = 0; found_wiimotes < max_wiimotes; ++index) + std::vector wiimotes; + for (int index = 0; wiimotes.size() < max_wiimotes; ++index) { - if (detail_data) - { - free(detail_data); - detail_data = NULL; - } + free(detail_data); + detail_data = NULL; // Query the next hid device info if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data)) @@ -188,7 +183,10 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) 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), @@ -199,18 +197,15 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) // Get device attributes attr.Size = sizeof(attr); HidD_GetAttributes(dev, &attr); - - // Find an unused slot - unsigned int k = 0; - auto const wm = new Wiimote; + wm->dev_handle = dev; +#endif wm->devicepath = detail_data->DevicePath; wiimotes.push_back(wm); } - if (detail_data) - free(detail_data); + free(detail_data); SetupDiDestroyDeviceInfoList(device_info); @@ -219,6 +214,8 @@ std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) bool WiimoteScanner::IsReady() const { + // TODO: don't search for a radio each time + BLUETOOTH_FIND_RADIO_PARAMS radioParam; radioParam.dwSize = sizeof(radioParam); @@ -241,7 +238,7 @@ bool Wiimote::Connect() { dev_handle = CreateFile(devicepath.c_str(), (GENERIC_READ | GENERIC_WRITE), - (FILE_SHARE_READ | FILE_SHARE_WRITE), + /*(FILE_SHARE_READ | FILE_SHARE_WRITE)*/ 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (dev_handle == INVALID_HANDLE_VALUE) @@ -281,8 +278,13 @@ bool Wiimote::IsConnected() const return dev_handle != 0; } +// positive = read packet +// negative = didn't read packet +// zero = error int Wiimote::IORead(unsigned char* buf) { + *buf = 0; + DWORD b; if (!ReadFile(dev_handle, buf, MAX_PAYLOAD, &b, &hid_overlap)) { @@ -291,7 +293,6 @@ int Wiimote::IORead(unsigned char* buf) if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) { // Remote disconnect - Disconnect(); return 0; } @@ -299,24 +300,23 @@ int Wiimote::IORead(unsigned char* buf) if (r == WAIT_TIMEOUT) { // 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 0; + return -1; } else if (r == WAIT_FAILED) { WARN_LOG(WIIMOTE, "A wait error occured on reading from wiimote %i.", index + 1); - return 0; + return -1; } if (!GetOverlappedResult(dev_handle, &hid_overlap, &b, 0)) { - return 0; + return -1; } } @@ -378,7 +378,6 @@ int Wiimote::IOWrite(const u8* buf, int len) { // Semaphore timeout NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to wiimote"); - Disconnect(); return 0; } @@ -418,6 +417,8 @@ int PairUp(bool unpair) radioParam.dwSize = sizeof(radioParam); HANDLE hRadio; + + // TODO: save radio(s) in the WiimoteScanner constructor // Enumerate BT radios HBLUETOOTH_RADIO_FIND hFindRadio = Bth_BluetoothFindFirstRadio(&radioParam, &hRadio); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 02f3941fc8..f3c90d810d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -213,16 +213,10 @@ bool Wiimote::Connect() // Disconnect a wiimote. void Wiimote::Disconnect() { - if (!IsConnected()) - return; - NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1); m_connected = false; - if (m_wiimote_thread.joinable()) - m_wiimote_thread.join(); - [btd closeConnection]; [ichan release]; [cchan release]; From 05ec90488b3951d5af29e41bec47955dc36baaec Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 03:39:09 -0600 Subject: [PATCH 18/37] Make real wiimotes not so crappy on Windows hopefully. --- .../Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 5 +- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 11 +- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 262 +++++++++++------- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 10 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 140 +++++----- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 23 +- .../Core/Src/HW/WiimoteReal/WiimoteRealBase.h | 5 +- 7 files changed, 259 insertions(+), 197 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index 6af169f5ee..3a017354eb 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -29,7 +29,10 @@ WiimoteScanner::WiimoteScanner() WiimoteScanner::~WiimoteScanner() {} -std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) +void WiimoteScanner::Update() +{} + +std::vector WiimoteScanner::FindWiimotes() { return std::vector(); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index e926d44ec0..62fd2e4ac5 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -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 WiimoteScanner::FindWiimotes(size_t max_wiimotes) +void WiimoteScanner::Update() +{} + +std::vector WiimoteScanner::FindWiimotes() { std::vector found_wiimotes; @@ -86,7 +85,7 @@ std::vector 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..."); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 8226c784e8..c88cdebdbc 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,8 @@ HINSTANCE bthprops_lib = NULL; static int initialized = 0; +static std::unordered_set 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 +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 WiimoteScanner::FindWiimotes(size_t max_wiimotes) +std::vector 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 WiimoteScanner::FindWiimotes(size_t max_wiimotes) device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); std::vector 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 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 +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; } }; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index f3c90d810d..9ed78800cc 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -111,7 +111,10 @@ WiimoteScanner::WiimoteScanner() WiimoteScanner::~WiimoteScanner() {} -std::vector WiimoteScanner::FindWiimotes(size_t max_wiimotes) +void WiimoteScanner::Update() +{} + +std::vector WiimoteScanner::FindWiimotes() { // TODO: find the device in the constructor and save it for later @@ -130,7 +133,7 @@ std::vector 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 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]; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 7ae1a9a961..6a5d91fa00 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -35,7 +35,7 @@ namespace WiimoteReal { void HandleFoundWiimotes(const std::vector&); -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 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 found_wiimotes; + + //NOTICE_LOG(WIIMOTE, "in loop"); + + if (m_want_wiimotes) + found_wiimotes = FindWiimotes(); + else { - // TODO: this code here is ugly - std::lock_guard 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 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 lk(g_refresh_lock); + std::lock_guard 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& 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 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(); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 139d59ce99..4b8f4365d3 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -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 m_read_reports; Common::FifoQueue 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 FindWiimotes(size_t max_wiimotes); + std::vector 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) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h index 75a6d3e6a3..15bbc2917f 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h @@ -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. From 7a053d0f0715a5308300a9ee05928433a8250953 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 03:50:54 -0600 Subject: [PATCH 19/37] buildfix! --- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 4 ++-- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 2 ++ Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 2 ++ Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 5 +---- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 62fd2e4ac5..87ddc5086b 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -27,8 +27,8 @@ namespace WiimoteReal { WiimoteScanner::WiimoteScanner() - : run_thread() - , want_wiimotes() + : m_run_thread() + , m_want_wiimotes() , device_id(-1) , device_sock(-1) { diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index c88cdebdbc..1920577de4 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -138,6 +138,8 @@ void RemoveWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi); bool ForgetWiimote(HANDLE hRadio, BLUETOOTH_DEVICE_INFO_STRUCT& btdi); WiimoteScanner::WiimoteScanner() + : m_run_thread() + , m_want_wiimotes() { init_lib(); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 9ed78800cc..51dcd17785 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -106,6 +106,8 @@ namespace WiimoteReal { WiimoteScanner::WiimoteScanner() + : m_run_thread() + , m_want_wiimotes() {} WiimoteScanner::~WiimoteScanner() diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 6a5d91fa00..821eccea0c 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -250,14 +250,11 @@ bool Wiimote::Prepare(int _index) index = _index; // Set the active LEDs. - u8 const led_report[] = {HID_TYPE_SET_REPORT, WM_CMD_LED, WIIMOTE_LED_1 << index}; + u8 const led_report[] = {HID_TYPE_SET_REPORT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index)}; // Rumble briefly u8 rumble_report[] = {HID_TYPE_SET_REPORT, WM_CMD_RUMBLE, 1}; - // 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)) From c267be2682cd6d6fbcf163893a1361aa49511c8f Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 05:30:51 -0600 Subject: [PATCH 20/37] Hopefully fix windows! --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 13 +++++++++++-- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 10 +++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 1920577de4..7c6f6f20d0 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -379,6 +380,14 @@ 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) { @@ -386,7 +395,7 @@ int Wiimote::IOWrite(const u8* buf, int len) { // Try to auto-detect the stack type - auto i = WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); + 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 @@ -433,7 +442,7 @@ int Wiimote::IOWrite(const u8* buf, int len) break; } case MSBT_STACK_BLUESOLEIL: - return WriteFile(dev_handle, buf + 1, 22, &bytes, &hid_overlap); + return WriteFile(dev_handle, buf + 1, MAX_PAYLOAD - 1, &bytes, &hid_overlap); break; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 821eccea0c..e006ec1f69 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -249,15 +249,19 @@ bool Wiimote::Prepare(int _index) { index = _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[] = {HID_TYPE_SET_REPORT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index)}; + u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index)}; // Rumble briefly - u8 rumble_report[] = {HID_TYPE_SET_REPORT, WM_CMD_RUMBLE, 1}; + u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 1}; // TODO: request status and check for sane response? - return (IOWrite(led_report, sizeof(led_report)) + 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)))); } From b8fd5c0c307aa45f846b4ec412e05608d0e93e41 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 05:57:55 -0600 Subject: [PATCH 21/37] Fix Windows for real! --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 7c6f6f20d0..d9b6a665ef 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -421,8 +421,7 @@ int Wiimote::IOWrite(const u8* buf, int len) else { ERROR_LOG(WIIMOTE, "IOWrite[MSBT_STACK_UNKNOWN]: ERROR: %08x", dw); - // Correct? - return -1; + return 0; } break; } From c2d2fb8c7c84ab2abf439f1ccdafd44d71b41b64 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 15:21:58 -0600 Subject: [PATCH 22/37] Try to improve real wiimotes on Windows. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 126 ++++++++++-------- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 56 +++++--- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 2 +- 3 files changed, 112 insertions(+), 72 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) + stack = MSBT_STACK_BLUESOLEIL; + if (IOWrite(buf, len)) + return 1; + + stack = MSBT_STACK_MS; + if (IOWrite(buf, len)) { - // Bluesoleil will always return 1 here, even if it's not connected - stack = MSBT_STACK_BLUESOLEIL; - return i; + // Don't mind me, just a random sleep to fix stuff on Windows + SLEEP(1000); + return 1; } - i = HidD_SetOutputReport(dev_handle, (unsigned char*) buf + 1, len - 1); - if (i) - { - stack = MSBT_STACK_MS; - return i; - } - - 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(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 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 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 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 lk(g_refresh_lock); - CheckForDisconnectedWiimotes(); + std::vector 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 From 0fb7f65e04f966f9eef1b8dfcb7d8d8ebec834ae Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 15:58:23 -0600 Subject: [PATCH 23/37] Problems on Windows? Just SLEEP twice as long! --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 6 +++++- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index d6bc5dd28b..3052f4b737 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -75,6 +75,7 @@ HINSTANCE bthprops_lib = NULL; static int initialized = 0; +std::mutex g_connected_devices_lock; static std::unordered_set g_connected_devices; inline void init_lib() @@ -182,7 +183,7 @@ std::vector WiimoteScanner::FindWiimotes() // Hacks... if (attached_some) - SLEEP(1000); + SLEEP(2000); GUID device_id; HDEVINFO device_info; @@ -253,6 +254,8 @@ bool WiimoteScanner::IsReady() const // Connect to a wiimote with a known device path. bool Wiimote::Connect() { + std::lock_guard lk(g_connected_devices_lock); + // This is where we disallow connecting to the same device twice if (g_connected_devices.count(devicepath)) return false; @@ -303,6 +306,7 @@ bool Wiimote::Connect() void Wiimote::Disconnect() { + std::lock_guard lk(g_connected_devices_lock); g_connected_devices.erase(devicepath); CloseHandle(dev_handle); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 55fc552abd..793a13ceb0 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -64,8 +64,6 @@ public: // 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(); From f3d25f2cb04002b0ede883f0c482acfd5de978a9 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 16:07:01 -0600 Subject: [PATCH 24/37] OSX buildfix! --- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 6e9a72eb00..7647698c63 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -259,7 +259,7 @@ bool Wiimote::Prepare(int _index) u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_REPORT_TYPE, 0, 0x30}; // 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}; + u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_LED, u8(WIIMOTE_LED_1 << index | 0x1)}; // Turn off rumble u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 0}; From fa10335c55520ec674e26835e1e0d0fc9d5dfb37 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 17:58:56 -0600 Subject: [PATCH 25/37] Make continuous scanning optional. --- Source/Core/Core/Src/ConfigManager.cpp | 4 +++- Source/Core/Core/Src/ConfigManager.h | 1 + .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 19 ++++++++++++------- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 12 ++++++++++-- Source/Core/DolphinWX/Src/WiimoteConfigDiag.h | 6 ++++++ 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 978eadace1..282c369161 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -241,6 +241,7 @@ void SConfig::SaveSettings() ini.Set("Core", "WiiSDCard", m_WiiSDCard); ini.Set("Core", "WiiKeyboard", m_WiiKeyboard); ini.Set("Core", "WiimoteReconnectOnLoad", m_WiimoteReconnectOnLoad); + ini.Set("Core", "WiimoteContinuousScanning", m_WiimoteContinuousScanning); ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); ini.Set("Core", "FrameLimit", m_Framelimit); @@ -390,7 +391,8 @@ void SConfig::LoadSettings() ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false); ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false); - ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); + ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); + ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, true); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false); diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index e3ad7b42a9..a633bded5c 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -42,6 +42,7 @@ struct SConfig : NonCopyable bool m_WiiSDCard; bool m_WiiKeyboard; bool m_WiimoteReconnectOnLoad; + bool m_WiimoteContinuousScanning; // name of the last used filename std::string m_LastFilename; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 7647698c63..4b3b737d36 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -24,6 +24,7 @@ #include "StringUtil.h" #include "Timer.h" #include "Host.h" +#include "ConfigManager.h" #include "WiimoteReal.h" @@ -303,9 +304,9 @@ void WiimoteScanner::WantWiimotes(bool do_want) void WiimoteScanner::StartScanning() { - m_run_thread = true; - if (IsReady()) + if (!m_run_thread && IsReady()) { + m_run_thread = true; m_scan_thread = std::thread(std::mem_fun(&WiimoteScanner::ThreadFunc), this); } } @@ -413,19 +414,23 @@ void LoadSettings() } } +// config dialog calls this when some settings change void Initialize() { + if (SConfig::GetInstance().m_WiimoteContinuousScanning) + g_wiimote_scanner.StartScanning(); + else + g_wiimote_scanner.StopScanning(); + std::lock_guard lk(g_refresh_lock); + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + if (g_real_wiimotes_initialized) return; NOTICE_LOG(WIIMOTE, "WiimoteReal::Initialize"); - g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); - - g_wiimote_scanner.StartScanning(); - g_real_wiimotes_initialized = true; } @@ -534,7 +539,7 @@ void Refresh() HandleFoundWiimotes(found_wiimotes); } - g_wiimote_scanner.StartScanning(); + Initialize(); } void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index a4af2d5d9a..56b75531cf 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -60,14 +60,22 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition); refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this); - // "Real wiimotes" layout wxStaticBoxSizer* const real_wiimotes_group = new wxStaticBoxSizer(wxVERTICAL, this, _("Real Wiimotes")); + wxBoxSizer* const real_wiimotes_sizer = new wxBoxSizer(wxHORIZONTAL); + if (!WiimoteReal::g_wiimote_scanner.IsReady()) real_wiimotes_group->Add(new wxStaticText(this, -1, _("A supported bluetooth device could not be found.\n" "You must manually pair your wiimotes.")), 0, wxALIGN_CENTER | wxALL, 5); + + wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning")); + continuous_scanning->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnContinuousScanning, this); + continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning); - real_wiimotes_group->Add(refresh_btn, 0, wxALIGN_CENTER); + real_wiimotes_sizer->Add(continuous_scanning, 0, wxALIGN_CENTER_VERTICAL); + real_wiimotes_sizer->AddStretchSpacer(1); + real_wiimotes_sizer->Add(refresh_btn, 0, wxALL | wxALIGN_CENTER, 5); + real_wiimotes_group->Add(real_wiimotes_sizer, 1, wxEXPAND); // "General Settings" controls const wxString str[] = { _("Bottom"), _("Top") }; diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index 316d0d48bf..26d6660ee2 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -57,6 +57,12 @@ public: SConfig::GetInstance().m_WiimoteReconnectOnLoad = event.IsChecked(); event.Skip(); } + void OnContinuousScanning(wxCommandEvent& event) + { + SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked(); + WiimoteReal::Initialize(); + event.Skip(); + } private: void Cancel(wxCommandEvent& event); From a6461ca186c67592c1bd6bb4f6cd175c03ddcde3 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Feb 2013 20:50:09 -0600 Subject: [PATCH 26/37] Improve wiimote reconnection on changing wiimote sources. --- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 48 +++++++++++++++---- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 2 +- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 4b3b737d36..34fc7e92f5 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -38,6 +38,7 @@ namespace WiimoteReal void HandleFoundWiimotes(const std::vector&); void TryToConnectWiimote(Wiimote*); void HandleWiimoteDisconnect(int index); +void DoneWithWiimote(int index); bool g_real_wiimotes_initialized = false; @@ -382,6 +383,7 @@ void Wiimote::ThreadFunc() Common::SetCurrentThreadName("Wiimote Device Thread"); Host_ConnectWiimote(index, true); + NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); // main loop while (m_run_thread && IsConnected()) @@ -453,15 +455,20 @@ void Shutdown(void) void ChangeWiimoteSource(unsigned int index, int source) { + { std::lock_guard lk(g_refresh_lock); - + g_wiimote_sources[index] = source; - - // source is emulated, kill any real connection - if (!(WIIMOTE_SRC_REAL & g_wiimote_sources[index])) - HandleWiimoteDisconnect(index); - g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + + // kill real connection (or swap to different slot) + DoneWithWiimote(index); + } + + // reconnect to emu + Host_ConnectWiimote(index, false); + if (WIIMOTE_SRC_EMU & source) + Host_ConnectWiimote(index, true); } void TryToConnectWiimote(Wiimote* wm) @@ -478,8 +485,6 @@ void TryToConnectWiimote(Wiimote* wm) g_wiimotes[i] = wm; wm->StartThread(); - - NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1); wm = NULL; break; @@ -491,6 +496,32 @@ void TryToConnectWiimote(Wiimote* wm) g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); } +void DoneWithWiimote(int index) +{ + std::lock_guard lk(g_refresh_lock); + + if (g_wiimotes[index]) + { + g_wiimotes[index]->StopThread(); + + // First see if we can use this real wiimote in another slot. + for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + { + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] + && !g_wiimotes[i] + && g_wiimotes[index]->Prepare(i)) + { + std::swap(g_wiimotes[i], g_wiimotes[index]); + g_wiimotes[i]->StartThread(); + break; + } + } + } + + // else, just disconnect the wiimote + HandleWiimoteDisconnect(index); +} + void HandleWiimoteDisconnect(int index) { std::lock_guard lk(g_refresh_lock); @@ -570,7 +601,6 @@ void Update(int _WiimoteNumber) // 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); } } diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index 56b75531cf..3cd050a293 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -66,7 +66,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin if (!WiimoteReal::g_wiimote_scanner.IsReady()) real_wiimotes_group->Add(new wxStaticText(this, -1, _("A supported bluetooth device could not be found.\n" - "You must manually pair your wiimotes.")), 0, wxALIGN_CENTER | wxALL, 5); + "You must manually connect your wiimotes.")), 0, wxALIGN_CENTER | wxALL, 5); wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning")); continuous_scanning->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnContinuousScanning, this); From da53ca8ee3127ff898f557212523b43d09207564 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 12 Feb 2013 00:19:27 -0600 Subject: [PATCH 27/37] "Wait for the wiimote to connect"? I think that's a horrible idea. --- Source/Core/DolphinWX/Src/FrameTools.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 56dde8e2ce..cb2750ade4 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -1355,10 +1355,6 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect) wxString msg(wxString::Format(wxT("Wiimote %i %s"), wm_idx + 1, connect ? wxT("Connected") : wxT("Disconnected"))); Core::DisplayMessage(msg.ToAscii(), 3000); - - // Wait for the wiimote to connect - while (GetUsbPointer()->AccessWiiMote(wm_idx | 0x100)->IsConnected() != connect) - {} Host_UpdateMainFrame(); } } From 12674b3164f809814c6059b4bfdf9e800819da0c Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 12 Feb 2013 17:01:51 -0600 Subject: [PATCH 28/37] Possibly improve real wiimotes on Windows. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 3052f4b737..0f00d3fa5f 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -432,7 +432,7 @@ int Wiimote::IOWrite(const u8* buf, int len) } else { - ERROR_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err); + WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err); } } @@ -488,7 +488,7 @@ void ProcessWiimotes(bool new_scan, T& callback) srch.fReturnUnknown = true; srch.fIssueInquiry = new_scan; // multiple of 1.28 seconds - srch.cTimeoutMultiplier = 1; + srch.cTimeoutMultiplier = 2; BLUETOOTH_FIND_RADIO_PARAMS radioParam; radioParam.dwSize = sizeof(radioParam); From 7f305ba82288fa86fbe200036b26fd2cb219a293 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 12 Feb 2013 18:56:36 -0600 Subject: [PATCH 29/37] Fix sloppy connection logic. --- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 34fc7e92f5..ee685aae9b 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -478,15 +478,14 @@ void TryToConnectWiimote(Wiimote* wm) for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) { if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] - && !g_wiimotes[i] - && wm->Connect() - && wm->Prepare(i)) + && !g_wiimotes[i]) { - g_wiimotes[i] = wm; - - wm->StartThread(); - - wm = NULL; + if (wm->Connect() && wm->Prepare(i)) + { + g_wiimotes[i] = wm; + wm->StartThread(); + wm = NULL; + } break; } } @@ -508,11 +507,13 @@ void DoneWithWiimote(int index) for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) { if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] - && !g_wiimotes[i] - && g_wiimotes[index]->Prepare(i)) + && !g_wiimotes[i]) { - std::swap(g_wiimotes[i], g_wiimotes[index]); - g_wiimotes[i]->StartThread(); + if (g_wiimotes[index]->Prepare(i)) + { + std::swap(g_wiimotes[i], g_wiimotes[index]); + g_wiimotes[i]->StartThread(); + } break; } } From 77381a1af2d59b799afeb326bba122fbefff7287 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Tue, 12 Feb 2013 21:37:47 -0600 Subject: [PATCH 30/37] Futile attempts at fixing OS X. --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 51dcd17785..8c3a0f10b2 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -150,7 +150,8 @@ std::vector WiimoteScanner::FindWiimotes() [bti stop]; int found_devices = [[bti foundDevices] count]; - NOTICE_LOG(WIIMOTE, "Found %i bluetooth devices", found_devices); + if (found_devices) + NOTICE_LOG(WIIMOTE, "Found %i bluetooth devices", found_devices); en = [[bti foundDevices] objectEnumerator]; for (int i = 0; i < found_devices; i++) @@ -180,11 +181,11 @@ bool WiimoteScanner::IsReady() const // Connect to a wiimote with a known address. bool Wiimote::Connect() { - ConnectBT *cbt = [[ConnectBT alloc] init]; - if (IsConnected()) return false; + ConnectBT *cbt = [[ConnectBT alloc] init]; + [btd openL2CAPChannelSync: &cchan withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt]; [btd openL2CAPChannelSync: &ichan @@ -215,6 +216,9 @@ bool Wiimote::Connect() // Disconnect a wiimote. void Wiimote::Disconnect() { + if (!IsConnected()) + return; + NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1); m_connected = false; From e57ff0613082c47a936ffef1c40a12780c489995 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 13 Feb 2013 14:00:15 -0600 Subject: [PATCH 31/37] Futile attempts at fixing Windows. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 109 ++++++++---------- 1 file changed, 50 insertions(+), 59 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 0f00d3fa5f..61abeffa2d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -19,7 +19,8 @@ #include #include #include -#include +#include +#include #include #include @@ -75,8 +76,7 @@ HINSTANCE bthprops_lib = NULL; static int initialized = 0; -std::mutex g_connected_devices_lock; -static std::unordered_set g_connected_devices; +std::unordered_map g_connect_times; inline void init_lib() { @@ -173,60 +173,50 @@ void WiimoteScanner::Update() // Returns the total number of found and connected wiimotes. std::vector 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); - 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 + GUID device_id; HidD_GetHidGuid(&device_id); // 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 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 + DWORD len; SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(len); detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Query the data for this device - if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) - continue; + if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) + { + auto const wm = new Wiimote; + wm->devicepath = detail_data->DevicePath; + wiimotes.push_back(wm); + } - auto const wm = new Wiimote; - wm->devicepath = detail_data->DevicePath; - wiimotes.push_back(wm); + free(detail_data); } - free(detail_data); - SetupDiDestroyDeviceInfoList(device_info); + // Don't mind me, just a random sleep to fix stuff on Windows + //if (!wiimotes.empty()) + // SLEEP(2000); + return wiimotes; } @@ -254,17 +244,14 @@ bool WiimoteScanner::IsReady() const // Connect to a wiimote with a known device path. bool Wiimote::Connect() { - std::lock_guard lk(g_connected_devices_lock); - - // This is where we disallow connecting to the same device twice - if (g_connected_devices.count(devicepath)) + if (IsConnected()) return false; dev_handle = CreateFile(devicepath.c_str(), - (GENERIC_READ | GENERIC_WRITE), - // TODO: Just do FILE_SHARE_READ and remove "g_connected_devices"? - // That is what "WiiYourself" does. - (FILE_SHARE_READ | FILE_SHARE_WRITE), + GENERIC_READ | GENERIC_WRITE, + // Having no FILE_SHARE_WRITE disallows us from connecting to the same wiimote twice. + // This is what "WiiYourself" does. + FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (dev_handle == INVALID_HANDLE_VALUE) @@ -299,15 +286,13 @@ bool Wiimote::Connect() ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority"); } */ - - g_connected_devices.insert(devicepath); return true; } void Wiimote::Disconnect() { - std::lock_guard lk(g_connected_devices_lock); - g_connected_devices.erase(devicepath); + if (!IsConnected()) + return; CloseHandle(dev_handle); dev_handle = 0; @@ -385,7 +370,7 @@ int Wiimote::IORead(u8* buf) 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); + std::copy_n(buf, MAX_PAYLOAD - 1, buf + 1); buf[0] = 0xa1; // TODO: is this really needed? @@ -408,11 +393,7 @@ int Wiimote::IOWrite(const u8* buf, int len) stack = MSBT_STACK_MS; if (IOWrite(buf, len)) - { - // Don't mind me, just a random sleep to fix stuff on Windows - SLEEP(1000); return 1; - } stack = MSBT_STACK_UNKNOWN; break; @@ -553,6 +534,8 @@ void RemoveWiimote(HANDLE, 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) { 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, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE); + g_connect_times[btdi.Address.ullLong] = std::time(nullptr); + if (FAILED(hr)) ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr); else @@ -575,14 +560,20 @@ 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. - // This is also required to detect a disconnect for some reason.. - NOTICE_LOG(WIIMOTE, "Removing remembered wiimote."); - Bth_BluetoothRemoveDevice(&btdi.Address); + // Time to avoid RemoveDevice after SetServiceState. + // Sometimes SetServiceState takes a while.. + auto const avoid_forget_seconds = 5.0; - 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; From 306e6b1d80c0426092001bb4653f93f217af152d Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 14 Feb 2013 14:02:51 -0600 Subject: [PATCH 32/37] Turn off continuous scanning by default. --- Source/Core/Core/Src/ConfigManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 282c369161..44a7591577 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -392,7 +392,7 @@ void SConfig::LoadSettings() ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false); ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false); ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); - ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, true); + ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false); @@ -426,4 +426,4 @@ void SConfig::LoadSettings() } m_SYSCONF = new SysConf(); -} \ No newline at end of file +} From cda88a8c1ee3ac1b407b09e8e392262fd606f6ab Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 14 Feb 2013 18:41:31 -0600 Subject: [PATCH 33/37] Random improvements. --- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 20 +++++++---- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 33 +++++++++++++++---- .../Core/Src/HW/WiimoteReal/WiimoteRealBase.h | 1 + 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 8c3a0f10b2..fda1d99462 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -216,19 +216,25 @@ bool Wiimote::Connect() // Disconnect a wiimote. void Wiimote::Disconnect() { + if (btd != NULL) + [btd closeConnection]; + + if (ichan != NULL) + [ichan release]; + + if (cchan != NULL) + [cchan release]; + + btd = NULL; + cchan = NULL; + ichan = NULL; + if (!IsConnected()) return; NOTICE_LOG(WIIMOTE, "Disconnecting wiimote %i", index + 1); m_connected = false; - - [btd closeConnection]; - [ichan release]; - [cchan release]; - btd = NULL; - cchan = NULL; - ichan = NULL; } bool Wiimote::IsConnected() const diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index ee685aae9b..311bf11de2 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -161,6 +161,18 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const { rpt.first[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) + { + auto& leds_rpt = *reinterpret_cast(&rpt.first[2]); + if (0 == leds_rpt.leds) + { + // Turn on ALL of the LEDs. + leds_rpt.leds = 0xf; + } + } m_write_reports.Push(rpt); } @@ -265,12 +277,15 @@ bool Wiimote::Prepare(int _index) // Turn off rumble u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_CMD_RUMBLE, 0}; - - // TODO: request status and check for sane response? + + // Request status report + u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0}; + // TODO: check for sane response? return (IOWrite(mode_report, sizeof(mode_report)) && IOWrite(led_report, sizeof(led_report)) - && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report)))); + && (SLEEP(200), IOWrite(rumble_report, sizeof(rumble_report))) + && IOWrite(req_status_report, sizeof(req_status_report))); } void Wiimote::EmuStart() @@ -382,9 +397,6 @@ void Wiimote::ThreadFunc() { Common::SetCurrentThreadName("Wiimote Device Thread"); - Host_ConnectWiimote(index, true); - NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); - // main loop while (m_run_thread && IsConnected()) { @@ -485,6 +497,8 @@ void TryToConnectWiimote(Wiimote* wm) g_wiimotes[i] = wm; wm->StartThread(); wm = NULL; + + Host_ConnectWiimote(i, true); } break; } @@ -513,6 +527,8 @@ void DoneWithWiimote(int index) { std::swap(g_wiimotes[i], g_wiimotes[index]); g_wiimotes[i]->StartThread(); + + Host_ConnectWiimote(i, true); } break; } @@ -563,9 +579,12 @@ void Refresh() // Brief rumble for already connected wiimotes. for (int i = 0; i != MAX_WIIMOTES; ++i) { - // kinda sloppy if (g_wiimotes[i]) + { + g_wiimotes[i]->StopThread(); g_wiimotes[i]->Prepare(i); + g_wiimotes[i]->StartThread(); + } } HandleFoundWiimotes(found_wiimotes); diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h index 15bbc2917f..1a1f6676cf 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteRealBase.h @@ -41,6 +41,7 @@ #define WM_SET_REPORT 0xA0 #endif +// TODO: duplicated in WiimoteHid.h // Commands #define WM_CMD_RUMBLE 0x10 #define WM_CMD_LED 0x11 From 891de527690a24a4e5c48ce04e85547905a694b9 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 14 Feb 2013 19:04:34 -0600 Subject: [PATCH 34/37] Don't need to hang dolphin when searching for wiimote with the refresh button. This code is getting pretty ugly. :/ --- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 311bf11de2..b628cf61fc 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -565,13 +565,15 @@ void Refresh() g_wiimote_scanner.StopScanning(); { - std::lock_guard lk(g_refresh_lock); - + std::unique_lock lk(g_refresh_lock); std::vector found_wiimotes; if (0 != CalculateWantedWiimotes()) { + // Don't hang dolphin when searching + lk.unlock(); found_wiimotes = g_wiimote_scanner.FindWiimotes(); + lk.lock(); } CheckForDisconnectedWiimotes(); From 1f20a24a04558d06f8584f0fcb35368c2a9c0f60 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 14 Feb 2013 21:02:41 -0600 Subject: [PATCH 35/37] Minor changes. --- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index b628cf61fc..751b24ac38 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -336,7 +336,6 @@ void WiimoteScanner::StopScanning() } } - void CheckForDisconnectedWiimotes() { std::lock_guard lk(g_refresh_lock); @@ -485,7 +484,7 @@ void ChangeWiimoteSource(unsigned int index, int source) void TryToConnectWiimote(Wiimote* wm) { - std::lock_guard lk(g_refresh_lock); + std::unique_lock lk(g_refresh_lock); for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) { @@ -494,9 +493,10 @@ void TryToConnectWiimote(Wiimote* wm) { if (wm->Connect() && wm->Prepare(i)) { - g_wiimotes[i] = wm; - wm->StartThread(); - wm = NULL; + NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", i + 1); + + std::swap(g_wiimotes[i], wm); + g_wiimotes[i]->StartThread(); Host_ConnectWiimote(i, true); } @@ -504,9 +504,11 @@ void TryToConnectWiimote(Wiimote* wm) } } - delete wm; - g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + + lk.unlock(); + + delete wm; } void DoneWithWiimote(int index) @@ -541,17 +543,19 @@ void DoneWithWiimote(int index) void HandleWiimoteDisconnect(int index) { - std::lock_guard lk(g_refresh_lock); - - if (g_wiimotes[index]) - { - delete g_wiimotes[index]; - g_wiimotes[index] = NULL; + Wiimote* wm = NULL; - NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1); + { + std::lock_guard lk(g_refresh_lock); + std::swap(wm, g_wiimotes[index]); + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); } - g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + if (wm) + { + delete wm; + NOTICE_LOG(WIIMOTE, "Disconnected wiimote %i.", index + 1); + } } void HandleFoundWiimotes(const std::vector& wiimotes) From ef90b15f3ed032acd6b32b67b0a55e7a0df6a5b7 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 15 Feb 2013 03:00:31 -0600 Subject: [PATCH 36/37] Provide an option to not send speaker data. It can cause rumble lag even when the speaker is muted. --- Source/Core/Core/Src/ConfigManager.cpp | 2 ++ Source/Core/Core/Src/ConfigManager.h | 1 + Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 9 +++++++++ Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 8 +++++++- Source/Core/DolphinWX/Src/WiimoteConfigDiag.h | 5 +++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 44a7591577..85ecc7143f 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -242,6 +242,7 @@ void SConfig::SaveSettings() ini.Set("Core", "WiiKeyboard", m_WiiKeyboard); ini.Set("Core", "WiimoteReconnectOnLoad", m_WiimoteReconnectOnLoad); ini.Set("Core", "WiimoteContinuousScanning", m_WiimoteContinuousScanning); + ini.Set("Core", "WiimoteEnableSpeaker", m_WiimoteEnableSpeaker); ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); ini.Set("Core", "FrameLimit", m_Framelimit); @@ -393,6 +394,7 @@ void SConfig::LoadSettings() ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false); ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false); + ini.Get("Core", "WiimoteEnableSpeaker", &m_WiimoteEnableSpeaker, true); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false); diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index a633bded5c..0c4ceffa9f 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -43,6 +43,7 @@ struct SConfig : NonCopyable bool m_WiiKeyboard; bool m_WiimoteReconnectOnLoad; bool m_WiimoteContinuousScanning; + bool m_WiimoteEnableSpeaker; // name of the last used filename std::string m_LastFilename; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 751b24ac38..b5a1703527 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -173,6 +173,15 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const leds_rpt.leds = 0xf; } } + else if (rpt.first[1] == WM_WRITE_SPEAKER_DATA + && !SConfig::GetInstance().m_WiimoteEnableSpeaker) + { + // Translate speaker data reports into rumble reports. + rpt.first[1] = WM_CMD_RUMBLE; + // Keep only the rumble bit. + rpt.first[2] &= 0x1; + rpt.second = 3; + } m_write_reports.Push(rpt); } diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index 3cd050a293..475718ed2e 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -71,11 +71,17 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin wxCheckBox* const continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning")); continuous_scanning->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnContinuousScanning, this); continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning); + + auto wiimote_speaker = new wxCheckBox(this, wxID_ANY, _("Enable Speaker Data")); + wiimote_speaker->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnEnableSpeaker, this); + wiimote_speaker->SetValue(SConfig::GetInstance().m_WiimoteEnableSpeaker); real_wiimotes_sizer->Add(continuous_scanning, 0, wxALIGN_CENTER_VERTICAL); real_wiimotes_sizer->AddStretchSpacer(1); real_wiimotes_sizer->Add(refresh_btn, 0, wxALL | wxALIGN_CENTER, 5); - real_wiimotes_group->Add(real_wiimotes_sizer, 1, wxEXPAND); + + real_wiimotes_group->Add(wiimote_speaker, 0); + real_wiimotes_group->Add(real_wiimotes_sizer, 0, wxEXPAND); // "General Settings" controls const wxString str[] = { _("Bottom"), _("Top") }; diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index 26d6660ee2..4c33661ca2 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -63,6 +63,11 @@ public: WiimoteReal::Initialize(); event.Skip(); } + void OnEnableSpeaker(wxCommandEvent& event) + { + SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked(); + event.Skip(); + } private: void Cancel(wxCommandEvent& event); From 6b2804e2960b4c8d9ba9ef95ad4c843eab9ae00b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 24 Feb 2013 22:29:33 -0600 Subject: [PATCH 37/37] Possible crashfix for OSX. --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 3 ++- Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index fda1d99462..cec18ed63a 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -195,6 +195,8 @@ bool Wiimote::Connect() ERROR_LOG(WIIMOTE, "Unable to open L2CAP channels " "for wiimote %i", index + 1); Disconnect(); + + [cbt release]; return false; } @@ -209,7 +211,6 @@ bool Wiimote::Connect() m_connected = true; [cbt release]; - return true; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index b5a1703527..3608c060fc 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -51,7 +51,7 @@ WiimoteScanner g_wiimote_scanner; Wiimote::Wiimote() : index() #ifdef __APPLE__ - , inputlen(0) + , btd(), ichan(), cchan(), inputlen(), m_connected() #elif defined(__linux__) && HAVE_BLUEZ , cmd_sock(-1), int_sock(-1) #elif defined(_WIN32)