From 0ad123bdbb935a2a3a7de8d26f15e406a690781e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sun, 26 Jul 2020 14:10:37 -0500 Subject: [PATCH] BTEmu: Fix home menu inquiry assigning multiple wii remotes to wrong slots. --- Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp | 74 ++++++++++--------- Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h | 2 +- .../Core/IOS/USB/Bluetooth/WiimoteDevice.cpp | 19 +++-- .../Core/IOS/USB/Bluetooth/WiimoteDevice.h | 2 +- Source/Core/Core/IOS/USB/Bluetooth/hci.h | 1 + 5 files changed, 52 insertions(+), 46 deletions(-) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp index 0614b25a95..e3b7cc4340 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp @@ -394,7 +394,7 @@ void BluetoothEmu::ACLPool::WriteToEndpoint(const USB::V0BulkMessage& endpoint) m_ios.EnqueueIPCReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size); } -bool BluetoothEmu::SendEventInquiryComplete() +bool BluetoothEmu::SendEventInquiryComplete(u8 num_responses) { SQueuedEvent event(sizeof(SHCIEventInquiryComplete), 0); @@ -402,6 +402,7 @@ bool BluetoothEmu::SendEventInquiryComplete() inquiry_complete->EventType = HCI_EVENT_INQUIRY_COMPL; inquiry_complete->PayloadLength = sizeof(SHCIEventInquiryComplete) - 2; inquiry_complete->EventStatus = 0x00; + inquiry_complete->num_responses = num_responses; AddEventToQueue(event); @@ -412,48 +413,54 @@ bool BluetoothEmu::SendEventInquiryComplete() bool BluetoothEmu::SendEventInquiryResponse() { - static_assert(sizeof(SHCIEventInquiryResult) - 2 + (MAX_BBMOTES * sizeof(hci_inquiry_response)) < - 256); + // We only respond with the first discoverable remote. + // The Wii instructs users to press 1+2 in the desired play order. + // Responding with all remotes at once can place them in undesirable slots. + // Additional scans will connect each remote in the proper order. + constexpr u8 num_responses = 1; - SQueuedEvent event(static_cast(sizeof(SHCIEventInquiryResult) + - m_wiimotes.size() * sizeof(hci_inquiry_response)), - 0); + static_assert( + sizeof(SHCIEventInquiryResult) - 2 + (num_responses * sizeof(hci_inquiry_response)) < 256); - SHCIEventInquiryResult* inquiry_result = (SHCIEventInquiryResult*)event.buffer; - - inquiry_result->EventType = HCI_EVENT_INQUIRY_RESULT; - inquiry_result->num_responses = 0; - - for (size_t i = 0; i != m_wiimotes.size(); ++i) + const auto iter = std::find_if(m_wiimotes.begin(), m_wiimotes.end(), + std::mem_fn(&WiimoteDevice::IsInquiryScanEnabled)); + if (iter == m_wiimotes.end()) { - if (!m_wiimotes[i]->IsInquiryScanEnabled()) - continue; - - ++inquiry_result->num_responses; - - u8* buffer = event.buffer + sizeof(SHCIEventInquiryResult) + i * sizeof(hci_inquiry_response); - hci_inquiry_response* response = (hci_inquiry_response*)buffer; - - response->bdaddr = m_wiimotes[i]->GetBD(); - std::copy_n(m_wiimotes[i]->GetClass().begin(), HCI_CLASS_SIZE, response->uclass); - - response->page_scan_rep_mode = 1; - response->page_scan_period_mode = 0; - response->page_scan_mode = 0; - response->clock_offset = 0x3818; - - DEBUG_LOG(IOS_WIIMOTE, "Event: Send Fake Inquiry of one controller"); - DEBUG_LOG(IOS_WIIMOTE, " bd: %02x:%02x:%02x:%02x:%02x:%02x", response->bdaddr[0], - response->bdaddr[1], response->bdaddr[2], response->bdaddr[3], response->bdaddr[4], - response->bdaddr[5]); + // No remotes are discoverable. + SendEventInquiryComplete(0); + return false; } + const auto& wiimote = *iter; + + SQueuedEvent event( + u32(sizeof(SHCIEventInquiryResult) + num_responses * sizeof(hci_inquiry_response)), 0); + + const auto inquiry_result = reinterpret_cast(event.buffer); + inquiry_result->EventType = HCI_EVENT_INQUIRY_RESULT; + inquiry_result->num_responses = num_responses; + + u8* const buffer = event.buffer + sizeof(SHCIEventInquiryResult); + const auto response = reinterpret_cast(buffer); + + response->bdaddr = wiimote->GetBD(); + response->page_scan_rep_mode = 1; + response->page_scan_period_mode = 0; + response->page_scan_mode = 0; + std::copy_n(wiimote->GetClass().begin(), HCI_CLASS_SIZE, response->uclass); + response->clock_offset = 0x3818; + + DEBUG_LOG(IOS_WIIMOTE, "Event: Send Fake Inquiry of one controller"); + DEBUG_LOG(IOS_WIIMOTE, " bd: %02x:%02x:%02x:%02x:%02x:%02x", response->bdaddr[0], + response->bdaddr[1], response->bdaddr[2], response->bdaddr[3], response->bdaddr[4], + response->bdaddr[5]); + inquiry_result->PayloadLength = u8(sizeof(SHCIEventInquiryResult) - 2 + (inquiry_result->num_responses * sizeof(hci_inquiry_response))); AddEventToQueue(event); - + SendEventInquiryComplete(num_responses); return true; } @@ -1109,7 +1116,6 @@ void BluetoothEmu::CommandInquiry(const u8* input) SendEventCommandStatus(HCI_CMD_INQUIRY); SendEventInquiryResponse(); - SendEventInquiryComplete(); } void BluetoothEmu::CommandInquiryCancel(const u8* input) diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h index dd26e43e7d..6a518a2180 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h @@ -118,7 +118,7 @@ private: bool SendEventCommandStatus(u16 opcode); void SendEventCommandComplete(u16 opcode, const void* data, u32 data_size); bool SendEventInquiryResponse(); - bool SendEventInquiryComplete(); + bool SendEventInquiryComplete(u8 num_responses); bool SendEventRemoteNameReq(const bdaddr_t& bd); bool SendEventRequestConnection(const WiimoteDevice& wiimote); bool SendEventConnectionComplete(const bdaddr_t& bd, u8 status); diff --git a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp index 6ebdb51d30..43169b5872 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp @@ -72,7 +72,7 @@ WiimoteDevice::WiimoteDevice(Device::BluetoothEmu* host, int number, bdaddr_t bd // UGLY: This prevents an OSD message in SetSource -> Activate. if (hid_source) - m_baseband_state = BasebandState::RequestConnection; + SetBasebandState(BasebandState::RequestConnection); SetSource(hid_source); } @@ -110,7 +110,7 @@ void WiimoteDevice::DoState(PointerWrap& p) p.Do(m_link_key); p.Do(m_name); p.Do(m_channels); - p.Do(m_last_connect_request_counter); + p.Do(m_connection_request_counter); } u32 WiimoteDevice::GetNumber() const @@ -133,6 +133,9 @@ bool WiimoteDevice::IsPageScanEnabled() const void WiimoteDevice::SetBasebandState(BasebandState new_state) { + // Prevent button press from immediately causing connection attempts. + m_connection_request_counter = ::Wiimote::UPDATE_FREQ; + const bool was_connected = IsConnected(); m_baseband_state = new_state; @@ -230,11 +233,7 @@ void WiimoteDevice::Activate(bool connect) } if (message) - { - // Prevent button press from immediately causing a connection attempt. - m_last_connect_request_counter = ::Wiimote::UPDATE_FREQ; Core::DisplayMessage(fmt::format(message, GetNumber() + 1), CONNECTION_MESSAGE_TIME); - } } bool WiimoteDevice::EventConnectionRequest() @@ -344,14 +343,14 @@ void WiimoteDevice::Update() void WiimoteDevice::UpdateInput() { - if (m_last_connect_request_counter) - --m_last_connect_request_counter; + if (m_connection_request_counter) + --m_connection_request_counter; if (!IsSourceValid()) return; - // Allow button press to trigger activation once per second. - if (!m_last_connect_request_counter && m_baseband_state == BasebandState::Inactive) + // Allow button press to trigger activation after a second of no connection activity. + if (!m_connection_request_counter && m_baseband_state == BasebandState::Inactive) { if (Wiimote::NetPlay_GetButtonPress(GetNumber(), m_hid_source->IsButtonPressed())) Activate(true); diff --git a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h index 082f23a271..6573db08f2 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.h @@ -130,7 +130,7 @@ private: LinkKeyType m_link_key; std::string m_name; ChannelMap m_channels; - u8 m_last_connect_request_counter = 0; + u8 m_connection_request_counter = 0; void SetBasebandState(BasebandState); diff --git a/Source/Core/Core/IOS/USB/Bluetooth/hci.h b/Source/Core/Core/IOS/USB/Bluetooth/hci.h index 794b9af0d7..c36bb3d8d6 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/hci.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/hci.h @@ -2652,6 +2652,7 @@ struct SHCIEventInquiryComplete u8 EventType; u8 PayloadLength; u8 EventStatus; + u8 num_responses; }; struct SHCIEventReadClockOffsetComplete