Line data Source code
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 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 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 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 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 4 : write(reinterpret_cast<uint8_t*>(scratchBuffer), size + 7, true);
58 4 : flush();
59 : }
60 :
61 0 : uint32_t TsChannelBase::writePacketHeader(const uint8_t responseCode, const size_t size) {
62 0 : uint8_t headerBuffer[3];
63 0 : *(uint16_t*)headerBuffer = SWAP_UINT16(size + 1);
64 0 : *(uint8_t*)(headerBuffer + 2) = responseCode;
65 : // Write header
66 0 : write(headerBuffer, sizeof(headerBuffer), /*isEndOfPacket*/false);
67 :
68 : // Command part of CRC
69 0 : return crc32((void*)(headerBuffer + 2), 1);
70 : }
71 :
72 0 : void TsChannelBase::writeCrcPacketLarge(const uint8_t responseCode, const uint8_t* buf, const size_t size) {
73 0 : uint8_t crcBuffer[4];
74 :
75 : // Command part of CRC
76 0 : uint32_t crc = writePacketHeader(responseCode, size);
77 : // Data part of CRC
78 0 : crc = crc32inc((void*)buf, crc, size);
79 0 : *(uint32_t*)crcBuffer = SWAP_UINT32(crc);
80 :
81 : // If data, write that
82 0 : if (size) {
83 0 : write(buf, size, /*isEndOfPacket*/false);
84 : }
85 :
86 : // Lastly the CRC footer
87 0 : write(crcBuffer, sizeof(crcBuffer), /*isEndOfPacket*/true);
88 0 : flush();
89 0 : }
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 4 : if (isBigPacket(size) && !allowLongPackets) {
97 0 : 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 4 : if (!buf) {
107 1 : size = 0;
108 : }
109 :
110 4 : assertPacketSize(size, allowLongPackets);
111 :
112 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 0 : 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 : if (mode == TS_CRC) {
123 1 : writeCrcPacket(TS_RESPONSE_OK, buffer, size, allowLongPackets);
124 : } else {
125 0 : if (size > 0) {
126 0 : write(buffer, size, true);
127 0 : flush();
128 : }
129 : }
130 1 : }
|