simplify the usb transfer process by using an aligned buffer to transfer to/from.

This commit is contained in:
ITotalJustice
2025-04-29 14:17:12 +01:00
parent 5b82e07b1c
commit 1eae35f072
4 changed files with 89 additions and 84 deletions

View File

@@ -2,6 +2,8 @@
#include "base.hpp"
#include "fs.hpp"
#include <vector>
#include <new>
#include <switch.h>
namespace sphaira::yati::source {
@@ -21,20 +23,47 @@ struct Usb final : Base {
~Usb();
Result Read(void* buf, s64 off, s64 size, u64* bytes_read) override;
Result Finished() const;
Result Finished();
Result Init();
Result WaitForConnection(u64 timeout, u32& speed, u32& count);
Result GetFileInfo(std::string& name_out, u64& size_out);
public:
// custom allocator for std::vector that respects alignment.
// https://en.cppreference.com/w/cpp/named_req/Allocator
template <typename T, std::size_t Align>
struct CustomVectorAllocator {
public:
// https://en.cppreference.com/w/cpp/memory/new/operator_new
auto allocate(std::size_t n) -> T* {
return new(align) T[n];
}
// https://en.cppreference.com/w/cpp/memory/new/operator_delete
auto deallocate(T* p, std::size_t n) noexcept -> void {
::operator delete[] (p, n, align);
}
private:
static constexpr inline std::align_val_t align{Align};
};
template <typename T>
struct PageAllocator : CustomVectorAllocator<T, 0x1000> {
using value_type = T; // used by std::vector
};
using PageAlignedVector = std::vector<u8, PageAllocator<u8>>;
private:
enum UsbSessionEndpoint {
UsbSessionEndpoint_In = 0,
UsbSessionEndpoint_Out = 1,
};
Result SendCommand(s64 off, s64 size) const;
Result InternalRead(void* buf, s64 off, s64 size) const;
Result SendCommand(s64 off, s64 size);
Result InternalRead(void* buf, s64 off, s64 size);
bool GetConfigured() const;
Event *GetCompletionEvent(UsbSessionEndpoint ep) const;
@@ -42,11 +71,15 @@ private:
Result TransferAsync(UsbSessionEndpoint ep, void *buffer, u32 size, u32 *out_urb_id) const;
Result GetTransferResult(UsbSessionEndpoint ep, u32 urb_id, u32 *out_requested_size, u32 *out_transferred_size) const;
Result TransferPacketImpl(bool read, void *page, u32 size, u32 *out_size_transferred, u64 timeout) const;
Result TransferAll(bool read, void *data, u32 size, u64 timeout);
private:
UsbDsInterface* m_interface{};
UsbDsEndpoint* m_endpoints[2]{};
u64 m_transfer_timeout{};
// aligned buffer that transfer data is copied to and from.
// a vector is used to avoid multiple alloc within the transfer loop.
PageAlignedVector m_aligned{};
};
} // namespace sphaira::yati::source