LCOV - code coverage report
Current view: top level - firmware/console/binary - tunerstudio_io.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 33 54 61.1 %
Date: 2024-07-27 03:14:29 Functions: 7 9 77.8 %

          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 : }

Generated by: LCOV version 1.14