Merge pull request #4690 from leoetlino/common-usb
IOS: Move out common USB structures
This commit is contained in:
commit
83dc03416e
|
@ -36,6 +36,7 @@ enum LOG_TYPE
|
||||||
IOS_SD,
|
IOS_SD,
|
||||||
IOS_SSL,
|
IOS_SSL,
|
||||||
IOS_STM,
|
IOS_STM,
|
||||||
|
IOS_USB,
|
||||||
IOS_WC24,
|
IOS_WC24,
|
||||||
IOS_WIIMOTE,
|
IOS_WIIMOTE,
|
||||||
MASTER_LOG,
|
MASTER_LOG,
|
||||||
|
|
|
@ -70,6 +70,7 @@ LogManager::LogManager()
|
||||||
m_Log[LogTypes::IOS_SSL] = new LogContainer("IOS_SSL", "IOS - SSL");
|
m_Log[LogTypes::IOS_SSL] = new LogContainer("IOS_SSL", "IOS - SSL");
|
||||||
m_Log[LogTypes::IOS_STM] = new LogContainer("IOS_STM", "IOS - State Transition Manager");
|
m_Log[LogTypes::IOS_STM] = new LogContainer("IOS_STM", "IOS - State Transition Manager");
|
||||||
m_Log[LogTypes::IOS_NET] = new LogContainer("IOS_NET", "IOS - Network");
|
m_Log[LogTypes::IOS_NET] = new LogContainer("IOS_NET", "IOS - Network");
|
||||||
|
m_Log[LogTypes::IOS_USB] = new LogContainer("IOS_USB", "IOS - USB");
|
||||||
m_Log[LogTypes::IOS_WC24] = new LogContainer("IOS_WC24", "IOS - WiiConnect24");
|
m_Log[LogTypes::IOS_WC24] = new LogContainer("IOS_WC24", "IOS - WiiConnect24");
|
||||||
m_Log[LogTypes::IOS_WIIMOTE] = new LogContainer("IOS_WIIMOTE", "IOS - Wii Remote");
|
m_Log[LogTypes::IOS_WIIMOTE] = new LogContainer("IOS_WIIMOTE", "IOS - Wii Remote");
|
||||||
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
|
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
|
||||||
|
|
|
@ -151,6 +151,8 @@ set(SRCS ActionReplay.cpp
|
||||||
IOS/Network/SSL.cpp
|
IOS/Network/SSL.cpp
|
||||||
IOS/SDIO/SDIOSlot0.cpp
|
IOS/SDIO/SDIOSlot0.cpp
|
||||||
IOS/STM/STM.cpp
|
IOS/STM/STM.cpp
|
||||||
|
IOS/USB/Common.cpp
|
||||||
|
IOS/USB/USBV0.cpp
|
||||||
IOS/USB/USB_KBD.cpp
|
IOS/USB/USB_KBD.cpp
|
||||||
IOS/USB/USB_VEN.cpp
|
IOS/USB/USB_VEN.cpp
|
||||||
IOS/USB/Bluetooth/BTBase.cpp
|
IOS/USB/Bluetooth/BTBase.cpp
|
||||||
|
|
|
@ -183,6 +183,8 @@
|
||||||
<ClCompile Include="IOS\Network\SSL.cpp" />
|
<ClCompile Include="IOS\Network\SSL.cpp" />
|
||||||
<ClCompile Include="IOS\SDIO\SDIOSlot0.cpp" />
|
<ClCompile Include="IOS\SDIO\SDIOSlot0.cpp" />
|
||||||
<ClCompile Include="IOS\STM\STM.cpp" />
|
<ClCompile Include="IOS\STM\STM.cpp" />
|
||||||
|
<ClCompile Include="IOS\USB\Common.cpp" />
|
||||||
|
<ClCompile Include="IOS\USB\USBV0.cpp" />
|
||||||
<ClCompile Include="IOS\USB\USB_HIDv4.cpp">
|
<ClCompile Include="IOS\USB\USB_HIDv4.cpp">
|
||||||
<!--
|
<!--
|
||||||
Disable "nonstandard extension used : zero-sized array in struct/union" warning,
|
Disable "nonstandard extension used : zero-sized array in struct/union" warning,
|
||||||
|
@ -412,6 +414,8 @@
|
||||||
<ClInclude Include="IOS\Network\SSL.h" />
|
<ClInclude Include="IOS\Network\SSL.h" />
|
||||||
<ClInclude Include="IOS\SDIO\SDIOSlot0.h" />
|
<ClInclude Include="IOS\SDIO\SDIOSlot0.h" />
|
||||||
<ClInclude Include="IOS\STM\STM.h" />
|
<ClInclude Include="IOS\STM\STM.h" />
|
||||||
|
<ClInclude Include="IOS\USB\Common.h" />
|
||||||
|
<ClInclude Include="IOS\USB\USBV0.h" />
|
||||||
<ClInclude Include="IOS\USB\USB_HIDv4.h" />
|
<ClInclude Include="IOS\USB\USB_HIDv4.h" />
|
||||||
<ClInclude Include="IOS\USB\USB_KBD.h" />
|
<ClInclude Include="IOS\USB\USB_KBD.h" />
|
||||||
<ClInclude Include="IOS\USB\USB_VEN.h" />
|
<ClInclude Include="IOS\USB\USB_VEN.h" />
|
||||||
|
|
|
@ -764,6 +764,12 @@
|
||||||
<ClCompile Include="IOS\STM\STM.cpp">
|
<ClCompile Include="IOS\STM\STM.cpp">
|
||||||
<Filter>IOS\STM</Filter>
|
<Filter>IOS\STM</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="IOS\USB\Common.cpp">
|
||||||
|
<Filter>IOS\USB</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="IOS\USB\USBV0.cpp">
|
||||||
|
<Filter>IOS\USB</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="IOS\USB\USB_HIDv4.cpp">
|
<ClCompile Include="IOS\USB\USB_HIDv4.cpp">
|
||||||
<Filter>IOS\USB</Filter>
|
<Filter>IOS\USB</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -1332,6 +1338,12 @@
|
||||||
<ClInclude Include="IOS\STM\STM.h">
|
<ClInclude Include="IOS\STM\STM.h">
|
||||||
<Filter>IOS\STM</Filter>
|
<Filter>IOS\STM</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="IOS\USB\Common.h">
|
||||||
|
<Filter>IOS\USB</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="IOS\USB\USBV0.h">
|
||||||
|
<Filter>IOS\USB</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="IOS\USB\USB_HIDv4.h">
|
<ClInclude Include="IOS\USB\USB_HIDv4.h">
|
||||||
<Filter>IOS\USB</Filter>
|
<Filter>IOS\USB</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1363,4 +1375,4 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="CMakeLists.txt" />
|
<Text Include="CMakeLists.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -53,32 +53,5 @@ void RestoreBTInfoSection(SysConf* sysconf)
|
||||||
sysconf->SetArrayData("BT.DINF", section.data(), static_cast<u16>(section.size()));
|
sysconf->SetArrayData("BT.DINF", section.data(), static_cast<u16>(section.size()));
|
||||||
File::Delete(filename);
|
File::Delete(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Device
|
|
||||||
{
|
|
||||||
BluetoothBase::CtrlMessage::CtrlMessage(const IOCtlVRequest& ioctlv) : ios_request(ioctlv)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothBase::CtrlBuffer::CtrlBuffer(const IOCtlVRequest& ioctlv) : ios_request(ioctlv)
|
|
||||||
{
|
|
||||||
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 BluetoothBase::CtrlBuffer::FillBuffer(const u8* src, const size_t size) const
|
|
||||||
{
|
|
||||||
_assert_msg_(IOS_WIIMOTE, size <= m_length, "FillBuffer: size %li > payload length %i", size,
|
|
||||||
m_length);
|
|
||||||
Memory::CopyToEmu(m_payload_addr, src, size);
|
|
||||||
}
|
|
||||||
} // namespace Device
|
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
|
|
@ -36,13 +36,6 @@ protected:
|
||||||
static constexpr int SCO_PKT_SIZE = 64;
|
static constexpr int SCO_PKT_SIZE = 64;
|
||||||
static constexpr int SCO_PKT_NUM = 0;
|
static constexpr int SCO_PKT_NUM = 0;
|
||||||
|
|
||||||
enum USBIOCtl
|
|
||||||
{
|
|
||||||
USBV0_IOCTL_CTRLMSG = 0,
|
|
||||||
USBV0_IOCTL_BLKMSG = 1,
|
|
||||||
USBV0_IOCTL_INTRMSG = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum USBEndpoint
|
enum USBEndpoint
|
||||||
{
|
{
|
||||||
HCI_CTRL = 0x00,
|
HCI_CTRL = 0x00,
|
||||||
|
@ -50,28 +43,6 @@ protected:
|
||||||
ACL_DATA_IN = 0x82,
|
ACL_DATA_IN = 0x82,
|
||||||
ACL_DATA_OUT = 0x02
|
ACL_DATA_OUT = 0x02
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CtrlMessage
|
|
||||||
{
|
|
||||||
CtrlMessage(const IOCtlVRequest& ioctlv);
|
|
||||||
IOCtlVRequest ios_request;
|
|
||||||
u8 request_type = 0;
|
|
||||||
u8 request = 0;
|
|
||||||
u16 value = 0;
|
|
||||||
u16 index = 0;
|
|
||||||
u16 length = 0;
|
|
||||||
u32 payload_addr = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CtrlBuffer
|
|
||||||
{
|
|
||||||
CtrlBuffer(const IOCtlVRequest& ioctlv);
|
|
||||||
IOCtlVRequest ios_request;
|
|
||||||
void FillBuffer(const u8* src, size_t size) const;
|
|
||||||
u8 m_endpoint = 0;
|
|
||||||
u16 m_length = 0;
|
|
||||||
u32 m_payload_addr = 0;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
} // namespace Device
|
} // namespace Device
|
||||||
} // namespace HLE
|
} // namespace HLE
|
||||||
|
|
|
@ -167,9 +167,9 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
|
||||||
bool send_reply = true;
|
bool send_reply = true;
|
||||||
switch (request.request)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
case USBV0_IOCTL_CTRLMSG: // HCI command is received from the stack
|
case USB::IOCTLV_USBV0_CTRLMSG: // HCI command is received from the stack
|
||||||
{
|
{
|
||||||
m_CtrlSetup = std::make_unique<CtrlMessage>(request);
|
m_CtrlSetup = std::make_unique<USB::V0CtrlMessage>(request);
|
||||||
// Replies are generated inside
|
// Replies are generated inside
|
||||||
ExecuteHCICommandMessage(*m_CtrlSetup);
|
ExecuteHCICommandMessage(*m_CtrlSetup);
|
||||||
m_CtrlSetup.reset();
|
m_CtrlSetup.reset();
|
||||||
|
@ -177,50 +177,50 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case USBV0_IOCTL_BLKMSG:
|
case USB::IOCTLV_USBV0_BLKMSG:
|
||||||
{
|
{
|
||||||
const CtrlBuffer ctrl{request};
|
const USB::V0BulkMessage ctrl{request};
|
||||||
switch (ctrl.m_endpoint)
|
switch (ctrl.endpoint)
|
||||||
{
|
{
|
||||||
case ACL_DATA_OUT: // ACL data is received from the stack
|
case ACL_DATA_OUT: // ACL data is received from the stack
|
||||||
{
|
{
|
||||||
// This is the ACL datapath from CPU to Wii Remote
|
// This is the ACL datapath from CPU to Wii Remote
|
||||||
const auto* acl_header =
|
const auto* acl_header =
|
||||||
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.m_payload_addr));
|
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.data_address));
|
||||||
|
|
||||||
_dbg_assert_(IOS_WIIMOTE, HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
|
_dbg_assert_(IOS_WIIMOTE, HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
|
||||||
_dbg_assert_(IOS_WIIMOTE, HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
|
_dbg_assert_(IOS_WIIMOTE, HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
|
||||||
|
|
||||||
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
|
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
|
||||||
Memory::GetPointer(ctrl.m_payload_addr + sizeof(hci_acldata_hdr_t)),
|
Memory::GetPointer(ctrl.data_address + sizeof(hci_acldata_hdr_t)),
|
||||||
acl_header->length);
|
acl_header->length);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ACL_DATA_IN: // We are given an ACL buffer to fill
|
case ACL_DATA_IN: // We are given an ACL buffer to fill
|
||||||
{
|
{
|
||||||
m_ACLEndpoint = std::make_unique<CtrlBuffer>(request);
|
m_ACLEndpoint = std::make_unique<USB::V0BulkMessage>(request);
|
||||||
DEBUG_LOG(IOS_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
|
DEBUG_LOG(IOS_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
|
||||||
send_reply = false;
|
send_reply = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
_dbg_assert_msg_(IOS_WIIMOTE, 0, "Unknown USBV0_IOCTL_BLKMSG: %x", ctrl.m_endpoint);
|
_dbg_assert_msg_(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_BLKMSG: %x", ctrl.endpoint);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case USBV0_IOCTL_INTRMSG:
|
case USB::IOCTLV_USBV0_INTRMSG:
|
||||||
{
|
{
|
||||||
const CtrlBuffer ctrl{request};
|
const USB::V0IntrMessage ctrl{request};
|
||||||
if (ctrl.m_endpoint == HCI_EVENT) // We are given a HCI buffer to fill
|
if (ctrl.endpoint == HCI_EVENT) // We are given a HCI buffer to fill
|
||||||
{
|
{
|
||||||
m_HCIEndpoint = std::make_unique<CtrlBuffer>(request);
|
m_HCIEndpoint = std::make_unique<USB::V0IntrMessage>(request);
|
||||||
DEBUG_LOG(IOS_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
|
DEBUG_LOG(IOS_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
|
||||||
send_reply = false;
|
send_reply = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(IOS_WIIMOTE, 0, "Unknown USBV0_IOCTL_INTRMSG: %x", ctrl.m_endpoint);
|
_dbg_assert_msg_(IOS_WIIMOTE, 0, "Unknown USB::IOCTLV_USBV0_INTRMSG: %x", ctrl.endpoint);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
|
||||||
return send_reply ? GetDefaultReply(IPC_SUCCESS) : GetNoReply();
|
return send_reply ? GetDefaultReply(IPC_SUCCESS) : GetNoReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we handle the USBV0_IOCTL_BLKMSG Ioctlv
|
// Here we handle the USB::IOCTLV_USBV0_BLKMSG Ioctlv
|
||||||
void BluetoothEmu::SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
void BluetoothEmu::SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size)
|
||||||
{
|
{
|
||||||
WiimoteDevice* pWiiMote = AccessWiiMote(_ConnectionHandle);
|
WiimoteDevice* pWiiMote = AccessWiiMote(_ConnectionHandle);
|
||||||
|
@ -261,7 +261,7 @@ void BluetoothEmu::SendACLPacket(u16 connection_handle, const u8* data, u32 size
|
||||||
m_ACLEndpoint->ios_request.address);
|
m_ACLEndpoint->ios_request.address);
|
||||||
|
|
||||||
hci_acldata_hdr_t* header =
|
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->data_address));
|
||||||
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||||
header->length = size;
|
header->length = size;
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ void BluetoothEmu::ACLPool::Store(const u8* data, const u16 size, const u16 conn
|
||||||
packet.conn_handle = conn_handle;
|
packet.conn_handle = conn_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothEmu::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
void BluetoothEmu::ACLPool::WriteToEndpoint(USB::V0BulkMessage& endpoint)
|
||||||
{
|
{
|
||||||
auto& packet = m_queue.front();
|
auto& packet = m_queue.front();
|
||||||
|
|
||||||
|
@ -424,7 +424,7 @@ void BluetoothEmu::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
|
||||||
"queue to %08x",
|
"queue to %08x",
|
||||||
endpoint.ios_request.address);
|
endpoint.ios_request.address);
|
||||||
|
|
||||||
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.m_payload_addr);
|
hci_acldata_hdr_t* pHeader = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.data_address);
|
||||||
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
pHeader->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
|
||||||
pHeader->length = size;
|
pHeader->length = size;
|
||||||
|
|
||||||
|
@ -964,11 +964,11 @@ bool BluetoothEmu::SendEventConPacketTypeChange(u16 _connectionHandle, u16 _pack
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command dispatcher
|
// Command dispatcher
|
||||||
// This is called from the USBV0_IOCTL_CTRLMSG Ioctlv
|
// This is called from the USB::IOCTLV_USBV0_CTRLMSG Ioctlv
|
||||||
void BluetoothEmu::ExecuteHCICommandMessage(const CtrlMessage& ctrl_message)
|
void BluetoothEmu::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message)
|
||||||
{
|
{
|
||||||
u8* pInput = Memory::GetPointer(ctrl_message.payload_addr + 3);
|
u8* pInput = Memory::GetPointer(ctrl_message.data_address + 3);
|
||||||
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(ctrl_message.payload_addr);
|
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(ctrl_message.data_address);
|
||||||
|
|
||||||
u16 ocf = HCI_OCF(pMsg->Opcode);
|
u16 ocf = HCI_OCF(pMsg->Opcode);
|
||||||
u16 ogf = HCI_OGF(pMsg->Opcode);
|
u16 ogf = HCI_OGF(pMsg->Opcode);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Core/IOS/USB/Bluetooth/BTBase.h"
|
#include "Core/IOS/USB/Bluetooth/BTBase.h"
|
||||||
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
|
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
|
||||||
#include "Core/IOS/USB/Bluetooth/hci.h"
|
#include "Core/IOS/USB/Bluetooth/hci.h"
|
||||||
|
#include "Core/IOS/USB/USBV0.h"
|
||||||
|
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
|
@ -70,9 +71,9 @@ private:
|
||||||
// this is used to trigger connecting via ACL
|
// this is used to trigger connecting via ACL
|
||||||
u8 m_ScanEnable = 0;
|
u8 m_ScanEnable = 0;
|
||||||
|
|
||||||
std::unique_ptr<CtrlMessage> m_CtrlSetup;
|
std::unique_ptr<USB::V0CtrlMessage> m_CtrlSetup;
|
||||||
std::unique_ptr<CtrlBuffer> m_HCIEndpoint;
|
std::unique_ptr<USB::V0IntrMessage> m_HCIEndpoint;
|
||||||
std::unique_ptr<CtrlBuffer> m_ACLEndpoint;
|
std::unique_ptr<USB::V0BulkMessage> m_ACLEndpoint;
|
||||||
std::deque<SQueuedEvent> m_EventQueue;
|
std::deque<SQueuedEvent> m_EventQueue;
|
||||||
|
|
||||||
class ACLPool
|
class ACLPool
|
||||||
|
@ -90,7 +91,7 @@ private:
|
||||||
ACLPool() : m_queue() {}
|
ACLPool() : m_queue() {}
|
||||||
void Store(const u8* data, const u16 size, const u16 conn_handle);
|
void Store(const u8* data, const u16 size, const u16 conn_handle);
|
||||||
|
|
||||||
void WriteToEndpoint(CtrlBuffer& endpoint);
|
void WriteToEndpoint(USB::V0BulkMessage& endpoint);
|
||||||
|
|
||||||
bool IsEmpty() const { return m_queue.empty(); }
|
bool IsEmpty() const { return m_queue.empty(); }
|
||||||
// For SaveStates
|
// For SaveStates
|
||||||
|
@ -126,7 +127,7 @@ private:
|
||||||
bool SendEventLinkKeyNotification(const u8 num_to_send);
|
bool SendEventLinkKeyNotification(const u8 num_to_send);
|
||||||
|
|
||||||
// Execute HCI Message
|
// Execute HCI Message
|
||||||
void ExecuteHCICommandMessage(const CtrlMessage& ctrl_message);
|
void ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message);
|
||||||
|
|
||||||
// OGF 0x01 - Link control commands and return parameters
|
// OGF 0x01 - Link control commands and return parameters
|
||||||
void CommandWriteInquiryMode(const u8* input);
|
void CommandWriteInquiryMode(const u8* input);
|
||||||
|
|
|
@ -178,10 +178,10 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
|
||||||
switch (request.request)
|
switch (request.request)
|
||||||
{
|
{
|
||||||
// HCI commands to the Bluetooth adapter
|
// HCI commands to the Bluetooth adapter
|
||||||
case USBV0_IOCTL_CTRLMSG:
|
case USB::IOCTLV_USBV0_CTRLMSG:
|
||||||
{
|
{
|
||||||
auto cmd = std::make_unique<CtrlMessage>(request);
|
auto cmd = std::make_unique<USB::V0CtrlMessage>(request);
|
||||||
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->payload_addr));
|
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address));
|
||||||
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
|
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
m_fake_read_buffer_size_reply.Set();
|
m_fake_read_buffer_size_reply.Set();
|
||||||
|
@ -196,68 +196,70 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
|
||||||
if (opcode == HCI_CMD_DELETE_STORED_LINK_KEY)
|
if (opcode == HCI_CMD_DELETE_STORED_LINK_KEY)
|
||||||
{
|
{
|
||||||
// Delete link key(s) from our own link key storage when the game tells the adapter to
|
// Delete link key(s) from our own link key storage when the game tells the adapter to
|
||||||
const auto* delete_cmd =
|
hci_delete_stored_link_key_cp delete_cmd;
|
||||||
reinterpret_cast<hci_delete_stored_link_key_cp*>(Memory::GetPointer(cmd->payload_addr));
|
Memory::CopyFromEmu(&delete_cmd, cmd->data_address, sizeof(delete_cmd));
|
||||||
if (delete_cmd->delete_all)
|
if (delete_cmd.delete_all)
|
||||||
{
|
{
|
||||||
s_link_keys.clear();
|
s_link_keys.clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
btaddr_t addr;
|
btaddr_t addr;
|
||||||
std::copy(std::begin(delete_cmd->bdaddr.b), std::end(delete_cmd->bdaddr.b), addr.begin());
|
std::copy(std::begin(delete_cmd.bdaddr.b), std::end(delete_cmd.bdaddr.b), addr.begin());
|
||||||
s_link_keys.erase(addr);
|
s_link_keys.erase(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto buffer = std::vector<u8>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
|
auto buffer = std::make_unique<u8[]>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
|
||||||
libusb_fill_control_setup(buffer.data(), cmd->request_type, cmd->request, cmd->value,
|
libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index,
|
||||||
cmd->index, cmd->length);
|
cmd->length);
|
||||||
Memory::CopyFromEmu(buffer.data() + LIBUSB_CONTROL_SETUP_SIZE, cmd->payload_addr, cmd->length);
|
Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
|
||||||
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||||
libusb_fill_control_transfer(transfer, m_handle, buffer.data(), CommandCallback, cmd.release(),
|
libusb_fill_control_transfer(transfer, m_handle, buffer.release(), CommandCallback,
|
||||||
0);
|
cmd.release(), 0);
|
||||||
libusb_submit_transfer(transfer);
|
libusb_submit_transfer(transfer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// ACL data (incoming or outgoing) and incoming HCI events (respectively)
|
// ACL data (incoming or outgoing) and incoming HCI events (respectively)
|
||||||
case USBV0_IOCTL_BLKMSG:
|
case USB::IOCTLV_USBV0_BLKMSG:
|
||||||
case USBV0_IOCTL_INTRMSG:
|
case USB::IOCTLV_USBV0_INTRMSG:
|
||||||
{
|
{
|
||||||
auto buffer = std::make_unique<CtrlBuffer>(request);
|
auto buffer = std::make_unique<USB::V0IntrMessage>(request);
|
||||||
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
|
if (request.request == USB::IOCTLV_USBV0_INTRMSG)
|
||||||
{
|
{
|
||||||
FakeReadBufferSizeReply(*buffer);
|
if (m_sync_button_state == SyncButtonState::Pressed)
|
||||||
return GetNoReply();
|
{
|
||||||
}
|
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
|
||||||
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
|
FakeSyncButtonPressedEvent(*buffer);
|
||||||
{
|
return GetNoReply();
|
||||||
FakeVendorCommandReply(*buffer);
|
}
|
||||||
return GetNoReply();
|
if (m_sync_button_state == SyncButtonState::LongPressed)
|
||||||
}
|
{
|
||||||
if (request.request == USBV0_IOCTL_INTRMSG && m_sync_button_state == SyncButtonState::Pressed)
|
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
|
||||||
{
|
FakeSyncButtonHeldEvent(*buffer);
|
||||||
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
|
return GetNoReply();
|
||||||
FakeSyncButtonPressedEvent(*buffer);
|
}
|
||||||
return GetNoReply();
|
if (m_fake_read_buffer_size_reply.TestAndClear())
|
||||||
}
|
{
|
||||||
if (request.request == USBV0_IOCTL_INTRMSG &&
|
FakeReadBufferSizeReply(*buffer);
|
||||||
m_sync_button_state == SyncButtonState::LongPressed)
|
return GetNoReply();
|
||||||
{
|
}
|
||||||
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
|
if (m_fake_vendor_command_reply.TestAndClear())
|
||||||
FakeSyncButtonHeldEvent(*buffer);
|
{
|
||||||
return GetNoReply();
|
FakeVendorCommandReply(*buffer);
|
||||||
|
return GetNoReply();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
libusb_transfer* transfer = libusb_alloc_transfer(0);
|
||||||
transfer->buffer = Memory::GetPointer(buffer->m_payload_addr);
|
transfer->buffer = Memory::GetPointer(buffer->data_address);
|
||||||
transfer->callback = TransferCallback;
|
transfer->callback = TransferCallback;
|
||||||
transfer->dev_handle = m_handle;
|
transfer->dev_handle = m_handle;
|
||||||
transfer->endpoint = buffer->m_endpoint;
|
transfer->endpoint = buffer->endpoint;
|
||||||
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||||
transfer->length = buffer->m_length;
|
transfer->length = buffer->length;
|
||||||
transfer->timeout = TIMEOUT;
|
transfer->timeout = TIMEOUT;
|
||||||
transfer->type = request.request == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
|
transfer->type = request.request == USB::IOCTLV_USBV0_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
|
||||||
LIBUSB_TRANSFER_TYPE_INTERRUPT;
|
LIBUSB_TRANSFER_TYPE_INTERRUPT;
|
||||||
transfer->user_data = buffer.release();
|
transfer->user_data = buffer.release();
|
||||||
libusb_submit_transfer(transfer);
|
libusb_submit_transfer(transfer);
|
||||||
break;
|
break;
|
||||||
|
@ -390,16 +392,16 @@ bool BluetoothReal::SendHCIStoreLinkKeyCommand()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothReal::FakeVendorCommandReply(CtrlBuffer& ctrl)
|
void BluetoothReal::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
|
||||||
{
|
{
|
||||||
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
SHCIEventCommand hci_event;
|
||||||
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
|
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
|
||||||
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
|
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
|
||||||
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
|
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2;
|
||||||
hci_event->PacketIndicator = 0x01;
|
hci_event.PacketIndicator = 0x01;
|
||||||
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
|
hci_event.Opcode = m_fake_vendor_command_reply_opcode;
|
||||||
|
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
|
||||||
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(SHCIEventCommand)));
|
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Due to how the widcomm stack which Nintendo uses is coded, we must never
|
// Due to how the widcomm stack which Nintendo uses is coded, we must never
|
||||||
|
@ -407,14 +409,15 @@ void BluetoothReal::FakeVendorCommandReply(CtrlBuffer& ctrl)
|
||||||
// - it will cause a u8 underflow and royally screw things up.
|
// - 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
|
// Therefore, the reply to this command has to be faked to avoid random, weird issues
|
||||||
// (including Wiimote disconnects and "event mismatch" warning messages).
|
// (including Wiimote disconnects and "event mismatch" warning messages).
|
||||||
void BluetoothReal::FakeReadBufferSizeReply(CtrlBuffer& ctrl)
|
void BluetoothReal::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl)
|
||||||
{
|
{
|
||||||
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
SHCIEventCommand hci_event;
|
||||||
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
|
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
|
||||||
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
|
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
|
||||||
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
|
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
|
||||||
hci_event->PacketIndicator = 0x01;
|
hci_event.PacketIndicator = 0x01;
|
||||||
hci_event->Opcode = HCI_CMD_READ_BUFFER_SIZE;
|
hci_event.Opcode = HCI_CMD_READ_BUFFER_SIZE;
|
||||||
|
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
|
||||||
|
|
||||||
hci_read_buffer_size_rp reply;
|
hci_read_buffer_size_rp reply;
|
||||||
reply.status = 0x00;
|
reply.status = 0x00;
|
||||||
|
@ -422,27 +425,26 @@ void BluetoothReal::FakeReadBufferSizeReply(CtrlBuffer& ctrl)
|
||||||
reply.num_acl_pkts = ACL_PKT_NUM;
|
reply.num_acl_pkts = ACL_PKT_NUM;
|
||||||
reply.max_sco_size = SCO_PKT_SIZE;
|
reply.max_sco_size = SCO_PKT_SIZE;
|
||||||
reply.num_sco_pkts = SCO_PKT_NUM;
|
reply.num_sco_pkts = SCO_PKT_NUM;
|
||||||
|
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
|
||||||
memcpy(packet + sizeof(SHCIEventCommand), &reply, sizeof(hci_read_buffer_size_rp));
|
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
|
||||||
EnqueueReply(ctrl.ios_request,
|
|
||||||
static_cast<s32>(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothReal::FakeSyncButtonEvent(CtrlBuffer& ctrl, const u8* payload, const u8 size)
|
void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload, const u8 size)
|
||||||
{
|
{
|
||||||
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
|
hci_event_hdr_t hci_event;
|
||||||
auto* hci_event = reinterpret_cast<hci_event_hdr_t*>(packet);
|
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
|
||||||
hci_event->event = HCI_EVENT_VENDOR;
|
hci_event.event = HCI_EVENT_VENDOR;
|
||||||
hci_event->length = size;
|
hci_event.length = size;
|
||||||
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
|
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
|
||||||
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event_hdr_t) + size));
|
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
|
||||||
|
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the red sync button is pressed, a HCI event is generated:
|
// When the red sync button is pressed, a HCI event is generated:
|
||||||
// > HCI Event: Vendor (0xff) plen 1
|
// > HCI Event: Vendor (0xff) plen 1
|
||||||
// 08
|
// 08
|
||||||
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
|
// This causes the emulated software to perform a BT inquiry and connect to found Wiimotes.
|
||||||
void BluetoothReal::FakeSyncButtonPressedEvent(CtrlBuffer& ctrl)
|
void BluetoothReal::FakeSyncButtonPressedEvent(USB::V0IntrMessage& ctrl)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(IOS_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
|
NOTICE_LOG(IOS_WIIMOTE, "Faking 'sync button pressed' (0x08) event packet");
|
||||||
const u8 payload[1] = {0x08};
|
const u8 payload[1] = {0x08};
|
||||||
|
@ -451,7 +453,7 @@ void BluetoothReal::FakeSyncButtonPressedEvent(CtrlBuffer& ctrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
|
// When the red sync button is held for 10 seconds, a HCI event with payload 09 is sent.
|
||||||
void BluetoothReal::FakeSyncButtonHeldEvent(CtrlBuffer& ctrl)
|
void BluetoothReal::FakeSyncButtonHeldEvent(USB::V0IntrMessage& ctrl)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(IOS_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
|
NOTICE_LOG(IOS_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
|
||||||
const u8 payload[1] = {0x09};
|
const u8 payload[1] = {0x09};
|
||||||
|
@ -565,7 +567,8 @@ void BluetoothReal::TransferThread()
|
||||||
// The callbacks are called from libusb code on a separate thread.
|
// The callbacks are called from libusb code on a separate thread.
|
||||||
void BluetoothReal::CommandCallback(libusb_transfer* tr)
|
void BluetoothReal::CommandCallback(libusb_transfer* tr)
|
||||||
{
|
{
|
||||||
const std::unique_ptr<CtrlMessage> cmd(static_cast<CtrlMessage*>(tr->user_data));
|
const std::unique_ptr<USB::CtrlMessage> cmd(static_cast<USB::CtrlMessage*>(tr->user_data));
|
||||||
|
const std::unique_ptr<u8[]> buffer(tr->buffer);
|
||||||
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_NO_DEVICE)
|
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_NO_DEVICE)
|
||||||
{
|
{
|
||||||
ERROR_LOG(IOS_WIIMOTE, "libusb command transfer failed, status: 0x%02x", tr->status);
|
ERROR_LOG(IOS_WIIMOTE, "libusb command transfer failed, status: 0x%02x", tr->status);
|
||||||
|
@ -580,13 +583,13 @@ void BluetoothReal::CommandCallback(libusb_transfer* tr)
|
||||||
{
|
{
|
||||||
s_showed_failed_transfer.Clear();
|
s_showed_failed_transfer.Clear();
|
||||||
}
|
}
|
||||||
|
cmd->FillBuffer(libusb_control_transfer_get_data(tr), tr->actual_length);
|
||||||
EnqueueReply(cmd->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
|
EnqueueReply(cmd->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothReal::TransferCallback(libusb_transfer* tr)
|
void BluetoothReal::TransferCallback(libusb_transfer* tr)
|
||||||
{
|
{
|
||||||
const std::unique_ptr<CtrlBuffer> ctrl(static_cast<CtrlBuffer*>(tr->user_data));
|
const std::unique_ptr<USB::V0IntrMessage> ctrl(static_cast<USB::V0IntrMessage*>(tr->user_data));
|
||||||
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_TIMED_OUT &&
|
if (tr->status != LIBUSB_TRANSFER_COMPLETED && tr->status != LIBUSB_TRANSFER_TIMED_OUT &&
|
||||||
tr->status != LIBUSB_TRANSFER_NO_DEVICE)
|
tr->status != LIBUSB_TRANSFER_NO_DEVICE)
|
||||||
{
|
{
|
||||||
|
@ -624,7 +627,6 @@ void BluetoothReal::TransferCallback(libusb_transfer* tr)
|
||||||
s_need_reset_keys.Set();
|
s_need_reset_keys.Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EnqueueReply(ctrl->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
|
EnqueueReply(ctrl->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
|
||||||
}
|
}
|
||||||
} // namespace Device
|
} // namespace Device
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "Common/Timer.h"
|
#include "Common/Timer.h"
|
||||||
#include "Core/IOS/IPC.h"
|
#include "Core/IOS/IPC.h"
|
||||||
#include "Core/IOS/USB/Bluetooth/BTBase.h"
|
#include "Core/IOS/USB/Bluetooth/BTBase.h"
|
||||||
|
#include "Core/IOS/USB/USBV0.h"
|
||||||
|
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
struct libusb_context;
|
struct libusb_context;
|
||||||
|
@ -85,11 +86,11 @@ private:
|
||||||
void SendHCIResetCommand();
|
void SendHCIResetCommand();
|
||||||
void SendHCIDeleteLinkKeyCommand();
|
void SendHCIDeleteLinkKeyCommand();
|
||||||
bool SendHCIStoreLinkKeyCommand();
|
bool SendHCIStoreLinkKeyCommand();
|
||||||
void FakeVendorCommandReply(CtrlBuffer& ctrl);
|
void FakeVendorCommandReply(USB::V0IntrMessage& ctrl);
|
||||||
void FakeReadBufferSizeReply(CtrlBuffer& ctrl);
|
void FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl);
|
||||||
void FakeSyncButtonEvent(CtrlBuffer& ctrl, const u8* payload, u8 size);
|
void FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload, u8 size);
|
||||||
void FakeSyncButtonPressedEvent(CtrlBuffer& ctrl);
|
void FakeSyncButtonPressedEvent(USB::V0IntrMessage& ctrl);
|
||||||
void FakeSyncButtonHeldEvent(CtrlBuffer& ctrl);
|
void FakeSyncButtonHeldEvent(USB::V0IntrMessage& ctrl);
|
||||||
|
|
||||||
void LoadLinkKeys();
|
void LoadLinkKeys();
|
||||||
void SaveLinkKeys();
|
void SaveLinkKeys();
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "Core/IOS/USB/Common.h"
|
||||||
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/HW/Memmap.h"
|
||||||
|
|
||||||
|
namespace IOS
|
||||||
|
{
|
||||||
|
namespace HLE
|
||||||
|
{
|
||||||
|
namespace USB
|
||||||
|
{
|
||||||
|
std::unique_ptr<u8[]> TransferCommand::MakeBuffer(const size_t size) const
|
||||||
|
{
|
||||||
|
_assert_msg_(IOS_USB, data_address != 0, "Invalid data_address");
|
||||||
|
auto buffer = std::make_unique<u8[]>(size);
|
||||||
|
Memory::CopyFromEmu(buffer.get(), data_address, size);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferCommand::FillBuffer(const u8* src, const size_t size) const
|
||||||
|
{
|
||||||
|
_assert_msg_(IOS_USB, size == 0 || data_address != 0, "Invalid data_address");
|
||||||
|
Memory::CopyToEmu(data_address, src, size);
|
||||||
|
}
|
||||||
|
} // namespace USB
|
||||||
|
} // namespace HLE
|
||||||
|
} // namespace IOS
|
|
@ -0,0 +1,114 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/IOS/Device.h"
|
||||||
|
|
||||||
|
namespace IOS
|
||||||
|
{
|
||||||
|
namespace HLE
|
||||||
|
{
|
||||||
|
namespace USB
|
||||||
|
{
|
||||||
|
struct DeviceDescriptor
|
||||||
|
{
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 bcdUSB;
|
||||||
|
u8 bDeviceClass;
|
||||||
|
u8 bDeviceSubClass;
|
||||||
|
u8 bDeviceProtocol;
|
||||||
|
u8 bMaxPacketSize0;
|
||||||
|
u16 idVendor;
|
||||||
|
u16 idProduct;
|
||||||
|
u16 bcdDevice;
|
||||||
|
u8 iManufacturer;
|
||||||
|
u8 iProduct;
|
||||||
|
u8 iSerialNumber;
|
||||||
|
u8 bNumConfigurations;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConfigDescriptor
|
||||||
|
{
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u16 wTotalLength;
|
||||||
|
u8 bNumInterfaces;
|
||||||
|
u8 bConfigurationValue;
|
||||||
|
u8 iConfiguration;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u8 MaxPower;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InterfaceDescriptor
|
||||||
|
{
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u8 bInterfaceNumber;
|
||||||
|
u8 bAlternateSetting;
|
||||||
|
u8 bNumEndpoints;
|
||||||
|
u8 bInterfaceClass;
|
||||||
|
u8 bInterfaceSubClass;
|
||||||
|
u8 bInterfaceProtocol;
|
||||||
|
u8 iInterface;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EndpointDescriptor
|
||||||
|
{
|
||||||
|
u8 bLength;
|
||||||
|
u8 bDescriptorType;
|
||||||
|
u8 bEndpointAddress;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u16 wMaxPacketSize;
|
||||||
|
u8 bInterval;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TransferCommand
|
||||||
|
{
|
||||||
|
Request ios_request;
|
||||||
|
u32 data_address = 0;
|
||||||
|
|
||||||
|
TransferCommand(const Request& ios_request_, u32 data_address_)
|
||||||
|
: ios_request(ios_request_), data_address(data_address_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~TransferCommand() = default;
|
||||||
|
// Called after a transfer has completed and before replying to the transfer request.
|
||||||
|
virtual void OnTransferComplete() const {}
|
||||||
|
std::unique_ptr<u8[]> MakeBuffer(size_t size) const;
|
||||||
|
void FillBuffer(const u8* src, size_t size) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CtrlMessage : TransferCommand
|
||||||
|
{
|
||||||
|
u8 request_type = 0;
|
||||||
|
u8 request = 0;
|
||||||
|
u16 value = 0;
|
||||||
|
u16 index = 0;
|
||||||
|
u16 length = 0;
|
||||||
|
using TransferCommand::TransferCommand;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BulkMessage : TransferCommand
|
||||||
|
{
|
||||||
|
u16 length = 0;
|
||||||
|
u8 endpoint = 0;
|
||||||
|
using TransferCommand::TransferCommand;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IntrMessage : TransferCommand
|
||||||
|
{
|
||||||
|
u16 length = 0;
|
||||||
|
u8 endpoint = 0;
|
||||||
|
using TransferCommand::TransferCommand;
|
||||||
|
};
|
||||||
|
} // namespace USB
|
||||||
|
} // namespace HLE
|
||||||
|
} // namespace IOS
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Common/CommonFuncs.h"
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/HW/Memmap.h"
|
||||||
|
#include "Core/IOS/Device.h"
|
||||||
|
#include "Core/IOS/USB/USBV0.h"
|
||||||
|
|
||||||
|
namespace IOS
|
||||||
|
{
|
||||||
|
namespace HLE
|
||||||
|
{
|
||||||
|
namespace USB
|
||||||
|
{
|
||||||
|
V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv)
|
||||||
|
: CtrlMessage(ioctlv, ioctlv.io_vectors[0].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));
|
||||||
|
}
|
||||||
|
|
||||||
|
V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length)
|
||||||
|
: BulkMessage(ioctlv, ioctlv.io_vectors[0].address)
|
||||||
|
{
|
||||||
|
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
|
||||||
|
if (long_length)
|
||||||
|
length = Memory::Read_U32(ioctlv.in_vectors[1].address);
|
||||||
|
else
|
||||||
|
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
|
||||||
|
}
|
||||||
|
|
||||||
|
V0IntrMessage::V0IntrMessage(const IOCtlVRequest& ioctlv)
|
||||||
|
: IntrMessage(ioctlv, ioctlv.io_vectors[0].address)
|
||||||
|
{
|
||||||
|
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
|
||||||
|
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
|
||||||
|
}
|
||||||
|
} // namespace USB
|
||||||
|
} // namespace HLE
|
||||||
|
} // namespace IOS
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/IOS/USB/Common.h"
|
||||||
|
|
||||||
|
// Used by early USB interfaces, such as /dev/usb/oh0 (except in IOS57, 58, 59) and /dev/usb/oh1.
|
||||||
|
|
||||||
|
namespace IOS
|
||||||
|
{
|
||||||
|
namespace HLE
|
||||||
|
{
|
||||||
|
struct IOCtlVRequest;
|
||||||
|
|
||||||
|
namespace USB
|
||||||
|
{
|
||||||
|
enum V0Requests
|
||||||
|
{
|
||||||
|
IOCTLV_USBV0_CTRLMSG = 0,
|
||||||
|
IOCTLV_USBV0_BLKMSG = 1,
|
||||||
|
IOCTLV_USBV0_INTRMSG = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct V0CtrlMessage final : CtrlMessage
|
||||||
|
{
|
||||||
|
explicit V0CtrlMessage(const IOCtlVRequest& ioctlv);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct V0BulkMessage final : BulkMessage
|
||||||
|
{
|
||||||
|
explicit V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct V0IntrMessage final : IntrMessage
|
||||||
|
{
|
||||||
|
explicit V0IntrMessage(const IOCtlVRequest& ioctlv);
|
||||||
|
};
|
||||||
|
} // namespace USB
|
||||||
|
} // namespace HLE
|
||||||
|
} // namespace IOS
|
|
@ -263,8 +263,7 @@ IPCCommandResult USB_HIDv4::IOCtlV(const IOCtlVRequest& request)
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void USB_HIDv4::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
|
void USB_HIDv4::ConvertDeviceToWii(USB::DeviceDescriptor* dest, const libusb_device_descriptor* src)
|
||||||
const struct libusb_device_descriptor* src)
|
|
||||||
{
|
{
|
||||||
dest->bLength = src->bLength;
|
dest->bLength = src->bLength;
|
||||||
dest->bDescriptorType = src->bDescriptorType;
|
dest->bDescriptorType = src->bDescriptorType;
|
||||||
|
@ -282,23 +281,22 @@ void USB_HIDv4::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
|
||||||
dest->bNumConfigurations = src->bNumConfigurations;
|
dest->bNumConfigurations = src->bNumConfigurations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USB_HIDv4::ConvertConfigToWii(WiiHIDConfigDescriptor* dest,
|
void USB_HIDv4::ConvertConfigToWii(USB::ConfigDescriptor* dest, const libusb_config_descriptor* src)
|
||||||
const struct libusb_config_descriptor* src)
|
|
||||||
{
|
{
|
||||||
memcpy(dest, src, sizeof(WiiHIDConfigDescriptor));
|
memcpy(dest, src, sizeof(USB::ConfigDescriptor));
|
||||||
dest->wTotalLength = Common::swap16(dest->wTotalLength);
|
dest->wTotalLength = Common::swap16(dest->wTotalLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void USB_HIDv4::ConvertInterfaceToWii(WiiHIDInterfaceDescriptor* dest,
|
void USB_HIDv4::ConvertInterfaceToWii(USB::InterfaceDescriptor* dest,
|
||||||
const struct libusb_interface_descriptor* src)
|
const libusb_interface_descriptor* src)
|
||||||
{
|
{
|
||||||
memcpy(dest, src, sizeof(WiiHIDInterfaceDescriptor));
|
memcpy(dest, src, sizeof(USB::InterfaceDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void USB_HIDv4::ConvertEndpointToWii(WiiHIDEndpointDescriptor* dest,
|
void USB_HIDv4::ConvertEndpointToWii(USB::EndpointDescriptor* dest,
|
||||||
const struct libusb_endpoint_descriptor* src)
|
const libusb_endpoint_descriptor* src)
|
||||||
{
|
{
|
||||||
memcpy(dest, src, sizeof(WiiHIDEndpointDescriptor));
|
memcpy(dest, src, sizeof(USB::EndpointDescriptor));
|
||||||
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
|
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +328,7 @@ void USB_HIDv4::FillOutDevices(const IOCtlRequest& request)
|
||||||
|
|
||||||
OffsetBuffer += 4; // skip devNum for now
|
OffsetBuffer += 4; // skip devNum for now
|
||||||
|
|
||||||
WiiHIDDeviceDescriptor wii_device;
|
USB::DeviceDescriptor wii_device;
|
||||||
ConvertDeviceToWii(&wii_device, &desc);
|
ConvertDeviceToWii(&wii_device, &desc);
|
||||||
Memory::CopyToEmu(OffsetBuffer, &wii_device, wii_device.bLength);
|
Memory::CopyToEmu(OffsetBuffer, &wii_device, wii_device.bLength);
|
||||||
OffsetBuffer += Common::AlignUp(wii_device.bLength, 4);
|
OffsetBuffer += Common::AlignUp(wii_device.bLength, 4);
|
||||||
|
@ -344,7 +342,7 @@ void USB_HIDv4::FillOutDevices(const IOCtlRequest& request)
|
||||||
// do not try to use usb devices with more than one interface, games can crash
|
// do not try to use usb devices with more than one interface, games can crash
|
||||||
if (cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES)
|
if (cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES)
|
||||||
{
|
{
|
||||||
WiiHIDConfigDescriptor wii_config;
|
USB::ConfigDescriptor wii_config;
|
||||||
ConvertConfigToWii(&wii_config, config);
|
ConvertConfigToWii(&wii_config, config);
|
||||||
Memory::CopyToEmu(OffsetBuffer, &wii_config, wii_config.bLength);
|
Memory::CopyToEmu(OffsetBuffer, &wii_config, wii_config.bLength);
|
||||||
OffsetBuffer += Common::AlignUp(wii_config.bLength, 4);
|
OffsetBuffer += Common::AlignUp(wii_config.bLength, 4);
|
||||||
|
@ -361,7 +359,7 @@ void USB_HIDv4::FillOutDevices(const IOCtlRequest& request)
|
||||||
if (interface->bInterfaceClass == LIBUSB_CLASS_HID)
|
if (interface->bInterfaceClass == LIBUSB_CLASS_HID)
|
||||||
isHID = true;
|
isHID = true;
|
||||||
|
|
||||||
WiiHIDInterfaceDescriptor wii_interface;
|
USB::InterfaceDescriptor wii_interface;
|
||||||
ConvertInterfaceToWii(&wii_interface, interface);
|
ConvertInterfaceToWii(&wii_interface, interface);
|
||||||
Memory::CopyToEmu(OffsetBuffer, &wii_interface, wii_interface.bLength);
|
Memory::CopyToEmu(OffsetBuffer, &wii_interface, wii_interface.bLength);
|
||||||
OffsetBuffer += Common::AlignUp(wii_interface.bLength, 4);
|
OffsetBuffer += Common::AlignUp(wii_interface.bLength, 4);
|
||||||
|
@ -370,7 +368,7 @@ void USB_HIDv4::FillOutDevices(const IOCtlRequest& request)
|
||||||
{
|
{
|
||||||
const struct libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
|
const struct libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
|
||||||
|
|
||||||
WiiHIDEndpointDescriptor wii_endpoint;
|
USB::EndpointDescriptor wii_endpoint;
|
||||||
ConvertEndpointToWii(&wii_endpoint, endpoint);
|
ConvertEndpointToWii(&wii_endpoint, endpoint);
|
||||||
Memory::CopyToEmu(OffsetBuffer, &wii_endpoint, wii_endpoint.bLength);
|
Memory::CopyToEmu(OffsetBuffer, &wii_endpoint, wii_endpoint.bLength);
|
||||||
OffsetBuffer += Common::AlignUp(wii_endpoint.bLength, 4);
|
OffsetBuffer += Common::AlignUp(wii_endpoint.bLength, 4);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Core/IOS/Device.h"
|
#include "Core/IOS/Device.h"
|
||||||
#include "Core/IOS/IPC.h"
|
#include "Core/IOS/IPC.h"
|
||||||
|
#include "Core/IOS/USB/Common.h"
|
||||||
|
|
||||||
// Forward declare things which we need from libusb header.
|
// Forward declare things which we need from libusb header.
|
||||||
// This prevents users of this file from indirectly pulling in libusb.
|
// This prevents users of this file from indirectly pulling in libusb.
|
||||||
|
@ -61,75 +62,16 @@ private:
|
||||||
IOCTL_HID_CANCEL_INTERRUPT = 0x08,
|
IOCTL_HID_CANCEL_INTERRUPT = 0x08,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WiiHIDDeviceDescriptor
|
|
||||||
{
|
|
||||||
u8 bLength;
|
|
||||||
u8 bDescriptorType;
|
|
||||||
u16 bcdUSB;
|
|
||||||
u8 bDeviceClass;
|
|
||||||
u8 bDeviceSubClass;
|
|
||||||
u8 bDeviceProtocol;
|
|
||||||
u8 bMaxPacketSize0;
|
|
||||||
u16 idVendor;
|
|
||||||
u16 idProduct;
|
|
||||||
u16 bcdDevice;
|
|
||||||
u8 iManufacturer;
|
|
||||||
u8 iProduct;
|
|
||||||
u8 iSerialNumber;
|
|
||||||
u8 bNumConfigurations;
|
|
||||||
u8 pad[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WiiHIDConfigDescriptor
|
|
||||||
{
|
|
||||||
u8 bLength;
|
|
||||||
u8 bDescriptorType;
|
|
||||||
u16 wTotalLength;
|
|
||||||
u8 bNumInterfaces;
|
|
||||||
u8 bConfigurationValue;
|
|
||||||
u8 iConfiguration;
|
|
||||||
u8 bmAttributes;
|
|
||||||
u8 MaxPower;
|
|
||||||
u8 pad[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WiiHIDInterfaceDescriptor
|
|
||||||
{
|
|
||||||
u8 bLength;
|
|
||||||
u8 bDescriptorType;
|
|
||||||
u8 bInterfaceNumber;
|
|
||||||
u8 bAlternateSetting;
|
|
||||||
u8 bNumEndpoints;
|
|
||||||
u8 bInterfaceClass;
|
|
||||||
u8 bInterfaceSubClass;
|
|
||||||
u8 bInterfaceProtocol;
|
|
||||||
u8 iInterface;
|
|
||||||
u8 pad[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WiiHIDEndpointDescriptor
|
|
||||||
{
|
|
||||||
u8 bLength;
|
|
||||||
u8 bDescriptorType;
|
|
||||||
u8 bEndpointAddress;
|
|
||||||
u8 bmAttributes;
|
|
||||||
u16 wMaxPacketSize;
|
|
||||||
u8 bInterval;
|
|
||||||
u8 bRefresh;
|
|
||||||
u8 bSynchAddress;
|
|
||||||
u8 pad[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 deviceCommandAddress;
|
u32 deviceCommandAddress;
|
||||||
void FillOutDevices(const IOCtlRequest& request);
|
void FillOutDevices(const IOCtlRequest& 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);
|
||||||
|
|
||||||
void ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest, const libusb_device_descriptor* src);
|
void ConvertDeviceToWii(USB::DeviceDescriptor* dest, const libusb_device_descriptor* src);
|
||||||
void ConvertConfigToWii(WiiHIDConfigDescriptor* dest, const libusb_config_descriptor* src);
|
void ConvertConfigToWii(USB::ConfigDescriptor* dest, const libusb_config_descriptor* src);
|
||||||
void ConvertInterfaceToWii(WiiHIDInterfaceDescriptor* dest,
|
void ConvertInterfaceToWii(USB::InterfaceDescriptor* dest,
|
||||||
const libusb_interface_descriptor* src);
|
const libusb_interface_descriptor* src);
|
||||||
void ConvertEndpointToWii(WiiHIDEndpointDescriptor* dest, const libusb_endpoint_descriptor* src);
|
void ConvertEndpointToWii(USB::EndpointDescriptor* dest, const libusb_endpoint_descriptor* src);
|
||||||
|
|
||||||
static void checkUsbUpdates(USB_HIDv4* hid);
|
static void checkUsbUpdates(USB_HIDv4* hid);
|
||||||
static void LIBUSB_CALL handleUsbUpdates(libusb_transfer* transfer);
|
static void LIBUSB_CALL handleUsbUpdates(libusb_transfer* transfer);
|
||||||
|
|
Loading…
Reference in New Issue