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 |