summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2017-11-02 21:56:16 +0100
committerLéo Lam <leo@innovatetechnologi.es>2017-11-03 19:01:48 +0100
commit6bb03d900c3bb61e4fb8b855f06de8dd3d9eebc7 (patch)
tree3fe0d3a043e92179373dd35763d9d175e3144dcb /Source
parentc6038155cc71256ef277746abc47624466cdb7f8 (diff)
USB: Separate the descriptor copy logic
The descriptor copy code is not actually the same in HIDv4 and VEN, so it did not make a lot of sense to put it in USB/Common.cpp. Separate and move it to HIDv4 and VEN. This cleanup is important because there are even more differences between HIDv4 and HIDv5.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/IOS/USB/Common.cpp77
-rw-r--r--Source/Core/Core/IOS/USB/Common.h7
-rw-r--r--Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp36
-rw-r--r--Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp37
4 files changed, 77 insertions, 80 deletions
diff --git a/Source/Core/Core/IOS/USB/Common.cpp b/Source/Core/Core/IOS/USB/Common.cpp
index a9627b0974..a91ac518b1 100644
--- a/Source/Core/Core/IOS/USB/Common.cpp
+++ b/Source/Core/Core/IOS/USB/Common.cpp
@@ -6,7 +6,6 @@
#include <algorithm>
-#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/StringUtil.h"
@@ -70,82 +69,26 @@ bool Device::HasClass(const u8 device_class) const
});
}
-static void CopyToBufferAligned(std::vector<u8>* buffer, const void* data, const size_t size)
+void DeviceDescriptor::Swap()
{
- buffer->insert(buffer->end(), static_cast<const u8*>(data), static_cast<const u8*>(data) + size);
- const size_t number_of_padding_bytes = Common::AlignUp(size, 4) - size;
- buffer->insert(buffer->end(), number_of_padding_bytes, 0);
+ bcdUSB = Common::swap16(bcdUSB);
+ idVendor = Common::swap16(idVendor);
+ idProduct = Common::swap16(idProduct);
+ bcdDevice = Common::swap16(bcdDevice);
}
-static void CopyDescriptorToBuffer(std::vector<u8>* buffer, DeviceDescriptor descriptor)
+void ConfigDescriptor::Swap()
{
- descriptor.bcdUSB = Common::swap16(descriptor.bcdUSB);
- descriptor.idVendor = Common::swap16(descriptor.idVendor);
- descriptor.idProduct = Common::swap16(descriptor.idProduct);
- descriptor.bcdDevice = Common::swap16(descriptor.bcdDevice);
- CopyToBufferAligned(buffer, &descriptor, descriptor.bLength);
+ wTotalLength = Common::swap16(wTotalLength);
}
-static void CopyDescriptorToBuffer(std::vector<u8>* buffer, ConfigDescriptor descriptor)
+void InterfaceDescriptor::Swap()
{
- descriptor.wTotalLength = Common::swap16(descriptor.wTotalLength);
- CopyToBufferAligned(buffer, &descriptor, descriptor.bLength);
}
-static void CopyDescriptorToBuffer(std::vector<u8>* buffer, InterfaceDescriptor descriptor)
+void EndpointDescriptor::Swap()
{
- CopyToBufferAligned(buffer, &descriptor, descriptor.bLength);
-}
-
-static void CopyDescriptorToBuffer(std::vector<u8>* buffer, EndpointDescriptor descriptor)
-{
- descriptor.wMaxPacketSize = Common::swap16(descriptor.wMaxPacketSize);
- // IOS only copies 8 bytes from the endpoint descriptor, regardless of the actual length
- CopyToBufferAligned(buffer, &descriptor, sizeof(descriptor));
-}
-
-std::vector<u8> Device::GetDescriptorsUSBV4() const
-{
- return GetDescriptors([](const auto& descriptor) { return true; });
-}
-
-std::vector<u8> Device::GetDescriptorsUSBV5(const u8 interface, const u8 alt_setting) const
-{
- return GetDescriptors([interface, alt_setting](const auto& descriptor) {
- // The USBV5 interfaces present each interface as a different device,
- // and the descriptors are filtered by alternate setting.
- return descriptor.bInterfaceNumber == interface && descriptor.bAlternateSetting == alt_setting;
- });
-}
-
-std::vector<u8>
-Device::GetDescriptors(std::function<bool(const InterfaceDescriptor&)> predicate) const
-{
- std::vector<u8> buffer;
-
- const auto device_descriptor = GetDeviceDescriptor();
- CopyDescriptorToBuffer(&buffer, device_descriptor);
-
- const auto configurations = GetConfigurations();
- for (size_t c = 0; c < configurations.size(); ++c)
- {
- const auto& config_descriptor = configurations[c];
- CopyDescriptorToBuffer(&buffer, config_descriptor);
-
- const auto interfaces = GetInterfaces(static_cast<u8>(c));
- for (size_t i = interfaces.size(); i-- > 0;)
- {
- const auto& descriptor = interfaces[i];
- if (!predicate(descriptor))
- continue;
-
- CopyDescriptorToBuffer(&buffer, descriptor);
- for (const auto& endpoint_descriptor : GetEndpoints(
- static_cast<u8>(c), descriptor.bInterfaceNumber, descriptor.bAlternateSetting))
- CopyDescriptorToBuffer(&buffer, endpoint_descriptor);
- }
- }
- return buffer;
+ wMaxPacketSize = Common::swap16(wMaxPacketSize);
}
std::string Device::GetErrorName(const int error_code) const
diff --git a/Source/Core/Core/IOS/USB/Common.h b/Source/Core/Core/IOS/USB/Common.h
index 9efb6630a1..2013716a07 100644
--- a/Source/Core/Core/IOS/USB/Common.h
+++ b/Source/Core/Core/IOS/USB/Common.h
@@ -44,6 +44,7 @@ constexpr u16 USBHDR(u8 dir, u8 type, u8 recipient, u8 request)
struct DeviceDescriptor
{
+ void Swap();
u8 bLength;
u8 bDescriptorType;
u16 bcdUSB;
@@ -62,6 +63,7 @@ struct DeviceDescriptor
struct ConfigDescriptor
{
+ void Swap();
u8 bLength;
u8 bDescriptorType;
u16 wTotalLength;
@@ -74,6 +76,7 @@ struct ConfigDescriptor
struct InterfaceDescriptor
{
+ void Swap();
u8 bLength;
u8 bDescriptorType;
u8 bInterfaceNumber;
@@ -87,6 +90,7 @@ struct InterfaceDescriptor
struct EndpointDescriptor
{
+ void Swap();
u8 bLength;
u8 bDescriptorType;
u8 bEndpointAddress;
@@ -158,8 +162,6 @@ public:
u16 GetVid() const;
u16 GetPid() const;
bool HasClass(u8 device_class) const;
- std::vector<u8> GetDescriptorsUSBV4() const;
- std::vector<u8> GetDescriptorsUSBV5(u8 interface, u8 alt_setting) const;
virtual DeviceDescriptor GetDeviceDescriptor() const = 0;
virtual std::vector<ConfigDescriptor> GetConfigurations() const = 0;
@@ -178,7 +180,6 @@ public:
virtual int SubmitTransfer(std::unique_ptr<IsoMessage> message) = 0;
protected:
- std::vector<u8> GetDescriptors(std::function<bool(const InterfaceDescriptor&)> predicate) const;
u64 m_id = 0xFFFFFFFFFFFFFFFF;
};
} // namespace USB
diff --git a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp
index edcf8b18c3..b0a1606e6c 100644
--- a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp
+++ b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp
@@ -210,6 +210,40 @@ void USB_HIDv4::TriggerDeviceChangeReply()
m_devicechange_hook_request.reset();
}
+template <typename T>
+static void CopyDescriptorToBuffer(std::vector<u8>* buffer, T descriptor)
+{
+ const size_t size = sizeof(descriptor);
+ descriptor.Swap();
+ buffer->insert(buffer->end(), reinterpret_cast<const u8*>(&descriptor),
+ reinterpret_cast<const u8*>(&descriptor) + size);
+ const size_t number_of_padding_bytes = Common::AlignUp(size, 4) - size;
+ buffer->insert(buffer->end(), number_of_padding_bytes, 0);
+}
+
+static std::vector<u8> GetDescriptors(const USB::Device& device)
+{
+ std::vector<u8> buffer;
+
+ CopyDescriptorToBuffer(&buffer, device.GetDeviceDescriptor());
+ const auto configurations = device.GetConfigurations();
+ for (size_t c = 0; c < configurations.size(); ++c)
+ {
+ CopyDescriptorToBuffer(&buffer, configurations[c]);
+ const auto interfaces = device.GetInterfaces(static_cast<u8>(c));
+ for (size_t i = interfaces.size(); i-- > 0;)
+ {
+ CopyDescriptorToBuffer(&buffer, interfaces[i]);
+ for (const auto& endpoint_descriptor : device.GetEndpoints(
+ static_cast<u8>(c), interfaces[i].bInterfaceNumber, interfaces[i].bAlternateSetting))
+ {
+ CopyDescriptorToBuffer(&buffer, endpoint_descriptor);
+ }
+ }
+ }
+ return buffer;
+}
+
std::vector<u8> USB_HIDv4::GetDeviceEntry(const USB::Device& device) const
{
std::lock_guard<std::mutex> id_map_lock{m_id_map_mutex};
@@ -219,7 +253,7 @@ std::vector<u8> USB_HIDv4::GetDeviceEntry(const USB::Device& device) const
// 4-8 bytes: device ID
// the rest of the buffer is device descriptors data
std::vector<u8> entry(8);
- const std::vector<u8> descriptors = device.GetDescriptorsUSBV4();
+ const std::vector<u8> descriptors = GetDescriptors(device);
const u32 entry_size = Common::swap32(static_cast<u32>(entry.size() + descriptors.size()));
const u32 ios_device_id = Common::swap32(m_device_ids.at(device.GetId()));
std::memcpy(entry.data(), &entry_size, sizeof(entry_size));
diff --git a/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp b/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp
index 552d278863..27fb03087d 100644
--- a/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp
+++ b/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp
@@ -186,20 +186,39 @@ IPCCommandResult USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest&
if (request.buffer_out == 0 || request.buffer_out_size != 0xc0)
return GetDefaultReply(IPC_EINVAL);
- const auto host_device = GetDeviceById(device.host_id);
+ const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 8);
- auto descriptors = host_device->GetDescriptorsUSBV5(device.interface_number, alt_setting);
- if (descriptors.empty())
- return GetDefaultReply(IPC_ENOENT);
-
- descriptors.resize(request.buffer_out_size - 20);
- if (descriptors.size() > request.buffer_out_size - 20)
- WARN_LOG(IOS_USB, "Buffer is too large. Only the first 172 bytes will be copied.");
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
Memory::Write_U32(Memory::Read_U32(request.buffer_in), request.buffer_out);
Memory::Write_U32(1, request.buffer_out + 4);
- Memory::CopyToEmu(request.buffer_out + 20, descriptors.data(), descriptors.size());
+
+ USB::DeviceDescriptor device_descriptor = host_device->GetDeviceDescriptor();
+ device_descriptor.Swap();
+ Memory::CopyToEmu(request.buffer_out + 20, &device_descriptor, sizeof(device_descriptor));
+
+ // VEN only cares about the first configuration.
+ USB::ConfigDescriptor config_descriptor = host_device->GetConfigurations()[0];
+ config_descriptor.Swap();
+ Memory::CopyToEmu(request.buffer_out + 40, &config_descriptor, sizeof(config_descriptor));
+
+ std::vector<USB::InterfaceDescriptor> interfaces = host_device->GetInterfaces(0);
+ auto it = std::find_if(interfaces.begin(), interfaces.end(), [&](const auto& interface) {
+ return interface.bInterfaceNumber == device.interface_number &&
+ interface.bAlternateSetting == alt_setting;
+ });
+ if (it == interfaces.end())
+ return GetDefaultReply(IPC_EINVAL);
+ it->Swap();
+ Memory::CopyToEmu(request.buffer_out + 52, &*it, sizeof(*it));
+
+ auto endpoints = host_device->GetEndpoints(0, it->bInterfaceNumber, it->bAlternateSetting);
+ for (size_t i = 0; i < endpoints.size(); ++i)
+ {
+ endpoints[i].Swap();
+ Memory::CopyToEmu(request.buffer_out + 64 + 8 * static_cast<u8>(i), &endpoints[i],
+ sizeof(endpoints[i]));
+ }
return GetDefaultReply(IPC_SUCCESS);
}