rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
tunerstudio_io.cpp
Go to the documentation of this file.
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
17size_t TsChannelBase::read(uint8_t* buffer, size_t size) {
18 return readTimeout(buffer, size, SR5_READ_TIMEOUT);
19}
20#endif
21
23 return ((TS_PACKET_HEADER_SIZE + size + TS_PACKET_TAIL_SIZE) > sizeof(scratchBuffer));
24}
25
26void TsChannelBase::copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size) {
27 // don't transmit too large a buffer
28 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 if (size) {
35 memcpy(scratchBuffer + TS_PACKET_HEADER_SIZE, buf, size);
36 }
37
38 crcAndWriteBuffer(responseCode, size);
39}
40
41void TsChannelBase::crcAndWriteBuffer(uint8_t responseCode, size_t size) {
42 criticalAssertVoid(!isBigPacket(size), "crcAndWriteBuffer tried to transmit too large a packet")
43
44 // Index 0/1 = packet size (big endian)
45 *(uint16_t*)scratchBuffer = SWAP_UINT16(size + 1);
46 // Index 2 = response code
47 scratchBuffer[2] = responseCode;
48
49 // CRC is computed on the responseCode and payload but not length
50 uint32_t crc = crc32(&scratchBuffer[2], size + 1); // command part of CRC
51
52 // Place the CRC at the end
53 crc = SWAP_UINT32(crc);
54 memcpy(scratchBuffer + size + TS_PACKET_HEADER_SIZE, &crc, sizeof(crc));
55
56 // Write to the underlying stream
57 write(reinterpret_cast<uint8_t*>(scratchBuffer), size + 7, true);
58 flush();
59}
60
61uint32_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
72void 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
91TsChannelBase::TsChannelBase(const char *p_name) {
92 this->name = p_name;
93}
94
95void TsChannelBase::assertPacketSize(size_t size, bool allowLongPackets) {
96 if (isBigPacket(size) && !allowLongPackets) {
97 criticalError("[USE PROPER CONSOLE VERSION ] disallowed long packet of size %d", size);
98 }
99}
100
101/**
102 * Adds size to the beginning of a packet and a crc32 at the end. Then send the packet.
103 */
104void TsChannelBase::writeCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size, bool allowLongPackets) {
105 // don't transmit a null buffer...
106 if (!buf) {
107 size = 0;
108 }
109
110 assertPacketSize(size, allowLongPackets);
111
112 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 copyAndWriteSmallCrcPacket(responseCode, buf, size);
118 }
119}
120
121void TsChannelBase::sendResponse(ts_response_format_e mode, const uint8_t * buffer, int size, bool allowLongPackets /* = false */) {
122 if (mode == TS_CRC) {
123 writeCrcPacket(TS_RESPONSE_OK, buffer, size, allowLongPackets);
124 } else {
125 if (size > 0) {
126 write(buffer, size, true);
127 flush();
128 }
129 }
130}
void crcAndWriteBuffer(const uint8_t responseCode, const size_t size)
void copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t *buf, size_t size)
size_t read(uint8_t *buffer, size_t size)
virtual void flush()
const char * name
bool isBigPacket(size_t size)
char scratchBuffer[scratchBuffer_SIZE+30]
uint32_t writePacketHeader(const uint8_t responseCode, const size_t size)
void writeCrcPacketLarge(uint8_t responseCode, const uint8_t *buf, size_t size)
void assertPacketSize(size_t size, bool allowLongPackets)
virtual void writeCrcPacket(uint8_t responseCode, const uint8_t *buf, size_t size, bool allowLongPackets=false)
virtual void write(const uint8_t *buffer, size_t size, bool isEndOfPacket=false)=0
virtual size_t readTimeout(uint8_t *buffer, size_t size, int timeout)=0
void sendResponse(ts_response_format_e mode, const uint8_t *buffer, int size, bool allowLongPackets=false)
TsChannelBase(const char *name)
uint32_t SWAP_UINT32(uint32_t x)
Definition efilib.h:27
uint16_t SWAP_UINT16(uint16_t x)
Definition efilib.h:22
composite packet size
static BigBufferHandle buffer
ts_response_format_e
@ TS_CRC