summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2013-02-01 19:00:10 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2013-02-01 19:00:10 -0600
commite4588e2dfc2e14bcf95a58c499eade0f61179f76 (patch)
tree645b2a05bc0f91d9affe820214c2e6822e3e090c /Source/Core
parente199d21513de1555b8e597fa9155a88cd9e2e3ce (diff)
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.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp53
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h59
2 files changed, 51 insertions, 61 deletions
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
index 33474af8c7..050cfe66eb 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
@@ -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();
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
index 61c439a7ec..eb091b1ff9 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
@@ -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;