GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 50.8% 33 / 0 / 65
Functions: 63.6% 7 / 0 / 11
Branches: 35.0% 14 / 0 / 40
Decisions: 43.8% 7 / - / 16

firmware/console/binary/tunerstudio_io.cpp
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 uint32_t TsChannelBase::writePacketBody(const uint8_t* buf, const size_t size, uint32_t crc) {
92 if ((size) && (buf)) {
93 write(buf, size, /*isEndOfPacket*/false);
94 crc = crc32inc((void *)buf, crc, size);
95 }
96
97 // return updated CRC
98 return crc;
99 }
100
101 void TsChannelBase::writeCrcPacketTail(uint32_t crc) {
102 uint8_t crcBuffer[4];
103
104 *(uint32_t *)crcBuffer = SWAP_UINT32(crc);
105
106 write(crcBuffer, sizeof(crcBuffer), /*isEndOfPacket*/true);
107 flush();
108 }
109
110 2 TsChannelBase::TsChannelBase(const char *p_name) {
111 2 this->name = p_name;
112 2 }
113
114 4 void TsChannelBase::assertPacketSize(size_t size, bool allowLongPackets) {
115
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) {
116 criticalError("[USE PROPER CONSOLE VERSION ] disallowed long packet of size %d", size);
117 }
118 4 }
119
120 /**
121 * Adds size to the beginning of a packet and a crc32 at the end. Then send the packet.
122 */
123 4 void TsChannelBase::writeCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size, bool allowLongPackets) {
124 // don't transmit a null buffer...
125
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) {
126 1 size = 0;
127 }
128
129 4 assertPacketSize(size, allowLongPackets);
130
131
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)) {
132 // for larger packets we do not use a buffer for CRC calculation meaning data is now allowed to modify while pending
133 writeCrcPacketLarge(responseCode, buf, size);
134 } else {
135 // for small packets we use a buffer for CRC calculation
136 4 copyAndWriteSmallCrcPacket(responseCode, buf, size);
137 }
138 4 }
139
140 1 void TsChannelBase::sendResponse(ts_response_format_e mode, const uint8_t * buffer, int size, bool allowLongPackets /* = false */) {
141
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) {
142 1 writeCrcPacket(TS_RESPONSE_OK, buffer, size, allowLongPackets);
143 } else {
144 if (size > 0) {
145 write(buffer, size, true);
146 flush();
147 }
148 }
149 1 }
150