Merge pull request #4690 from leoetlino/common-usb

IOS: Move out common USB structures
This commit is contained in:
Matthew Parlane 2017-01-21 12:33:06 +13:00 committed by GitHub
commit 83dc03416e
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);