From 19252f4e0e7ecc0f75d78616bb0ac43825623e52 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sat, 18 May 2013 20:31:37 +1200 Subject: [PATCH 01/11] Initial commit with balance board working on Linux. Will not work on any other platform currently. Missing any sort of config, and definitely no emulation mode. --- Source/Core/Core/Src/Core.cpp | 6 +- Source/Core/Core/Src/HW/Wiimote.cpp | 9 +- Source/Core/Core/Src/HW/Wiimote.h | 13 +- Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp | 25 ++-- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 137 +++++++++++++----- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 7 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 66 ++++++--- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h | 6 +- .../Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp | 6 +- Source/Core/Core/Src/Movie.cpp | 2 +- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 4 +- Source/Core/DolphinWX/Src/WiimoteConfigDiag.h | 4 +- 12 files changed, 196 insertions(+), 89 deletions(-) diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index ffd2c35472..268d474ae6 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -394,10 +394,10 @@ void EmuThread() Wiimote::Initialize(g_pWindowHandle); // Activate wiimotes which don't have source set to "None" - for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + for (unsigned int i = 0; i != MAX_BBMOTES; ++i) if (g_wiimote_sources[i]) - GetUsbPointer()->AccessWiiMote(i | 0x100)-> - Activate(true); + GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true); + } // The hardware is initialized. diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp index 20e10b5fb8..6723a26d28 100644 --- a/Source/Core/Core/Src/HW/Wiimote.cpp +++ b/Source/Core/Core/Src/HW/Wiimote.cpp @@ -42,9 +42,10 @@ void Shutdown() void Initialize(void* const hwnd) { // add 4 wiimotes - for (unsigned int i = 0; i<4; ++i) + for (unsigned int i = WIIMOTE_CHAN_0; iDoState(p); } diff --git a/Source/Core/Core/Src/HW/Wiimote.h b/Source/Core/Core/Src/HW/Wiimote.h index fa4ec895bd..51ab018417 100644 --- a/Source/Core/Core/Src/HW/Wiimote.h +++ b/Source/Core/Core/Src/HW/Wiimote.h @@ -8,7 +8,16 @@ #include "../../InputCommon/Src/InputConfig.h" #include "ChunkFile.h" -#define MAX_WIIMOTES 4 +enum { + WIIMOTE_CHAN_0 = 0, + WIIMOTE_CHAN_1, + WIIMOTE_CHAN_2, + WIIMOTE_CHAN_3, + WIIMOTE_BALANCE_BOARD, + MAX_WIIMOTES = WIIMOTE_BALANCE_BOARD, + MAX_BBMOTES = 5, +}; + #define WIIMOTE_INI_NAME "WiimoteNew" @@ -20,7 +29,7 @@ enum WIIMOTE_SRC_HYBRID = 3, // emu + real }; -extern unsigned int g_wiimote_sources[MAX_WIIMOTES]; +extern unsigned int g_wiimote_sources[MAX_BBMOTES]; namespace Wiimote { diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 87ddc5086b..edd79f2bf6 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -63,23 +63,22 @@ WiimoteScanner::~WiimoteScanner() void WiimoteScanner::Update() {} -std::vector WiimoteScanner::FindWiimotes() +void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board) { - std::vector found_wiimotes; - // supposedly 1.28 seconds int const wait_len = 1; int const max_infos = 255; inquiry_info scan_infos[max_infos] = {}; auto* scan_infos_ptr = scan_infos; - + found_board = NULL; + // 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) { ERROR_LOG(WIIMOTE, "Error searching for bluetooth devices."); - return found_wiimotes; + return; } DEBUG_LOG(WIIMOTE, "Found %i bluetooth device(s).", found_devices); @@ -91,7 +90,7 @@ std::vector WiimoteScanner::FindWiimotes() // 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) + if (hci_read_remote_name(device_sock, &scan_infos[i].bdaddr, sizeof(name), name, 1000) < 0) { ERROR_LOG(WIIMOTE, "name request failed"); continue; @@ -119,14 +118,20 @@ std::vector WiimoteScanner::FindWiimotes() auto* const wm = new Wiimote; wm->bdaddr = scan_infos[i].bdaddr; - found_wiimotes.push_back(wm); - - NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str); + if(IsBalanceBoardName(name)) + { + found_board = wm; + NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str); + } + else + { + found_wiimotes.push_back(wm); + NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str); + } } } } - return found_wiimotes; } // Connect to a wiimote with a known address. diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index aaaaff6301..1d3be13cc5 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -17,12 +17,13 @@ #include "../WiimoteEmu/WiimoteHid.h" -unsigned int g_wiimote_sources[MAX_WIIMOTES]; +unsigned int g_wiimote_sources[MAX_BBMOTES]; namespace WiimoteReal { void HandleFoundWiimotes(const std::vector&); +void TryToConnectBalanceBoard(Wiimote*); void TryToConnectWiimote(Wiimote*); void HandleWiimoteDisconnect(int index); void DoneWithWiimote(int index); @@ -31,8 +32,7 @@ bool g_real_wiimotes_initialized = false; std::recursive_mutex g_refresh_lock; -Wiimote* g_wiimotes[MAX_WIIMOTES]; - +Wiimote* g_wiimotes[MAX_BBMOTES]; WiimoteScanner g_wiimote_scanner; Wiimote::Wiimote() @@ -285,7 +285,7 @@ bool Wiimote::Prepare(int _index) u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE}; // Set the active LEDs and turn on rumble. - u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << index | 0x1)}; + u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)}; // Turn off rumble u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0}; @@ -325,11 +325,25 @@ unsigned int CalculateWantedWiimotes() return wanted_wiimotes; } +unsigned int CalculateWantedBB() +{ + unsigned int wanted_bb = 0; + if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD] && !g_wiimotes[WIIMOTE_BALANCE_BOARD]) + ++wanted_bb; + return wanted_bb; +} + void WiimoteScanner::WantWiimotes(bool do_want) { m_want_wiimotes = do_want; } + +void WiimoteScanner::WantBB(bool do_want) +{ + m_want_bb = do_want; +} + void WiimoteScanner::StartScanning() { if (!m_run_thread) @@ -352,7 +366,7 @@ void CheckForDisconnectedWiimotes() { std::lock_guard lk(g_refresh_lock); - for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + for (unsigned int i = 0; i < MAX_BBMOTES; ++i) if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected()) HandleWiimoteDisconnect(i); } @@ -366,12 +380,13 @@ void WiimoteScanner::ThreadFunc() while (m_run_thread) { std::vector found_wiimotes; + Wiimote* found_board = NULL; //NOTICE_LOG(WIIMOTE, "In loop"); - if (m_want_wiimotes) + if (m_want_wiimotes || m_want_bb) { - found_wiimotes = FindWiimotes(); + FindWiimotes(found_wiimotes, found_board); } else { @@ -384,7 +399,10 @@ void WiimoteScanner::ThreadFunc() // TODO: this is a fairly lame place for this CheckForDisconnectedWiimotes(); - HandleFoundWiimotes(found_wiimotes); + if(m_want_wiimotes) + HandleFoundWiimotes(found_wiimotes); + if(m_want_bb && found_board) + TryToConnectBalanceBoard(found_board); //std::this_thread::yield(); Common::SleepCurrentThread(500); @@ -439,6 +457,7 @@ void LoadSettings() sec.Get("Source", &g_wiimote_sources[i], i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU); } + g_wiimote_sources[WIIMOTE_BALANCE_BOARD] = WIIMOTE_SRC_REAL; } // config dialog calls this when some settings change @@ -452,6 +471,7 @@ void Initialize() std::lock_guard lk(g_refresh_lock); g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + g_wiimote_scanner.WantBB(0 != CalculateWantedBB()); if (g_real_wiimotes_initialized) return; @@ -474,7 +494,7 @@ void Shutdown(void) g_real_wiimotes_initialized = false; - for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) + for (unsigned int i = 0; i < MAX_BBMOTES; ++i) HandleWiimoteDisconnect(i); } @@ -482,9 +502,10 @@ void ChangeWiimoteSource(unsigned int index, int source) { { std::lock_guard lk(g_refresh_lock); - g_wiimote_sources[index] = source; g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + g_wiimote_scanner.WantBB(0 != CalculateWantedBB()); + // kill real connection (or swap to different slot) DoneWithWiimote(index); @@ -500,7 +521,7 @@ void TryToConnectWiimote(Wiimote* wm) { std::unique_lock lk(g_refresh_lock); - for (unsigned int i = 0; i != MAX_WIIMOTES; ++i) + for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) { if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i]) @@ -525,16 +546,41 @@ void TryToConnectWiimote(Wiimote* wm) delete wm; } +void TryToConnectBalanceBoard(Wiimote* wm) +{ + std::unique_lock lk(g_refresh_lock); + + if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD] + && !g_wiimotes[WIIMOTE_BALANCE_BOARD]) + { + if (wm->Connect() && wm->Prepare(WIIMOTE_BALANCE_BOARD)) + { + NOTICE_LOG(WIIMOTE, "Connected to Balance Board %i.", WIIMOTE_BALANCE_BOARD + 1); + + std::swap(g_wiimotes[WIIMOTE_BALANCE_BOARD], wm); + g_wiimotes[WIIMOTE_BALANCE_BOARD]->StartThread(); + + Host_ConnectWiimote(WIIMOTE_BALANCE_BOARD, true); + } + } + + g_wiimote_scanner.WantBB(0 != CalculateWantedBB()); + + lk.unlock(); + + delete wm; +} + 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) + for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) { if (WIIMOTE_SRC_REAL & g_wiimote_sources[i] && !g_wiimotes[i]) @@ -560,9 +606,11 @@ void HandleWiimoteDisconnect(int index) Wiimote* wm = NULL; { - std::lock_guard lk(g_refresh_lock); - std::swap(wm, g_wiimotes[index]); - g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + std::lock_guard lk(g_refresh_lock); + + std::swap(wm, g_wiimotes[index]); + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + g_wiimote_scanner.WantBB(0 != CalculateWantedBB()); } if (wm) @@ -583,31 +631,34 @@ void Refresh() g_wiimote_scanner.StopScanning(); { - 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(); - - // Brief rumble for already connected Wiimotes. - for (int i = 0; i != MAX_WIIMOTES; ++i) - { - if (g_wiimotes[i]) + std::unique_lock lk(g_refresh_lock); + std::vector found_wiimotes; + Wiimote* found_board = NULL; + + if (0 != CalculateWantedWiimotes()) { - g_wiimotes[i]->StopThread(); - g_wiimotes[i]->Prepare(i); - g_wiimotes[i]->StartThread(); + // Don't hang Dolphin when searching + lk.unlock(); + g_wiimote_scanner.FindWiimotes(found_wiimotes, found_board); + lk.lock(); } - } - HandleFoundWiimotes(found_wiimotes); + CheckForDisconnectedWiimotes(); + + // Brief rumble for already connected Wiimotes. + for (int i = 0; i < MAX_BBMOTES; ++i) + { + if (g_wiimotes[i]) + { + g_wiimotes[i]->StopThread(); + g_wiimotes[i]->Prepare(i); + g_wiimotes[i]->StartThread(); + } + } + + HandleFoundWiimotes(found_wiimotes); + if(found_board) + TryToConnectBalanceBoard(found_board); } Initialize(); @@ -616,7 +667,6 @@ void Refresh() void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { std::lock_guard lk(g_refresh_lock); - if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); } @@ -656,7 +706,14 @@ bool IsValidBluetoothName(const std::string& name) { return "Nintendo RVL-CNT-01" == name || - "Nintendo RVL-CNT-01-TR" == name; + "Nintendo RVL-CNT-01-TR" == name || + IsBalanceBoardName(name); +} + +bool IsBalanceBoardName(const std::string& name) +{ + return + "Nintendo RVL-WBC-01" == name; } }; // end of namespace diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index b57e1be2f4..695dc86b82 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -117,11 +117,12 @@ public: bool IsReady() const; void WantWiimotes(bool do_want); + void WantBB(bool do_want); void StartScanning(); void StopScanning(); - std::vector FindWiimotes(); + void FindWiimotes(std::vector&, Wiimote*&); // function called when not looking for more wiimotes void Update(); @@ -133,6 +134,7 @@ private: volatile bool m_run_thread; volatile bool m_want_wiimotes; + volatile bool m_want_bb; #if defined(_WIN32) @@ -145,7 +147,7 @@ private: extern std::recursive_mutex g_refresh_lock; extern WiimoteScanner g_wiimote_scanner; -extern Wiimote *g_wiimotes[4]; +extern Wiimote *g_wiimotes[MAX_BBMOTES]; void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); @@ -158,6 +160,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes); void ChangeWiimoteSource(unsigned int index, int source); bool IsValidBluetoothName(const std::string& name); +bool IsBalanceBoardName(const std::string& name); }; // WiimoteReal diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 41f751cb77..daa28b340d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -32,7 +32,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De } else { - u8 maxWM = min(BT_DINF.num_registered, CONF_PAD_MAX_ACTIVE); + u8 maxWM = min(BT_DINF.num_registered, MAX_BBMOTES); bdaddr_t tmpBD = BDADDR_ANY; u8 i = 0; while (i < maxWM) @@ -43,28 +43,60 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3]; tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4]; tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5]; + if(i == WIIMOTE_BALANCE_BOARD) + { + const char * wmName = "Nintendo RVL-WBC-01"; + memcpy(BT_DINF.registered[i].name, wmName, 20); + memcpy(BT_DINF.balance_board.name, wmName, 20); + } + else + { + const char * wmName = "Nintendo RVL-CNT-01"; + memcpy(BT_DINF.registered[i].name, wmName, 20); + memcpy(BT_DINF.active[i].name, wmName, 20); + } INFO_LOG(WII_IPC_WIIMOTE, "Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]); m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false)); i++; } - while (i < CONF_PAD_MAX_ACTIVE) + while (i < MAX_BBMOTES) { - const char * wmName = "Nintendo RVL-CNT-01"; - ++BT_DINF.num_registered; - BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i; - BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0; - BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79; - BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19; - BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2; - BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11; - memcpy(BT_DINF.registered[i].name, wmName, 20); + if(i == WIIMOTE_BALANCE_BOARD) + { + const char * wmName = "Nintendo RVL-WBC-01"; + ++BT_DINF.num_registered; + BT_DINF.balance_board.bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i; + BT_DINF.balance_board.bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0; + BT_DINF.balance_board.bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79; + BT_DINF.balance_board.bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19; + BT_DINF.balance_board.bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2; + BT_DINF.balance_board.bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11; + memcpy(BT_DINF.registered[i].name, wmName, 20); + memcpy(BT_DINF.balance_board.name, wmName, 20); + + INFO_LOG(WII_IPC_WIIMOTE, "Balance Board %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]); + m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false)); + } + else + { + const char * wmName = "Nintendo RVL-CNT-01"; + ++BT_DINF.num_registered; + BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i; + BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0; + BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79; + BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19; + BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2; + BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11; + memcpy(BT_DINF.registered[i].name, wmName, 20); - INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]); - m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false)); + INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]); + m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false)); + + } i++; } - + // save now so that when games load sysconf file it includes the new wiimotes // and the correct order for connected wiimotes if (!SConfig::GetInstance().m_SYSCONF->SetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads)) || !SConfig::GetInstance().m_SYSCONF->Save()) @@ -99,18 +131,18 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p) p.DoPOD(m_HCIEndpoint); p.DoPOD(m_ACLEndpoint); p.Do(m_last_ticks); - p.DoArray(m_PacketCount,4); + p.DoArray(m_PacketCount,MAX_BBMOTES); p.Do(m_ScanEnable); p.Do(m_EventQueue); m_acl_pool.DoState(p); - for (unsigned int i = 0; i < 4; i++) + for (unsigned int i = 0; i < MAX_BBMOTES; i++) m_WiiMotes[i].DoState(p); // Reset the connection of real and hybrid wiimotes if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad) { - for (unsigned int i = 0; i < 4; i++) + for (unsigned int i = 0; i < MAX_BBMOTES; i++) { if (WIIMOTE_SRC_EMU == g_wiimote_sources[i] || WIIMOTE_SRC_NONE == g_wiimote_sources[i]) continue; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h index f3d79b0fb8..7ac93b5be1 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h @@ -12,6 +12,7 @@ #include "WII_IPC_HLE.h" #include "WII_IPC_HLE_Device.h" #include "WII_IPC_HLE_WiiMote.h" +#include "../HW/Wiimote.h" struct SQueuedEvent { @@ -193,7 +194,7 @@ private: } } m_acl_pool; - u32 m_PacketCount[4]; + u32 m_PacketCount[MAX_BBMOTES]; u64 m_last_ticks; // Send ACL data to a device (wiimote) @@ -274,7 +275,6 @@ private: #pragma pack(push,1) #define CONF_PAD_MAX_REGISTERED 10 -#define CONF_PAD_MAX_ACTIVE 4 struct _conf_pad_device { @@ -286,7 +286,7 @@ private: { u8 num_registered; _conf_pad_device registered[CONF_PAD_MAX_REGISTERED]; - _conf_pad_device active[CONF_PAD_MAX_ACTIVE]; + _conf_pad_device active[MAX_WIIMOTES]; _conf_pad_device balance_board; u8 unknown[0x45]; }; 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 22930eb94c..9386682106 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 @@ -37,7 +37,7 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* , m_HIDInterruptChannel_Config(false) , m_HIDInterruptChannel_ConfigWait(false) , m_BD(_BD) - , m_Name("Nintendo RVL-CNT-01") + , m_Name(_Number == WIIMOTE_BALANCE_BOARD ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01") , m_pHost(_pHost) { DEBUG_LOG(WII_IPC_WIIMOTE, "Wiimote: #%i Constructed", _Number); @@ -277,13 +277,13 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size) break; case L2CAP_PSM_HID_CNTL: - if (number < 4) + if (number < MAX_BBMOTES) Wiimote::ControlChannel(number, pHeader->dcid, pData, DataSize); break; case L2CAP_PSM_HID_INTR: { - if (number < 4) + if (number < MAX_BBMOTES) { DEBUG_LOG(WIIMOTE, "Wiimote_InterruptChannel"); DEBUG_LOG(WIIMOTE, " Channel ID: %04x", pHeader->dcid); diff --git a/Source/Core/Core/Src/Movie.cpp b/Source/Core/Core/Src/Movie.cpp index c57ce8d4cc..75951df67d 100644 --- a/Source/Core/Core/Src/Movie.cpp +++ b/Source/Core/Core/Src/Movie.cpp @@ -392,7 +392,7 @@ void ChangeWiiPads(bool instantly) if (instantly && (g_numPads >> 4) == controllers) return; - for (int i = 0; i < 4; i++) + for (int i = 0; i < MAX_BBMOTES; i++) { g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE; GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i)); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index f039fe4938..1a1544373c 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -15,7 +15,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin wxStaticText* wiimote_label[4]; wxChoice* wiimote_source_ch[4]; - for (unsigned int i = 0; i < 4; ++i) + for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) { wxString str; str.Printf(_("Wiimote %i"), i + 1); @@ -206,7 +206,7 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) void WiimoteConfigDiag::RevertSource() { - for (int i = 0; i < 4; ++i) + for (int i = 0; i < MAX_WIIMOTES; ++i) g_wiimote_sources[i] = m_orig_wiimote_sources[i]; } diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index 4c33661ca2..88fea037a9 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -76,9 +76,9 @@ private: wxNotebook* m_pad_notebook; std::map m_wiimote_index_from_ctrl_id; - unsigned int m_orig_wiimote_sources[4]; + unsigned int m_orig_wiimote_sources[MAX_WIIMOTES]; - wxButton* wiimote_configure_bt[4]; + wxButton* wiimote_configure_bt[MAX_WIIMOTES]; std::map m_wiimote_index_from_conf_bt_id; }; From fccf37718072cc6ff63cdc10a62d0a5c3588bfbc Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sat, 18 May 2013 20:35:37 +1200 Subject: [PATCH 02/11] Fix IODummy FindWiimote method. --- Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index 3a017354eb..59025f9040 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -32,9 +32,10 @@ WiimoteScanner::~WiimoteScanner() void WiimoteScanner::Update() {} -std::vector WiimoteScanner::FindWiimotes() +void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board) { - return std::vector(); + found_wiimotes.clear(); + found_board = NULL; } bool WiimoteScanner::IsReady() const From 0b869cf12d914773d78fb5ee5234f208661d9280 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sat, 18 May 2013 22:26:00 +1200 Subject: [PATCH 03/11] Add mac support for balance board. --- .../Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index cec18ed63a..9f9192423c 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -116,22 +116,21 @@ WiimoteScanner::~WiimoteScanner() void WiimoteScanner::Update() {} -std::vector WiimoteScanner::FindWiimotes() +void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board) { // TODO: find the device in the constructor and save it for later - - std::vector wiimotes; IOBluetoothHostController *bth; IOBluetoothDeviceInquiry *bti; SearchBT *sbt; NSEnumerator *en; + found_board = NULL; bth = [[IOBluetoothHostController alloc] init]; if ([bth addressAsString] == nil) { WARN_LOG(WIIMOTE, "No bluetooth host controller"); [bth release]; - return wiimotes; + return; } sbt = [[SearchBT alloc] init]; @@ -162,14 +161,22 @@ std::vector WiimoteScanner::FindWiimotes() Wiimote *wm = new Wiimote(); wm->btd = dev; - wiimotes.push_back(wm); + + if(IsBalanceBoardName(name)) + { + found_board = wm; + NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str); + } + else + { + found_wiimotes.push_back(wm); + NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str); + } } [bth release]; [bti release]; [sbt release]; - - return wiimotes; } bool WiimoteScanner::IsReady() const From 08f6ba8274b39ca9b0edc31f0b65e5182e0622cc Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sat, 18 May 2013 22:29:51 +1200 Subject: [PATCH 04/11] I'm bad at mac.. sorry. Used the correct name string. --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 9f9192423c..4eac3ca5ff 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -162,7 +162,7 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot Wiimote *wm = new Wiimote(); wm->btd = dev; - if(IsBalanceBoardName(name)) + if(IsBalanceBoardName([[dev name] UTF8String])) { found_board = wm; NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str); From 59924d0291ec78a5763c675e2c943702fedfefb3 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sat, 18 May 2013 22:31:22 +1200 Subject: [PATCH 05/11] It never had logging here anyway... --- Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index 4eac3ca5ff..6f85f62a82 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -165,12 +165,10 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot if(IsBalanceBoardName([[dev name] UTF8String])) { found_board = wm; - NOTICE_LOG(WIIMOTE, "Found balance board (%s).", bdaddr_str); } else { found_wiimotes.push_back(wm); - NOTICE_LOG(WIIMOTE, "Found wiimote (%s).", bdaddr_str); } } From 7208823396762ae9659ec03addabe696fa93256b Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 19 May 2013 00:30:20 +1200 Subject: [PATCH 06/11] Added config for enabling Balance Board. Fixed other structures that still assumed 4 of everything. --- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 26 +++++++----- .../Core/DolphinWX/Src/WiimoteConfigDiag.cpp | 42 +++++++++++++++---- Source/Core/DolphinWX/Src/WiimoteConfigDiag.h | 2 +- Source/Core/InputCommon/Src/InputConfig.cpp | 9 ++-- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 1d3be13cc5..40c6ee0554 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -457,7 +457,10 @@ void LoadSettings() sec.Get("Source", &g_wiimote_sources[i], i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU); } - g_wiimote_sources[WIIMOTE_BALANCE_BOARD] = WIIMOTE_SRC_REAL; + + std::string secname("BalanceBoard"); + IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str()); + sec.Get("Source", &g_wiimote_sources[WIIMOTE_BALANCE_BOARD], WIIMOTE_SRC_NONE); } // config dialog calls this when some settings change @@ -501,14 +504,14 @@ void Shutdown(void) void ChangeWiimoteSource(unsigned int index, int source) { { - std::lock_guard lk(g_refresh_lock); - g_wiimote_sources[index] = source; - g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); - g_wiimote_scanner.WantBB(0 != CalculateWantedBB()); - - - // kill real connection (or swap to different slot) - DoneWithWiimote(index); + std::lock_guard lk(g_refresh_lock); + g_wiimote_sources[index] = source; + g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes()); + g_wiimote_scanner.WantBB(0 != CalculateWantedBB()); + + + // kill real connection (or swap to different slot) + DoneWithWiimote(index); } // reconnect to the emulator @@ -635,7 +638,7 @@ void Refresh() std::vector found_wiimotes; Wiimote* found_board = NULL; - if (0 != CalculateWantedWiimotes()) + if (0 != CalculateWantedWiimotes() || 0 != CalculateWantedBB()) { // Don't hang Dolphin when searching lk.unlock(); @@ -646,7 +649,8 @@ void Refresh() CheckForDisconnectedWiimotes(); // Brief rumble for already connected Wiimotes. - for (int i = 0; i < MAX_BBMOTES; ++i) + // Don't do this for Balance Board as it doesn't have rumble anyway. + for (int i = 0; i < MAX_WIIMOTES; ++i) { if (g_wiimotes[i]) { diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index 1a1544373c..be29f11015 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -54,8 +54,25 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin wiimote_sizer->Add(wiimote_configure_bt[i]); } wiimote_group->Add(wiimote_sizer, 1, wxEXPAND, 5 ); + + + // "BalanceBoard" layout + wxStaticBoxSizer* const bb_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board")); + wxFlexGridSizer* const bb_sizer = new wxFlexGridSizer(1, 5, 5); + int source_ctrl_id = wxWindow::NewControlId(); + m_wiimote_index_from_ctrl_id.insert(std::pair(source_ctrl_id, WIIMOTE_BALANCE_BOARD)); + const wxString src_choices[] = { _("None"), _("Real Balance Board") }; + wxChoice* bb_source = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize, sizeof(src_choices)/sizeof(*src_choices), src_choices); + bb_source->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &WiimoteConfigDiag::SelectSource, this); + + m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] = g_wiimote_sources[WIIMOTE_BALANCE_BOARD]; + bb_source->Select(m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] ? 1 : 0); + + bb_sizer->Add(bb_source, 0, wxALIGN_CENTER_VERTICAL); + + bb_group->Add(bb_sizer, 1, wxEXPAND, 5 ); - + // "Real wiimotes" controls wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition); refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this); @@ -166,6 +183,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin // Dialog layout main_sizer->Add(wiimote_group, 0, wxEXPAND | wxALL, 5); + main_sizer->Add(bb_group, 0, wxEXPAND | wxALL, 5); main_sizer->Add(real_wiimotes_group, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); main_sizer->Add(general_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5); @@ -196,17 +214,23 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event) // Revert if the dialog is canceled. int index = m_wiimote_index_from_ctrl_id[event.GetId()]; - 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(); + if(index != WIIMOTE_BALANCE_BOARD) + { + 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(); + } else - wiimote_configure_bt[index]->Enable(); + { + WiimoteReal::ChangeWiimoteSource(index, event.GetInt() ? WIIMOTE_SRC_REAL : WIIMOTE_SRC_NONE); + } } void WiimoteConfigDiag::RevertSource() { - for (int i = 0; i < MAX_WIIMOTES; ++i) + for (int i = 0; i < MAX_BBMOTES; ++i) g_wiimote_sources[i] = m_orig_wiimote_sources[i]; } @@ -225,6 +249,10 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event) sec.Set("Source", (int)g_wiimote_sources[i]); } + + std::string secname("BalanceBoard"); + IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str()); + sec.Set("Source", (int)g_wiimote_sources[WIIMOTE_BALANCE_BOARD]); inifile.Save(ini_filename); diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h index 88fea037a9..dac963d9f3 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.h @@ -76,7 +76,7 @@ private: wxNotebook* m_pad_notebook; std::map m_wiimote_index_from_ctrl_id; - unsigned int m_orig_wiimote_sources[MAX_WIIMOTES]; + unsigned int m_orig_wiimote_sources[MAX_BBMOTES]; wxButton* wiimote_configure_bt[MAX_WIIMOTES]; std::map m_wiimote_index_from_conf_bt_id; diff --git a/Source/Core/InputCommon/Src/InputConfig.cpp b/Source/Core/InputCommon/Src/InputConfig.cpp index 65529b0a3f..e1af00f41d 100644 --- a/Source/Core/InputCommon/Src/InputConfig.cpp +++ b/Source/Core/InputCommon/Src/InputConfig.cpp @@ -3,7 +3,8 @@ // Refer to the license.txt file included. #include "InputConfig.h" -#include "../../Core/Src/ConfigManager.h" +#include "../Src/ConfigManager.h" +#include "../Src/HW/Wiimote.h" InputPlugin::~InputPlugin() { @@ -18,9 +19,9 @@ bool InputPlugin::LoadConfig(bool isGC) { IniFile inifile; IniFile game_ini; - bool useProfile[4] = {false, false, false, false}; - std::string num[4] = {"1", "2", "3", "4"}; - std::string profile[4]; + bool useProfile[MAX_BBMOTES] = {false, false, false, false, false}; + std::string num[MAX_BBMOTES] = {"1", "2", "3", "4", "BB"}; + std::string profile[MAX_BBMOTES]; std::string path; if (SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() != "00000000") From 065d772696fd66720574fadbcbf4ce8190ff5d20 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 19 May 2013 14:45:24 +1200 Subject: [PATCH 07/11] Windows should have support for Balance Board now. Needs to be tested. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 25 +++++++++++++++---- Source/Core/InputCommon/Src/InputConfig.cpp | 4 +-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 4aae05fa3a..cf47315066 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -183,7 +183,7 @@ void WiimoteScanner::Update() // 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() +void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimote* & found_board) { ProcessWiimotes(true, [](HANDLE hRadio, const BLUETOOTH_RADIO_INFO& rinfo, BLUETOOTH_DEVICE_INFO_STRUCT& btdi) { @@ -198,8 +198,6 @@ std::vector WiimoteScanner::FindWiimotes() // Get all hid devices connected HDEVINFO const device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); - std::vector wiimotes; - SP_DEVICE_INTERFACE_DATA device_data; device_data.cbSize = sizeof(device_data); PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; @@ -217,7 +215,25 @@ std::vector WiimoteScanner::FindWiimotes() { auto const wm = new Wiimote; wm->devicepath = detail_data->DevicePath; - wiimotes.push_back(wm); + + TCHAR name[128] = {}; + HANDLE dev_handle = CreateFile(wm->devicepath.c_str(), + GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + + if (dev_handle != INVALID_HANDLE_VALUE && HidD_GetProductString(dev_handle, name, 128) && IsBalanceBoardName(TStrToUTF8(name))) + { + found_board = wm; + } + else + { + found_wiimotes.push_back(wm); + } + + if(dev_handle != INVALID_HANDLE_VALUE) + { + CloseHandle(dev_handle); + } } free(detail_data); @@ -229,7 +245,6 @@ std::vector WiimoteScanner::FindWiimotes() //if (!wiimotes.empty()) // SLEEP(2000); - return wiimotes; } bool WiimoteScanner::IsReady() const diff --git a/Source/Core/InputCommon/Src/InputConfig.cpp b/Source/Core/InputCommon/Src/InputConfig.cpp index e1af00f41d..96fc6205db 100644 --- a/Source/Core/InputCommon/Src/InputConfig.cpp +++ b/Source/Core/InputCommon/Src/InputConfig.cpp @@ -3,8 +3,8 @@ // Refer to the license.txt file included. #include "InputConfig.h" -#include "../Src/ConfigManager.h" -#include "../Src/HW/Wiimote.h" +#include "../../Core/Src/ConfigManager.h" +#include "../../Core/Src/HW/Wiimote.h" InputPlugin::~InputPlugin() { From 56976ad6ea5491809732129b54221bc5674e68b6 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Sun, 19 May 2013 14:57:04 +1200 Subject: [PATCH 08/11] Fix coding style. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index cf47315066..4eded21d2d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -217,11 +217,17 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot wm->devicepath = detail_data->DevicePath; TCHAR name[128] = {}; - HANDLE dev_handle = CreateFile(wm->devicepath.c_str(), - GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + HANDLE dev_handle = CreateFile(wm->devicepath.c_str(), + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); - if (dev_handle != INVALID_HANDLE_VALUE && HidD_GetProductString(dev_handle, name, 128) && IsBalanceBoardName(TStrToUTF8(name))) + if (dev_handle != INVALID_HANDLE_VALUE && + HidD_GetProductString(dev_handle, name, 128) && + IsBalanceBoardName(TStrToUTF8(name))) { found_board = wm; } @@ -230,7 +236,7 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot found_wiimotes.push_back(wm); } - if(dev_handle != INVALID_HANDLE_VALUE) + if (dev_handle != INVALID_HANDLE_VALUE) { CloseHandle(dev_handle); } From e2b0632334622ed9eacd5955ce90e150ccf59c30 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Tue, 21 May 2013 21:42:19 +1200 Subject: [PATCH 09/11] Added a method for detecting Wiimote extension. This is run before a Wiimote will be considered. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 327 +++++++++++++----- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 3 +- 2 files changed, 250 insertions(+), 80 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 4eded21d2d..84cbe93bfa 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -138,6 +138,10 @@ inline void init_lib() namespace WiimoteReal { + + +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len); +int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index); template void ProcessWiimotes(bool new_scan, T& callback); @@ -212,33 +216,23 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot // Query the data for this device if (SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) - { + { auto const wm = new Wiimote; wm->devicepath = detail_data->DevicePath; - - TCHAR name[128] = {}; - HANDLE dev_handle = CreateFile(wm->devicepath.c_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); - - if (dev_handle != INVALID_HANDLE_VALUE && - HidD_GetProductString(dev_handle, name, 128) && - IsBalanceBoardName(TStrToUTF8(name))) + bool real_wiimote = false, is_bb = false; + + CheckDeviceType(wm->devicepath, real_wiimote, is_bb); + if (is_bb) { found_board = wm; } - else + else if (real_wiimote) { found_wiimotes.push_back(wm); } - - if (dev_handle != INVALID_HANDLE_VALUE) + else { - CloseHandle(dev_handle); + free(wm); } } @@ -252,6 +246,169 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot // SLEEP(2000); } +int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, int size, int attempts) +{ + OVERLAPPED hid_overlap_write = OVERLAPPED(); + hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL); + enum win_bt_stack_t stack = MSBT_STACK_UNKNOWN; + + DWORD written = 0; + + for (; attempts>0; --attempts) + { + if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, size)) + { + auto const wait_result = WaitForSingleObject(hid_overlap_write.hEvent, WIIMOTE_DEFAULT_TIMEOUT); + if (WAIT_TIMEOUT == wait_result) + { + WARN_LOG(WIIMOTE, "CheckDeviceType_Write: A timeout occurred on writing to Wiimote."); + CancelIo(dev_handle); + continue; + } + else if (WAIT_FAILED == wait_result) + { + WARN_LOG(WIIMOTE, "CheckDeviceType_Write: A wait error occurred on writing to Wiimote."); + CancelIo(dev_handle); + continue; + } + if (GetOverlappedResult(dev_handle, &hid_overlap_write, &written, TRUE)) + { + break; + } + } + } + + CloseHandle(hid_overlap_write.hEvent); + + return written; +} + +int CheckDeviceType_Read(HANDLE &dev_handle, u8* buf, int attempts) +{ + OVERLAPPED hid_overlap_read = OVERLAPPED(); + hid_overlap_read.hEvent = CreateEvent(NULL, true, false, NULL); + int read = 0; + for (; attempts>0; --attempts) + { + read = _IORead(dev_handle, hid_overlap_read, buf, 1); + if (read > 0) + break; + } + + CloseHandle(hid_overlap_read.hEvent); + + return read; +} + +// A convoluted way of checking if a device is a Wii Balance Board and if it is a connectable Wiimote. +// Because nothing on Windows should be easy. +// (We can't seem to easily identify the bluetooth device an HID device belongs to...) +void WiimoteScanner::CheckDeviceType(std::basic_string &devicepath, bool &real_wiimote, bool &is_bb) +{ + real_wiimote = false; + is_bb = false; + +#ifdef SHARE_WRITE_WIIMOTES + std::lock_guard lk(g_connected_wiimotes_lock); + if (g_connected_wiimotes.count(devicepath) != 0) + return; +#endif + + HANDLE dev_handle = CreateFile(devicepath.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, + NULL); + if (dev_handle == INVALID_HANDLE_VALUE) + return; + // enable to only check for official nintendo wiimotes/bb's + bool check_vidpid = false; + HIDD_ATTRIBUTES attrib; + attrib.Size = sizeof(attrib); + if (!check_vidpid || + (HidD_GetAttributes(dev_handle, &attrib) && + (attrib.VendorID == 0x057e) && + (attrib.ProductID == 0x0306))) + { + int rc = 0; + // max_cycles insures we are never stuck here due to bad coding... + int max_cycles = 20; + u8 buf[MAX_PAYLOAD] = {0}; + + u8 const req_status_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REQUEST_STATUS, 0}; + + rc = CheckDeviceType_Write(dev_handle, + req_status_report, + sizeof(req_status_report), + 1); + while (rc > 0 && --max_cycles > 0) + { + if ((rc = CheckDeviceType_Read(dev_handle, buf, 1)) <= 0) + break; + + switch (buf[1]) + { + case WM_STATUS_REPORT: + { + real_wiimote = true; + wm_status_report * wsr = (wm_status_report*)&buf[2]; + if (wsr->extension) + { + // Wiimote with extension, we ask it what kind. + u8 read_ext[MAX_PAYLOAD] = {0}; + read_ext[0] = WM_SET_REPORT | WM_BT_OUTPUT; + read_ext[1] = WM_READ_DATA; + // Extension type register. + *(u32*)&read_ext[2] = Common::swap32(0x4a400fa); + // Size. + *(u16*)&read_ext[6] = Common::swap16(6); + rc = CheckDeviceType_Write(dev_handle, read_ext, 8, 1); + } + else + { + // Normal Wiimote, exit while and be happy. + rc = -1; + } + break; + } + case WM_ACK_DATA: + { + real_wiimote = true; + break; + } + case WM_READ_DATA_REPLY: + { + wm_read_data_reply * wrdr + = (wm_read_data_reply*)&buf[2]; + // Check if it has returned what we asked. + if (Common::swap16(wrdr->address) == 0x00fa) + { + // 0x020420A40000ULL means balance board. + u64 ext_type = (*(u64*)&wrdr->data[0]); + is_bb = ext_type == 0x020420A40000ULL; + } + else + { + ERROR_LOG(WIIMOTE, + "CheckDeviceType: GOT UNREQUESTED ADDRESS %X", + Common::swap16(wrdr->address)); + } + // force end + rc = -1; + + break; + } + default: + { + // We let read try again incase there is another packet waiting. + // ERROR_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]); + break; + } + } + } + } + CloseHandle(dev_handle); +} bool WiimoteScanner::IsReady() const { @@ -376,7 +533,7 @@ bool Wiimote::IsConnected() const // positive = read packet // negative = didn't read packet // zero = error -int Wiimote::IORead(u8* buf) +int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index) { // Add data report indicator byte (here, 0xa1) buf[0] = 0xa1; @@ -429,78 +586,92 @@ int Wiimote::IORead(u8* buf) return bytes + 1; } -int Wiimote::IOWrite(const u8* buf, int len) +// positive = read packet +// negative = didn't read packet +// zero = error +int Wiimote::IORead(u8* buf) +{ + return _IORead(dev_handle, hid_overlap_read, buf, index); +} + + +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len) { switch (stack) { - case MSBT_STACK_UNKNOWN: - { - // Try to auto-detect the stack type - stack = MSBT_STACK_BLUESOLEIL; - if (IOWrite(buf, len)) - return 1; - - stack = MSBT_STACK_MS; - if (IOWrite(buf, len)) - return 1; - - stack = MSBT_STACK_UNKNOWN; - break; - } - case MSBT_STACK_MS: - { - auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1); - //FlushFileBuffers(dev_handle); - - if (!result) + case MSBT_STACK_UNKNOWN: { - auto err = GetLastError(); - if (err == 121) + // Try to auto-detect the stack type + stack = MSBT_STACK_BLUESOLEIL; + if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, len)) + return 1; + + stack = MSBT_STACK_MS; + if (_IOWrite(dev_handle, hid_overlap_write, stack, buf, len)) + return 1; + + stack = MSBT_STACK_UNKNOWN; + break; + } + case MSBT_STACK_MS: + { + auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1); + //FlushFileBuffers(dev_handle); + + if (!result) { - // Semaphore timeout - NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote"); + auto err = GetLastError(); + if (err == 121) + { + // Semaphore timeout + NOTICE_LOG(WIIMOTE, "WiimoteIOWrite[MSBT_STACK_MS]: Unable to send data to the Wiimote"); + } + else + { + WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err); + } + } + + return result; + break; + } + case MSBT_STACK_BLUESOLEIL: + { + 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 { - WARN_LOG(WIIMOTE, "IOWrite[MSBT_STACK_MS]: ERROR: %08x", err); + auto const err = GetLastError(); + if (ERROR_IO_PENDING == err) + { + CancelIo(dev_handle); + } } + break; } - - return result; - break; } - case MSBT_STACK_BLUESOLEIL: - { - 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; } +int Wiimote::IOWrite(const u8* buf, int len) +{ + return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len); +} + // invokes callback for each found wiimote bluetooth device template void ProcessWiimotes(bool new_scan, T& callback) @@ -519,7 +690,7 @@ void ProcessWiimotes(bool new_scan, T& callback) BLUETOOTH_FIND_RADIO_PARAMS radioParam; radioParam.dwSize = sizeof(radioParam); - + HANDLE hRadio; // TODO: save radio(s) in the WiimoteScanner constructor? diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 695dc86b82..d195f92120 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -137,8 +137,7 @@ private: volatile bool m_want_bb; #if defined(_WIN32) - - + void CheckDeviceType(std::basic_string &devicepath, bool &real_wiimote, bool &is_bb); #elif defined(__linux__) && HAVE_BLUEZ int device_id; int device_sock; From f178015461a558bfde468611e203757098af1740 Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Tue, 21 May 2013 22:54:01 +1200 Subject: [PATCH 10/11] Better checking for extension. --- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 84cbe93bfa..5e4f32caab 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -344,13 +344,16 @@ void WiimoteScanner::CheckDeviceType(std::basic_string &devicepath, bool while (rc > 0 && --max_cycles > 0) { if ((rc = CheckDeviceType_Read(dev_handle, buf, 1)) <= 0) + { + // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Read failed..."); break; + } switch (buf[1]) { case WM_STATUS_REPORT: { - real_wiimote = true; + // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Status Report"); wm_status_report * wsr = (wm_status_report*)&buf[2]; if (wsr->extension) { @@ -366,6 +369,7 @@ void WiimoteScanner::CheckDeviceType(std::basic_string &devicepath, bool } else { + real_wiimote = true; // Normal Wiimote, exit while and be happy. rc = -1; } @@ -373,18 +377,23 @@ void WiimoteScanner::CheckDeviceType(std::basic_string &devicepath, bool } case WM_ACK_DATA: { - real_wiimote = true; + // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Ack"); break; } case WM_READ_DATA_REPLY: { + // DEBUG_LOG(WIIMOTE, "CheckDeviceType: Got Data Reply"); wm_read_data_reply * wrdr = (wm_read_data_reply*)&buf[2]; // Check if it has returned what we asked. if (Common::swap16(wrdr->address) == 0x00fa) { + real_wiimote = true; // 0x020420A40000ULL means balance board. u64 ext_type = (*(u64*)&wrdr->data[0]); + // DEBUG_LOG(WIIMOTE, + // "CheckDeviceType: GOT EXT TYPE %llX", + // ext_type); is_bb = ext_type == 0x020420A40000ULL; } else @@ -401,7 +410,7 @@ void WiimoteScanner::CheckDeviceType(std::basic_string &devicepath, bool default: { // We let read try again incase there is another packet waiting. - // ERROR_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]); + // DEBUG_LOG(WIIMOTE, "CheckDeviceType: GOT UNKNOWN REPLY: %X", buf[1]); break; } } From d642abce46fa3a999f762b329ae0154891c7170a Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Tue, 21 May 2013 23:31:41 +1200 Subject: [PATCH 11/11] Only show 4 config dialogs in wiimote config. --- Source/Core/DolphinWX/Src/InputConfigDiag.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp index cd17c4c682..ef4ae8d29b 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp @@ -5,6 +5,7 @@ #include "InputConfigDiag.h" #include "UDPConfigDiag.h" #include "WxUtils.h" +#include "HW/Wiimote.h" void GamepadPage::ConfigUDPWii(wxCommandEvent &event) { @@ -947,7 +948,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin , m_plugin(plugin) { m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT); - for (unsigned int i = 0; i < plugin.controllers.size(); ++i) + for (unsigned int i = 0; i < std::min(plugin.controllers.size(), (size_t)MAX_WIIMOTES); ++i) { GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this); m_padpages.push_back(gp);