IOS: Move out common USB structures

Some structures will be reused and shared between several IOS USB
device implementations. This prepares for the upcoming USB PR.

I've also removed GetPointer calls in the trivial case (BT passthrough)
This commit is contained in:
Léo Lam 2017-01-18 22:32:22 +01:00
parent 25c779943b
commit 954c41d6e9
17 changed files with 387 additions and 242 deletions

View File

@ -36,6 +36,7 @@ enum LOG_TYPE
IOS_SD,
IOS_SSL,
IOS_STM,
IOS_USB,
IOS_WC24,
IOS_WIIMOTE,
MASTER_LOG,

View File

@ -70,6 +70,7 @@ LogManager::LogManager()
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_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_WIIMOTE] = new LogContainer("IOS_WIIMOTE", "IOS - Wii Remote");
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");

View File

@ -151,6 +151,8 @@ set(SRCS ActionReplay.cpp
IOS/Network/SSL.cpp
IOS/SDIO/SDIOSlot0.cpp
IOS/STM/STM.cpp
IOS/USB/Common.cpp
IOS/USB/USBV0.cpp
IOS/USB/USB_KBD.cpp
IOS/USB/USB_VEN.cpp
IOS/USB/Bluetooth/BTBase.cpp

View File

@ -183,6 +183,8 @@
<ClCompile Include="IOS\Network\SSL.cpp" />
<ClCompile Include="IOS\SDIO\SDIOSlot0.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">
<!--
Disable "nonstandard extension used : zero-sized array in struct/union" warning,
@ -412,6 +414,8 @@
<ClInclude Include="IOS\Network\SSL.h" />
<ClInclude Include="IOS\SDIO\SDIOSlot0.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_KBD.h" />
<ClInclude Include="IOS\USB\USB_VEN.h" />

View File

@ -764,6 +764,12 @@
<ClCompile Include="IOS\STM\STM.cpp">
<Filter>IOS\STM</Filter>
</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">
<Filter>IOS\USB</Filter>
</ClCompile>
@ -1332,6 +1338,12 @@
<ClInclude Include="IOS\STM\STM.h">
<Filter>IOS\STM</Filter>
</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">
<Filter>IOS\USB</Filter>
</ClInclude>
@ -1363,4 +1375,4 @@
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>

View File

@ -53,32 +53,5 @@ void RestoreBTInfoSection(SysConf* sysconf)
sysconf->SetArrayData("BT.DINF", section.data(), static_cast<u16>(section.size()));
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 IOS

View File

@ -36,13 +36,6 @@ protected:
static constexpr int SCO_PKT_SIZE = 64;
static constexpr int SCO_PKT_NUM = 0;
enum USBIOCtl
{
USBV0_IOCTL_CTRLMSG = 0,
USBV0_IOCTL_BLKMSG = 1,
USBV0_IOCTL_INTRMSG = 2,
};
enum USBEndpoint
{
HCI_CTRL = 0x00,
@ -50,28 +43,6 @@ protected:
ACL_DATA_IN = 0x82,
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 HLE

View File

@ -167,9 +167,9 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
bool send_reply = true;
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
ExecuteHCICommandMessage(*m_CtrlSetup);
m_CtrlSetup.reset();
@ -177,50 +177,50 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
break;
}
case USBV0_IOCTL_BLKMSG:
case USB::IOCTLV_USBV0_BLKMSG:
{
const CtrlBuffer ctrl{request};
switch (ctrl.m_endpoint)
const USB::V0BulkMessage ctrl{request};
switch (ctrl.endpoint)
{
case ACL_DATA_OUT: // ACL data is received from the stack
{
// This is the ACL datapath from CPU to Wii Remote
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_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
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);
break;
}
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);
send_reply = false;
break;
}
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;
}
case USBV0_IOCTL_INTRMSG:
case USB::IOCTLV_USBV0_INTRMSG:
{
const CtrlBuffer ctrl{request};
if (ctrl.m_endpoint == HCI_EVENT) // We are given a HCI buffer to fill
const USB::V0IntrMessage ctrl{request};
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);
send_reply = false;
}
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;
}
@ -232,7 +232,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
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)
{
WiimoteDevice* pWiiMote = AccessWiiMote(_ConnectionHandle);
@ -261,7 +261,7 @@ void BluetoothEmu::SendACLPacket(u16 connection_handle, const u8* data, u32 size
m_ACLEndpoint->ios_request.address);
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->length = size;
@ -412,7 +412,7 @@ void BluetoothEmu::ACLPool::Store(const u8* data, const u16 size, const u16 conn
packet.conn_handle = conn_handle;
}
void BluetoothEmu::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
void BluetoothEmu::ACLPool::WriteToEndpoint(USB::V0BulkMessage& endpoint)
{
auto& packet = m_queue.front();
@ -424,7 +424,7 @@ void BluetoothEmu::ACLPool::WriteToEndpoint(CtrlBuffer& endpoint)
"queue to %08x",
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->length = size;
@ -964,11 +964,11 @@ bool BluetoothEmu::SendEventConPacketTypeChange(u16 _connectionHandle, u16 _pack
}
// Command dispatcher
// This is called from the USBV0_IOCTL_CTRLMSG Ioctlv
void BluetoothEmu::ExecuteHCICommandMessage(const CtrlMessage& ctrl_message)
// This is called from the USB::IOCTLV_USBV0_CTRLMSG Ioctlv
void BluetoothEmu::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message)
{
u8* pInput = Memory::GetPointer(ctrl_message.payload_addr + 3);
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(ctrl_message.payload_addr);
u8* pInput = Memory::GetPointer(ctrl_message.data_address + 3);
SCommandMessage* pMsg = (SCommandMessage*)Memory::GetPointer(ctrl_message.data_address);
u16 ocf = HCI_OCF(pMsg->Opcode);
u16 ogf = HCI_OGF(pMsg->Opcode);

View File

@ -18,6 +18,7 @@
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
#include "Core/IOS/USB/Bluetooth/hci.h"
#include "Core/IOS/USB/USBV0.h"
class PointerWrap;
@ -70,9 +71,9 @@ private:
// this is used to trigger connecting via ACL
u8 m_ScanEnable = 0;
std::unique_ptr<CtrlMessage> m_CtrlSetup;
std::unique_ptr<CtrlBuffer> m_HCIEndpoint;
std::unique_ptr<CtrlBuffer> m_ACLEndpoint;
std::unique_ptr<USB::V0CtrlMessage> m_CtrlSetup;
std::unique_ptr<USB::V0IntrMessage> m_HCIEndpoint;
std::unique_ptr<USB::V0BulkMessage> m_ACLEndpoint;
std::deque<SQueuedEvent> m_EventQueue;
class ACLPool
@ -90,7 +91,7 @@ private:
ACLPool() : m_queue() {}
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(); }
// For SaveStates
@ -126,7 +127,7 @@ private:
bool SendEventLinkKeyNotification(const u8 num_to_send);
// Execute HCI Message
void ExecuteHCICommandMessage(const CtrlMessage& ctrl_message);
void ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message);
// OGF 0x01 - Link control commands and return parameters
void CommandWriteInquiryMode(const u8* input);

View File

@ -178,10 +178,10 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
switch (request.request)
{
// HCI commands to the Bluetooth adapter
case USBV0_IOCTL_CTRLMSG:
case USB::IOCTLV_USBV0_CTRLMSG:
{
auto cmd = std::make_unique<CtrlMessage>(request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->payload_addr));
auto cmd = std::make_unique<USB::V0CtrlMessage>(request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
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)
{
// Delete link key(s) from our own link key storage when the game tells the adapter to
const auto* delete_cmd =
reinterpret_cast<hci_delete_stored_link_key_cp*>(Memory::GetPointer(cmd->payload_addr));
if (delete_cmd->delete_all)
hci_delete_stored_link_key_cp delete_cmd;
Memory::CopyFromEmu(&delete_cmd, cmd->data_address, sizeof(delete_cmd));
if (delete_cmd.delete_all)
{
s_link_keys.clear();
}
else
{
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);
}
}
auto buffer = std::vector<u8>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(buffer.data(), cmd->request_type, cmd->request, cmd->value,
cmd->index, cmd->length);
Memory::CopyFromEmu(buffer.data() + LIBUSB_CONTROL_SETUP_SIZE, cmd->payload_addr, cmd->length);
auto buffer = std::make_unique<u8[]>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index,
cmd->length);
Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.data(), CommandCallback, cmd.release(),
0);
libusb_fill_control_transfer(transfer, m_handle, buffer.release(), CommandCallback,
cmd.release(), 0);
libusb_submit_transfer(transfer);
break;
}
// ACL data (incoming or outgoing) and incoming HCI events (respectively)
case USBV0_IOCTL_BLKMSG:
case USBV0_IOCTL_INTRMSG:
case USB::IOCTLV_USBV0_BLKMSG:
case USB::IOCTLV_USBV0_INTRMSG:
{
auto buffer = std::make_unique<CtrlBuffer>(request);
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_read_buffer_size_reply.TestAndClear())
auto buffer = std::make_unique<USB::V0IntrMessage>(request);
if (request.request == USB::IOCTLV_USBV0_INTRMSG)
{
FakeReadBufferSizeReply(*buffer);
return GetNoReply();
}
if (request.request == USBV0_IOCTL_INTRMSG && m_fake_vendor_command_reply.TestAndClear())
{
FakeVendorCommandReply(*buffer);
return GetNoReply();
}
if (request.request == USBV0_IOCTL_INTRMSG && m_sync_button_state == SyncButtonState::Pressed)
{
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
FakeSyncButtonPressedEvent(*buffer);
return GetNoReply();
}
if (request.request == USBV0_IOCTL_INTRMSG &&
m_sync_button_state == SyncButtonState::LongPressed)
{
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
FakeSyncButtonHeldEvent(*buffer);
return GetNoReply();
if (m_sync_button_state == SyncButtonState::Pressed)
{
Core::DisplayMessage("Scanning for Wii Remotes", 2000);
FakeSyncButtonPressedEvent(*buffer);
return GetNoReply();
}
if (m_sync_button_state == SyncButtonState::LongPressed)
{
Core::DisplayMessage("Reset saved Wii Remote pairings", 2000);
FakeSyncButtonHeldEvent(*buffer);
return GetNoReply();
}
if (m_fake_read_buffer_size_reply.TestAndClear())
{
FakeReadBufferSizeReply(*buffer);
return GetNoReply();
}
if (m_fake_vendor_command_reply.TestAndClear())
{
FakeVendorCommandReply(*buffer);
return GetNoReply();
}
}
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->dev_handle = m_handle;
transfer->endpoint = buffer->m_endpoint;
transfer->endpoint = buffer->endpoint;
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
transfer->length = buffer->m_length;
transfer->length = buffer->length;
transfer->timeout = TIMEOUT;
transfer->type = request.request == USBV0_IOCTL_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
LIBUSB_TRANSFER_TYPE_INTERRUPT;
transfer->type = request.request == USB::IOCTLV_USBV0_BLKMSG ? LIBUSB_TRANSFER_TYPE_BULK :
LIBUSB_TRANSFER_TYPE_INTERRUPT;
transfer->user_data = buffer.release();
libusb_submit_transfer(transfer);
break;
@ -390,16 +392,16 @@ bool BluetoothReal::SendHCIStoreLinkKeyCommand()
return true;
}
void BluetoothReal::FakeVendorCommandReply(CtrlBuffer& ctrl)
void BluetoothReal::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
{
u8* packet = Memory::GetPointer(ctrl.m_payload_addr);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event->PacketIndicator = 0x01;
hci_event->Opcode = m_fake_vendor_command_reply_opcode;
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(SHCIEventCommand)));
SHCIEventCommand hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event.PacketIndicator = 0x01;
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(hci_event)));
}
// 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.
// Therefore, the reply to this command has to be faked to avoid random, weird issues
// (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);
auto* hci_event = reinterpret_cast<SHCIEventCommand*>(packet);
hci_event->EventType = HCI_EVENT_COMMAND_COMPL;
hci_event->PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
hci_event->PacketIndicator = 0x01;
hci_event->Opcode = HCI_CMD_READ_BUFFER_SIZE;
SHCIEventCommand hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = HCI_CMD_READ_BUFFER_SIZE;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
hci_read_buffer_size_rp reply;
reply.status = 0x00;
@ -422,27 +425,26 @@ void BluetoothReal::FakeReadBufferSizeReply(CtrlBuffer& ctrl)
reply.num_acl_pkts = ACL_PKT_NUM;
reply.max_sco_size = SCO_PKT_SIZE;
reply.num_sco_pkts = SCO_PKT_NUM;
memcpy(packet + sizeof(SHCIEventCommand), &reply, sizeof(hci_read_buffer_size_rp));
EnqueueReply(ctrl.ios_request,
static_cast<s32>(sizeof(SHCIEventCommand) + sizeof(hci_read_buffer_size_rp)));
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
}
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);
auto* hci_event = reinterpret_cast<hci_event_hdr_t*>(packet);
hci_event->event = HCI_EVENT_VENDOR;
hci_event->length = size;
memcpy(packet + sizeof(hci_event_hdr_t), payload, size);
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event_hdr_t) + size));
hci_event_hdr_t hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.event = HCI_EVENT_VENDOR;
hci_event.length = size;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
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:
// > HCI Event: Vendor (0xff) plen 1
// 08
// 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");
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.
void BluetoothReal::FakeSyncButtonHeldEvent(CtrlBuffer& ctrl)
void BluetoothReal::FakeSyncButtonHeldEvent(USB::V0IntrMessage& ctrl)
{
NOTICE_LOG(IOS_WIIMOTE, "Faking 'sync button held' (0x09) event packet");
const u8 payload[1] = {0x09};
@ -565,7 +567,8 @@ void BluetoothReal::TransferThread()
// The callbacks are called from libusb code on a separate thread.
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)
{
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();
}
cmd->FillBuffer(libusb_control_transfer_get_data(tr), tr->actual_length);
EnqueueReply(cmd->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
}
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 &&
tr->status != LIBUSB_TRANSFER_NO_DEVICE)
{
@ -624,7 +627,6 @@ void BluetoothReal::TransferCallback(libusb_transfer* tr)
s_need_reset_keys.Set();
}
}
EnqueueReply(ctrl->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
}
} // namespace Device

View File

@ -15,6 +15,7 @@
#include "Common/Timer.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/IOS/USB/USBV0.h"
class PointerWrap;
struct libusb_context;
@ -85,11 +86,11 @@ private:
void SendHCIResetCommand();
void SendHCIDeleteLinkKeyCommand();
bool SendHCIStoreLinkKeyCommand();
void FakeVendorCommandReply(CtrlBuffer& ctrl);
void FakeReadBufferSizeReply(CtrlBuffer& ctrl);
void FakeSyncButtonEvent(CtrlBuffer& ctrl, const u8* payload, u8 size);
void FakeSyncButtonPressedEvent(CtrlBuffer& ctrl);
void FakeSyncButtonHeldEvent(CtrlBuffer& ctrl);
void FakeVendorCommandReply(USB::V0IntrMessage& ctrl);
void FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl);
void FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload, u8 size);
void FakeSyncButtonPressedEvent(USB::V0IntrMessage& ctrl);
void FakeSyncButtonHeldEvent(USB::V0IntrMessage& ctrl);
void LoadLinkKeys();
void SaveLinkKeys();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -263,8 +263,7 @@ IPCCommandResult USB_HIDv4::IOCtlV(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}
void USB_HIDv4::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
const struct libusb_device_descriptor* src)
void USB_HIDv4::ConvertDeviceToWii(USB::DeviceDescriptor* dest, const libusb_device_descriptor* src)
{
dest->bLength = src->bLength;
dest->bDescriptorType = src->bDescriptorType;
@ -282,23 +281,22 @@ void USB_HIDv4::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
dest->bNumConfigurations = src->bNumConfigurations;
}
void USB_HIDv4::ConvertConfigToWii(WiiHIDConfigDescriptor* dest,
const struct libusb_config_descriptor* src)
void USB_HIDv4::ConvertConfigToWii(USB::ConfigDescriptor* dest, const libusb_config_descriptor* src)
{
memcpy(dest, src, sizeof(WiiHIDConfigDescriptor));
memcpy(dest, src, sizeof(USB::ConfigDescriptor));
dest->wTotalLength = Common::swap16(dest->wTotalLength);
}
void USB_HIDv4::ConvertInterfaceToWii(WiiHIDInterfaceDescriptor* dest,
const struct libusb_interface_descriptor* src)
void USB_HIDv4::ConvertInterfaceToWii(USB::InterfaceDescriptor* dest,
const libusb_interface_descriptor* src)
{
memcpy(dest, src, sizeof(WiiHIDInterfaceDescriptor));
memcpy(dest, src, sizeof(USB::InterfaceDescriptor));
}
void USB_HIDv4::ConvertEndpointToWii(WiiHIDEndpointDescriptor* dest,
const struct libusb_endpoint_descriptor* src)
void USB_HIDv4::ConvertEndpointToWii(USB::EndpointDescriptor* dest,
const libusb_endpoint_descriptor* src)
{
memcpy(dest, src, sizeof(WiiHIDEndpointDescriptor));
memcpy(dest, src, sizeof(USB::EndpointDescriptor));
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
}
@ -330,7 +328,7 @@ void USB_HIDv4::FillOutDevices(const IOCtlRequest& request)
OffsetBuffer += 4; // skip devNum for now
WiiHIDDeviceDescriptor wii_device;
USB::DeviceDescriptor wii_device;
ConvertDeviceToWii(&wii_device, &desc);
Memory::CopyToEmu(OffsetBuffer, &wii_device, wii_device.bLength);
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
if (cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES)
{
WiiHIDConfigDescriptor wii_config;
USB::ConfigDescriptor wii_config;
ConvertConfigToWii(&wii_config, config);
Memory::CopyToEmu(OffsetBuffer, &wii_config, wii_config.bLength);
OffsetBuffer += Common::AlignUp(wii_config.bLength, 4);
@ -361,7 +359,7 @@ void USB_HIDv4::FillOutDevices(const IOCtlRequest& request)
if (interface->bInterfaceClass == LIBUSB_CLASS_HID)
isHID = true;
WiiHIDInterfaceDescriptor wii_interface;
USB::InterfaceDescriptor wii_interface;
ConvertInterfaceToWii(&wii_interface, interface);
Memory::CopyToEmu(OffsetBuffer, &wii_interface, wii_interface.bLength);
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];
WiiHIDEndpointDescriptor wii_endpoint;
USB::EndpointDescriptor wii_endpoint;
ConvertEndpointToWii(&wii_endpoint, endpoint);
Memory::CopyToEmu(OffsetBuffer, &wii_endpoint, wii_endpoint.bLength);
OffsetBuffer += Common::AlignUp(wii_endpoint.bLength, 4);

View File

@ -13,6 +13,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/USB/Common.h"
// Forward declare things which we need from libusb header.
// This prevents users of this file from indirectly pulling in libusb.
@ -61,75 +62,16 @@ private:
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;
void FillOutDevices(const IOCtlRequest& request);
int GetAvailableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check);
bool ClaimDevice(libusb_device_handle* dev);
void ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest, const libusb_device_descriptor* src);
void ConvertConfigToWii(WiiHIDConfigDescriptor* dest, const libusb_config_descriptor* src);
void ConvertInterfaceToWii(WiiHIDInterfaceDescriptor* dest,
void ConvertDeviceToWii(USB::DeviceDescriptor* dest, const libusb_device_descriptor* src);
void ConvertConfigToWii(USB::ConfigDescriptor* dest, const libusb_config_descriptor* src);
void ConvertInterfaceToWii(USB::InterfaceDescriptor* dest,
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 LIBUSB_CALL handleUsbUpdates(libusb_transfer* transfer);