IOS HLE: Deduplicate request code in OH1

This commit is contained in:
Léo Lam 2017-01-15 11:46:50 +01:00
parent d4de87a973
commit f9e806fd71
9 changed files with 150 additions and 233 deletions

View File

@ -50,24 +50,23 @@ void RestoreBTInfoSection(SysConf* sysconf)
File::Delete(filename);
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlMessage::CtrlMessage(const SIOCtlVBuffer& cmd_buffer)
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlMessage::CtrlMessage(const IOSIOCtlVRequest& ioctlv)
: ios_request(ioctlv)
{
request_type = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
request = Memory::Read_U8(cmd_buffer.InBuffer[1].m_Address);
value = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[2].m_Address));
index = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[3].m_Address));
length = Common::swap16(Memory::Read_U16(cmd_buffer.InBuffer[4].m_Address));
payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
address = cmd_buffer.m_Address;
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address);
request = Memory::Read_U8(ioctlv.in_vectors[1].address);
value = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[2].address));
index = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[3].address));
length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address));
payload_addr = ioctlv.io_vectors[0].address;
}
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::CtrlBuffer(const SIOCtlVBuffer& cmd_buffer,
const u32 command_address)
CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::CtrlBuffer(const IOSIOCtlVRequest& ioctlv)
: ios_request(ioctlv)
{
m_endpoint = Memory::Read_U8(cmd_buffer.InBuffer[0].m_Address);
m_length = Memory::Read_U16(cmd_buffer.InBuffer[1].m_Address);
m_payload_addr = cmd_buffer.PayloadBuffer[0].m_Address;
m_cmd_address = command_address;
m_endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
m_length = Memory::Read_U16(ioctlv.in_vectors[1].address);
m_payload_addr = ioctlv.io_vectors[0].address;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8* src,
@ -77,8 +76,3 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::FillBuffer(const u8*
m_length);
Memory::CopyToEmu(m_payload_addr, src, size);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_base::CtrlBuffer::SetRetVal(const u32 retval) const
{
Memory::Write_U32(retval, m_cmd_address + 4);
}

View File

@ -24,11 +24,6 @@ public:
: IWII_IPC_HLE_Device(device_id, device_name)
{
}
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_base() override = default;
virtual IPCCommandResult Open(u32 command_address, u32 mode) override = 0;
virtual void DoState(PointerWrap& p) override = 0;
virtual void UpdateSyncButtonState(bool is_held) {}
virtual void TriggerSyncButtonPressedEvent() {}
@ -56,31 +51,23 @@ protected:
struct CtrlMessage
{
CtrlMessage() = default;
CtrlMessage(const SIOCtlVBuffer& cmd_buffer);
CtrlMessage(const IOSIOCtlVRequest& ioctlv);
IOSIOCtlVRequest ios_request;
u8 request_type = 0;
u8 request = 0;
u16 value = 0;
u16 index = 0;
u16 length = 0;
u32 payload_addr = 0;
u32 address = 0;
};
class CtrlBuffer
struct CtrlBuffer
{
public:
CtrlBuffer() = default;
CtrlBuffer(const SIOCtlVBuffer& cmd_buffer, u32 command_address);
CtrlBuffer(const IOSIOCtlVRequest& ioctlv);
IOSIOCtlVRequest ios_request;
void FillBuffer(const u8* src, size_t size) const;
void SetRetVal(const u32 retval) const;
bool IsValid() const { return m_cmd_address != 0; }
void Invalidate() { m_cmd_address = m_payload_addr = 0; }
u8 m_endpoint = 0;
u16 m_length = 0;
u32 m_payload_addr = 0;
u32 m_cmd_address = 0;
};
};

View File

@ -95,8 +95,6 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::CWII_IPC_HLE_Device_usb_oh1_57e_305_emu
m_ControllerBD.b[4] = 0x00;
m_ControllerBD.b[5] = 0xFF;
memset(m_PacketCount, 0, sizeof(m_PacketCount));
Host_SetWiiMoteConnectionState(0);
}
@ -106,6 +104,18 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::~CWII_IPC_HLE_Device_usb_oh1_57e_305_em
SetUsbPointer(nullptr);
}
template <typename T>
static void DoStateForMessage(PointerWrap& p, std::unique_ptr<T>& message)
{
u32 request_address = (message != nullptr) ? message->ios_request.address : 0;
p.Do(request_address);
if (request_address != 0)
{
IOSIOCtlVRequest request{request_address};
message = std::make_unique<T>(request);
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DoState(PointerWrap& p)
{
bool passthrough_bluetooth = false;
@ -119,10 +129,9 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::DoState(PointerWrap& p)
p.Do(m_is_active);
p.Do(m_ControllerBD);
p.Do(m_CtrlSetup);
p.Do(m_ACLSetup);
p.DoPOD(m_HCIEndpoint);
p.DoPOD(m_ACLEndpoint);
DoStateForMessage(p, m_CtrlSetup);
DoStateForMessage(p, m_HCIEndpoint);
DoStateForMessage(p, m_ACLEndpoint);
p.Do(m_last_ticks);
p.DoArray(m_PacketCount);
p.Do(m_ScanEnable);
@ -138,75 +147,41 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::RemoteDisconnect(u16 _connectionHa
return SendEventDisconnect(_connectionHandle, 0x13);
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Open(u32 _CommandAddress, u32 _Mode)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Close()
{
// Clean up state
m_ScanEnable = 0;
m_last_ticks = 0;
memset(m_PacketCount, 0, sizeof(m_PacketCount));
m_HCIEndpoint.m_cmd_address = 0;
m_ACLEndpoint.m_cmd_address = 0;
m_is_active = true;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Close(u32 _CommandAddress, bool _bForce)
{
m_ScanEnable = 0;
m_last_ticks = 0;
memset(m_PacketCount, 0, sizeof(m_PacketCount));
m_HCIEndpoint.m_cmd_address = 0;
m_ACLEndpoint.m_cmd_address = 0;
m_HCIEndpoint.reset();
m_ACLEndpoint.reset();
m_is_active = false;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(const IOSIOCtlVRequest& request)
{
bool _SendReply = false;
SIOCtlVBuffer CommandBuffer(_CommandAddress);
switch (CommandBuffer.Parameter)
bool send_reply = true;
switch (request.request)
{
case USBV0_IOCTL_CTRLMSG: // HCI command is received from the stack
{
// This is the HCI datapath from CPU to Wii Remote, the USB stuff is little endian..
m_CtrlSetup.bRequestType = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[0].m_Address);
m_CtrlSetup.bRequest = *(u8*)Memory::GetPointer(CommandBuffer.InBuffer[1].m_Address);
m_CtrlSetup.wValue = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[2].m_Address);
m_CtrlSetup.wIndex = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[3].m_Address);
m_CtrlSetup.wLength = *(u16*)Memory::GetPointer(CommandBuffer.InBuffer[4].m_Address);
m_CtrlSetup.m_PayLoadAddr = CommandBuffer.PayloadBuffer[0].m_Address;
m_CtrlSetup.m_PayLoadSize = CommandBuffer.PayloadBuffer[0].m_Size;
m_CtrlSetup.m_Address = CommandBuffer.m_Address;
// check termination
_dbg_assert_msg_(WII_IPC_WIIMOTE,
*(u8*)Memory::GetPointer(CommandBuffer.InBuffer[5].m_Address) == 0,
"WIIMOTE: Termination != 0");
m_CtrlSetup = std::make_unique<CtrlMessage>(request);
// Replies are generated inside
ExecuteHCICommandMessage(m_CtrlSetup);
ExecuteHCICommandMessage(*m_CtrlSetup);
m_CtrlSetup.reset();
send_reply = false;
break;
}
break;
case USBV0_IOCTL_BLKMSG:
{
const CtrlBuffer ctrl(CommandBuffer, _CommandAddress);
const CtrlBuffer ctrl{request};
switch (ctrl.m_endpoint)
{
case ACL_DATA_OUT: // ACL data is received from the stack
{
// This is the ACL datapath from CPU to Wii Remote
// Here we only need to record the command address in case we need to delay the reply
m_ACLSetup = CommandBuffer.m_Address;
const auto* acl_header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.m_payload_addr));
@ -216,65 +191,43 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::IOCtlV(u32 _CommandAdd
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
Memory::GetPointer(ctrl.m_payload_addr + sizeof(hci_acldata_hdr_t)),
acl_header->length);
_SendReply = true;
break;
}
break;
case ACL_DATA_IN: // We are given an ACL buffer to fill
{
CtrlBuffer temp(CommandBuffer, _CommandAddress);
m_ACLEndpoint = temp;
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL_DATA_IN: 0x%08x ", _CommandAddress);
m_ACLEndpoint = std::make_unique<CtrlBuffer>(request);
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
send_reply = false;
break;
}
break;
default:
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_BLKMSG: %x", ctrl.m_endpoint);
}
break;
}
}
break;
case USBV0_IOCTL_INTRMSG:
{
const CtrlBuffer ctrl(CommandBuffer, _CommandAddress);
const CtrlBuffer ctrl{request};
if (ctrl.m_endpoint == HCI_EVENT) // We are given a HCI buffer to fill
{
CtrlBuffer temp(CommandBuffer, _CommandAddress);
m_HCIEndpoint = temp;
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI_EVENT: 0x%08x ", _CommandAddress);
m_HCIEndpoint = std::make_unique<CtrlBuffer>(request);
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
send_reply = false;
}
else
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown USBV0_IOCTL_INTRMSG: %x", ctrl.m_endpoint);
}
break;
}
break;
default:
{
_dbg_assert_msg_(WII_IPC_WIIMOTE, 0, "Unknown CWII_IPC_HLE_Device_usb_oh1_57e_305: %x",
CommandBuffer.Parameter);
INFO_LOG(WII_IPC_WIIMOTE, "%s - IOCtlV:", GetDeviceName().c_str());
INFO_LOG(WII_IPC_WIIMOTE, " Parameter: 0x%x", CommandBuffer.Parameter);
INFO_LOG(WII_IPC_WIIMOTE, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer);
INFO_LOG(WII_IPC_WIIMOTE, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer);
INFO_LOG(WII_IPC_WIIMOTE, " BufferVector: 0x%08x", CommandBuffer.BufferVector);
INFO_LOG(WII_IPC_WIIMOTE, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address);
INFO_LOG(WII_IPC_WIIMOTE, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size);
}
break;
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_WIIMOTE);
}
// write return value
Memory::Write_U32(0, _CommandAddress + 4);
return _SendReply ? GetDefaultReply() : GetNoReply();
request.SetReturnValue(IPC_SUCCESS);
return send_reply ? GetDefaultReply() : GetNoReply();
}
// Here we handle the USBV0_IOCTL_BLKMSG Ioctlv
@ -302,22 +255,22 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendACLPacket(u16 connection_handl
{
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", connection_handle);
if (m_ACLEndpoint.IsValid() && !m_HCIEndpoint.IsValid() && m_EventQueue.empty())
if (m_ACLEndpoint && !m_HCIEndpoint && m_EventQueue.empty())
{
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint valid, sending packet to %08x",
m_ACLEndpoint.m_cmd_address);
m_ACLEndpoint->ios_request.address);
hci_acldata_hdr_t* header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint.m_payload_addr));
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_ACLEndpoint->m_payload_addr));
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;
// Write the packet to the buffer
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
WII_IPC_HLE_Interface::EnqueueReply(m_ACLEndpoint.m_cmd_address);
m_ACLEndpoint.Invalidate();
m_ACLEndpoint->ios_request.SetReturnValue(sizeof(hci_acldata_hdr_t) + size);
WII_IPC_HLE_Interface::EnqueueReply(m_ACLEndpoint->ios_request);
m_ACLEndpoint.reset();
}
else
{
@ -336,17 +289,17 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x completed...",
((hci_event_hdr_t*)_event.m_buffer)->event);
if (m_HCIEndpoint.IsValid())
if (m_HCIEndpoint)
{
if (m_EventQueue.empty()) // fast path :)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI endpoint valid, sending packet to %08x",
m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.FillBuffer(_event.m_buffer, _event.m_size);
m_HCIEndpoint.SetRetVal(_event.m_size);
m_HCIEndpoint->ios_request.address);
m_HCIEndpoint->FillBuffer(_event.m_buffer, _event.m_size);
m_HCIEndpoint->ios_request.SetReturnValue(_event.m_size);
// Send a reply to indicate HCI buffer is filled
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.Invalidate();
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint->ios_request);
m_HCIEndpoint.reset();
}
else // push new one, pop oldest
{
@ -357,12 +310,12 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x "
"being written from queue (%zu) to %08x...",
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint.SetRetVal(event.m_size);
m_HCIEndpoint->ios_request.address);
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint->ios_request.SetReturnValue(event.m_size);
// Send a reply to indicate HCI buffer is filled
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.Invalidate();
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint->ios_request);
m_HCIEndpoint.reset();
m_EventQueue.pop_front();
}
}
@ -377,24 +330,27 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::AddEventToQueue(const SQueuedEvent
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
{
// check HCI queue
if (!m_EventQueue.empty() && m_HCIEndpoint.IsValid())
if (!m_EventQueue.empty() && m_HCIEndpoint)
{
// an endpoint has become available, and we have a stored response.
const SQueuedEvent& event = m_EventQueue.front();
DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x being written from queue (%zu) to %08x...",
((hci_event_hdr_t*)event.m_buffer)->event, m_EventQueue.size() - 1,
m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint.SetRetVal(event.m_size);
m_HCIEndpoint->ios_request.address);
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint->ios_request.SetReturnValue(event.m_size);
// Send a reply to indicate HCI buffer is filled
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint.m_cmd_address);
m_HCIEndpoint.Invalidate();
WII_IPC_HLE_Interface::EnqueueReply(m_HCIEndpoint->ios_request);
m_HCIEndpoint.reset();
m_EventQueue.pop_front();
}
// check ACL queue
if (!m_acl_pool.IsEmpty() && m_ACLEndpoint.IsValid() && m_EventQueue.empty())
m_acl_pool.WriteToEndpoint(m_ACLEndpoint);
if (!m_acl_pool.IsEmpty() && m_ACLEndpoint && m_EventQueue.empty())
{
m_acl_pool.WriteToEndpoint(*m_ACLEndpoint);
m_ACLEndpoint.reset();
}
// We wait for ScanEnable to be sent from the Bluetooth stack through HCI_CMD_WRITE_SCAN_ENABLE
// before we initiate the connection.
@ -402,7 +358,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
// FiRES: TODO find a better way to do this
// Create ACL connection
if (m_HCIEndpoint.IsValid() && (m_ScanEnable & HCI_PAGE_SCAN_ENABLE))
if (m_HCIEndpoint && (m_ScanEnable & HCI_PAGE_SCAN_ENABLE))
{
for (auto& wiimote : m_WiiMotes)
{
@ -415,7 +371,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::Update()
}
// Link channels when connected
if (m_ACLEndpoint.IsValid())
if (m_ACLEndpoint)
{
for (auto& wiimote : m_WiiMotes)
{
@ -469,7 +425,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ACLPool::WriteToEndpoint(CtrlBuffe
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
"queue to %08x",
endpoint.m_cmd_address);
endpoint.ios_request.address);
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_payload_addr);
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
@ -478,12 +434,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ACLPool::WriteToEndpoint(CtrlBuffe
// Write the packet to the buffer
std::copy(data, data + size, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
endpoint.ios_request.SetReturnValue(sizeof(hci_acldata_hdr_t) + size);
m_queue.pop_front();
WII_IPC_HLE_Interface::EnqueueReply(endpoint.m_cmd_address);
endpoint.Invalidate();
WII_IPC_HLE_Interface::EnqueueReply(endpoint.ios_request);
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventInquiryComplete()
@ -1023,10 +978,10 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::SendEventConPacketTypeChange(u16 _
// Command dispatcher
// This is called from the USBV0_IOCTL_CTRLMSG Ioctlv
void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
const SHCICommandMessage& _rHCICommandMessage)
const CtrlMessage& ctrl_message)
{
u8* pInput = Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr + 3);
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(_rHCICommandMessage.m_PayLoadAddr);
u8* pInput = Memory::GetPointer(ctrl_message.payload_addr + 3);
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(ctrl_message.payload_addr);
u16 ocf = HCI_OCF(pMsg->Opcode);
u16 ogf = HCI_OGF(pMsg->Opcode);
@ -1110,11 +1065,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
// vendor specific...
case 0xFC4C:
CommandVendorSpecific_FC4C(pInput, _rHCICommandMessage.m_PayLoadSize - 3);
CommandVendorSpecific_FC4C(pInput, ctrl_message.length - 3);
break;
case 0xFC4F:
CommandVendorSpecific_FC4F(pInput, _rHCICommandMessage.m_PayLoadSize - 3);
CommandVendorSpecific_FC4F(pInput, ctrl_message.length - 3);
break;
case HCI_CMD_INQUIRY_CANCEL:
@ -1203,7 +1158,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_emu::ExecuteHCICommandMessage(
}
// HCI command is finished, send a reply to command
WII_IPC_HLE_Interface::EnqueueReply(_rHCICommandMessage.m_Address);
WII_IPC_HLE_Interface::EnqueueReply(ctrl_message.ios_request);
}
//

View File

@ -6,6 +6,7 @@
#include <algorithm>
#include <deque>
#include <memory>
#include <queue>
#include <string>
#include <vector>
@ -43,10 +44,8 @@ public:
virtual ~CWII_IPC_HLE_Device_usb_oh1_57e_305_emu();
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
void Close() override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
void Update() override;
@ -62,31 +61,16 @@ public:
void DoState(PointerWrap& p) override;
private:
struct SHCICommandMessage
{
u8 bRequestType;
u8 bRequest;
u16 wValue;
u16 wIndex;
u16 wLength;
u32 m_PayLoadAddr;
u32 m_PayLoadSize;
u32 m_Address;
};
bdaddr_t m_ControllerBD;
// this is used to trigger connecting via ACL
u8 m_ScanEnable = 0;
SHCICommandMessage m_CtrlSetup;
CtrlBuffer m_HCIEndpoint;
std::unique_ptr<CtrlMessage> m_CtrlSetup;
std::unique_ptr<CtrlBuffer> m_HCIEndpoint;
std::unique_ptr<CtrlBuffer> m_ACLEndpoint;
std::deque<SQueuedEvent> m_EventQueue;
u32 m_ACLSetup;
CtrlBuffer m_ACLEndpoint;
class ACLPool
{
struct Packet
@ -109,7 +93,7 @@ private:
void DoState(PointerWrap& p) { p.Do(m_queue); }
} m_acl_pool;
u32 m_PacketCount[MAX_BBMOTES];
u32 m_PacketCount[MAX_BBMOTES] = {};
u64 m_last_ticks = 0;
// Send ACL data to a device (wiimote)
@ -138,7 +122,7 @@ private:
bool SendEventLinkKeyNotification(const u8 num_to_send);
// Execute HCI Message
void ExecuteHCICommandMessage(const SHCICommandMessage& _rCtrlMessage);
void ExecuteHCICommandMessage(const CtrlMessage& ctrl_message);
// OGF 0x01 - Link control commands and return parameters
void CommandWriteInquiryMode(const u8* input);

View File

@ -18,6 +18,7 @@
#include "Common/Assert.h"
#include "Common/ChunkFile.h"
#include "Common/CommonFuncs.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/Network.h"
@ -89,7 +90,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305_real::~CWII_IPC_HLE_Device_usb_oh1_57e_305_r
SaveLinkKeys();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(u32 command_address, u32 mode)
IOSReturnCode CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(const IOSOpenRequest& request)
{
libusb_device** list;
const ssize_t cnt = libusb_get_device_list(m_libusb_context, &list);
@ -136,18 +137,18 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Open(u32 command_addr
PanicAlertT("Bluetooth passthrough mode is enabled, "
"but no usable Bluetooth USB device was found. Aborting.");
Core::QueueHostJob(Core::Stop);
return GetNoReply();
return IPC_ENOENT;
}
StartTransferThread();
m_is_active = true;
return GetDefaultReply();
return IPC_SUCCESS;
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close(u32 command_address, bool force)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close()
{
if (!force)
if (m_handle)
{
libusb_release_interface(m_handle, 0);
StopTransferThread();
@ -156,10 +157,9 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::Close(u32 command_add
}
m_is_active = false;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_address)
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(const IOSIOCtlVRequest& request)
{
if (!m_is_wii_bt_module && s_need_reset_keys.TestAndClear())
{
@ -170,14 +170,13 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
WaitForHCICommandComplete(HCI_CMD_WRITE_STORED_LINK_KEY);
}
const SIOCtlVBuffer cmd_buffer(command_address);
switch (cmd_buffer.Parameter)
switch (request.request)
{
// HCI commands to the Bluetooth adapter
case USBV0_IOCTL_CTRLMSG:
{
auto cmd = std::make_unique<CtrlMessage>(cmd_buffer);
const u16 opcode = *reinterpret_cast<u16*>(Memory::GetPointer(cmd->payload_addr));
auto cmd = std::make_unique<CtrlMessage>(request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->payload_addr));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
m_fake_read_buffer_size_reply.Set();
@ -220,25 +219,24 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
case USBV0_IOCTL_BLKMSG:
case USBV0_IOCTL_INTRMSG:
{
auto buffer = std::make_unique<CtrlBuffer>(cmd_buffer, command_address);
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
auto buffer = std::make_unique<CtrlBuffer>(request);
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
{
FakeReadBufferSizeReply(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
if (request.request == 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)
if (request.request == USBV0_IOCTL_INTRMSG && m_sync_button_state == SyncButtonState::Pressed)
{
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
FakeSyncButtonPressedEvent(*buffer);
return GetNoReply();
}
if (cmd_buffer.Parameter == USBV0_IOCTL_INTRMSG &&
if (request.request == USBV0_IOCTL_INTRMSG &&
m_sync_button_state == SyncButtonState::LongPressed)
{
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
@ -253,8 +251,8 @@ IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_real::IOCtlV(u32 command_ad
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
transfer->length = buffer->m_length;
transfer->timeout = TIMEOUT;
transfer->type = cmd_buffer.Parameter == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
LIBUSB_TRANSFER_TYPE_INTERRUPT;
transfer->type = request.request == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
LIBUSB_TRANSFER_TYPE_INTERRUPT;
transfer->user_data = buffer.release();
libusb_submit_transfer(transfer);
break;
@ -387,7 +385,7 @@ 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)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(CtrlBuffer& ctrl)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
@ -395,8 +393,8 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const Ctrl
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event->PacketIndicator = 0x01;
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
ctrl.SetRetVal(sizeof(SHCIEventCommand));
WII_IPC_HLE_Interface::EnqueueReply(ctrl.m_cmd_address);
ctrl.ios_request.SetReturnValue(sizeof(SHCIEventCommand));
WII_IPC_HLE_Interface::EnqueueReply(ctrl.ios_request);
}
// Due to how the widcomm stack which Nintendo uses is coded, we must never
@ -404,7 +402,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeVendorCommandReply(const Ctrl
// - it will cause a u8 underflow and royally screw things up.
// Therefore, the reply to this command has to be faked to avoid random, weird issues
// (including Wiimote disconnects and "event mismatch" warning messages).
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(const CtrlBuffer& ctrl)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(CtrlBuffer& ctrl)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
@ -421,11 +419,11 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeReadBufferSizeReply(const Ctr
reply.num_sco_pkts = SCO_PKT_NUM;
memcpy(packet + sizeof(SHCIEventCommand), &reply, sizeof(hci_read_buffer_size_rp));
ctrl.SetRetVal(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp));
WII_IPC_HLE_Interface::EnqueueReply(ctrl.m_cmd_address);
ctrl.ios_request.SetReturnValue(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp));
WII_IPC_HLE_Interface::EnqueueReply(ctrl.ios_request);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(const CtrlBuffer& ctrl,
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(CtrlBuffer& ctrl,
const u8* payload, const u8 size)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
@ -433,15 +431,15 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonEvent(const CtrlBuf
hci_event->event = HCI_EVENT_VENDOR;
hci_event->length = size;
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
ctrl.SetRetVal(sizeof(hci_event_hdr_t) + size);
WII_IPC_HLE_Interface::EnqueueReply(ctrl.m_cmd_address);
ctrl.ios_request.SetReturnValue(sizeof(hci_event_hdr_t) + size);
WII_IPC_HLE_Interface::EnqueueReply(ctrl.ios_request);
}
// When the red sync button is pressed, a HCI event is generated:
// > HCI Event: Vendor (0xff) plen 1
// 08
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(const CtrlBuffer& ctrl)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(CtrlBuffer& ctrl)
{
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
const u8 payload[1] = {0x08};
@ -450,7 +448,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonPressedEvent(const
}
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl)
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::FakeSyncButtonHeldEvent(CtrlBuffer& ctrl)
{
NOTICE_LOG(WII_IPC_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
const u8 payload[1] = {0x09};
@ -580,7 +578,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::CommandCallback(libusb_transfer*
s_showed_failed_transfer.Clear();
}
WII_IPC_HLE_Interface::EnqueueReply(cmd->address, 0, CoreTiming::FromThread::NON_CPU);
WII_IPC_HLE_Interface::EnqueueReply(cmd->ios_request, 0, CoreTiming::FromThread::NON_CPU);
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer* tr)
@ -624,6 +622,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305_real::TransferCallback(libusb_transfer*
}
}
ctrl->SetRetVal(tr->actual_length);
WII_IPC_HLE_Interface::EnqueueReply(ctrl->m_cmd_address, 0, CoreTiming::FromThread::NON_CPU);
ctrl->ios_request.SetReturnValue(tr->actual_length);
WII_IPC_HLE_Interface::EnqueueReply(ctrl->ios_request, 0, CoreTiming::FromThread::NON_CPU);
}

View File

@ -42,9 +42,9 @@ public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_real(u32 device_id, const std::string& device_name);
~CWII_IPC_HLE_Device_usb_oh1_57e_305_real() override;
IPCCommandResult Open(u32 command_address, u32 mode) override;
IPCCommandResult Close(u32 command_address, bool force) override;
IPCCommandResult IOCtlV(u32 command_address) override;
IOSReturnCode Open(const IOSOpenRequest& request) override;
void Close() override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
void DoState(PointerWrap& p) override;
void UpdateSyncButtonState(bool is_held) override;
@ -80,11 +80,11 @@ 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);
void FakeSyncButtonHeldEvent(const CtrlBuffer& ctrl);
void FakeVendorCommandReply(CtrlBuffer& ctrl);
void FakeReadBufferSizeReply(CtrlBuffer& ctrl);
void FakeSyncButtonEvent(CtrlBuffer& ctrl, const u8* payload, u8 size);
void FakeSyncButtonPressedEvent(CtrlBuffer& ctrl);
void FakeSyncButtonHeldEvent(CtrlBuffer& ctrl);
void LoadLinkKeys();
void SaveLinkKeys();

View File

@ -12,11 +12,11 @@ namespace Core
void DisplayMessage(const std::string& message, int time_in_ms);
}
IPCCommandResult CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::Open(u32 command_address, u32 mode)
IOSReturnCode CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::Open(const IOSOpenRequest& request)
{
PanicAlertT("Bluetooth passthrough mode is enabled, but Dolphin was built without libusb."
" Passthrough mode cannot be used.");
return GetNoReply();
return IPC_ENOENT;
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305_stub::DoState(PointerWrap& p)

View File

@ -16,11 +16,10 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305_stub final
: public CWII_IPC_HLE_Device_usb_oh1_57e_305_base
{
public:
CWII_IPC_HLE_Device_usb_oh1_57e_305_stub(u32 device_id, const std::string& device_name)
CWII_IPC_HLE_Device_usb_oh1_57e_305_stub(const u32 device_id, const std::string& device_name)
: CWII_IPC_HLE_Device_usb_oh1_57e_305_base(device_id, device_name)
{
}
~CWII_IPC_HLE_Device_usb_oh1_57e_305_stub() override {}
IPCCommandResult Open(u32 command_address, u32 mode) override;
IOSReturnCode Open(const IOSOpenRequest& request) override;
void DoState(PointerWrap& p) override;
};

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 68; // Last changed in PR 4638
static const u32 STATE_VERSION = 69; // Last changed in PR 4661
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,