IOS HLE: Deduplicate request code in USB_HID

This commit is contained in:
Léo Lam 2017-01-15 11:48:52 +01:00
parent 0e979ec75f
commit 6bf0b487d1
2 changed files with 51 additions and 88 deletions

View File

@ -37,13 +37,10 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
std::lock_guard<std::mutex> lk(hid->m_device_list_reply_mutex); std::lock_guard<std::mutex> lk(hid->m_device_list_reply_mutex);
if (hid->deviceCommandAddress != 0) if (hid->deviceCommandAddress != 0)
{ {
hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18), IOSIOCtlRequest request{hid->deviceCommandAddress};
Memory::Read_U32(hid->deviceCommandAddress + 0x1C)); hid->FillOutDevices(request);
request.SetReturnValue(IPC_SUCCESS);
// Return value WII_IPC_HLE_Interface::EnqueueReply(request, 0, CoreTiming::FromThread::NON_CPU);
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
WII_IPC_HLE_Interface::EnqueueReply(hid->deviceCommandAddress, 0,
CoreTiming::FromThread::NON_CPU);
hid->deviceCommandAddress = 0; hid->deviceCommandAddress = 0;
} }
} }
@ -56,16 +53,16 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer* transfer) void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer* transfer)
{ {
int ret = IPC_EINVAL; s32 ret = IPC_EINVAL;
u32 replyAddress = (u32)(size_t)transfer->user_data; u32 replyAddress = (u32)(size_t)transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
{ {
ret = transfer->length; ret = transfer->length;
} }
// Return value IOSIOCtlRequest request{replyAddress};
Memory::Write_U32(ret, replyAddress + 4); request.SetReturnValue(ret);
WII_IPC_HLE_Interface::EnqueueReply(replyAddress, 0, CoreTiming::FromThread::NON_CPU); WII_IPC_HLE_Interface::EnqueueReply(request, 0, CoreTiming::FromThread::NON_CPU);
} }
CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName) CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName)
@ -105,53 +102,37 @@ CWII_IPC_HLE_Device_hid::~CWII_IPC_HLE_Device_hid()
libusb_exit(nullptr); libusb_exit(nullptr);
} }
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress) IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(const IOSIOCtlRequest& request)
{ {
if (Core::g_want_determinism) if (Core::g_want_determinism)
{ {
Memory::Write_U32(-1, _CommandAddress + 0x4); request.SetReturnValue(-1);
return GetDefaultReply(); return GetDefaultReply();
} }
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC); s32 return_value = IPC_SUCCESS;
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); switch (request.request)
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
u32 ReturnValue = 0;
switch (Parameter)
{ {
case IOCTL_HID_GET_ATTACHED: case IOCTL_HID_GET_ATTACHED:
{ {
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", deviceCommandAddress = request.address;
BufferIn, BufferInSize, BufferOut, BufferOutSize);
deviceCommandAddress = _CommandAddress;
return GetNoReply(); return GetNoReply();
} }
case IOCTL_HID_OPEN: case IOCTL_HID_OPEN:
{ {
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn,
BufferInSize, BufferOut, BufferOutSize);
// hid version, apparently // hid version, apparently
ReturnValue = 0x40001; return_value = 0x40001;
break; break;
} }
case IOCTL_HID_SET_SUSPEND: case IOCTL_HID_SET_SUSPEND:
{ {
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize);
// not actually implemented in IOS // not actually implemented in IOS
ReturnValue = 0; return_value = IPC_SUCCESS;
break; break;
} }
case IOCTL_HID_CANCEL_INTERRUPT: case IOCTL_HID_CANCEL_INTERRUPT:
{ {
DEBUG_LOG(WII_IPC_HID, return_value = IPC_SUCCESS;
"HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn,
BufferInSize, BufferOut, BufferOutSize);
ReturnValue = 0;
break; break;
} }
case IOCTL_HID_CONTROL: case IOCTL_HID_CONTROL:
@ -161,15 +142,15 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
-4 Can't find device specified -4 Can't find device specified
*/ */
u32 dev_num = Memory::Read_U32(BufferIn + 0x10); u32 dev_num = Memory::Read_U32(request.buffer_in + 0x10);
u8 bmRequestType = Memory::Read_U8(BufferIn + 0x14); u8 bmRequestType = Memory::Read_U8(request.buffer_in + 0x14);
u8 bRequest = Memory::Read_U8(BufferIn + 0x15); u8 bRequest = Memory::Read_U8(request.buffer_in + 0x15);
u16 wValue = Memory::Read_U16(BufferIn + 0x16); u16 wValue = Memory::Read_U16(request.buffer_in + 0x16);
u16 wIndex = Memory::Read_U16(BufferIn + 0x18); u16 wIndex = Memory::Read_U16(request.buffer_in + 0x18);
u16 wLength = Memory::Read_U16(BufferIn + 0x1A); u16 wLength = Memory::Read_U16(request.buffer_in + 0x1A);
u32 data = Memory::Read_U32(BufferIn + 0x1C); u32 data = Memory::Read_U32(request.buffer_in + 0x1C);
ReturnValue = IPC_EINVAL; return_value = IPC_EINVAL;
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num); libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
@ -185,12 +166,14 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength); libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
Memory::CopyFromEmu(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength); Memory::CopyFromEmu(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates, libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates,
(void*)(size_t)_CommandAddress, /* no timeout */ 0); (void*)(size_t)request.address, /* no timeout */ 0);
libusb_submit_transfer(transfer); libusb_submit_transfer(transfer);
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i), BufferOut: // DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i),
// request.buffer_out:
// (%08x, %i)", // (%08x, %i)",
// bmRequestType, bRequest, BufferIn, BufferInSize, BufferOut, BufferOutSize); // bmRequestType, bRequest, BufferIn, request.buffer_in_size, request.buffer_out,
// request.buffer_out_size);
// It's the async way! // It's the async way!
return GetNoReply(); return GetNoReply();
@ -198,13 +181,13 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
case IOCTL_HID_INTERRUPT_OUT: case IOCTL_HID_INTERRUPT_OUT:
case IOCTL_HID_INTERRUPT_IN: case IOCTL_HID_INTERRUPT_IN:
{ {
u32 dev_num = Memory::Read_U32(BufferIn + 0x10); u32 dev_num = Memory::Read_U32(request.buffer_in + 0x10);
u32 endpoint = Memory::Read_U32(BufferIn + 0x14); u32 endpoint = Memory::Read_U32(request.buffer_in + 0x14);
u32 length = Memory::Read_U32(BufferIn + 0x18); u32 length = Memory::Read_U32(request.buffer_in + 0x18);
u32 data = Memory::Read_U32(BufferIn + 0x1C); u32 data = Memory::Read_U32(request.buffer_in + 0x1C);
ReturnValue = IPC_EINVAL; return_value = IPC_EINVAL;
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num); libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
@ -217,14 +200,9 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
struct libusb_transfer* transfer = libusb_alloc_transfer(0); struct libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER; transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length, libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length,
handleUsbUpdates, (void*)(size_t)_CommandAddress, 0); handleUsbUpdates, (void*)(size_t)request.address, 0);
libusb_submit_transfer(transfer); libusb_submit_transfer(transfer);
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt %s)(%d,%d,%X) (BufferIn: (%08x, %i), BufferOut:
// (%08x, %i)",
// Parameter == IOCTL_HID_INTERRUPT_IN ? "In" : "Out", endpoint, length, data,
// BufferIn, BufferInSize, BufferOut, BufferOutSize);
// It's the async way! // It's the async way!
return GetNoReply(); return GetNoReply();
} }
@ -233,27 +211,22 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
std::lock_guard<std::mutex> lk(m_device_list_reply_mutex); std::lock_guard<std::mutex> lk(m_device_list_reply_mutex);
if (deviceCommandAddress != 0) if (deviceCommandAddress != 0)
{ {
Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18)); IOSIOCtlRequest pending_request{deviceCommandAddress};
Memory::Write_U32(0xFFFFFFFF, pending_request.buffer_out);
// Return value pending_request.SetReturnValue(-1);
Memory::Write_U32(-1, deviceCommandAddress + 4); WII_IPC_HLE_Interface::EnqueueReply(pending_request);
WII_IPC_HLE_Interface::EnqueueReply(deviceCommandAddress);
deviceCommandAddress = 0; deviceCommandAddress = 0;
} }
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", INFO_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize); request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size);
break; break;
} }
default: default:
{ request.Log(GetDeviceName(), LogTypes::WII_IPC_HID);
INFO_LOG(WII_IPC_HID, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize);
break;
}
} }
Memory::Write_U32(ReturnValue, _CommandAddress + 4); request.SetReturnValue(return_value);
return GetDefaultReply(); return GetDefaultReply();
} }
@ -283,21 +256,11 @@ bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle* dev)
return true; return true;
} }
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtlV(u32 _CommandAddress) IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtlV(const IOSIOCtlVRequest& request)
{ {
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING); Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING);
u32 ReturnValue = 0; request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HID);
SIOCtlVBuffer CommandBuffer(_CommandAddress); request.SetReturnValue(IPC_SUCCESS);
INFO_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str());
INFO_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter);
INFO_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer);
INFO_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer);
INFO_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector);
INFO_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address);
INFO_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size);
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
return GetDefaultReply(); return GetDefaultReply();
} }
@ -340,10 +303,10 @@ void CWII_IPC_HLE_Device_hid::ConvertEndpointToWii(WiiHIDEndpointDescriptor* des
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize); dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
} }
void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) void CWII_IPC_HLE_Device_hid::FillOutDevices(const IOSIOCtlRequest& request)
{ {
static u16 check = 1; static u16 check = 1;
int OffsetBuffer = BufferOut; int OffsetBuffer = request.buffer_out;
int OffsetStart = 0; int OffsetStart = 0;
// int OffsetDevice = 0; // int OffsetDevice = 0;
int d, c, ic, i, e; /* config, interface container, interface, endpoint */ int d, c, ic, i, e; /* config, interface container, interface, endpoint */

View File

@ -38,8 +38,8 @@ public:
virtual ~CWII_IPC_HLE_Device_hid(); virtual ~CWII_IPC_HLE_Device_hid();
IPCCommandResult IOCtlV(u32 _CommandAddress) override; IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override; IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
private: private:
enum enum
@ -115,7 +115,7 @@ private:
}; };
u32 deviceCommandAddress; u32 deviceCommandAddress;
void FillOutDevices(u32 BufferOut, u32 BufferOutSize); void FillOutDevices(const IOSIOCtlRequest& request);
int GetAvailableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check); int GetAvailableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check);
bool ClaimDevice(libusb_device_handle* dev); bool ClaimDevice(libusb_device_handle* dev);