From 19a50b3c51c46a2ed903c501c583600fa3f69eeb Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Thu, 16 Sep 2010 22:50:18 +0000 Subject: [PATCH] New Wiimote Plugin: Added a real wiimote "Pair Up" button on Windows for the Microsoft bluetooth stack, like the old plugin. The PairUp function was copied from the old plugin and cleaned up. (Mostly untested because I'm not using the MS stack) Please test. Other minor changes to emu-wiimote and DInput. (Perhaps the "Refresh" button should call PairUp() followed by Refresh() to make the dialog simpler.) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6213 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../DInput/DInputJoystick.cpp | 6 +- .../Src/WiimoteConfigDiag.cpp | 47 ++++++-- .../Plugin_WiimoteNew/Src/WiimoteConfigDiag.h | 4 + .../Src/WiimoteEmu/EmuSubroutines.cpp | 13 +++ .../Src/WiimoteReal/WiimoteReal.cpp | 106 ++++++++++++++++++ .../Src/WiimoteReal/WiimoteReal.h | 4 + 6 files changed, 169 insertions(+), 11 deletions(-) diff --git a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp index 720f41b2d3..f88e90b1cc 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/DInput/DInputJoystick.cpp @@ -26,9 +26,9 @@ static const struct {GUID_Square, "Square"}, // DIPERIODIC ... {GUID_Sine, "Sine"}, {GUID_Triangle, "Triangle"}, - {GUID_SawtoothUp, "SawtoothUp"}, - {GUID_SawtoothDown, "SawtoothDown"}, - //{GUID_Spring, "Spring"}, // DIEFT_CUSTOMFORCE ... < i think + {GUID_SawtoothUp, "Sawtooth Up"}, + {GUID_SawtoothDown, "Sawtooth Down"}, + //{GUID_Spring, "Spring"}, // DICUSTOMFORCE ... < i think //{GUID_Damper, "Damper"}, //{GUID_Inertia, "Inertia"}, //{GUID_Friction, "Friction"}, diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp index 082c4d9933..f39f786eaa 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp @@ -4,6 +4,13 @@ #define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler( f ), (wxObject*)0, (wxEvtHandler*)s) +const wxString& ConnectedWiimotesString() +{ + static wxString str = wxT("Connected to . Wiimotes"); + str[13] = wxChar(wxT('0') + WiimoteReal::Initialize()); + return str; +} + WiimoteConfigPage::WiimoteConfigPage(wxWindow* const parent, const int index) : wxNotebookPage(parent, -1, wxDefaultPosition, wxDefaultSize) , m_index(index) @@ -28,19 +35,26 @@ WiimoteConfigPage::WiimoteConfigPage(wxWindow* const parent, const int index) // real wiimote m_connected_wiimotes_txt = new wxStaticText(this, -1, wxEmptyString); - wxStaticBoxSizer* const wiimote_real_sizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Real Wiimote")); + m_connected_wiimotes_txt->SetLabel(ConnectedWiimotesString()); + wxButton* const refresh_btn = new wxButton(this, -1, wxT("Refresh"), wxDefaultPosition); _connect_macro_(refresh_btn, WiimoteConfigPage::RefreshRealWiimotes, wxEVT_COMMAND_BUTTON_CLICKED, this); - wiimote_real_sizer->Add(m_connected_wiimotes_txt, 1, wxALIGN_CENTER | wxALL, 5); - wiimote_real_sizer->Add(refresh_btn, 1, wxALIGN_CENTER | wxALL, 5); - - m_connected_wiimotes_txt->SetLabel(wxString(wxT("Connected to ")) + wxChar(wxT('0') + WiimoteReal::Initialize()) + wxT(" Real Wiimotes")); + wxStaticBoxSizer* const wiimote_real_sizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Real Wiimote")); + wiimote_real_sizer->AddStretchSpacer(1); + wiimote_real_sizer->Add(m_connected_wiimotes_txt, 0, wxALIGN_CENTER | wxBOTTOM | wxLEFT | wxRIGHT, 5); +#ifdef _WIN32 + wxButton* const pairup_btn = new wxButton(this, -1, wxT("Pair Up"), wxDefaultPosition); + _connect_macro_(pairup_btn, WiimoteConfigPage::PairUpRealWiimotes, wxEVT_COMMAND_BUTTON_CLICKED, this); + wiimote_real_sizer->Add(pairup_btn, 0, wxALIGN_CENTER | wxBOTTOM, 5); +#endif + wiimote_real_sizer->Add(refresh_btn, 0, wxALIGN_CENTER, 5); + wiimote_real_sizer->AddStretchSpacer(1); // sizers wxBoxSizer* const left_sizer = new wxBoxSizer(wxVERTICAL); - left_sizer->Add(input_src_sizer, 1, wxEXPAND | wxBOTTOM, 5); - left_sizer->Add(wiimote_emu_sizer, 1, wxEXPAND, 0); + left_sizer->Add(input_src_sizer, 0, wxEXPAND | wxBOTTOM, 5); + left_sizer->Add(wiimote_emu_sizer, 0, wxEXPAND, 0); wxBoxSizer* const main_sizer = new wxBoxSizer(wxHORIZONTAL); main_sizer->Add(left_sizer, 1, wxLEFT | wxTOP | wxBOTTOM | wxEXPAND, 5); @@ -81,10 +95,27 @@ void WiimoteConfigDiag::ConfigEmulatedWiimote(wxCommandEvent& event) m_emu_config_diag->Destroy(); } +#ifdef _WIN32 +void WiimoteConfigPage::PairUpRealWiimotes(wxCommandEvent& event) +{ + const int paired = WiimoteReal::PairUp(); + + if (paired > 0) + { + // Will this message be anoying? + //PanicAlert("Paired %d wiimotes.", paired); + WiimoteReal::Refresh(); + } + else if (paired < 0) + PanicAlert("A supported bluetooth device was not found!\n" + "(Only the Microsoft bluetooth stack is supported.)"); +} +#endif + void WiimoteConfigPage::RefreshRealWiimotes(wxCommandEvent& event) { WiimoteReal::Refresh(); - m_connected_wiimotes_txt->SetLabel(wxString(wxT("Connected to ")) + wxChar(wxT('0') + WiimoteReal::Initialize()) + wxT(" Real Wiimotes")); + m_connected_wiimotes_txt->SetLabel(ConnectedWiimotesString()); } void WiimoteConfigPage::SelectSource(wxCommandEvent& event) diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.h index 1aed269dd1..75c3e482a8 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.h +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.h @@ -20,7 +20,11 @@ class WiimoteConfigPage : public wxNotebookPage public: WiimoteConfigPage(wxWindow* const parent, const int index); +#ifdef _WIN32 + void PairUpRealWiimotes(wxCommandEvent& event); +#endif void RefreshRealWiimotes(wxCommandEvent& event); + void SelectSource(wxCommandEvent& event); private: diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp index b330f9fe4b..23eec2d416 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp @@ -105,6 +105,7 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) case WM_LEDS : // 0x11 //INFO_LOG(WIIMOTE, "Set LEDs: 0x%02x", sr->data[0]); m_status.leds = sr->data[0] >> 4; + return; // no ack break; case WM_REPORT_MODE : // 0x12 @@ -114,12 +115,18 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) case WM_IR_PIXEL_CLOCK : // 0x13 //INFO_LOG(WIIMOTE, "WM IR Clock: 0x%02x", sr->data[0]); //m_ir_clock = (sr->data[0] & 0x04) ? 1 : 0; + + if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set + return; break; case WM_SPEAKER_ENABLE : // 0x14 //INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]); //PanicAlert( "WM Speaker Enable: %d", sr->data[0] ); m_status.speaker = (sr->data[0] & 0x04) ? 1 : 0; + + if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set + return; break; case WM_REQUEST_STATUS : // 0x15 @@ -153,6 +160,9 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) memset(&m_channel_status, 0, sizeof(m_channel_status)); #endif m_speaker_mute = (sr->data[0] & 0x04) ? 1 : 0; + + if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set + return; break; case WM_IR_LOGIC: // 0x1a @@ -161,6 +171,9 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) // so that WmRequestStatus() knows about it //INFO_LOG(WIIMOTE, "WM IR Enable: 0x%02x", sr->data[0]); m_status.ir = (sr->data[0] & 0x04) ? 1 : 0; + + if (0 == (sr->data[0] & 0x02)) // only ack if 0x02 bit is set + return; break; default: diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp index be2cc345c6..867d40f1f8 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp @@ -28,6 +28,12 @@ #include "../WiimoteEmu/WiimoteHid.h" +// used for pair up +#ifdef _WIN32 +#include +#pragma comment(lib, "Bthprops.lib") +#endif + unsigned int g_wiimote_sources[MAX_WIIMOTES]; namespace WiimoteReal @@ -484,4 +490,104 @@ THREAD_RETURN WiimoteThreadFunc(void* arg) return 0; } +#ifdef _WIN32 +// WiiMote Pair-Up, function will return amount of either new paired or unpaired devices +// negative number on failure +int PairUp(bool unpair) +{ + int nPaired = 0; + + BLUETOOTH_DEVICE_SEARCH_PARAMS srch; + srch.dwSize = sizeof(srch); + srch.fReturnAuthenticated = true; + srch.fReturnRemembered = true; + srch.fReturnConnected = true; // does not filter properly somehow, so we've to do an additional check on fConnected BT Devices + srch.fReturnUnknown = true; + srch.fIssueInquiry = true; + srch.cTimeoutMultiplier = 2; // == (2 * 1.28) seconds + + BLUETOOTH_FIND_RADIO_PARAMS radioParam; + radioParam.dwSize = sizeof(radioParam); + + HANDLE hRadio; + + // Enumerate BT radios + HBLUETOOTH_RADIO_FIND hFindRadio = BluetoothFindFirstRadio(&radioParam, &hRadio); + + if (NULL == hFindRadio) + return -1; + + while (hFindRadio) + { + BLUETOOTH_RADIO_INFO radioInfo; + radioInfo.dwSize = sizeof(radioInfo); + + // TODO: check for SUCCEEDED() + BluetoothGetRadioInfo(hRadio, &radioInfo); + + srch.hRadio = hRadio; + + BLUETOOTH_DEVICE_INFO btdi; + btdi.dwSize = sizeof(btdi); + + // Enumerate BT devices + HBLUETOOTH_DEVICE_FIND hFindDevice = BluetoothFindFirstDevice(&srch, &btdi); + while (hFindDevice) + { + //btdi.szName is sometimes missings it's content - it's a bt feature.. + DEBUG_LOG(WIIMOTE, "authed %i connected %i remembered %i ", btdi.fAuthenticated, btdi.fConnected, btdi.fRemembered); + + // TODO: Probably could just check for "Nintendo RVL" + if (0 == wcscmp(btdi.szName, L"Nintendo RVL-WBC-01") || 0 == wcscmp(btdi.szName, L"Nintendo RVL-CNT-01")) + { + if (unpair) + { + if (SUCCEEDED(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. + BluetoothRemoveDevice(&btdi.Address); + } + + // Activate service + const DWORD hr = BluetoothSetServiceState(hRadio, &btdi, &HumanInterfaceDeviceServiceClass_UUID, BLUETOOTH_SERVICE_ENABLE); + if (SUCCEEDED(hr)) + ++nPaired; + else + ERROR_LOG(WIIMOTE, "Pair-Up: BluetoothSetServiceState() returned %08x", hr); + } + } + } + + if (false == BluetoothFindNextDevice(hFindDevice, &btdi)) + { + BluetoothFindDeviceClose(hFindDevice); + hFindDevice = NULL; + } + } + + if (false == BluetoothFindNextRadio(hFindRadio, &hRadio)) + { + BluetoothFindRadioClose(hFindRadio); + hFindRadio = NULL; + } + } + + return nPaired; +} +#endif + }; // end of namespace diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h index a2b9458223..c772ed06fa 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h @@ -96,6 +96,10 @@ void Update(int _WiimoteNumber); void DoState(PointerWrap &p); void StateChange(PLUGIN_EMUSTATE newState); +#ifdef _WIN32 +int PairUp(bool unpair = false); +#endif + }; // WiiMoteReal #endif