| Line | Branch | Decision | Exec | Source |
|---|---|---|---|---|
| 1 | /** | |||
| 2 | * @file tunerstudio_io.cpp | |||
| 3 | * | |||
| 4 | * @date Mar 8, 2015 | |||
| 5 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
| 6 | */ | |||
| 7 | ||||
| 8 | #include "pch.h" | |||
| 9 | ||||
| 10 | #include "tunerstudio_io.h" | |||
| 11 | ||||
| 12 | #if EFI_SIMULATOR | |||
| 13 | #include "rusEfiFunctionalTest.h" | |||
| 14 | #endif // EFI_SIMULATOR | |||
| 15 | ||||
| 16 | #if EFI_PROD_CODE || EFI_SIMULATOR | |||
| 17 | size_t TsChannelBase::read(uint8_t* buffer, size_t size) { | |||
| 18 | return readTimeout(buffer, size, SR5_READ_TIMEOUT); | |||
| 19 | } | |||
| 20 | #endif | |||
| 21 | ||||
| 22 | 16 | bool TsChannelBase::isBigPacket(size_t size) { | ||
| 23 | 16 | return ((TS_PACKET_HEADER_SIZE + size + TS_PACKET_TAIL_SIZE) > sizeof(scratchBuffer)); | ||
| 24 | } | |||
| 25 | ||||
| 26 | 4 | void TsChannelBase::copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size) { | ||
| 27 | // don't transmit too large a buffer | |||
| 28 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | criticalAssertVoid(!isBigPacket(size), "copyAndWriteSmallCrcPacket tried to transmit too large a packet") | |
| 29 | ||||
| 30 | // If transmitting data, copy it in to place in the scratch buffer | |||
| 31 | // We want to prevent the data changing itself (higher priority threads could write | |||
| 32 | // tsOutputChannels) during the CRC computation. Instead compute the CRC on our | |||
| 33 | // local buffer that nobody else will write. | |||
| 34 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
|
2/2✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1 time.
|
4 | if (size) { |
| 35 | 3 | memcpy(scratchBuffer + TS_PACKET_HEADER_SIZE, buf, size); | ||
| 36 | } | |||
| 37 | ||||
| 38 | 4 | crcAndWriteBuffer(responseCode, size); | ||
| 39 | } | |||
| 40 | ||||
| 41 | 4 | void TsChannelBase::crcAndWriteBuffer(uint8_t responseCode, size_t size) { | ||
| 42 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
|
4 | criticalAssertVoid(!isBigPacket(size), "crcAndWriteBuffer tried to transmit too large a packet") | |
| 43 | ||||
| 44 | // Index 0/1 = packet size (big endian) | |||
| 45 | 4 | *(uint16_t*)scratchBuffer = SWAP_UINT16(size + 1); | ||
| 46 | // Index 2 = response code | |||
| 47 | 4 | scratchBuffer[2] = responseCode; | ||
| 48 | ||||
| 49 | // CRC is computed on the responseCode and payload but not length | |||
| 50 |
1/1✓ Branch 2 taken 4 times.
|
4 | uint32_t crc = crc32(&scratchBuffer[2], size + 1); // command part of CRC | |
| 51 | ||||
| 52 | // Place the CRC at the end | |||
| 53 | 4 | crc = SWAP_UINT32(crc); | ||
| 54 | 4 | memcpy(scratchBuffer + size + TS_PACKET_HEADER_SIZE, &crc, sizeof(crc)); | ||
| 55 | ||||
| 56 | // Write to the underlying stream | |||
| 57 |
1/1✓ Branch 1 taken 4 times.
|
4 | write(reinterpret_cast<uint8_t*>(scratchBuffer), size + 7, true); | |
| 58 |
1/1✓ Branch 1 taken 4 times.
|
4 | flush(); | |
| 59 | } | |||
| 60 | ||||
| 61 | ✗ | uint32_t TsChannelBase::writePacketHeader(const uint8_t responseCode, const size_t size) { | ||
| 62 | ✗ | uint8_t headerBuffer[3]; | ||
| 63 | ✗ | *(uint16_t*)headerBuffer = SWAP_UINT16(size + 1); | ||
| 64 | ✗ | *(uint8_t*)(headerBuffer + 2) = responseCode; | ||
| 65 | // Write header | |||
| 66 | ✗ | write(headerBuffer, sizeof(headerBuffer), /*isEndOfPacket*/false); | ||
| 67 | ||||
| 68 | // Command part of CRC | |||
| 69 | ✗ | return crc32((void*)(headerBuffer + 2), 1); | ||
| 70 | } | |||
| 71 | ||||
| 72 | ✗ | void TsChannelBase::writeCrcPacketLarge(const uint8_t responseCode, const uint8_t* buf, const size_t size) { | ||
| 73 | ✗ | uint8_t crcBuffer[4]; | ||
| 74 | ||||
| 75 | // Command part of CRC | |||
| 76 | ✗ | uint32_t crc = writePacketHeader(responseCode, size); | ||
| 77 | // Data part of CRC | |||
| 78 | ✗ | crc = crc32inc((void*)buf, crc, size); | ||
| 79 | ✗ | *(uint32_t*)crcBuffer = SWAP_UINT32(crc); | ||
| 80 | ||||
| 81 | // If data, write that | |||
| 82 | ✗ | if (size) { | ||
| 83 | ✗ | write(buf, size, /*isEndOfPacket*/false); | ||
| 84 | } | |||
| 85 | ||||
| 86 | // Lastly the CRC footer | |||
| 87 | ✗ | write(crcBuffer, sizeof(crcBuffer), /*isEndOfPacket*/true); | ||
| 88 | ✗ | flush(); | ||
| 89 | ✗ | } | ||
| 90 | ||||
| 91 | 2 | TsChannelBase::TsChannelBase(const char *p_name) { | ||
| 92 | 2 | this->name = p_name; | ||
| 93 | 2 | } | ||
| 94 | ||||
| 95 | 4 | void TsChannelBase::assertPacketSize(size_t size, bool allowLongPackets) { | ||
| 96 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 4 times.
|
4 | if (isBigPacket(size) && !allowLongPackets) { |
| 97 | ✗ | criticalError("[USE PROPER CONSOLE VERSION ] disallowed long packet of size %d", size); | ||
| 98 | } | |||
| 99 | 4 | } | ||
| 100 | ||||
| 101 | /** | |||
| 102 | * Adds size to the beginning of a packet and a crc32 at the end. Then send the packet. | |||
| 103 | */ | |||
| 104 | 4 | void TsChannelBase::writeCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size, bool allowLongPackets) { | ||
| 105 | // don't transmit a null buffer... | |||
| 106 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 3 times.
|
4 | if (!buf) { |
| 107 | 1 | size = 0; | ||
| 108 | } | |||
| 109 | ||||
| 110 | 4 | assertPacketSize(size, allowLongPackets); | ||
| 111 | ||||
| 112 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 4 times.
|
4 | if (isBigPacket(size)) { |
| 113 | // for larger packets we do not use a buffer for CRC calculation meaning data is now allowed to modify while pending | |||
| 114 | ✗ | writeCrcPacketLarge(responseCode, buf, size); | ||
| 115 | } else { | |||
| 116 | // for small packets we use a buffer for CRC calculation | |||
| 117 | 4 | copyAndWriteSmallCrcPacket(responseCode, buf, size); | ||
| 118 | } | |||
| 119 | 4 | } | ||
| 120 | ||||
| 121 | 1 | void TsChannelBase::sendResponse(ts_response_format_e mode, const uint8_t * buffer, int size, bool allowLongPackets /* = false */) { | ||
| 122 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1/2✓ Decision 'true' taken 1 time.
✗ Decision 'false' not taken.
|
1 | if (mode == TS_CRC) { |
| 123 | 1 | writeCrcPacket(TS_RESPONSE_OK, buffer, size, allowLongPackets); | ||
| 124 | } else { | |||
| 125 | ✗ | if (size > 0) { | ||
| 126 | ✗ | write(buffer, size, true); | ||
| 127 | ✗ | flush(); | ||
| 128 | } | |||
| 129 | } | |||
| 130 | 1 | } | ||
| 131 |