TunerStudio reconnect speedup (#4358)

* TunerStudio: do not emit tons of errors if we are not in sync

Track state of sync with ither side. Emit only ONE error when sync
is lost.
Also no need to wait 1sec for second byte in binary mode. 10mS is
enought.

* TunerStudio: remove duplicated debug print

* TunerStudio: comment about in_sync

* TunerStudio: clear comments
This commit is contained in:
Andrey G 2022-07-21 00:54:10 +03:00 committed by GitHub
parent 64a5536d41
commit 7caef0ba92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 34 deletions

View File

@ -418,6 +418,7 @@ static int tsProcessOne(TsChannelBase* tsChannel) {
// assume there's connection loss and notify the bluetooth init code
bluetoothSoftwareDisconnectNotify();
#endif /* EFI_BLUETOOTH_SETUP */
tsChannel->in_sync = false;
return -1;
}
@ -430,63 +431,89 @@ static int tsProcessOne(TsChannelBase* tsChannel) {
received = tsChannel->readTimeout(&secondByte, 1, TS_COMMUNICATION_TIMEOUT_SHORT);
if (received != 1) {
tunerStudioError(tsChannel, "TS: ERROR: no second byte");
tsChannel->in_sync = false;
return -1;
}
uint16_t incomingPacketSize = firstByte << 8 | secondByte;
size_t expectedSize = incomingPacketSize + CRC_VALUE_SIZE;
if (incomingPacketSize == 0 || incomingPacketSize > (sizeof(tsChannel->scratchBuffer) - CRC_WRAPPING_SIZE)) {
efiPrintf("process_ts: channel=%s invalid size: %d", tsChannel->name, incomingPacketSize);
tunerStudioError(tsChannel, "process_ts: ERROR: CRC header size");
sendErrorCode(tsChannel, TS_RESPONSE_UNDERRUN);
if (incomingPacketSize == 0 || expectedSize > sizeof(tsChannel->scratchBuffer)) {
if (tsChannel->in_sync) {
efiPrintf("process_ts: channel=%s invalid size: %d", tsChannel->name, incomingPacketSize);
tunerStudioError(tsChannel, "process_ts: ERROR: CRC header size");
/* send error only if previously we where in sync */
sendErrorCode(tsChannel, TS_RESPONSE_UNDERRUN);
}
tsChannel->in_sync = false;
return -1;
}
received = tsChannel->readTimeout((uint8_t* )tsChannel->scratchBuffer, 1, TS_COMMUNICATION_TIMEOUT);
if (received != 1) {
tunerStudioError(tsChannel, "ERROR: did not receive command");
sendErrorCode(tsChannel, TS_RESPONSE_UNDERRUN);
return -1;
}
char command;
if (tsChannel->in_sync) {
/* we are in sync state, packet size should be correct so lets receive full packet and then check if command is supported
* otherwise (if abort reception in middle of packet) it will break syncronization and cause error on next packet */
received = tsChannel->readTimeout((uint8_t*)(tsChannel->scratchBuffer), expectedSize, TS_COMMUNICATION_TIMEOUT);
command = tsChannel->scratchBuffer[0];
char command = tsChannel->scratchBuffer[0];
if (!isKnownCommand(command)) {
efiPrintf("unexpected command %x", command);
sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND);
return -1;
if (received != expectedSize) {
/* print and send error as we where in sync */
efiPrintf("Got only %d bytes while expecting %d for command %c", received,
expectedSize, command);
tunerStudioError(tsChannel, "ERROR: not enough bytes in stream");
sendErrorCode(tsChannel, TS_RESPONSE_UNDERRUN);
tsChannel->in_sync = false;
return -1;
}
if (!isKnownCommand(command)) {
/* print and send error as we where in sync */
efiPrintf("unexpected command %x", command);
sendErrorCode(tsChannel, TS_RESPONSE_UNRECOGNIZED_COMMAND);
tsChannel->in_sync = false;
return -1;
}
} else {
/* receive only command byte to check if it is supported */
received = tsChannel->readTimeout((uint8_t*)(tsChannel->scratchBuffer), 1, TS_COMMUNICATION_TIMEOUT_SHORT);
command = tsChannel->scratchBuffer[0];
if (!isKnownCommand(command)) {
/* do not report any error as we are not in sync */
return -1;
}
received = tsChannel->readTimeout((uint8_t*)(tsChannel->scratchBuffer) + 1, expectedSize - 1, TS_COMMUNICATION_TIMEOUT);
if (received != expectedSize - 1) {
/* do not report any error as we are not in sync */
return -1;
}
}
#if EFI_SIMULATOR
logMsg("command %c\r\n", command);
logMsg("command %c\r\n", command);
#endif
int expectedSize = incomingPacketSize + CRC_VALUE_SIZE - 1;
received = tsChannel->readTimeout((uint8_t*)(tsChannel->scratchBuffer + 1), expectedSize, TS_COMMUNICATION_TIMEOUT);
if (received != expectedSize) {
efiPrintf("Got only %d bytes while expecting %d for command %c", received,
expectedSize, command);
tunerStudioError(tsChannel, "ERROR: not enough bytes in stream");
sendErrorCode(tsChannel, TS_RESPONSE_UNDERRUN);
return -1;
}
uint32_t expectedCrc = *(uint32_t*) (tsChannel->scratchBuffer + incomingPacketSize);
expectedCrc = SWAP_UINT32(expectedCrc);
uint32_t actualCrc = crc32(tsChannel->scratchBuffer, incomingPacketSize);
if (actualCrc != expectedCrc) {
efiPrintf("TunerStudio: CRC %x %x %x %x", tsChannel->scratchBuffer[incomingPacketSize + 0],
tsChannel->scratchBuffer[incomingPacketSize + 1], tsChannel->scratchBuffer[incomingPacketSize + 2],
tsChannel->scratchBuffer[incomingPacketSize + 3]);
efiPrintf("TunerStudio: command %c actual CRC %x/expected %x", tsChannel->scratchBuffer[0],
actualCrc, expectedCrc);
tunerStudioError(tsChannel, "ERROR: CRC issue");
sendErrorCode(tsChannel, TS_RESPONSE_CRC_FAILURE);
/* send error only if previously we where in sync */
if (tsChannel->in_sync) {
efiPrintf("TunerStudio: command %c actual CRC %x/expected %x", tsChannel->scratchBuffer[0],
actualCrc, expectedCrc);
tunerStudioError(tsChannel, "ERROR: CRC issue");
sendErrorCode(tsChannel, TS_RESPONSE_CRC_FAILURE);
tsChannel->in_sync = false;
}
return -1;
}
/* we were able to receive known command with correct crc and size! */
tsChannel->in_sync = true;
int success = tsInstance.handleCrcCommand(tsChannel, tsChannel->scratchBuffer, incomingPacketSize);
if (!success) {

View File

@ -62,6 +62,18 @@ public:
void crcAndWriteBuffer(uint8_t responseCode, size_t size);
void copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size);
/* When TsChannel is in "not in sync" state tsProcessOne will silently try to find
* begining of packet.
* As soon as tsProcessOne was able to receive valid packet with valid size and crc
* TsChannel becomes "in sync". That means it will react on any futher errors: it will
* emit packet with error code and switch back to "not in sync" mode.
* This insures that RE will send only one error message after lost of syncronization
* with TS.
* Also while in "not in sync" state - tsProcessOne will not try to receive whole packet
* by one read. Instead after getting packet size it will try to receive one byte of
* command and check if it is supported. */
bool in_sync = false;
private:
void writeCrcPacketLarge(uint8_t responseCode, const uint8_t* buf, size_t size);
};