Merge pull request #230 from Parlane/libogc_ios_fix

Fixes Wiimotes for libogc.
This commit is contained in:
Matthew Parlane 2014-03-30 12:07:02 +13:00
commit 2e119af086
10 changed files with 96 additions and 62 deletions

View File

@ -82,6 +82,9 @@ static int enque_reply;
static u64 last_reply_time; static u64 last_reply_time;
// NOTE: Only call this if you have correctly handled
// CommandAddress+0 and CommandAddress+8.
// Please search for examples of this being called elsewhere.
void EnqueReplyCallback(u64 userdata, int) void EnqueReplyCallback(u64 userdata, int)
{ {
std::lock_guard<std::mutex> lk(s_reply_queue); std::lock_guard<std::mutex> lk(s_reply_queue);
@ -347,7 +350,7 @@ void ExecuteCommand(u32 _Address)
{ {
bool CmdSuccess = false; bool CmdSuccess = false;
ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address)); IPCCommandType Command = static_cast<IPCCommandType>(Memory::Read_U32(_Address));
volatile s32 DeviceID = Memory::Read_U32(_Address + 8); volatile s32 DeviceID = Memory::Read_U32(_Address + 8);
IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr; IWII_IPC_HLE_Device* pDevice = (DeviceID >= 0 && DeviceID < IPC_MAX_FDS) ? g_FdMap[DeviceID] : nullptr;
@ -356,7 +359,7 @@ void ExecuteCommand(u32 _Address)
switch (Command) switch (Command)
{ {
case COMMAND_OPEN_DEVICE: case IPC_CMD_OPEN:
{ {
u32 Mode = Memory::Read_U32(_Address + 0x10); u32 Mode = Memory::Read_U32(_Address + 0x10);
DeviceID = getFreeDeviceId(); DeviceID = getFreeDeviceId();
@ -431,7 +434,7 @@ void ExecuteCommand(u32 _Address)
} }
break; break;
} }
case COMMAND_CLOSE_DEVICE: case IPC_CMD_CLOSE:
{ {
if (pDevice) if (pDevice)
{ {
@ -461,7 +464,7 @@ void ExecuteCommand(u32 _Address)
} }
break; break;
} }
case COMMAND_READ: case IPC_CMD_READ:
{ {
if (pDevice) if (pDevice)
{ {
@ -474,7 +477,7 @@ void ExecuteCommand(u32 _Address)
} }
break; break;
} }
case COMMAND_WRITE: case IPC_CMD_WRITE:
{ {
if (pDevice) if (pDevice)
{ {
@ -487,7 +490,7 @@ void ExecuteCommand(u32 _Address)
} }
break; break;
} }
case COMMAND_SEEK: case IPC_CMD_SEEK:
{ {
if (pDevice) if (pDevice)
{ {
@ -500,7 +503,7 @@ void ExecuteCommand(u32 _Address)
} }
break; break;
} }
case COMMAND_IOCTL: case IPC_CMD_IOCTL:
{ {
if (pDevice) if (pDevice)
{ {
@ -508,7 +511,7 @@ void ExecuteCommand(u32 _Address)
} }
break; break;
} }
case COMMAND_IOCTLV: case IPC_CMD_IOCTLV:
{ {
if (pDevice) if (pDevice)
{ {
@ -526,10 +529,9 @@ void ExecuteCommand(u32 _Address)
if (CmdSuccess) if (CmdSuccess)
{ {
// It seems that the original hardware overwrites the command after it has been // The original hardware overwrites the command type with the async reply type.
// executed. We write 8 which is not any valid command, and what IOS does Memory::Write_U32(IPC_REP_ASYNC, _Address);
Memory::Write_U32(8, _Address); // IOS also seems to write back the command that was responded to in the FD field.
// IOS seems to write back the command that was responded to
Memory::Write_U32(Command, _Address + 8); Memory::Write_U32(Command, _Address + 8);
// Ensure replies happen in order, fairly ugly // Ensure replies happen in order, fairly ugly
@ -557,6 +559,9 @@ void EnqRequest(u32 _Address)
} }
// Called when IOS module has some reply // Called when IOS module has some reply
// NOTE: Only call this if you have correctly handled
// CommandAddress+0 and CommandAddress+8.
// Please search for examples of this being called elsewhere.
void EnqReply(u32 _Address, int cycles_in_future) void EnqReply(u32 _Address, int cycles_in_future)
{ {
CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address); CoreTiming::ScheduleEvent(cycles_in_future, enque_reply, _Address);

View File

@ -8,6 +8,21 @@
class IWII_IPC_HLE_Device; class IWII_IPC_HLE_Device;
enum IPCCommandType : u32
{
IPC_CMD_OPEN = 1,
IPC_CMD_CLOSE = 2,
IPC_CMD_READ = 3,
IPC_CMD_WRITE = 4,
IPC_CMD_SEEK = 5,
IPC_CMD_IOCTL = 6,
IPC_CMD_IOCTLV = 7,
// IPC_REP_ASYNC is used for messages that are automatically
// sent to an IOS queue when an asynchronous syscall completes.
// Reference: http://wiibrew.org/wiki/IOS
IPC_REP_ASYNC = 8
};
namespace WII_IPC_HLE_Interface namespace WII_IPC_HLE_Interface
{ {
@ -52,15 +67,4 @@ void ExecuteCommand(u32 _Address);
void EnqRequest(u32 _Address); void EnqRequest(u32 _Address);
void EnqReply(u32 _Address, int cycles_in_future = 0); void EnqReply(u32 _Address, int cycles_in_future = 0);
enum ECommandType
{
COMMAND_OPEN_DEVICE = 1,
COMMAND_CLOSE_DEVICE = 2,
COMMAND_READ = 3,
COMMAND_WRITE = 4,
COMMAND_SEEK = 5,
COMMAND_IOCTL = 6,
COMMAND_IOCTLV = 7,
};
} // end of namespace WII_IPC_HLE_Interface } // end of namespace WII_IPC_HLE_Interface

View File

@ -991,11 +991,10 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
// This is necessary because Reset(true) above deleted this object. Ew. // This is necessary because Reset(true) above deleted this object. Ew.
// It seems that the original hardware overwrites the command after it has been // The original hardware overwrites the command type with the async reply type.
// executed. We write 8 which is not any valid command, and what IOS does Memory::Write_U32(IPC_REP_ASYNC, _CommandAddress);
Memory::Write_U32(8, _CommandAddress); // IOS also seems to write back the command that was responded to in the FD field.
// IOS seems to write back the command that was responded to Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8);
Memory::Write_U32(7, _CommandAddress + 8);
// Generate a reply to the IPC command // Generate a reply to the IPC command
WII_IPC_HLE_Interface::EnqReply(_CommandAddress, 0); WII_IPC_HLE_Interface::EnqReply(_CommandAddress, 0);

View File

@ -29,9 +29,10 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
if (hid->deviceCommandAddress != 0){ if (hid->deviceCommandAddress != 0){
hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18), Memory::Read_U32(hid->deviceCommandAddress + 0x1C)); hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18), Memory::Read_U32(hid->deviceCommandAddress + 0x1C));
Memory::Write_U32(8, hid->deviceCommandAddress); // The original hardware overwrites the command type with the async reply type.
// IOS seems to write back the command that was responded to Memory::Write_U32(IPC_REP_ASYNC, hid->deviceCommandAddress);
Memory::Write_U32(/*COMMAND_IOCTL*/ 6, hid->deviceCommandAddress + 8); // IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTL, hid->deviceCommandAddress + 8);
// Return value // Return value
Memory::Write_U32(0, hid->deviceCommandAddress + 4); Memory::Write_U32(0, hid->deviceCommandAddress + 4);
@ -56,9 +57,10 @@ void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer *transfer)
ret = transfer->length; ret = transfer->length;
} }
Memory::Write_U32(8, replyAddress); // The original hardware overwrites the command type with the async reply type.
// IOS seems to write back the command that was responded to Memory::Write_U32(IPC_REP_ASYNC, replyAddress);
Memory::Write_U32(/*COMMAND_IOCTL*/ 6, replyAddress + 8); // IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTL, replyAddress + 8);
// Return value // Return value
Memory::Write_U32(ret, replyAddress + 4); Memory::Write_U32(ret, replyAddress + 4);
@ -247,9 +249,10 @@ bool CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
if (deviceCommandAddress != 0){ if (deviceCommandAddress != 0){
Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18)); Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18));
Memory::Write_U32(8, deviceCommandAddress); // The original hardware overwrites the command type with the async reply type.
// IOS seems to write back the command that was responded to Memory::Write_U32(IPC_REP_ASYNC, deviceCommandAddress);
Memory::Write_U32(/*COMMAND_IOCTL*/ 6, deviceCommandAddress + 8); // IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTL, deviceCommandAddress + 8);
// Return value // Return value
Memory::Write_U32(-1, deviceCommandAddress + 4); Memory::Write_U32(-1, deviceCommandAddress + 4);

View File

@ -12,6 +12,18 @@
#include "Core/IPC_HLE/WII_IPC_HLE.h" #include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device_sdio_slot0.h"
void CWII_IPC_HLE_Device_sdio_slot0::EnqueueReply(u32 CommandAddress, u32 ReturnValue)
{
// IOS seems to write back the command that was responded to, this class does not
// overwrite the command so it is safe to read.
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8);
// The original hardware overwrites the command type with the async reply type.
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
Memory::Write_U32(ReturnValue, CommandAddress + 4);
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
}
CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName) CWII_IPC_HLE_Device_sdio_slot0::CWII_IPC_HLE_Device_sdio_slot0(u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
@ -39,8 +51,7 @@ void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) || if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) ||
(!SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_REMOVE)) (!SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_REMOVE))
{ {
Memory::Write_U32(m_event.type, m_event.addr + 4); EnqueueReply(m_event.addr, m_event.type);
WII_IPC_HLE_Interface::EnqReply(m_event.addr);
m_event.addr = 0; m_event.addr = 0;
m_event.type = EVENT_NONE; m_event.type = EVENT_NONE;
} }
@ -222,8 +233,7 @@ bool CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
// release returns 0 // release returns 0
// unknown sd int // unknown sd int
// technically we do it out of order, oh well // technically we do it out of order, oh well
Memory::Write_U32(EVENT_INVALID, m_event.addr + 4); EnqueueReply(m_event.addr, EVENT_INVALID);
WII_IPC_HLE_Interface::EnqReply(m_event.addr);
m_event.addr = 0; m_event.addr = 0;
m_event.type = EVENT_NONE; m_event.type = EVENT_NONE;
Memory::Write_U32(0, _CommandAddress + 0x4); Memory::Write_U32(0, _CommandAddress + 0x4);

View File

@ -21,6 +21,7 @@ public:
bool IOCtl(u32 _CommandAddress) override; bool IOCtl(u32 _CommandAddress) override;
bool IOCtlV(u32 _CommandAddress) override; bool IOCtlV(u32 _CommandAddress) override;
static void EnqueueReply(u32 CommandAddress, u32 ReturnValue);
void EventNotify(); void EventNotify();
private: private:

View File

@ -14,6 +14,19 @@
#include "Core/IPC_HLE/WII_IPC_HLE.h" #include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h"
void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress)
{
// IOS seems to write back the command that was responded to in the FD field, this
// class does not overwrite the command so it is safe to read back.
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8);
// The original hardware overwrites the command type with the async reply type.
Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
WII_IPC_HLE_Interface::EnqReply(CommandAddress);
}
// The device class // The device class
CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName) CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName)
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
@ -340,7 +353,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u
memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), _pData, pHeader->length); memcpy((u8*)pHeader + sizeof(hci_acldata_hdr_t), _pData, pHeader->length);
m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + _Size); m_ACLEndpoint.SetRetVal(sizeof(hci_acldata_hdr_t) + _Size);
WII_IPC_HLE_Interface::EnqReply(m_ACLEndpoint.m_address); EnqueueReply(m_ACLEndpoint.m_address);
m_ACLEndpoint.Invalidate(); m_ACLEndpoint.Invalidate();
} }
else else
@ -367,7 +380,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
m_HCIEndpoint.FillBuffer(_event.m_buffer, _event.m_size); m_HCIEndpoint.FillBuffer(_event.m_buffer, _event.m_size);
m_HCIEndpoint.SetRetVal(_event.m_size); m_HCIEndpoint.SetRetVal(_event.m_size);
// Send a reply to indicate HCI buffer is filled // Send a reply to indicate HCI buffer is filled
WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address); EnqueueReply(m_HCIEndpoint.m_address);
m_HCIEndpoint.Invalidate(); m_HCIEndpoint.Invalidate();
} }
else // push new one, pop oldest else // push new one, pop oldest
@ -385,7 +398,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size); m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint.SetRetVal(event.m_size); m_HCIEndpoint.SetRetVal(event.m_size);
// Send a reply to indicate HCI buffer is filled // Send a reply to indicate HCI buffer is filled
WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address); EnqueueReply(m_HCIEndpoint.m_address);
m_HCIEndpoint.Invalidate(); m_HCIEndpoint.Invalidate();
m_EventQueue.pop_front(); m_EventQueue.pop_front();
} }
@ -415,7 +428,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size); m_HCIEndpoint.FillBuffer(event.m_buffer, event.m_size);
m_HCIEndpoint.SetRetVal(event.m_size); m_HCIEndpoint.SetRetVal(event.m_size);
// Send a reply to indicate HCI buffer is filled // Send a reply to indicate HCI buffer is filled
WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address); EnqueueReply(m_HCIEndpoint.m_address);
m_HCIEndpoint.Invalidate(); m_HCIEndpoint.Invalidate();
m_EventQueue.pop_front(); m_EventQueue.pop_front();
packet_transferred = true; packet_transferred = true;
@ -517,7 +530,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ACLPool::WriteToEndpoint(CtrlBuffer& e
m_queue.pop_front(); m_queue.pop_front();
WII_IPC_HLE_Interface::EnqReply(endpoint.m_address); EnqueueReply(endpoint.m_address);
endpoint.Invalidate(); endpoint.Invalidate();
} }
@ -1214,7 +1227,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::ExecuteHCICommandMessage(const SHCICom
} }
// HCI command is finished, send a reply to command // HCI command is finished, send a reply to command
WII_IPC_HLE_Interface::EnqReply(_rHCICommandMessage.m_Address); EnqueueReply(_rHCICommandMessage.m_Address);
} }

View File

@ -58,6 +58,8 @@ public:
virtual u32 Update() override; virtual u32 Update() override;
static void EnqueueReply(u32 CommandAddress);
// Send ACL data back to bt stack // Send ACL data back to bt stack
void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size); void SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size);

View File

@ -8,11 +8,6 @@
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
#include "Core/IPC_HLE/WII_Socket.h" // No Wii socket support while using NetPlay or TAS #include "Core/IPC_HLE/WII_Socket.h" // No Wii socket support while using NetPlay or TAS
using WII_IPC_HLE_Interface::ECommandType;
using WII_IPC_HLE_Interface::COMMAND_IOCTL;
using WII_IPC_HLE_Interface::COMMAND_IOCTLV;
#ifdef _WIN32 #ifdef _WIN32
#define ERRORCODE(name) WSA ## name #define ERRORCODE(name) WSA ## name
#define EITHER(win32, posix) win32 #define EITHER(win32, posix) win32
@ -180,8 +175,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
{ {
s32 ReturnValue = 0; s32 ReturnValue = 0;
bool forceNonBlock = false; bool forceNonBlock = false;
ECommandType ct = static_cast<ECommandType>(Memory::Read_U32(it->_CommandAddress)); IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(it->_CommandAddress));
if (!it->is_ssl && ct == COMMAND_IOCTL) if (!it->is_ssl && ct == IPC_CMD_IOCTL)
{ {
u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10); u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14); u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14);
@ -267,7 +262,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
} }
} }
} }
else if (ct == COMMAND_IOCTLV) else if (ct == IPC_CMD_IOCTLV)
{ {
SIOCtlVBuffer CommandBuffer(it->_CommandAddress); SIOCtlVBuffer CommandBuffer(it->_CommandAddress);
u32 BufferIn = 0, BufferIn2 = 0; u32 BufferIn = 0, BufferIn2 = 0;
@ -523,7 +518,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
DEBUG_LOG(WII_IPC_NET, DEBUG_LOG(WII_IPC_NET,
"IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", "IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d",
fd, it->is_ssl ? (int) it->ssl_type : (int) it->net_type, ReturnValue, nonBlock, forceNonBlock); fd, it->is_ssl ? (int) it->ssl_type : (int) it->net_type, ReturnValue, nonBlock, forceNonBlock);
WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue); WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue, ct);
it = pending_sockops.erase(it); it = pending_sockops.erase(it);
} }
else else
@ -625,11 +620,12 @@ void WiiSockMan::Update()
} }
} }
void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue) void WiiSockMan::EnqueueReply(u32 CommandAddress, s32 ReturnValue, IPCCommandType CommandType)
{ {
Memory::Write_U32(8, CommandAddress); // The original hardware overwrites the command type with the async reply type.
// IOS seems to write back the command that was responded to Memory::Write_U32(IPC_REP_ASYNC, CommandAddress);
Memory::Write_U32(Memory::Read_U32(CommandAddress), CommandAddress + 8); // IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(CommandType, CommandAddress + 8);
// Return value // Return value
Memory::Write_U32(ReturnValue, CommandAddress + 4); Memory::Write_U32(ReturnValue, CommandAddress + 4);

View File

@ -204,7 +204,7 @@ public:
return instance; // Instantiated on first use. return instance; // Instantiated on first use.
} }
void Update(); void Update();
static void EnqueueReply(u32 CommandAddress, s32 ReturnValue); static void EnqueueReply(u32 CommandAddress, s32 ReturnValue, IPCCommandType CommandType);
static void Convert(WiiSockAddrIn const & from, sockaddr_in& to); static void Convert(WiiSockAddrIn const & from, sockaddr_in& to);
static void Convert(sockaddr_in const & from, WiiSockAddrIn& to, s32 addrlen=-1); static void Convert(sockaddr_in const & from, WiiSockAddrIn& to, s32 addrlen=-1);
// NON-BLOCKING FUNCTIONS // NON-BLOCKING FUNCTIONS
@ -224,10 +224,11 @@ public:
{ {
if (WiiSockets.find(sock) == WiiSockets.end()) if (WiiSockets.find(sock) == WiiSockets.end())
{ {
IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(CommandAddress));
ERROR_LOG(WII_IPC_NET, ERROR_LOG(WII_IPC_NET,
"DoSock: Error, fd not found (%08x, %08X, %08X)", "DoSock: Error, fd not found (%08x, %08X, %08X)",
sock, CommandAddress, type); sock, CommandAddress, type);
EnqueueReply(CommandAddress, -SO_EBADF); EnqueueReply(CommandAddress, -SO_EBADF, ct);
} }
else else
{ {