LCOV - code coverage report
Current view: top level - firmware/console/binary - tunerstudio_io.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 31 52 59.6 %
Date: 2024-04-25 02:23:43 Functions: 6 8 75.0 %

          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             : #define isBigPacket(size) ((size) > BLOCKING_FACTOR + 7)
      23             : 
      24           4 : void TsChannelBase::copyAndWriteSmallCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size) {
      25             :         // don't transmit too large a buffer
      26           4 :         criticalAssertVoid(!isBigPacket(size), "copyAndWriteSmallCrcPacket tried to transmit too large a packet")
      27             : 
      28             :         // If transmitting data, copy it in to place in the scratch buffer
      29             :         // We want to prevent the data changing itself (higher priority threads could write
      30             :         // tsOutputChannels) during the CRC computation.  Instead compute the CRC on our
      31             :         // local buffer that nobody else will write.
      32           4 :         if (size) {
      33           3 :                 memcpy(scratchBuffer + SCRATCH_BUFFER_PREFIX_SIZE, buf, size);
      34             :         }
      35             : 
      36           4 :         crcAndWriteBuffer(responseCode, size);
      37             : }
      38             : 
      39           4 : void TsChannelBase::crcAndWriteBuffer(uint8_t responseCode, size_t size) {
      40           4 :         criticalAssertVoid(!isBigPacket(size), "crcAndWriteBuffer tried to transmit too large a packet")
      41             : 
      42             :         // Index 0/1 = packet size (big endian)
      43           4 :         *(uint16_t*)scratchBuffer = SWAP_UINT16(size + 1);
      44             :         // Index 2 = response code
      45           4 :         scratchBuffer[2] = responseCode;
      46             : 
      47             :         // CRC is computed on the responseCode and payload but not length
      48           4 :         uint32_t crc = crc32(&scratchBuffer[2], size + 1); // command part of CRC
      49             : 
      50             :         // Place the CRC at the end
      51           4 :         crc = SWAP_UINT32(crc);
      52           4 :         memcpy(scratchBuffer + size + SCRATCH_BUFFER_PREFIX_SIZE, &crc, sizeof(crc));
      53             : 
      54             :         // Write to the underlying stream
      55           4 :         write(reinterpret_cast<uint8_t*>(scratchBuffer), size + 7, true);
      56           4 :         flush();
      57             : }
      58             : 
      59           0 : uint32_t TsChannelBase::writePacketHeader(const uint8_t responseCode, const size_t size) {
      60           0 :         uint8_t headerBuffer[3];
      61           0 :         *(uint16_t*)headerBuffer = SWAP_UINT16(size + 1);
      62           0 :         *(uint8_t*)(headerBuffer + 2) = responseCode;
      63             :         // Write header
      64           0 :         write(headerBuffer, sizeof(headerBuffer), /*isEndOfPacket*/false);
      65             : 
      66             :          // Command part of CRC
      67           0 :         return crc32((void*)(headerBuffer + 2), 1);
      68             : }
      69             : 
      70           0 : void TsChannelBase::writeCrcPacketLarge(const uint8_t responseCode, const uint8_t* buf, const size_t size) {
      71           0 :         uint8_t crcBuffer[4];
      72             : 
      73             :         // Command part of CRC
      74           0 :         uint32_t crc = writePacketHeader(responseCode, size);
      75             :         // Data part of CRC
      76           0 :         crc = crc32inc((void*)buf, crc, size);
      77           0 :         *(uint32_t*)crcBuffer = SWAP_UINT32(crc);
      78             : 
      79             :         // If data, write that
      80           0 :         if (size) {
      81           0 :                 write(buf, size, /*isEndOfPacket*/false);
      82             :         }
      83             : 
      84             :         // Lastly the CRC footer
      85           0 :         write(crcBuffer, sizeof(crcBuffer), /*isEndOfPacket*/true);
      86           0 :         flush();
      87           0 : }
      88             : 
      89           2 : TsChannelBase::TsChannelBase(const char *p_name) {
      90           2 :         this->name = p_name;
      91           2 : }
      92             : 
      93           4 : void TsChannelBase::assertPacketSize(size_t size, bool allowLongPackets) {
      94           4 :         if (isBigPacket(size) && !allowLongPackets) {
      95           0 :                 criticalError("[USE PROPER CONSOLE VERSION ] disallowed long packet of size %d", size);
      96             :         }
      97           4 : }
      98             : 
      99             : /**
     100             :  * Adds size to the beginning of a packet and a crc32 at the end. Then send the packet.
     101             :  */
     102           4 : void TsChannelBase::writeCrcPacket(uint8_t responseCode, const uint8_t* buf, size_t size, bool allowLongPackets) {
     103             :         // don't transmit a null buffer...
     104           4 :         if (!buf) {
     105           1 :                 size = 0;
     106             :         }
     107             : 
     108           4 :         assertPacketSize(size, allowLongPackets);
     109             : 
     110           4 :         if (isBigPacket(size)) {
     111             :                 // for larger packets we do not use a buffer for CRC calculation meaning data is now allowed to modify while pending
     112           0 :                 writeCrcPacketLarge(responseCode, buf, size);
     113             :         } else {
     114             :                 // for small packets we use a buffer for CRC calculation
     115           4 :                 copyAndWriteSmallCrcPacket(responseCode, buf, size);
     116             :         }
     117           4 : }
     118             : 
     119           1 : void TsChannelBase::sendResponse(ts_response_format_e mode, const uint8_t * buffer, int size, bool allowLongPackets /* = false */) {
     120           1 :         if (mode == TS_CRC) {
     121           1 :                 writeCrcPacket(TS_RESPONSE_OK, buffer, size, allowLongPackets);
     122             :         } else {
     123           0 :                 if (size > 0) {
     124           0 :                         write(buffer, size, true);
     125           0 :                         flush();
     126             :                 }
     127             :         }
     128           1 : }

Generated by: LCOV version 1.14