IPC_HLE/57e_305: Fake vendor-specific command replies

Homebrew programs seem to rely on getting a reply to the vendor
specific commands, without which Bluetooth initialisation will never
complete.

This vendor-specific command is typically used to patch the Wii's
Bluetooth module, so the replies are only faked when the passed through
adapter is not a Wii Bluetooth module.
This commit is contained in:
Léo Lam 2016-09-27 21:33:45 +02:00
parent 5b50b1e1aa
commit b91095a9fc
2 changed files with 27 additions and 1 deletions

View File

@ -171,6 +171,12 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
m_fake_read_buffer_size_reply.Set();
return GetNoReply();
}
if (!m_is_wii_bt_module && (opcode == 0xFC4C || opcode == 0xFC4F))
{
m_fake_vendor_command_reply.Set();
m_fake_vendor_command_reply_opcode = opcode;
return GetNoReply();
}
if (opcode == HCI_CMD_DELETE_STORED_LINK_KEY)
{
// Delete link key(s) from our own link key storage when the game tells the adapter to
@ -208,6 +214,11 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
FakeReadBufferSizeReply(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
{
FakeVendorCommandReply(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
m_sync_button_state == SyncButtonState::Pressed)
{
@ -364,6 +375,18 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305_real::SendHCIStoreLinkKeyCommand()
return true;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const CtrlBuffer& ctrl)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event->PacketIndicator = 0x01;
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
ctrl.SetRetVal(sizeof(SHCIEventCommand));
EnqueueReply(ctrl.m_cmd_address);
}
// Due to how the widcomm stack which Nintendo uses is coded, we must never
// let the stack think the controller is buffering more than 10 data packets
// - it will cause a u8 underflow and royally screw things up.

View File

@ -68,8 +68,10 @@ private:
Common::Flag m_thread_running;
std::thread m_thread;
// Set when we received a command to read the buffer size, and we need to fake a reply
// Set when we received a command to which we need to fake a reply
Common::Flag m_fake_read_buffer_size_reply;
Common::Flag m_fake_vendor_command_reply;
u16 m_fake_vendor_command_reply_opcode;
bool m_is_wii_bt_module = false;
@ -77,6 +79,7 @@ private:
void SendHCIResetCommand();
void SendHCIDeleteLinkKeyCommand();
bool SendHCIStoreLinkKeyCommand();
void FakeVendorCommandReply(const CtrlBuffer& ctrl);
void FakeReadBufferSizeReply(const CtrlBuffer& ctrl);
void FakeSyncButtonEvent(const CtrlBuffer& ctrl, const u8* payload, u8 size);
void FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl);