GCC Code Coverage Report


Directory: ./
File: firmware/console/binary/tunerstudio_io.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 61.1% 33 0 54
Functions: 77.8% 7 0 9
Branches: 41.2% 14 0 34
Decisions: 50.0% 7 - 14

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