Extracting ACK validation function

This commit is contained in:
Rodrigo Alfonso
2024-02-03 02:50:10 -03:00
parent 26a115792a
commit 7de48bc7ac
2 changed files with 93 additions and 82 deletions

View File

@@ -42,11 +42,11 @@
#define LINK_WIRELESS_MULTIBOOT_SETUP_MAGIC 0x003F0000
#define LINK_WIRELESS_MULTIBOOT_SETUP_TX 1
#define LINK_WIRELESS_MULTIBOOT_SETUP_WAIT_TIMEOUT 32
#define LINK_WIRELESS_MULTIBOOT_GAME_ID_MULTIBOOT_FLAG 0b1000000000000000
#define LINK_WIRELESS_MULTIBOOT_GAME_ID_MULTIBOOT_FLAG (1 << 15)
#define LINK_WIRELESS_MULTIBOOT_FRAME_LINES 228
#define LINK_WIRELESS_MULTIBOOT_TRY(CALL) \
if ((progress.lastResult = CALL) != SUCCESS) { \
return finish(progress.lastResult); \
#define LINK_WIRELESS_MULTIBOOT_TRY(CALL) \
if ((lastResult = CALL) != SUCCESS) { \
return finish(lastResult); \
}
const u8 LINK_WIRELESS_MULTIBOOT_CMD_START[] = {0x00, 0x54, 0x00, 0x00,
@@ -74,9 +74,7 @@ class LinkWirelessMultiboot {
struct MultibootProgress {
State state = STOPPED;
u32 connectedPlayers = 1;
Result lastResult;
LinkWirelessOpenSDK::ClientSDKHeader lastValidHeader;
u32 percentage = 0;
};
template <typename C>
@@ -106,41 +104,32 @@ class LinkWirelessMultiboot {
linkRawWireless->wait(LINK_WIRELESS_MULTIBOOT_FRAME_LINES);
LWMLOG("rom start command...");
LINK_WIRELESS_MULTIBOOT_TRY(exchangeData(
0,
[this](LinkRawWireless::ReceiveDataResponse& response) {
return sendAndExpectData(
linkWirelessOpenSDK->createServerBuffer(
LINK_WIRELESS_MULTIBOOT_CMD_START,
LINK_WIRELESS_MULTIBOOT_CMD_START_SIZE, {1, 0},
LinkWirelessOpenSDK::CommState::STARTING, 0, 0b0001),
response);
},
[](LinkWirelessOpenSDK::ClientPacket packet) {
auto header = packet.header;
return header.isACK == 1 && header.n == 1 && header.phase == 0 &&
header.commState == LinkWirelessOpenSDK::CommState::STARTING;
},
LINK_WIRELESS_MULTIBOOT_TRY(exchangeNewData(
0, // TODO: Multiple clients
linkWirelessOpenSDK->createServerBuffer(
LINK_WIRELESS_MULTIBOOT_CMD_START,
LINK_WIRELESS_MULTIBOOT_CMD_START_SIZE,
{1, 0, LinkWirelessOpenSDK::CommState::STARTING}, 0, 0b0001),
cancel))
LWMLOG("SENDING ROM!");
progress.state = SENDING;
LinkWirelessOpenSDK::ChildrenData childrenData;
LinkWirelessOpenSDK::SequenceNumber sequence = {.n = 1, .phase = 0};
LinkWirelessOpenSDK::SequenceNumber sequence = {
.n = 1,
.phase = 0,
.commState = LinkWirelessOpenSDK::CommState::COMMUNICATING};
u32 transferredBytes = 0;
u32 percent = 0;
progress.percentage = 0;
while (transferredBytes < romSize) {
if (cancel(progress))
return finish(CANCELED);
// TODO: Multiple clients
auto sendBuffer = linkWirelessOpenSDK->createServerBuffer(
rom, romSize, sequence, LinkWirelessOpenSDK::CommState::COMMUNICATING,
transferredBytes, 0b0001);
rom, romSize, sequence, transferredBytes, 0b0001);
LinkRawWireless::ReceiveDataResponse response;
LINK_WIRELESS_MULTIBOOT_TRY(
sendAndExpectData(sendBuffer.data, sendBuffer.dataSize,
sendBuffer.totalByteCount, response))
LINK_WIRELESS_MULTIBOOT_TRY(sendAndExpectData(sendBuffer, response))
childrenData = linkWirelessOpenSDK->getChildrenData(response);
for (u32 i = 0; i < childrenData.responses[0].packetsSize; i++) {
@@ -148,10 +137,10 @@ class LinkWirelessMultiboot {
if (header.isACK && header.sequence() == sequence) {
sequence.inc();
transferredBytes += sendBuffer.header.payloadSize;
u32 newPercent = transferredBytes * 100 / romSize;
if (newPercent != percent) {
percent = newPercent;
LWMLOG("-> " + std::to_string(percent));
u32 newPercentage = transferredBytes * 100 / romSize;
if (newPercentage != progress.percentage) {
progress.percentage = newPercentage;
LWMLOG("-> " + std::to_string(newPercentage));
}
break;
}
@@ -160,27 +149,18 @@ class LinkWirelessMultiboot {
LWMLOG("confirming (1/2)...");
progress.state = CONFIRMING;
LINK_WIRELESS_MULTIBOOT_TRY(exchangeData(
0,
[this](LinkRawWireless::ReceiveDataResponse& response) {
return sendAndExpectData(
linkWirelessOpenSDK->createServerBuffer(
{}, 0, {0, 0}, LinkWirelessOpenSDK::CommState::ENDING, 0,
0b0001),
response);
},
[](LinkWirelessOpenSDK::ClientPacket packet) {
auto header = packet.header;
return header.isACK == 1 && header.n == 0 && header.phase == 0 &&
header.commState == LinkWirelessOpenSDK::CommState::ENDING;
},
LINK_WIRELESS_MULTIBOOT_TRY(exchangeNewData(
0, // TODO: Multiple clients
linkWirelessOpenSDK->createServerBuffer(
{}, 0, {0, 0, LinkWirelessOpenSDK::CommState::ENDING}, 0, 0b0001),
cancel))
LWMLOG("confirming (2/2)...");
// TODO: Multiple clients
LinkRawWireless::ReceiveDataResponse response;
LINK_WIRELESS_MULTIBOOT_TRY(sendAndExpectData(
linkWirelessOpenSDK->createServerBuffer(
{}, 0, {1, 0}, LinkWirelessOpenSDK::CommState::OFF, 0, 0b0001),
{}, 0, {1, 0, LinkWirelessOpenSDK::CommState::OFF}, 0, 0b0001),
response))
LWMLOG("SUCCESS!");
@@ -197,6 +177,8 @@ class LinkWirelessMultiboot {
private:
MultibootProgress progress;
Result lastResult;
LinkWirelessOpenSDK::ClientSDKHeader lastValidHeader;
Result activate() {
if (!linkRawWireless->activate()) {
@@ -271,7 +253,7 @@ class LinkWirelessMultiboot {
// initial packet received
LWMLOG("handshake (1/2)...");
LINK_WIRELESS_MULTIBOOT_TRY(exchangeACK(
LINK_WIRELESS_MULTIBOOT_TRY(exchangeACKData(
clientNumber,
[](LinkWirelessOpenSDK::ClientPacket packet) {
auto header = packet.header;
@@ -282,7 +264,7 @@ class LinkWirelessMultiboot {
// n = 2, commState = 1
LWMLOG("handshake (2/2)...");
LINK_WIRELESS_MULTIBOOT_TRY(exchangeACK(
LINK_WIRELESS_MULTIBOOT_TRY(exchangeACKData(
clientNumber,
[](LinkWirelessOpenSDK::ClientPacket packet) {
auto header = packet.header;
@@ -294,10 +276,10 @@ class LinkWirelessMultiboot {
// n = 1, commState = 2
LWMLOG("receiving name...");
LINK_WIRELESS_MULTIBOOT_TRY(exchangeACK(
LINK_WIRELESS_MULTIBOOT_TRY(exchangeACKData(
clientNumber,
[this](LinkWirelessOpenSDK::ClientPacket packet) {
progress.lastValidHeader = packet.header;
lastValidHeader = packet.header;
return packet.header.commState == LinkWirelessOpenSDK::CommState::OFF;
},
cancel))
@@ -320,13 +302,36 @@ class LinkWirelessMultiboot {
return SUCCESS;
}
template <typename C>
__attribute__((noinline)) Result exchangeNewData(
u8 clientNumber,
LinkWirelessOpenSDK::SendBuffer<LinkWirelessOpenSDK::ServerSDKHeader>
sendBuffer,
C cancel) {
LINK_WIRELESS_MULTIBOOT_TRY(exchangeData(
clientNumber,
[this, &sendBuffer](LinkRawWireless::ReceiveDataResponse& response) {
return sendAndExpectData(sendBuffer, response);
},
[&sendBuffer](LinkWirelessOpenSDK::ClientPacket packet) {
auto header = packet.header;
return header.isACK == 1 &&
header.sequence() == sendBuffer.header.sequence();
},
cancel))
return SUCCESS;
}
template <typename V, typename C>
Result exchangeACK(u8 clientNumber, V validatePacket, C cancel) {
__attribute__((noinline)) Result exchangeACKData(u8 clientNumber,
V validatePacket,
C cancel) {
LINK_WIRELESS_MULTIBOOT_TRY(exchangeData(
clientNumber,
[this, clientNumber](LinkRawWireless::ReceiveDataResponse& response) {
return sendAndExpectData(linkWirelessOpenSDK->createServerACKBuffer(
progress.lastValidHeader, clientNumber),
lastValidHeader, clientNumber),
response);
},
validatePacket, cancel))
@@ -335,10 +340,10 @@ class LinkWirelessMultiboot {
}
template <typename F, typename V, typename C>
Result exchangeData(u8 clientNumber,
F sendAction,
V validatePacket,
C cancel) {
__attribute__((noinline)) Result exchangeData(u8 clientNumber,
F sendAction,
V validatePacket,
C cancel) {
bool hasFinished = false;
while (!hasFinished) {
if (cancel(progress))
@@ -354,7 +359,7 @@ class LinkWirelessMultiboot {
auto header = packet.header;
if (validatePacket(packet)) {
hasFinished = true;
progress.lastValidHeader = header;
lastValidHeader = header;
break;
}
}
@@ -363,14 +368,15 @@ class LinkWirelessMultiboot {
return SUCCESS;
}
Result sendAndExpectData(LinkWirelessOpenSDK::SendBuffer<
LinkWirelessOpenSDK::ServerSDKHeader> sendBuffer,
LinkRawWireless::ReceiveDataResponse& response) {
__attribute__((noinline)) Result sendAndExpectData(
LinkWirelessOpenSDK::SendBuffer<LinkWirelessOpenSDK::ServerSDKHeader>
sendBuffer,
LinkRawWireless::ReceiveDataResponse& response) {
return sendAndExpectData(sendBuffer.data, sendBuffer.dataSize,
sendBuffer.totalByteCount, response);
}
Result sendAndExpectData(
__attribute__((noinline)) Result sendAndExpectData(
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data,
u32 dataSize,
u32 _bytes,
@@ -408,10 +414,11 @@ class LinkWirelessMultiboot {
return SUCCESS;
}
Result finish(Result result) {
__attribute__((noinline)) Result finish(Result result) {
linkRawWireless->deactivate();
progress.state = STOPPED;
progress.connectedPlayers = 1;
progress.percentage = 0;
return result;
}

View File

@@ -57,6 +57,7 @@ class LinkWirelessOpenSDK {
struct SequenceNumber {
u32 n = 0;
u32 phase = 0;
CommState commState = OFF;
void inc() {
phase++;
@@ -69,7 +70,8 @@ class LinkWirelessOpenSDK {
}
bool operator==(const SequenceNumber& other) {
return n == other.n && phase == other.phase;
return n == other.n && phase == other.phase &&
commState == other.commState;
}
};
@@ -82,7 +84,9 @@ class LinkWirelessOpenSDK {
CommState commState : 4;
unsigned int targetSlots : 4;
SequenceNumber sequence() { return SequenceNumber{.n = n, .phase = phase}; }
SequenceNumber sequence() {
return SequenceNumber{.n = n, .phase = phase, .commState = commState};
}
};
union ServerSDKHeaderSerializer {
ServerSDKHeader asStruct;
@@ -107,7 +111,9 @@ class LinkWirelessOpenSDK {
unsigned int isACK : 1;
CommState commState : 4;
SequenceNumber sequence() { return SequenceNumber{.n = n, .phase = phase}; }
SequenceNumber sequence() {
return SequenceNumber{.n = n, .phase = phase, .commState = commState};
}
};
union ClientSDKHeaderSerializer {
ClientSDKHeader asStruct;
@@ -200,13 +206,12 @@ class LinkWirelessOpenSDK {
return parentData;
}
SendBuffer<ServerSDKHeader> createServerBuffer(
const u8* fullPayload,
u32 fullPayloadSize,
SequenceNumber sequence,
CommState commState = CommState::COMMUNICATING,
u32 offset = 0,
u8 targetSlots = 0b1111) {
// TODO: MOVE OFFSET TO END
SendBuffer<ServerSDKHeader> createServerBuffer(const u8* fullPayload,
u32 fullPayloadSize,
SequenceNumber sequence,
u32 offset = 0,
u8 targetSlots = 0b1111) {
SendBuffer<ServerSDKHeader> buffer;
u32 payloadSize =
min(fullPayloadSize, LINK_WIRELESS_OPEN_SDK_MAX_PAYLOAD_SERVER);
@@ -216,7 +221,7 @@ class LinkWirelessOpenSDK {
buffer.header.payloadSize = payloadSize;
buffer.header.n = sequence.n;
buffer.header.phase = sequence.phase;
buffer.header.commState = commState;
buffer.header.commState = sequence.commState;
u32 headerInt = serializeServerHeader(buffer.header);
buffer.data[buffer.dataSize++] = headerInt;
@@ -255,12 +260,11 @@ class LinkWirelessOpenSDK {
return buffer;
}
SendBuffer<ClientSDKHeader> createClientBuffer(
const u8* fullPayload,
u32 fullPayloadSize,
SequenceNumber sequence,
CommState commState = CommState::COMMUNICATING,
u32 offset = 0) {
// TODO: MOVE OFFSET TO END
SendBuffer<ClientSDKHeader> createClientBuffer(const u8* fullPayload,
u32 fullPayloadSize,
SequenceNumber sequence,
u32 offset = 0) {
SendBuffer<ClientSDKHeader> buffer;
u32 payloadSize =
min(fullPayloadSize, LINK_WIRELESS_OPEN_SDK_MAX_PAYLOAD_CLIENT);
@@ -269,7 +273,7 @@ class LinkWirelessOpenSDK {
buffer.header.payloadSize = payloadSize;
buffer.header.n = sequence.n;
buffer.header.phase = sequence.phase;
buffer.header.commState = commState;
buffer.header.commState = sequence.commState;
u16 headerInt = serializeClientHeader(buffer.header);
buffer.data[buffer.dataSize++] = headerInt;