Workaround ACL overflow issues by not dropping packets until buffer reaches size of 100.
It seems to work without causing input delays or anything bad.
This commit is contained in:
parent
e199d21513
commit
e4588e2dfc
|
@ -336,23 +336,23 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8
|
|||
pWiiMote->ExecuteL2capCmd(_pData, _Size);
|
||||
}
|
||||
|
||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||
// ---------------------------------------------------
|
||||
// AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately
|
||||
// rather than enqueue it to some other memory
|
||||
// But...the only exception comes from the Wiimote_Plugin
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle)
|
||||
{
|
||||
m_PacketCount[_ConnectionHandle & 0xff]++;
|
||||
|
||||
// I don't think this makes sense or should be necessary
|
||||
// m_PacketCount refers to "completed" packets and is not related to some buffer size, yes?
|
||||
#if 0
|
||||
if (m_PacketCount[_ConnectionHandle & 0xff] > (unsigned int)m_acl_pkts_num)
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL buffer overflow");
|
||||
m_PacketCount[_ConnectionHandle & 0xff] = m_acl_pkts_num;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Here we send ACL packets to CPU. They will consist of header + data.
|
||||
// The header is for example 07 00 41 00 which means size 0x0007 and channel 0x0041.
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", _ConnectionHandle);
|
||||
|
@ -374,8 +374,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
|
|||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, "
|
||||
"queueing(%d)...", m_acl_pool.GetWritePos());
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint not currently valid, queueing...");
|
||||
m_acl_pool.Store(_pData, _Size, _ConnectionHandle);
|
||||
}
|
||||
}
|
||||
|
@ -518,25 +517,51 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
|
|||
return packet_transferred;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||
{
|
||||
if (m_queue.size() >= 100)
|
||||
{
|
||||
// Many simultaneous exchanges of ACL packets tend to cause the
|
||||
// queue to fill up. Typically, this occurs when
|
||||
// many emulated Wiimotes are requesting connections at once.
|
||||
// See issue 4608 for more info.
|
||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue size reached 100 - current packet will be "
|
||||
"dropped! (Hopefully you never see this.)");
|
||||
return;
|
||||
}
|
||||
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||
|
||||
m_queue.push_back(Packet());
|
||||
auto& packet = m_queue.back();
|
||||
|
||||
std::copy_n(data, size, packet.data);
|
||||
packet.size = size;
|
||||
packet.conn_handle = conn_handle;
|
||||
}
|
||||
|
||||
void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
||||
{
|
||||
const u8 *data = m_pool + m_acl_pkt_size * m_read_ptr;
|
||||
const u16 size = m_info[m_read_ptr].size;
|
||||
const u16 conn_handle = m_info[m_read_ptr].conn_handle;
|
||||
auto& packet = m_queue.front();
|
||||
|
||||
const u8* const data = packet.data;
|
||||
const u16 size = packet.size;
|
||||
const u16 conn_handle = packet.conn_handle;
|
||||
|
||||
DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet being written from "
|
||||
"queue(%d) to %08x", GetReadPos(), endpoint.m_address);
|
||||
"queue to %08x", endpoint.m_address);
|
||||
|
||||
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_buffer);
|
||||
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||
pHeader->length = size;
|
||||
|
||||
// Write the packet to the buffer
|
||||
memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), data, pHeader->length);
|
||||
std::copy_n(data, pHeader->length, (u8*)pHeader + sizeof(hci_acldata_hdr_t));
|
||||
|
||||
endpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + size);
|
||||
|
||||
m_read_ptr = (m_read_ptr + 1) % m_acl_pkts_num;
|
||||
m_queue.pop_front();
|
||||
|
||||
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address);
|
||||
endpoint.Invalidate();
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hci.h"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "hci.h"
|
||||
#include "WII_IPC_HLE.h"
|
||||
#include "WII_IPC_HLE_Device.h"
|
||||
#include "WII_IPC_HLE_WiiMote.h"
|
||||
|
@ -168,70 +170,33 @@ private:
|
|||
|
||||
class ACLPool
|
||||
{
|
||||
u8 m_pool[m_acl_pkt_size * m_acl_pkts_num];
|
||||
int m_read_ptr;
|
||||
int m_write_ptr;
|
||||
|
||||
struct
|
||||
struct Packet
|
||||
{
|
||||
u8 data[m_acl_pkt_size];
|
||||
u16 size;
|
||||
u16 conn_handle;
|
||||
} m_info[m_acl_pkts_num];
|
||||
};
|
||||
|
||||
std::deque<Packet> m_queue;
|
||||
|
||||
public:
|
||||
ACLPool()
|
||||
: m_read_ptr(0)
|
||||
, m_write_ptr(0)
|
||||
: m_queue()
|
||||
{}
|
||||
|
||||
void Store(const u8* data, const u16 size, const u16 conn_handle)
|
||||
{
|
||||
_dbg_assert_msg_(WII_IPC_WIIMOTE,
|
||||
size < m_acl_pkt_size, "acl packet too large for pool");
|
||||
|
||||
const int next_write_ptr = (m_write_ptr + 1) % m_acl_pkts_num;
|
||||
if (next_write_ptr == m_read_ptr)
|
||||
{
|
||||
// Many simultaneous exchanges of ACL packets tend to cause the
|
||||
// 10-packet limit to be exceeded. Typically, this occurs when
|
||||
// many emulated Wiimotes are requesting connections at once.
|
||||
// See issue 4608 for more info.
|
||||
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue is full - current packet will be "
|
||||
"dropped! (m_write_ptr(%d) was about to overlap m_read_ptr(%d))",
|
||||
m_write_ptr, m_read_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(m_pool + m_acl_pkt_size * m_write_ptr, data, size);
|
||||
m_info[m_write_ptr].size = size;
|
||||
m_info[m_write_ptr].conn_handle = conn_handle;
|
||||
m_write_ptr = next_write_ptr;
|
||||
}
|
||||
void Store(const u8* data, const u16 size, const u16 conn_handle);
|
||||
|
||||
void WriteToEndpoint(CtrlBuffer& endpoint);
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return m_write_ptr == m_read_ptr;
|
||||
}
|
||||
|
||||
int GetWritePos() const
|
||||
{
|
||||
return m_write_ptr;
|
||||
}
|
||||
|
||||
int GetReadPos() const
|
||||
{
|
||||
return m_read_ptr;
|
||||
return m_queue.empty();
|
||||
}
|
||||
|
||||
// For SaveStates
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.Do(m_write_ptr);
|
||||
p.Do(m_read_ptr);
|
||||
p.DoArray((u8 *)m_pool, sizeof(m_pool));
|
||||
p.DoArray((u8 *)m_info, sizeof(m_info));
|
||||
p.Do(m_queue);
|
||||
}
|
||||
} m_acl_pool;
|
||||
|
||||
|
|
Loading…
Reference in New Issue