Matter SDK Coverage Report
Current view: top level - setup_payload - ManualSetupPayloadGenerator.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 96.6 % 59 57
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /**
       2              :  *
       3              :  *    Copyright (c) 2020 Project CHIP Authors
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : /**
      19              :  *    @file
      20              :  *      This file describes a Manual Entry Code Generator.
      21              :  *
      22              :  */
      23              : 
      24              : #include "ManualSetupPayloadGenerator.h"
      25              : 
      26              : #include <inttypes.h>
      27              : 
      28              : #include <lib/support/logging/CHIPLogging.h>
      29              : #include <lib/support/verhoeff/Verhoeff.h>
      30              : 
      31              : namespace chip {
      32              : 
      33           12 : static uint32_t chunk1PayloadRepresentation(const PayloadContents & payload)
      34              : {
      35              :     /* <1 digit> Represents:
      36              :      *     - <bits 1..0> Discriminator <bits 11.10>
      37              :      *     - <bit 2> VID/PID present flag
      38              :      */
      39              : 
      40           12 :     constexpr int kDiscriminatorShift = (kManualSetupDiscriminatorFieldLengthInBits - kManualSetupChunk1DiscriminatorMsbitsLength);
      41           12 :     constexpr uint32_t kDiscriminatorMask = (1 << kManualSetupChunk1DiscriminatorMsbitsLength) - 1;
      42              : 
      43              :     static_assert(kManualSetupChunk1VidPidPresentBitPos >=
      44              :                       kManualSetupChunk1DiscriminatorMsbitsPos + kManualSetupChunk1DiscriminatorMsbitsLength,
      45              :                   "Discriminator won't fit");
      46              : 
      47           12 :     uint32_t discriminatorChunk = (payload.discriminator.GetShortValue() >> kDiscriminatorShift) & kDiscriminatorMask;
      48           12 :     uint32_t vidPidPresentFlag  = payload.commissioningFlow != CommissioningFlow::kStandard ? 1 : 0;
      49              : 
      50           12 :     uint32_t result = (discriminatorChunk << kManualSetupChunk1DiscriminatorMsbitsPos) |
      51           12 :         (vidPidPresentFlag << kManualSetupChunk1VidPidPresentBitPos);
      52              : 
      53           12 :     return result;
      54              : }
      55              : 
      56           12 : static uint32_t chunk2PayloadRepresentation(const PayloadContents & payload)
      57              : {
      58              :     /* <5 digits> Represents:
      59              :      *     - <bits 13..0> PIN Code <bits 13..0>
      60              :      *     - <bits 15..14> Discriminator <bits 9..8>
      61              :      */
      62              : 
      63           12 :     constexpr uint32_t kDiscriminatorMask = (1 << kManualSetupChunk2DiscriminatorLsbitsLength) - 1;
      64           12 :     constexpr uint32_t kPincodeMask       = (1 << kManualSetupChunk2PINCodeLsbitsLength) - 1;
      65              : 
      66           12 :     uint32_t discriminatorChunk = payload.discriminator.GetShortValue() & kDiscriminatorMask;
      67              : 
      68           12 :     uint32_t result = ((payload.setUpPINCode & kPincodeMask) << kManualSetupChunk2PINCodeLsbitsPos) |
      69           12 :         (discriminatorChunk << kManualSetupChunk2DiscriminatorLsbitsPos);
      70              : 
      71           12 :     return result;
      72              : }
      73              : 
      74           12 : static uint32_t chunk3PayloadRepresentation(const PayloadContents & payload)
      75              : {
      76              :     /* <4 digits> Represents:
      77              :      *     - <bits 12..0> PIN Code <bits 26..14>
      78              :      */
      79              : 
      80           12 :     constexpr int kPincodeShift     = (kSetupPINCodeFieldLengthInBits - kManualSetupChunk3PINCodeMsbitsLength);
      81           12 :     constexpr uint32_t kPincodeMask = (1 << kManualSetupChunk3PINCodeMsbitsLength) - 1;
      82              : 
      83           12 :     uint32_t result = ((payload.setUpPINCode >> kPincodeShift) & kPincodeMask) << kManualSetupChunk3PINCodeMsbitsPos;
      84              : 
      85           12 :     return result;
      86              : }
      87              : 
      88           62 : static CHIP_ERROR decimalStringWithPadding(MutableCharSpan buffer, uint32_t number)
      89              : {
      90           62 :     int len    = static_cast<int>(buffer.size() - 1);
      91           62 :     int retval = snprintf(buffer.data(), buffer.size(), "%0*" PRIu32, len, number);
      92              : 
      93           62 :     return (retval >= static_cast<int>(buffer.size())) ? CHIP_ERROR_BUFFER_TOO_SMALL : CHIP_NO_ERROR;
      94              : }
      95              : 
      96           13 : CHIP_ERROR ManualSetupPayloadGenerator::payloadDecimalStringRepresentation(MutableCharSpan & outBuffer)
      97              : {
      98              :     static_assert(kManualSetupCodeChunk1CharLength + kManualSetupCodeChunk2CharLength + kManualSetupCodeChunk3CharLength ==
      99              :                       kManualSetupShortCodeCharLength,
     100              :                   "Manual code length mismatch (short)");
     101              :     static_assert(kManualSetupShortCodeCharLength + kManualSetupVendorIdCharLength + kManualSetupProductIdCharLength ==
     102              :                       kManualSetupLongCodeCharLength,
     103              :                   "Manual code length mismatch (long)");
     104              :     static_assert(kManualSetupChunk1DiscriminatorMsbitsLength + kManualSetupChunk2DiscriminatorLsbitsLength ==
     105              :                       kManualSetupDiscriminatorFieldLengthInBits,
     106              :                   "Discriminator won't fit");
     107              :     static_assert(kManualSetupChunk2PINCodeLsbitsLength + kManualSetupChunk3PINCodeMsbitsLength == kSetupPINCodeFieldLengthInBits,
     108              :                   "PIN code won't fit");
     109              : 
     110           13 :     if (!mAllowInvalidPayload && !mPayloadContents.isValidManualCode())
     111              :     {
     112            1 :         ChipLogError(SetupPayload, "Failed encoding invalid payload");
     113            1 :         return CHIP_ERROR_INVALID_ARGUMENT;
     114              :     }
     115              : 
     116           12 :     bool useLongCode = (mPayloadContents.commissioningFlow != CommissioningFlow::kStandard) && !mForceShortCode;
     117              : 
     118              :     // Add two for the check digit and null terminator.
     119           24 :     if ((useLongCode && outBuffer.size() < kManualSetupLongCodeCharLength + 2) ||
     120           12 :         (!useLongCode && outBuffer.size() < kManualSetupShortCodeCharLength + 2))
     121              :     {
     122            0 :         ChipLogError(SetupPayload, "Failed encoding payload to buffer");
     123            0 :         return CHIP_ERROR_BUFFER_TOO_SMALL;
     124              :     }
     125              : 
     126           12 :     uint32_t chunk1 = chunk1PayloadRepresentation(mPayloadContents);
     127           12 :     uint32_t chunk2 = chunk2PayloadRepresentation(mPayloadContents);
     128           12 :     uint32_t chunk3 = chunk3PayloadRepresentation(mPayloadContents);
     129              : 
     130           12 :     size_t offset = 0;
     131              : 
     132              :     // Add one to the length of each chunk, since snprintf writes a null terminator.
     133           12 :     ReturnErrorOnFailure(decimalStringWithPadding(outBuffer.SubSpan(offset, kManualSetupCodeChunk1CharLength + 1), chunk1));
     134           12 :     offset += kManualSetupCodeChunk1CharLength;
     135           12 :     ReturnErrorOnFailure(decimalStringWithPadding(outBuffer.SubSpan(offset, kManualSetupCodeChunk2CharLength + 1), chunk2));
     136           12 :     offset += kManualSetupCodeChunk2CharLength;
     137           12 :     ReturnErrorOnFailure(decimalStringWithPadding(outBuffer.SubSpan(offset, kManualSetupCodeChunk3CharLength + 1), chunk3));
     138           12 :     offset += kManualSetupCodeChunk3CharLength;
     139              : 
     140           12 :     if (useLongCode)
     141              :     {
     142            7 :         ReturnErrorOnFailure(
     143              :             decimalStringWithPadding(outBuffer.SubSpan(offset, kManualSetupVendorIdCharLength + 1), mPayloadContents.vendorID));
     144            7 :         offset += kManualSetupVendorIdCharLength;
     145            7 :         ReturnErrorOnFailure(
     146              :             decimalStringWithPadding(outBuffer.SubSpan(offset, kManualSetupProductIdCharLength + 1), mPayloadContents.productID));
     147            7 :         offset += kManualSetupProductIdCharLength;
     148              :     }
     149              : 
     150           12 :     int checkDigit = Verhoeff10::CharToVal(Verhoeff10::ComputeCheckChar(outBuffer.data()));
     151           12 :     ReturnErrorOnFailure(decimalStringWithPadding(outBuffer.SubSpan(offset, 2), static_cast<uint32_t>(checkDigit)));
     152           12 :     offset += 1;
     153              : 
     154              :     // Reduce outBuffer span size to be the size of written data and to not include null-terminator.
     155           12 :     outBuffer.reduce_size(offset);
     156              : 
     157           12 :     return CHIP_NO_ERROR;
     158              : }
     159              : 
     160           13 : CHIP_ERROR ManualSetupPayloadGenerator::payloadDecimalStringRepresentation(std::string & outDecimalString)
     161              : {
     162              :     // One extra char for the check digit, another for the null terminator.
     163           13 :     char decimalString[kManualSetupLongCodeCharLength + 1 + 1] = "";
     164           13 :     MutableCharSpan outBuffer(decimalString);
     165              : 
     166           13 :     ReturnErrorOnFailure(payloadDecimalStringRepresentation(outBuffer));
     167           12 :     outDecimalString.assign(decimalString);
     168              : 
     169           12 :     return CHIP_NO_ERROR;
     170              : }
     171              : 
     172              : } // namespace chip
        

Generated by: LCOV version 2.0-1