Files
sphaira/sphaira/include/yati/source/usb.hpp
ITotalJustice 8f39acbaa2 replace usb protocol with tinfoils protocol, in order to support applications supporting said protocol.
- replace the python script with the one included with tinfoil, minor changes such as changing the supported extension,
  removing unused imports.
- tested with the included script, fluffy and ns-usbloader on linux.
  a user was unable to get it working on mac however...
- added build instructions to the readme, i think they're correct.
- added install instructions to the readme.
2025-04-29 18:11:07 +01:00

89 lines
2.8 KiB
C++

#pragma once
#include "base.hpp"
#include "fs.hpp"
#include <vector>
#include <string>
#include <new>
#include <switch.h>
namespace sphaira::yati::source {
struct Usb final : Base {
enum { USBModule = 523 };
enum : Result {
Result_BadMagic = MAKERESULT(USBModule, 0),
Result_BadVersion = MAKERESULT(USBModule, 1),
Result_BadCount = MAKERESULT(USBModule, 2),
Result_BadTransferSize = MAKERESULT(USBModule, 3),
Result_BadTotalSize = MAKERESULT(USBModule, 4),
};
Usb(u64 transfer_timeout);
~Usb();
Result Read(void* buf, s64 off, s64 size, u64* bytes_read) override;
Result Finished();
Result Init();
Result IsUsbConnected(u64 timeout) const;
Result WaitForConnection(u64 timeout, std::vector<std::string>& out_names);
void SetFileNameForTranfser(const std::string& name);
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 SendCmdHeader(u32 cmdId, size_t dataSize);
Result SendFileRangeCmd(u64 offset, u64 size);
Event *GetCompletionEvent(UsbSessionEndpoint ep) const;
Result WaitTransferCompletion(UsbSessionEndpoint ep, u64 timeout) const;
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{};
std::string m_transfer_file_name{};
};
} // namespace sphaira::yati::source