usb: change api so that every packet sent is crc32c, update python usb api, add automated tests for usb.

This commit is contained in:
ITotalJustice
2025-08-31 06:12:02 +01:00
parent b6b1af5959
commit 22e965521a
13 changed files with 469 additions and 71 deletions

View File

@@ -7,7 +7,7 @@ namespace sphaira::usb::api {
enum : u32 {
MAGIC = 0x53504830,
PACKET_SIZE = 16,
PACKET_SIZE = 24,
};
enum : u32 {
@@ -26,39 +26,87 @@ enum : u32 {
FLAG_STREAM = 1 << 0,
};
struct SendHeader {
u32 magic;
u32 cmd;
u32 arg3;
u32 arg4;
struct UsbPacket {
u32 magic{};
u32 arg2{};
u32 arg3{};
u32 arg4{};
u32 arg5{};
u32 crc32c{}; // crc32 over the above 16 bytes.
protected:
u32 CalculateCrc32c() const {
return crc32cCalculate(this, 20);
}
void GenerateCrc32c() {
crc32c = CalculateCrc32c();
}
Result Verify() const {
R_UNLESS(crc32c == CalculateCrc32c(), 1); // todo: add error code.
R_UNLESS(magic == MAGIC, Result_UsbBadMagic);
R_SUCCEED();
}
};
struct ResultHeader {
u32 magic;
u32 result;
u32 arg3;
u32 arg4;
struct SendPacket : UsbPacket {
static SendPacket Build(u32 cmd, u32 arg3 = 0, u32 arg4 = 0) {
SendPacket packet{MAGIC, cmd, arg3, arg4};
packet.GenerateCrc32c();
return packet;
}
Result Verify() const {
R_UNLESS(magic == MAGIC, Result_UsbBadMagic);
R_UNLESS(result == RESULT_OK, 1); // todo: create error code.
return UsbPacket::Verify();
}
u32 GetCmd() const {
return arg2;
}
};
struct ResultPacket : UsbPacket {
static ResultPacket Build(u32 result, u32 arg3 = 0, u32 arg4 = 0) {
ResultPacket packet{MAGIC, result, arg3, arg4};
packet.GenerateCrc32c();
return packet;
}
Result Verify() const {
R_TRY(UsbPacket::Verify());
R_UNLESS(arg2 == RESULT_OK, 1); // todo: create error code.
R_SUCCEED();
}
};
struct SendDataHeader {
u64 offset;
u32 size;
u32 crc32c;
struct SendDataPacket : UsbPacket {
static SendDataPacket Build(u64 off, u32 size, u32 crc32c) {
SendDataPacket packet{MAGIC, u32(off >> 32), u32(off), size, crc32c};
packet.GenerateCrc32c();
return packet;
}
Result Verify() const {
return UsbPacket::Verify();
}
u64 GetOffset() const {
return (u64(arg2) << 32) | arg3;
}
u32 GetSize() const {
return arg4;
}
u32 GetCrc32c() const {
return arg5;
}
};
static_assert(sizeof(SendHeader) == PACKET_SIZE);
static_assert(sizeof(ResultHeader) == PACKET_SIZE);
static_assert(sizeof(SendDataHeader) == PACKET_SIZE);
static_assert(sizeof(UsbPacket) == PACKET_SIZE);
static_assert(sizeof(SendPacket) == PACKET_SIZE);
static_assert(sizeof(ResultPacket) == PACKET_SIZE);
static_assert(sizeof(SendDataPacket) == PACKET_SIZE);
} // namespace sphaira::usb::api

View File

@@ -25,8 +25,8 @@ struct Usb {
Result CloseFile();
private:
Result SendAndVerify(const void* data, u32 size, u64 timeout, api::ResultHeader* out = nullptr);
Result SendAndVerify(const void* data, u32 size, api::ResultHeader* out = nullptr);
Result SendAndVerify(const void* data, u32 size, u64 timeout, api::ResultPacket* out = nullptr);
Result SendAndVerify(const void* data, u32 size, api::ResultPacket* out = nullptr);
private:
std::unique_ptr<usb::UsbDs> m_usb{};

View File

@@ -26,8 +26,8 @@ struct Usb {
Result CloseFile();
private:
Result SendAndVerify(const void* data, u32 size, u64 timeout, api::ResultHeader* out = nullptr);
Result SendAndVerify(const void* data, u32 size, api::ResultHeader* out = nullptr);
Result SendAndVerify(const void* data, u32 size, u64 timeout, api::ResultPacket* out = nullptr);
Result SendAndVerify(const void* data, u32 size, api::ResultPacket* out = nullptr);
private:
std::unique_ptr<usb::UsbDs> m_usb{};