3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2018 Google LLC.
5 * Copyright (c) 2016-2017 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 * This file defines CHIP interaction model message parsers and encoders
21 * Interaction model profile.
25 // __STDC_FORMAT_MACROS must be defined for PRIX64 to be defined for pre-C++11 clib
26 #ifndef __STDC_FORMAT_MACROS
27 #define __STDC_FORMAT_MACROS
28 #endif // __STDC_FORMAT_MACROS
30 // __STDC_LIMIT_MACROS must be defined for UINT8_MAX and INT32_MAX to be defined for pre-C++11 clib
31 #ifndef __STDC_LIMIT_MACROS
32 #define __STDC_LIMIT_MACROS
33 #endif // __STDC_LIMIT_MACROS
35 // __STDC_CONSTANT_MACROS must be defined for INT64_C and UINT64_C to be defined for pre-C++11 clib
36 #ifndef __STDC_CONSTANT_MACROS
37 #define __STDC_CONSTANT_MACROS
38 #endif // __STDC_CONSTANT_MACROS
40 #include "MessageDef.h"
47 using namespace chip::TLV;
49 #ifndef CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
50 #define CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK 1
51 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
56 #if CHIP_DETAIL_LOGGING
59 // this is used to run in signle thread for IM message debug purpose
60 uint32_t gPrettyPrintingDepthLevel = 0;
61 char gLineBuffer[256];
62 size_t gCurLineBufferSize = 0;
65 class PrettyPrintCheckpoint
68 PrettyPrintCheckpoint() { mLevel = gPrettyPrintingDepthLevel; }
69 ~PrettyPrintCheckpoint() { gPrettyPrintingDepthLevel = mLevel; }
74 #define PRETTY_PRINT_CHECKPOINT() PrettyPrintCheckpoint lPrettyPrintCheckpoint;
76 #define PRETTY_PRINT(fmt, ...) \
79 PrettyPrintIM(true, fmt, ##__VA_ARGS__); \
81 #define PRETTY_PRINT_SAMELINE(fmt, ...) \
84 PrettyPrintIM(false, fmt, ##__VA_ARGS__); \
86 #define PRETTY_PRINT_INCDEPTH() \
89 gPrettyPrintingDepthLevel++; \
91 #define PRETTY_PRINT_DECDEPTH() \
94 gPrettyPrintingDepthLevel--; \
97 static void PrettyPrintIM(bool aIsNewLine, const char * aFmt, ...)
103 va_start(args, aFmt);
107 if (gCurLineBufferSize)
109 // Don't need to explicitly NULL-terminate the string because
110 // snprintf takes care of that.
111 ChipLogDetail(DataManagement, "%s", gLineBuffer);
112 gCurLineBufferSize = 0;
115 for (uint32_t i = 0; i < gPrettyPrintingDepthLevel; i++)
117 if (sizeof(gLineBuffer) > gCurLineBufferSize)
119 sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize;
120 ret = (size_t)(snprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, "\t"));
123 gCurLineBufferSize += std::min(ret, sizeLeft);
129 if (sizeof(gLineBuffer) > gCurLineBufferSize)
131 sizeLeft = sizeof(gLineBuffer) - gCurLineBufferSize;
132 ret = (size_t)(vsnprintf(gLineBuffer + gCurLineBufferSize, sizeLeft, aFmt, args));
135 gCurLineBufferSize += std::min(ret, sizeLeft);
141 #else // CHIP_DETAIL_LOGGING
142 #define PRETTY_PRINT_CHECKPOINT()
143 #define PRETTY_PRINT(fmt, ...)
144 #define PRETTY_PRINT(fmt, ...)
145 #define PRETTY_PRINT_INCDEPTH()
146 #define PRETTY_PRINT_DECDEPTH()
147 #endif // CHIP_DETAIL_LOGGING
149 Parser::Parser() : mOuterContainerType(chip::TLV::kTLVType_NotSpecified) {}
151 void Parser::Init(const chip::TLV::TLVReader & aReader, chip::TLV::TLVType aOuterContainerType)
153 mReader.Init(aReader);
154 mOuterContainerType = aOuterContainerType;
157 CHIP_ERROR Parser::GetReaderOnTag(const uint64_t aTagToFind, chip::TLV::TLVReader * const apReader) const
159 return mReader.FindElementWithTag(aTagToFind, *apReader);
162 template <typename T>
163 CHIP_ERROR Parser::GetUnsignedInteger(const uint8_t aContextTag, T * const apLValue) const
165 return GetSimpleValue(aContextTag, chip::TLV::kTLVType_UnsignedInteger, apLValue);
168 template <typename T>
169 CHIP_ERROR Parser::GetSimpleValue(const uint8_t aContextTag, const chip::TLV::TLVType aTLVType, T * const apLValue) const
171 CHIP_ERROR err = CHIP_NO_ERROR;
172 chip::TLV::TLVReader reader;
176 err = mReader.FindElementWithTag(chip::TLV::ContextTag(aContextTag), reader);
179 VerifyOrExit(aTLVType == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
181 err = reader.Get(*apLValue);
185 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
190 void Parser::GetReader(chip::TLV::TLVReader * const apReader)
192 apReader->Init(mReader);
195 ListParser::ListParser() {}
197 CHIP_ERROR ListParser::Init(const chip::TLV::TLVReader & aReader)
199 CHIP_ERROR err = CHIP_NO_ERROR;
201 // make a copy of the reader here
202 mReader.Init(aReader);
204 VerifyOrExit(chip::TLV::kTLVType_Array == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
206 // This is just a dummy, as we're not going to exit this container ever
207 chip::TLV::TLVType OuterContainerType;
208 err = mReader.EnterContainer(OuterContainerType);
211 ChipLogFunctError(err);
216 CHIP_ERROR ListParser::InitIfPresent(const chip::TLV::TLVReader & aReader, const uint8_t aContextTagToFind)
218 CHIP_ERROR err = CHIP_NO_ERROR;
219 chip::TLV::TLVReader reader;
221 err = mReader.FindElementWithTag(chip::TLV::ContextTag(aContextTagToFind), reader);
228 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
233 CHIP_ERROR ListParser::Next()
235 CHIP_ERROR err = mReader.Next();
237 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
242 Builder::Builder() : mError(CHIP_ERROR_INCORRECT_STATE), mpWriter(NULL), mOuterContainerType(chip::TLV::kTLVType_NotSpecified) {}
244 void Builder::Init(chip::TLV::TLVWriter * const apWriter, chip::TLV::TLVType aOuterContainerType)
247 mOuterContainerType = aOuterContainerType;
250 void Builder::ResetError()
252 ResetError(CHIP_NO_ERROR);
255 void Builder::ResetError(CHIP_ERROR aErr)
258 mOuterContainerType = chip::TLV::kTLVType_NotSpecified;
261 void Builder::EndOfContainer()
263 // skip if error has already been set
264 SuccessOrExit(mError);
266 mError = mpWriter->EndContainer(mOuterContainerType);
267 SuccessOrExit(mError);
269 // we've just closed properly
270 // mark it so we do not panic when the build object destructor is called
271 mOuterContainerType = chip::TLV::kTLVType_NotSpecified;
276 CHIP_ERROR Builder::InitAnonymousStructure(chip::TLV::TLVWriter * const apWriter)
279 mOuterContainerType = chip::TLV::kTLVType_NotSpecified;
280 mError = mpWriter->StartContainer(chip::TLV::AnonymousTag, chip::TLV::kTLVType_Structure, mOuterContainerType);
281 ChipLogFunctError(mError);
286 ListBuilder::ListBuilder() {}
288 CHIP_ERROR ListBuilder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
291 mError = mpWriter->StartContainer(chip::TLV::ContextTag(aContextTagToUse), chip::TLV::kTLVType_Array, mOuterContainerType);
292 ChipLogFunctError(mError);
297 CHIP_ERROR ListBuilder::Init(chip::TLV::TLVWriter * const apWriter)
300 mError = mpWriter->StartContainer(chip::TLV::AnonymousTag, chip::TLV::kTLVType_Array, mOuterContainerType);
301 ChipLogFunctError(mError);
306 CHIP_ERROR AttributePath::Parser::Init(const chip::TLV::TLVReader & aReader)
308 CHIP_ERROR err = CHIP_NO_ERROR;
310 // make a copy of the reader here
311 mReader.Init(aReader);
313 VerifyOrExit(chip::TLV::kTLVType_Path == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
315 // This is just a dummy, as we're not going to exit this container ever
316 chip::TLV::TLVType dummyContainerType;
317 // enter into the Path
318 err = mReader.EnterContainer(dummyContainerType);
322 ChipLogFunctError(err);
327 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
328 CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const
330 CHIP_ERROR err = CHIP_NO_ERROR;
331 uint16_t TagPresenceMask = 0;
332 chip::TLV::TLVReader reader;
334 PRETTY_PRINT("AttributePath =");
337 // make a copy of the Path reader
338 reader.Init(mReader);
340 while (CHIP_NO_ERROR == (err = reader.Next()))
342 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
343 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
346 // check if this tag has appeared before
347 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NodeId)), err = CHIP_ERROR_INVALID_TLV_TAG);
348 TagPresenceMask |= (1 << kCsTag_NodeId);
349 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
351 #if CHIP_DETAIL_LOGGING
355 PRETTY_PRINT("\tNodeId = 0x%" PRIx64 ",", nodeId);
357 #endif // CHIP_DETAIL_LOGGING
359 case kCsTag_EndpointId:
360 // check if this tag has appeared before
361 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EndpointId)), err = CHIP_ERROR_INVALID_TLV_TAG);
362 TagPresenceMask |= (1 << kCsTag_EndpointId);
363 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
364 #if CHIP_DETAIL_LOGGING
367 reader.Get(endpointId);
368 PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId);
370 #endif // CHIP_DETAIL_LOGGING
372 case kCsTag_NamespacedClusterId:
373 // check if this tag has appeared before
374 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NamespacedClusterId)), err = CHIP_ERROR_INVALID_TLV_TAG);
375 TagPresenceMask |= (1 << kCsTag_NamespacedClusterId);
376 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
378 #if CHIP_DETAIL_LOGGING
379 if (chip::TLV::kTLVType_UnsignedInteger == reader.GetType())
381 chip::ClusterId namespacedClusterId;
382 reader.Get(namespacedClusterId);
383 PRETTY_PRINT("\tNamespacedClusterId = 0x%" PRIx32 ",", namespacedClusterId);
385 #endif // CHIP_DETAIL_LOGGING
388 // check if this tag has appeared before
389 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_FieldId)), err = CHIP_ERROR_INVALID_TLV_TAG);
390 TagPresenceMask |= (1 << kCsTag_FieldId);
391 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
392 #if CHIP_DETAIL_LOGGING
395 reader.Get(fieldTag);
396 PRETTY_PRINT("\tFieldTag = 0x%" PRIx8 ",", fieldTag);
398 #endif // CHIP_DETAIL_LOGGING
400 case kCsTag_ListIndex:
401 // check if this tag has appeared before
402 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ListIndex)), err = CHIP_ERROR_INVALID_TLV_TAG);
403 TagPresenceMask |= (1 << kCsTag_ListIndex);
404 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
405 #if CHIP_DETAIL_LOGGING
406 if (chip::TLV::kTLVType_UnsignedInteger == reader.GetType())
409 reader.Get(listIndex);
410 PRETTY_PRINT("\tListIndex = 0x%" PRIx16 ",", listIndex);
412 #endif // CHIP_DETAIL_LOGGING
415 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
421 // if we have exhausted this container
422 if (CHIP_END_OF_TLV == err)
424 // check for required fields:
425 const uint16_t RequiredFields = (1 << kCsTag_EndpointId) | (1 << kCsTag_NamespacedClusterId);
427 if ((TagPresenceMask & RequiredFields) == RequiredFields)
433 err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH;
439 ChipLogFunctError(err);
443 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
445 CHIP_ERROR AttributePath::Parser::GetNodeId(chip::NodeId * const apNodeId) const
447 return GetUnsignedInteger(kCsTag_NodeId, apNodeId);
450 CHIP_ERROR AttributePath::Parser::GetEndpointId(chip::EndpointId * const apEndpointId) const
452 return GetUnsignedInteger(kCsTag_EndpointId, apEndpointId);
455 CHIP_ERROR AttributePath::Parser::GetNamespacedClusterId(chip::ClusterId * const apClusterId) const
457 return GetUnsignedInteger(kCsTag_NamespacedClusterId, apClusterId);
460 CHIP_ERROR AttributePath::Parser::GetFieldId(uint8_t * const apFieldId) const
462 return GetUnsignedInteger(kCsTag_FieldId, apFieldId);
465 CHIP_ERROR AttributePath::Parser::GetListIndex(uint16_t * const apListIndex) const
467 return GetUnsignedInteger(kCsTag_ListIndex, apListIndex);
470 CHIP_ERROR AttributePath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const uint64_t aTag)
473 mError = mpWriter->StartContainer(aTag, chip::TLV::kTLVType_Path, mOuterContainerType);
474 SuccessOrExit(mError);
477 ChipLogFunctError(mError);
481 CHIP_ERROR AttributePath::Builder::Init(chip::TLV::TLVWriter * const apWriter)
483 return _Init(apWriter, chip::TLV::AnonymousTag);
486 CHIP_ERROR AttributePath::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
488 return _Init(apWriter, chip::TLV::ContextTag(aContextTagToUse));
491 AttributePath::Builder & AttributePath::Builder::NodeId(const uint64_t aNodeId)
493 // skip if error has already been set
494 SuccessOrExit(mError);
496 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NodeId), aNodeId);
497 ChipLogFunctError(mError);
504 AttributePath::Builder & AttributePath::Builder::EndpointId(const chip::EndpointId aEndpointId)
506 // skip if error has already been set
507 SuccessOrExit(mError);
509 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EndpointId), aEndpointId);
510 ChipLogFunctError(mError);
516 AttributePath::Builder & AttributePath::Builder::NamespacedClusterId(const chip::ClusterId aClusterId)
518 // skip if error has already been set
519 SuccessOrExit(mError);
521 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NamespacedClusterId), aClusterId);
522 ChipLogFunctError(mError);
528 AttributePath::Builder & AttributePath::Builder::FieldId(const uint8_t aFieldId)
530 // skip if error has already been set
531 SuccessOrExit(mError);
533 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_FieldId), aFieldId);
534 ChipLogFunctError(mError);
540 AttributePath::Builder & AttributePath::Builder::ListIndex(const uint16_t aListIndex)
542 // skip if error has already been set
543 SuccessOrExit(mError);
545 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ListIndex), aListIndex);
546 ChipLogFunctError(mError);
552 AttributePath::Builder & AttributePath::Builder::EndOfAttributePath()
558 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
559 CHIP_ERROR AttributePathList::Parser::CheckSchemaValidity() const
561 CHIP_ERROR err = CHIP_NO_ERROR;
563 chip::TLV::TLVReader reader;
565 PRETTY_PRINT("AttributePathList =");
568 // make a copy of the AttributePathList reader
569 reader.Init(mReader);
571 while (CHIP_NO_ERROR == (err = reader.Next()))
573 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
574 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
576 AttributePath::Parser path;
577 err = path.Init(reader);
580 PRETTY_PRINT_INCDEPTH();
581 err = path.CheckSchemaValidity();
583 PRETTY_PRINT_DECDEPTH();
591 // if we have exhausted this container
592 if (CHIP_END_OF_TLV == err)
598 ChipLogFunctError(err);
602 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
604 // Re-initialize the shared PathBuilder with anonymous tag
605 AttributePath::Builder & AttributePathList::Builder::CreateAttributePathBuilder()
607 // skip if error has already been set
608 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributePathBuilder.ResetError(mError));
610 mError = mAttributePathBuilder.Init(mpWriter);
611 ChipLogFunctError(mError);
614 // on error, mAttributePathBuilder would be un-/partial initialized and cannot be used to write anything
615 return mAttributePathBuilder;
618 // Mark the end of this array and recover the type for outer container
619 AttributePathList::Builder & AttributePathList::Builder::EndOfAttributePathList()
626 CHIP_ERROR EventPath::Parser::Init(const chip::TLV::TLVReader & aReader)
628 CHIP_ERROR err = CHIP_NO_ERROR;
630 // make a copy of the reader here
631 mReader.Init(aReader);
633 VerifyOrExit(chip::TLV::kTLVType_Path == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
635 // This is just a dummy, as we're not going to exit this container ever
636 chip::TLV::TLVType dummyContainerType;
637 // enter into the Path
638 err = mReader.EnterContainer(dummyContainerType);
642 ChipLogFunctError(err);
647 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
648 CHIP_ERROR EventPath::Parser::CheckSchemaValidity() const
650 CHIP_ERROR err = CHIP_NO_ERROR;
651 uint16_t TagPresenceMask = 0;
652 chip::TLV::TLVReader reader;
654 PRETTY_PRINT("EventPath =");
657 // make a copy of the Path reader
658 reader.Init(mReader);
660 while (CHIP_NO_ERROR == (err = reader.Next()))
662 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
663 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
666 // check if this tag has appeared before
667 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NodeId)), err = CHIP_ERROR_INVALID_TLV_TAG);
668 TagPresenceMask |= (1 << kCsTag_NodeId);
669 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
670 #if CHIP_DETAIL_LOGGING
674 PRETTY_PRINT("\tNodeId = 0x%" PRIx64 ",", nodeId);
676 #endif // CHIP_DETAIL_LOGGING
678 case kCsTag_EndpointId:
679 // check if this tag has appeared before
680 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EndpointId)), err = CHIP_ERROR_INVALID_TLV_TAG);
681 TagPresenceMask |= (1 << kCsTag_EndpointId);
682 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
683 #if CHIP_DETAIL_LOGGING
686 reader.Get(endpointId);
687 PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId);
689 #endif // CHIP_DETAIL_LOGGING
691 case kCsTag_NamespacedClusterId:
692 // check if this tag has appeared before
693 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NamespacedClusterId)), err = CHIP_ERROR_INVALID_TLV_TAG);
694 TagPresenceMask |= (1 << kCsTag_NamespacedClusterId);
695 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
697 #if CHIP_DETAIL_LOGGING
699 chip::ClusterId namespacedClusterId;
700 reader.Get(namespacedClusterId);
701 PRETTY_PRINT("\tNamespacedClusterId = 0x%" PRIx32 ",", namespacedClusterId);
703 #endif // CHIP_DETAIL_LOGGING
705 case chip::app::EventPath::kCsTag_EventId:
706 // check if this tag has appeared before
707 VerifyOrExit(!(TagPresenceMask & (1 << chip::app::EventPath::kCsTag_EventId)), err = CHIP_ERROR_INVALID_TLV_TAG);
708 TagPresenceMask |= (1 << chip::app::EventPath::kCsTag_EventId);
709 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
711 #if CHIP_DETAIL_LOGGING
713 chip::EventId eventId;
715 PRETTY_PRINT("\tEventId = 0x%" PRIx16 ",", eventId);
717 #endif // CHIP_DETAIL_LOGGING
720 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
727 // if we have exhausted this container
728 if (CHIP_END_OF_TLV == err)
730 // check for required fields:
731 const uint16_t RequiredFields = (1 << kCsTag_EndpointId) | (1 << kCsTag_NamespacedClusterId);
733 if ((TagPresenceMask & RequiredFields) == RequiredFields)
739 err = CHIP_ERROR_IM_MALFORMED_EVENT_PATH;
745 ChipLogFunctError(err);
749 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
751 CHIP_ERROR EventPath::Parser::GetNodeId(chip::NodeId * const apNodeId) const
753 return GetUnsignedInteger(kCsTag_NodeId, apNodeId);
756 CHIP_ERROR EventPath::Parser::GetEndpointId(chip::EndpointId * const apEndpointID) const
758 return GetUnsignedInteger(kCsTag_EndpointId, apEndpointID);
761 CHIP_ERROR EventPath::Parser::GetNamespacedClusterId(chip::ClusterId * const apClusterId) const
763 return GetUnsignedInteger(kCsTag_NamespacedClusterId, apClusterId);
766 CHIP_ERROR EventPath::Parser::GetEventId(chip::EventId * const apEventId) const
768 return GetUnsignedInteger(kCsTag_EventId, apEventId);
771 CHIP_ERROR EventPath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const uint64_t aTag)
774 mError = mpWriter->StartContainer(aTag, chip::TLV::kTLVType_Path, mOuterContainerType);
775 SuccessOrExit(mError);
778 ChipLogFunctError(mError);
782 CHIP_ERROR EventPath::Builder::Init(chip::TLV::TLVWriter * const apWriter)
784 return _Init(apWriter, chip::TLV::AnonymousTag);
787 CHIP_ERROR EventPath::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
789 return _Init(apWriter, chip::TLV::ContextTag(aContextTagToUse));
792 EventPath::Builder & EventPath::Builder::NodeId(const uint64_t aNodeId)
794 // skip if error has already been set
795 SuccessOrExit(mError);
797 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NodeId), aNodeId);
798 ChipLogFunctError(mError);
804 EventPath::Builder & EventPath::Builder::EndpointId(const chip::EndpointId aEndpointId)
806 // skip if error has already been set
807 SuccessOrExit(mError);
809 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EndpointId), aEndpointId);
810 ChipLogFunctError(mError);
816 EventPath::Builder & EventPath::Builder::NamespacedClusterId(const chip::ClusterId aClusterId)
818 // skip if error has already been set
819 SuccessOrExit(mError);
821 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NamespacedClusterId), aClusterId);
822 ChipLogFunctError(mError);
828 EventPath::Builder & EventPath::Builder::EventId(const chip::EventId aEventId)
830 // skip if error has already been set
831 SuccessOrExit(mError);
833 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EventId), aEventId);
834 ChipLogFunctError(mError);
840 EventPath::Builder & EventPath::Builder::EndOfEventPath()
846 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
847 CHIP_ERROR EventPathList::Parser::CheckSchemaValidity() const
849 CHIP_ERROR err = CHIP_NO_ERROR;
851 chip::TLV::TLVReader reader;
853 PRETTY_PRINT("EventPathList =");
856 // make a copy of the EventPathList reader
857 reader.Init(mReader);
859 while (CHIP_NO_ERROR == (err = reader.Next()))
861 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
862 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
865 EventPath::Parser path;
866 err = path.Init(reader);
869 PRETTY_PRINT_INCDEPTH();
870 err = path.CheckSchemaValidity();
872 PRETTY_PRINT_DECDEPTH();
881 // if we have exhausted this container
882 if (CHIP_END_OF_TLV == err)
888 ChipLogFunctError(err);
892 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
894 EventPath::Builder & EventPathList::Builder::CreateEventPathBuilder()
896 // skip if error has already been set
897 VerifyOrExit(CHIP_NO_ERROR == mError, mEventPathBuilder.ResetError(mError));
899 mError = mEventPathBuilder.Init(mpWriter);
900 ChipLogFunctError(mError);
903 // on error, mPathBuilder would be un-/partial initialized and cannot be used to write anything
904 return mEventPathBuilder;
907 EventPathList::Builder & EventPathList::Builder::EndOfEventPathList()
914 CHIP_ERROR CommandPath::Parser::Init(const chip::TLV::TLVReader & aReader)
916 CHIP_ERROR err = CHIP_NO_ERROR;
918 // make a copy of the reader here
919 mReader.Init(aReader);
921 VerifyOrExit(chip::TLV::kTLVType_Path == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
923 // This is just a dummy, as we're not going to exit this container ever
924 chip::TLV::TLVType dummyContainerType;
925 // enter into the Path
926 err = mReader.EnterContainer(dummyContainerType);
930 ChipLogFunctError(err);
935 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
936 CHIP_ERROR CommandPath::Parser::CheckSchemaValidity() const
938 CHIP_ERROR err = CHIP_NO_ERROR;
939 uint16_t TagPresenceMask = 0;
940 chip::TLV::TLVReader reader;
941 PRETTY_PRINT("CommandPath =");
944 // make a copy of the Path reader
945 reader.Init(mReader);
947 while (CHIP_NO_ERROR == (err = reader.Next()))
949 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
950 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
952 case kCsTag_EndpointId:
953 // check if this tag has appeared before
954 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EndpointId)), err = CHIP_ERROR_INVALID_TLV_TAG);
955 TagPresenceMask |= (1 << kCsTag_EndpointId);
956 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
958 #if CHIP_DETAIL_LOGGING
961 reader.Get(endpointId);
962 PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId);
964 #endif // CHIP_DETAIL_LOGGING
967 // check if this tag has appeared before
968 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_GroupId)), err = CHIP_ERROR_INVALID_TLV_TAG);
969 TagPresenceMask |= (1 << kCsTag_GroupId);
970 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
971 #if CHIP_DETAIL_LOGGING
975 PRETTY_PRINT("\tGroupId = 0x%" PRIx64 ",", groupId);
977 #endif // CHIP_DETAIL_LOGGING
979 case kCsTag_NamespacedClusterId:
980 // check if this tag has appeared before
981 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NamespacedClusterId)), err = CHIP_ERROR_INVALID_TLV_TAG);
982 TagPresenceMask |= (1 << kCsTag_NamespacedClusterId);
983 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
984 #if CHIP_DETAIL_LOGGING
986 chip::ClusterId namespacedClusterId;
987 reader.Get(namespacedClusterId);
988 PRETTY_PRINT("\tNamespacedClusterId = 0x%" PRIx32 ",", namespacedClusterId);
990 #endif // CHIP_DETAIL_LOGGING
992 case kCsTag_CommandId:
993 // check if this tag has appeared before
994 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_CommandId)), err = CHIP_ERROR_INVALID_TLV_TAG);
995 TagPresenceMask |= (1 << kCsTag_CommandId);
996 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
997 #if CHIP_DETAIL_LOGGING
999 chip::CommandId commandId;
1000 reader.Get(commandId);
1001 PRETTY_PRINT("\tCommandId = 0x%" PRIx16 ",", commandId);
1003 #endif // CHIP_DETAIL_LOGGING
1006 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
1011 // if we have exhausted this container
1012 if (CHIP_END_OF_TLV == err)
1014 // check for required fields:
1015 const uint16_t RequiredFields = (1 << kCsTag_CommandId) | (1 << kCsTag_NamespacedClusterId);
1017 if ((TagPresenceMask & RequiredFields) == RequiredFields)
1019 err = CHIP_NO_ERROR;
1023 err = CHIP_ERROR_IM_MALFORMED_COMMAND_PATH;
1028 ChipLogFunctError(err);
1032 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1034 CHIP_ERROR CommandPath::Parser::GetEndpointId(chip::EndpointId * const apEndpointID) const
1036 return GetUnsignedInteger(kCsTag_EndpointId, apEndpointID);
1039 CHIP_ERROR CommandPath::Parser::GetGroupId(chip::GroupId * const apGroupId) const
1041 return GetUnsignedInteger(kCsTag_GroupId, apGroupId);
1044 CHIP_ERROR CommandPath::Parser::GetNamespacedClusterId(chip::ClusterId * const apClusterId) const
1046 return GetUnsignedInteger(kCsTag_NamespacedClusterId, apClusterId);
1049 CHIP_ERROR CommandPath::Parser::GetCommandId(chip::CommandId * const apCommandId) const
1051 return GetUnsignedInteger(kCsTag_CommandId, apCommandId);
1054 CHIP_ERROR CommandPath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const uint64_t aTag)
1056 mpWriter = apWriter;
1057 mError = mpWriter->StartContainer(aTag, chip::TLV::kTLVType_Path, mOuterContainerType);
1058 SuccessOrExit(mError);
1061 ChipLogFunctError(mError);
1065 CHIP_ERROR CommandPath::Builder::Init(chip::TLV::TLVWriter * const apWriter)
1067 return _Init(apWriter, chip::TLV::AnonymousTag);
1070 CHIP_ERROR CommandPath::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
1072 return _Init(apWriter, chip::TLV::ContextTag(aContextTagToUse));
1075 CommandPath::Builder & CommandPath::Builder::EndpointId(const chip::EndpointId aEndpointId)
1077 // skip if error has already been set
1078 SuccessOrExit(mError);
1080 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EndpointId), aEndpointId);
1081 ChipLogFunctError(mError);
1087 CommandPath::Builder & CommandPath::Builder::GroupId(const chip::GroupId aGroupId)
1089 // skip if error has already been set
1090 SuccessOrExit(mError);
1092 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_GroupId), aGroupId);
1093 ChipLogFunctError(mError);
1099 CommandPath::Builder & CommandPath::Builder::NamespacedClusterId(const chip::ClusterId aClusterId)
1101 // skip if error has already been set
1102 SuccessOrExit(mError);
1104 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NamespacedClusterId), aClusterId);
1105 ChipLogFunctError(mError);
1111 CommandPath::Builder & CommandPath::Builder::CommandId(const chip::CommandId aCommandId)
1113 // skip if error has already been set
1114 SuccessOrExit(mError);
1116 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_CommandId), aCommandId);
1117 ChipLogFunctError(mError);
1123 CommandPath::Builder & CommandPath::Builder::EndOfCommandPath()
1129 CHIP_ERROR EventDataElement::Parser::Init(const chip::TLV::TLVReader & aReader)
1131 CHIP_ERROR err = CHIP_NO_ERROR;
1133 // make a copy of the reader here
1134 mReader.Init(aReader);
1136 VerifyOrExit(chip::TLV::kTLVType_Structure == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1138 // This is just a dummy, as we're not going to exit this container ever
1139 chip::TLV::TLVType OuterContainerType;
1140 err = mReader.EnterContainer(OuterContainerType);
1143 ChipLogFunctError(err);
1149 EventDataElement::Parser::ParseData(chip::TLV::TLVReader & aReader, int aDepth) const
1151 CHIP_ERROR err = CHIP_NO_ERROR;
1155 PRETTY_PRINT("EventData = ");
1159 if (chip::TLV::IsContextTag(aReader.GetTag()))
1161 PRETTY_PRINT("0x%" PRIx32 " = ", chip::TLV::TagNumFromTag(aReader.GetTag()));
1163 else if (chip::TLV::IsProfileTag(aReader.GetTag()))
1165 PRETTY_PRINT("0x%" PRIx32 "::0x%" PRIx32 " = ", chip::TLV::ProfileIdFromTag(aReader.GetTag()),
1166 chip::TLV::TagNumFromTag(aReader.GetTag()));
1170 // Anonymous tag, don't print anything
1174 switch (aReader.GetType())
1176 case chip::TLV::kTLVType_Structure:
1180 case chip::TLV::kTLVType_Array:
1181 PRETTY_PRINT_SAMELINE("[");
1182 PRETTY_PRINT("\t\t");
1185 case chip::TLV::kTLVType_SignedInteger: {
1188 err = aReader.Get(value_s64);
1191 PRETTY_PRINT_SAMELINE("%" PRId64 ", ", value_s64);
1195 case chip::TLV::kTLVType_UnsignedInteger: {
1198 err = aReader.Get(value_u64);
1201 PRETTY_PRINT_SAMELINE("%" PRIu64 ", ", value_u64);
1205 case chip::TLV::kTLVType_Boolean: {
1208 err = aReader.Get(value_b);
1211 PRETTY_PRINT_SAMELINE("%s, ", value_b ? "true" : "false");
1215 case chip::TLV::kTLVType_UTF8String: {
1218 err = aReader.GetString(value_s, sizeof(value_s));
1219 VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, );
1221 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
1223 PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
1224 err = CHIP_NO_ERROR;
1228 PRETTY_PRINT_SAMELINE("\"%s\", ", value_s);
1233 case chip::TLV::kTLVType_ByteString: {
1234 uint8_t value_b[256];
1235 uint32_t len, readerLen;
1237 readerLen = aReader.GetLength();
1239 err = aReader.GetBytes(value_b, sizeof(value_b));
1240 VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, );
1242 PRETTY_PRINT_SAMELINE("[");
1243 PRETTY_PRINT("\t\t");
1245 if (readerLen < sizeof(value_b))
1251 len = sizeof(value_b);
1254 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
1256 PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
1260 for (size_t i = 0; i < len; i++)
1262 PRETTY_PRINT_SAMELINE("0x%" PRIx8 ", ", value_b[i]);
1266 err = CHIP_NO_ERROR;
1267 PRETTY_PRINT("\t\t]");
1271 case chip::TLV::kTLVType_Null:
1272 PRETTY_PRINT_SAMELINE("NULL");
1276 PRETTY_PRINT_SAMELINE("--");
1280 if (aReader.GetType() == chip::TLV::kTLVType_Structure || aReader.GetType() == chip::TLV::kTLVType_Array)
1282 const char terminating_char = (aReader.GetType() == chip::TLV::kTLVType_Structure) ? '}' : ']';
1283 chip::TLV::TLVType type;
1285 IgnoreUnusedVariable(terminating_char);
1287 err = aReader.EnterContainer(type);
1290 while ((err = aReader.Next()) == CHIP_NO_ERROR)
1292 PRETTY_PRINT_INCDEPTH();
1294 err = ParseData(aReader, aDepth + 1);
1297 PRETTY_PRINT_DECDEPTH();
1300 PRETTY_PRINT("%c,", terminating_char);
1302 err = aReader.ExitContainer(type);
1307 ChipLogFunctError(err);
1311 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1312 CHIP_ERROR EventDataElement::Parser::CheckSchemaValidity() const
1314 CHIP_ERROR err = CHIP_NO_ERROR;
1315 uint16_t TagPresenceMask = 0;
1316 chip::TLV::TLVReader reader;
1318 PRETTY_PRINT("EventDataElement =");
1321 // make a copy of the Path reader
1322 reader.Init(mReader);
1324 while (CHIP_NO_ERROR == (err = reader.Next()))
1326 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
1327 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
1329 case kCsTag_EventPath:
1330 // check if this tag has appeared before
1331 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EventPath)), err = CHIP_ERROR_INVALID_TLV_TAG);
1332 TagPresenceMask |= (1 << kCsTag_EventPath);
1334 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1336 #if CHIP_DETAIL_LOGGING
1338 EventPath::Parser path;
1339 err = path.Init(reader);
1342 PRETTY_PRINT_INCDEPTH();
1343 err = path.CheckSchemaValidity();
1345 PRETTY_PRINT_DECDEPTH();
1347 #endif // CHIP_DETAIL_LOGGING
1349 case kCsTag_ImportanceLevel:
1350 // check if this tag has appeared before
1351 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ImportanceLevel)), err = CHIP_ERROR_INVALID_TLV_TAG);
1352 TagPresenceMask |= (1 << kCsTag_ImportanceLevel);
1353 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1355 #if CHIP_DETAIL_LOGGING
1358 err = reader.Get(value);
1361 PRETTY_PRINT("\tImportanceLevel = 0x%" PRIx64 ",", value);
1363 #endif // CHIP_DETAIL_LOGGING
1366 // check if this tag has appeared before
1367 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_Number)), err = CHIP_ERROR_INVALID_TLV_TAG);
1368 TagPresenceMask |= (1 << kCsTag_Number);
1370 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1372 #if CHIP_DETAIL_LOGGING
1375 err = reader.Get(value);
1378 PRETTY_PRINT("\tNumber = 0x%" PRIx64 ",", value);
1380 #endif // CHIP_DETAIL_LOGGING
1382 case kCsTag_UTCTimestamp:
1383 // check if this tag has appeared before
1384 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_UTCTimestamp)), err = CHIP_ERROR_INVALID_TLV_TAG);
1385 TagPresenceMask |= (1 << kCsTag_UTCTimestamp);
1387 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1389 #if CHIP_DETAIL_LOGGING
1392 err = reader.Get(value);
1395 PRETTY_PRINT("\tUTCTimestamp = 0x%" PRIx64 ",", value);
1397 #endif // CHIP_DETAIL_LOGGING
1400 case kCsTag_SystemTimestamp:
1401 // check if this tag has appeared before
1402 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_SystemTimestamp)), err = CHIP_ERROR_INVALID_TLV_TAG);
1403 TagPresenceMask |= (1 << kCsTag_SystemTimestamp);
1405 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1407 #if CHIP_DETAIL_LOGGING
1410 err = reader.Get(value);
1413 PRETTY_PRINT("\tSystemTimestamp = 0x%" PRIx64 ",", value);
1415 #endif // CHIP_DETAIL_LOGGING
1417 case kCsTag_DeltaUTCTimestamp:
1418 // check if this tag has appeared before
1419 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_DeltaUTCTimestamp)), err = CHIP_ERROR_INVALID_TLV_TAG);
1420 TagPresenceMask |= (1 << kCsTag_DeltaUTCTimestamp);
1422 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1424 #if CHIP_DETAIL_LOGGING
1427 err = reader.Get(value);
1430 PRETTY_PRINT("\tDeltaUTCTimestamp= 0x%" PRIx64 ",", value);
1432 #endif // CHIP_DETAIL_LOGGING
1434 case kCsTag_DeltaSystemTimestamp:
1435 // check if this tag has appeared before
1436 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_DeltaSystemTimestamp)), err = CHIP_ERROR_INVALID_TLV_TAG);
1437 TagPresenceMask |= (1 << kCsTag_DeltaSystemTimestamp);
1439 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1441 #if CHIP_DETAIL_LOGGING
1444 err = reader.Get(value);
1447 PRETTY_PRINT("\tDeltaSystemTimestamp= 0x%" PRIx64 ",", value);
1449 #endif // CHIP_DETAIL_LOGGING
1452 // check if this tag has appeared before
1453 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_Data)), err = CHIP_ERROR_INVALID_TLV_TAG);
1454 TagPresenceMask |= (1 << kCsTag_Data);
1456 PRETTY_PRINT_INCDEPTH();
1457 err = ParseData(reader, 0);
1459 PRETTY_PRINT_DECDEPTH();
1462 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
1467 // if we have exhausted this container
1468 if (CHIP_END_OF_TLV == err)
1470 // check for required fields:
1471 const uint16_t RequiredFields =
1472 (1 << kCsTag_EventPath) | (1 << kCsTag_ImportanceLevel) | (1 << kCsTag_Number) | (1 << kCsTag_Data);
1474 if ((TagPresenceMask & RequiredFields) == RequiredFields)
1476 err = CHIP_NO_ERROR;
1480 err = CHIP_ERROR_IM_MALFORMED_EVENT_DATA_ELEMENT;
1486 ChipLogFunctError(err);
1490 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1492 CHIP_ERROR EventDataElement::Parser::GetEventPath(EventPath::Parser * const apEventPath)
1494 CHIP_ERROR err = CHIP_NO_ERROR;
1495 chip::TLV::TLVReader reader;
1497 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_EventPath), reader);
1500 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1502 err = apEventPath->Init(reader);
1506 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
1511 CHIP_ERROR EventDataElement::Parser::GetImportanceLevel(uint8_t * const apImportanceLevel)
1513 return GetUnsignedInteger(kCsTag_ImportanceLevel, apImportanceLevel);
1516 CHIP_ERROR EventDataElement::Parser::GetNumber(uint64_t * const apNumber)
1518 return GetUnsignedInteger(kCsTag_Number, apNumber);
1521 CHIP_ERROR EventDataElement::Parser::GetUTCTimestamp(uint64_t * const apUTCTimestamp)
1523 return GetUnsignedInteger(kCsTag_UTCTimestamp, apUTCTimestamp);
1526 CHIP_ERROR EventDataElement::Parser::GetSystemTimestamp(uint64_t * const apSystemTimestamp)
1528 return GetUnsignedInteger(kCsTag_SystemTimestamp, apSystemTimestamp);
1531 CHIP_ERROR EventDataElement::Parser::GetDeltaUTCTime(uint64_t * const apDeltaUTCTimestamp)
1533 return GetUnsignedInteger(kCsTag_DeltaUTCTimestamp, apDeltaUTCTimestamp);
1536 CHIP_ERROR EventDataElement::Parser::GetDeltaSystemTime(uint64_t * const apDeltaSystemTimestamp)
1538 return GetUnsignedInteger(kCsTag_DeltaSystemTimestamp, apDeltaSystemTimestamp);
1541 CHIP_ERROR EventDataElement::Parser::GetData(chip::TLV::TLVReader * const apReader) const
1543 CHIP_ERROR err = CHIP_NO_ERROR;
1545 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_Data), *apReader);
1546 ChipLogFunctError(err);
1551 CHIP_ERROR EventDataElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
1553 return InitAnonymousStructure(apWriter);
1556 EventPath::Builder & EventDataElement::Builder::CreateEventPathBuilder()
1558 // skip if error has already been set
1559 VerifyOrExit(CHIP_NO_ERROR == mError, mEventPathBuilder.ResetError(mError));
1561 mError = mEventPathBuilder.Init(mpWriter, kCsTag_EventPath);
1562 ChipLogFunctError(mError);
1565 return mEventPathBuilder;
1568 EventDataElement::Builder EventDataElement::Builder::ImportanceLevel(const uint8_t aImportanceLevel)
1570 // skip if error has already been set
1571 SuccessOrExit(mError);
1573 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ImportanceLevel), aImportanceLevel);
1574 ChipLogFunctError(mError);
1580 EventDataElement::Builder EventDataElement::Builder::Number(const uint64_t aNumber)
1582 // skip if error has already been set
1583 SuccessOrExit(mError);
1585 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_Number), aNumber);
1586 ChipLogFunctError(mError);
1592 EventDataElement::Builder EventDataElement::Builder::UTCTimestamp(const uint64_t aUTCTimestamp)
1594 // skip if error has already been set
1595 SuccessOrExit(mError);
1597 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_UTCTimestamp), aUTCTimestamp);
1598 ChipLogFunctError(mError);
1604 EventDataElement::Builder EventDataElement::Builder::SystemTimestamp(const uint64_t aSystemTimestamp)
1606 // skip if error has already been set
1607 SuccessOrExit(mError);
1609 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_SystemTimestamp), aSystemTimestamp);
1610 ChipLogFunctError(mError);
1616 EventDataElement::Builder EventDataElement::Builder::DeltaUTCTime(const uint64_t aDeltaUTCTimestamp)
1618 // skip if error has already been set
1619 SuccessOrExit(mError);
1621 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_DeltaUTCTimestamp), aDeltaUTCTimestamp);
1622 ChipLogFunctError(mError);
1628 EventDataElement::Builder EventDataElement::Builder::DeltaSystemTime(const uint64_t aDeltaSystemTimestamp)
1630 // skip if error has already been set
1631 SuccessOrExit(mError);
1633 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_DeltaSystemTimestamp), aDeltaSystemTimestamp);
1634 ChipLogFunctError(mError);
1640 // Mark the end of this element and recover the type for outer container
1641 EventDataElement::Builder & EventDataElement::Builder::EndOfEventDataElement()
1647 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1648 CHIP_ERROR EventList::Parser::CheckSchemaValidity() const
1650 CHIP_ERROR err = CHIP_NO_ERROR;
1651 size_t NumDataElement = 0;
1652 chip::TLV::TLVReader reader;
1654 PRETTY_PRINT("EventList =");
1657 // make a copy of the EventList reader
1658 reader.Init(mReader);
1660 while (CHIP_NO_ERROR == (err = reader.Next()))
1662 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
1663 VerifyOrExit(chip::TLV::kTLVType_Structure == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1666 EventDataElement::Parser event;
1667 err = event.Init(reader);
1670 PRETTY_PRINT_INCDEPTH();
1671 err = event.CheckSchemaValidity();
1673 PRETTY_PRINT_DECDEPTH();
1682 // if we have exhausted this container
1683 if (CHIP_END_OF_TLV == err)
1685 // if we have at least one data element
1686 if (NumDataElement > 0)
1688 err = CHIP_NO_ERROR;
1690 // NOTE: temporarily disable this check, to allow test to continue
1693 ChipLogError(DataManagement, "PROTOCOL ERROR: Empty event list");
1694 err = CHIP_NO_ERROR;
1699 ChipLogFunctError(err);
1703 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1705 EventDataElement::Builder & EventList::Builder::CreateEventBuilder()
1707 // skip if error has already been set
1708 VerifyOrExit(CHIP_NO_ERROR == mError, mEventDataElementBuilder.ResetError(mError));
1710 mError = mEventDataElementBuilder.Init(mpWriter);
1711 ChipLogFunctError(mError);
1714 // on error, mEventDataElementBuilder would be un-/partial initialized and cannot be used to write anything
1715 return mEventDataElementBuilder;
1718 EventList::Builder & EventList::Builder::EndOfEventList()
1724 CHIP_ERROR StatusElement::Parser::Init(const chip::TLV::TLVReader & aReader)
1726 CHIP_ERROR err = CHIP_NO_ERROR;
1728 // make a copy of the reader here
1729 mReader.Init(aReader);
1730 VerifyOrExit(chip::TLV::kTLVType_Array == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1732 // This is just a dummy, as we're not going to exit this container ever
1733 chip::TLV::TLVType OuterContainerType;
1734 err = mReader.EnterContainer(OuterContainerType);
1737 ChipLogFunctError(err);
1741 CHIP_ERROR StatusElement::Parser::DecodeStatusElement(uint16_t * apGeneralCode, uint32_t * apProtocolId, uint16_t * apProtocolCode,
1742 chip::ClusterId * apClusterId) const
1744 CHIP_ERROR err = CHIP_NO_ERROR;
1745 chip::TLV::TLVReader lReader;
1747 lReader.Init(mReader);
1749 err = lReader.Next();
1751 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
1752 err = lReader.Get(*apGeneralCode);
1755 err = lReader.Next();
1757 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
1758 err = lReader.Get(*apProtocolId);
1761 err = lReader.Next();
1763 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
1764 err = lReader.Get(*apProtocolCode);
1767 err = lReader.Next();
1769 VerifyOrExit(lReader.GetType() == chip::TLV::kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
1770 err = lReader.Get(*apClusterId);
1774 ChipLogFunctError(err);
1778 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1779 CHIP_ERROR StatusElement::Parser::CheckSchemaValidity() const
1781 CHIP_ERROR err = CHIP_NO_ERROR;
1782 uint16_t TagPresenceMask = 0;
1783 chip::TLV::TLVReader reader;
1785 PRETTY_PRINT("StatusElement =");
1788 // make a copy of the reader
1789 reader.Init(mReader);
1791 while (CHIP_NO_ERROR == (err = reader.Next()))
1793 // This is an array; all elements are anonymous.
1794 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
1796 if (!(TagPresenceMask & (1 << kCsTag_GeneralCode)))
1798 TagPresenceMask |= (1 << kCsTag_GeneralCode);
1799 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1801 #if CHIP_DETAIL_LOGGING
1803 uint16_t generalCode;
1804 err = reader.Get(generalCode);
1807 PRETTY_PRINT("\tGeneralCode = 0x%" PRIx16 ",", generalCode);
1809 #endif // CHIP_DETAIL_LOGGING
1811 else if (!(TagPresenceMask & (1 << kCsTag_ProtocolId)))
1813 TagPresenceMask |= (1 << kCsTag_ProtocolId);
1814 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1816 #if CHIP_DETAIL_LOGGING
1818 uint32_t kCsTag_ProtocolId;
1819 err = reader.Get(kCsTag_ProtocolId);
1822 PRETTY_PRINT("\tProtocolId = 0x%" PRIx32 ",", kCsTag_ProtocolId);
1824 #endif // CHIP_DETAIL_LOGGING
1826 else if (!(TagPresenceMask & (1 << kCsTag_ProtocolCode)))
1828 TagPresenceMask |= (1 << kCsTag_ProtocolCode);
1829 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1831 #if CHIP_DETAIL_LOGGING
1833 uint16_t protocolCode;
1834 err = reader.Get(protocolCode);
1837 PRETTY_PRINT("\tprotocolCode = 0x%" PRIx16 ",", protocolCode);
1839 #endif // CHIP_DETAIL_LOGGING
1841 else if (!(TagPresenceMask & (1 << kCsTag_NamespacedClusterId)))
1843 TagPresenceMask |= (1 << kCsTag_NamespacedClusterId);
1845 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1847 #if CHIP_DETAIL_LOGGING
1849 chip::ClusterId namespacedClusterId;
1850 err = reader.Get(namespacedClusterId);
1853 PRETTY_PRINT("\tNamespacedClusterId = 0x%" PRIx32 ",", namespacedClusterId);
1855 #endif // CHIP_DETAIL_LOGGING
1859 PRETTY_PRINT("\tExtra element in StatusElement");
1865 // if we have exhausted this container
1866 if (CHIP_END_OF_TLV == err)
1868 // check for required fields:
1869 const uint16_t RequiredFields = (1 << kCsTag_GeneralCode) | (1 << kCsTag_ProtocolId) | (1 << kCsTag_ProtocolCode);
1871 if ((TagPresenceMask & RequiredFields) == RequiredFields)
1873 err = CHIP_NO_ERROR;
1877 err = CHIP_ERROR_IM_MALFORMED_STATUS_CODE;
1882 ChipLogFunctError(err);
1886 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1888 CHIP_ERROR StatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
1890 return ListBuilder::Init(apWriter);
1893 CHIP_ERROR StatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
1895 return ListBuilder::Init(apWriter, aContextTagToUse);
1898 StatusElement::Builder & StatusElement::Builder::EncodeStatusElement(const uint16_t aGeneralCode, const uint32_t aProtocolId,
1899 const uint16_t aStatusElement,
1900 const chip::ClusterId aNamespacedClusterId)
1902 uint64_t tag = chip::TLV::AnonymousTag;
1904 SuccessOrExit(mError);
1906 mError = mpWriter->Put(tag, aGeneralCode);
1907 SuccessOrExit(mError);
1909 mError = mpWriter->Put(tag, aProtocolId);
1910 SuccessOrExit(mError);
1912 mError = mpWriter->Put(tag, aStatusElement);
1913 SuccessOrExit(mError);
1915 mError = mpWriter->Put(tag, aNamespacedClusterId);
1916 SuccessOrExit(mError);
1919 ChipLogFunctError(mError);
1923 StatusElement::Builder & StatusElement::Builder::EndOfStatusElement()
1929 CHIP_ERROR AttributeStatusElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
1931 return InitAnonymousStructure(apWriter);
1934 AttributePath::Builder & AttributeStatusElement::Builder::CreateAttributePathBuilder()
1936 // skip if error has already been set
1937 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributePathBuilder.ResetError(mError));
1939 mError = mAttributePathBuilder.Init(mpWriter, kCsTag_AttributePath);
1942 ChipLogFunctError(mError);
1943 return mAttributePathBuilder;
1946 StatusElement::Builder & AttributeStatusElement::Builder::CreateStatusElementBuilder()
1948 // skip if error has already been set
1949 VerifyOrExit(CHIP_NO_ERROR == mError, mStatusElementBuilder.ResetError(mError));
1951 mError = mStatusElementBuilder.Init(mpWriter, kCsTag_StatusElement);
1954 ChipLogFunctError(mError);
1955 return mStatusElementBuilder;
1958 AttributeStatusElement::Builder & AttributeStatusElement::Builder::EndOfAttributeStatusElement()
1964 CHIP_ERROR AttributeStatusElement::Parser::Init(const chip::TLV::TLVReader & aReader)
1966 CHIP_ERROR err = CHIP_NO_ERROR;
1968 // make a copy of the reader here
1969 mReader.Init(aReader);
1970 VerifyOrExit(chip::TLV::kTLVType_Structure == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
1972 // This is just a dummy, as we're not going to exit this container ever
1973 chip::TLV::TLVType OuterContainerType;
1974 err = mReader.EnterContainer(OuterContainerType);
1977 ChipLogFunctError(err);
1981 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
1982 CHIP_ERROR AttributeStatusElement::Parser::CheckSchemaValidity() const
1984 CHIP_ERROR err = CHIP_NO_ERROR;
1985 uint16_t TagPresenceMask = 0;
1986 chip::TLV::TLVReader reader;
1988 PRETTY_PRINT("AttributeStatusElement =");
1991 // make a copy of the reader
1992 reader.Init(mReader);
1994 while (CHIP_NO_ERROR == (err = reader.Next()))
1996 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
1997 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
1999 case kCsTag_AttributePath:
2000 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_AttributePath)), err = CHIP_ERROR_INVALID_TLV_TAG);
2001 TagPresenceMask |= (1 << kCsTag_AttributePath);
2003 AttributePath::Parser path;
2004 err = path.Init(reader);
2007 PRETTY_PRINT_INCDEPTH();
2008 err = path.CheckSchemaValidity();
2010 PRETTY_PRINT_DECDEPTH();
2013 case kCsTag_StatusElement:
2014 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_StatusElement)), err = CHIP_ERROR_INVALID_TLV_TAG);
2015 TagPresenceMask |= (1 << kCsTag_StatusElement);
2017 StatusElement::Parser status;
2018 err = status.Init(reader);
2021 PRETTY_PRINT_INCDEPTH();
2022 err = status.CheckSchemaValidity();
2024 PRETTY_PRINT_DECDEPTH();
2028 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
2035 // if we have exhausted this container
2036 if (CHIP_END_OF_TLV == err)
2038 // check for required fields:
2039 const uint16_t RequiredFields = (1 << kCsTag_AttributePath) | (1 << kCsTag_StatusElement);
2041 if ((TagPresenceMask & RequiredFields) == RequiredFields)
2043 err = CHIP_NO_ERROR;
2047 err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_STATUS_ELEMENT;
2052 ChipLogFunctError(err);
2056 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2058 CHIP_ERROR AttributeStatusElement::Parser::GetAttributePath(AttributePath::Parser * const apAttributePath) const
2060 CHIP_ERROR err = CHIP_NO_ERROR;
2061 chip::TLV::TLVReader reader;
2063 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_AttributePath), reader);
2066 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2068 err = apAttributePath->Init(reader);
2072 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2077 CHIP_ERROR AttributeStatusElement::Parser::GetStatusElement(StatusElement::Parser * const apStatusElement) const
2079 CHIP_ERROR err = CHIP_NO_ERROR;
2080 chip::TLV::TLVReader reader;
2082 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_StatusElement), reader);
2085 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2087 err = apStatusElement->Init(reader);
2091 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2096 AttributeStatusElement::Builder & AttributeStatusList::Builder::CreateAttributeStatusBuilder()
2098 // skip if error has already been set
2099 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributeStatusBuilder.ResetError(mError));
2101 mError = mAttributeStatusBuilder.Init(mpWriter);
2102 ChipLogFunctError(mError);
2105 // on error, mAttributeStatusBuilder would be un-/partial initialized and cannot be used to write anything
2106 return mAttributeStatusBuilder;
2109 AttributeStatusList::Builder & AttributeStatusList::Builder::EndOfAttributeStatusList()
2115 CHIP_ERROR AttributeStatusList::Parser::CheckSchemaValidity() const
2117 CHIP_ERROR err = CHIP_NO_ERROR;
2118 size_t NumAttributeStateElement = 0;
2119 chip::TLV::TLVReader reader;
2121 PRETTY_PRINT("AttributeStatusList =");
2124 // make a copy of the EventList reader
2125 reader.Init(mReader);
2127 while (CHIP_NO_ERROR == (err = reader.Next()))
2129 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
2130 VerifyOrExit(chip::TLV::kTLVType_Structure == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2133 AttributeStatusElement::Parser status;
2134 err = status.Init(reader);
2137 PRETTY_PRINT_INCDEPTH();
2138 err = status.CheckSchemaValidity();
2140 PRETTY_PRINT_DECDEPTH();
2143 ++NumAttributeStateElement;
2148 // if we have exhausted this container
2149 if (CHIP_END_OF_TLV == err)
2151 // if we have at least one data element
2152 if (NumAttributeStateElement > 0)
2154 err = CHIP_NO_ERROR;
2156 // NOTE: temporarily disable this check, to allow test to continue
2159 ChipLogError(DataManagement, "PROTOCOL ERROR: Empty attribute status list");
2160 err = CHIP_NO_ERROR;
2165 ChipLogFunctError(err);
2170 CHIP_ERROR AttributeDataElement::Parser::Init(const chip::TLV::TLVReader & aReader)
2172 CHIP_ERROR err = CHIP_NO_ERROR;
2174 // make a copy of the reader here
2175 mReader.Init(aReader);
2177 VerifyOrExit(chip::TLV::kTLVType_Structure == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2179 // This is just a dummy, as we're not going to exit this container ever
2180 chip::TLV::TLVType OuterContainerType;
2181 err = mReader.EnterContainer(OuterContainerType);
2184 ChipLogFunctError(err);
2190 AttributeDataElement::Parser::ParseData(chip::TLV::TLVReader & aReader, int aDepth) const
2192 CHIP_ERROR err = CHIP_NO_ERROR;
2196 PRETTY_PRINT("\tData = ");
2200 if (chip::TLV::IsContextTag(aReader.GetTag()))
2202 PRETTY_PRINT("\t0x%" PRIx32 " = ", chip::TLV::TagNumFromTag(aReader.GetTag()));
2204 else if (chip::TLV::IsProfileTag(aReader.GetTag()))
2206 PRETTY_PRINT("\t0x%" PRIx32 "::0x%" PRIx32 " = ", chip::TLV::ProfileIdFromTag(aReader.GetTag()),
2207 chip::TLV::TagNumFromTag(aReader.GetTag()));
2211 // Anonymous tag, don't print anything
2215 switch (aReader.GetType())
2217 case chip::TLV::kTLVType_Structure:
2218 PRETTY_PRINT("\t{");
2221 case chip::TLV::kTLVType_Array:
2222 PRETTY_PRINT_SAMELINE("[");
2223 PRETTY_PRINT("\t\t");
2226 case chip::TLV::kTLVType_SignedInteger: {
2229 err = aReader.Get(value_s64);
2232 PRETTY_PRINT_SAMELINE("%" PRId64 ", ", value_s64);
2236 case chip::TLV::kTLVType_UnsignedInteger: {
2239 err = aReader.Get(value_u64);
2242 PRETTY_PRINT_SAMELINE("%" PRIu64 ", ", value_u64);
2246 case chip::TLV::kTLVType_Boolean: {
2249 err = aReader.Get(value_b);
2252 PRETTY_PRINT_SAMELINE("%s, ", value_b ? "true" : "false");
2256 case chip::TLV::kTLVType_UTF8String: {
2259 err = aReader.GetString(value_s, sizeof(value_s));
2260 VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, );
2262 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
2264 PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
2265 err = CHIP_NO_ERROR;
2269 PRETTY_PRINT_SAMELINE("\"%s\", ", value_s);
2274 case chip::TLV::kTLVType_ByteString: {
2275 uint8_t value_b[256];
2276 uint32_t len, readerLen;
2278 readerLen = aReader.GetLength();
2280 err = aReader.GetBytes(value_b, sizeof(value_b));
2281 VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, );
2283 PRETTY_PRINT_SAMELINE("[");
2284 PRETTY_PRINT("\t\t");
2286 if (readerLen < sizeof(value_b))
2292 len = sizeof(value_b);
2295 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
2297 PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
2301 for (size_t i = 0; i < len; i++)
2303 PRETTY_PRINT_SAMELINE("0x%" PRIx8 ", ", value_b[i]);
2307 err = CHIP_NO_ERROR;
2308 PRETTY_PRINT("\t]");
2312 case chip::TLV::kTLVType_Null:
2313 PRETTY_PRINT_SAMELINE("NULL");
2317 PRETTY_PRINT_SAMELINE("--");
2321 if (aReader.GetType() == chip::TLV::kTLVType_Structure || aReader.GetType() == chip::TLV::kTLVType_Array)
2323 const char terminating_char = (aReader.GetType() == chip::TLV::kTLVType_Structure) ? '}' : ']';
2324 chip::TLV::TLVType type;
2326 IgnoreUnusedVariable(terminating_char);
2328 err = aReader.EnterContainer(type);
2331 while ((err = aReader.Next()) == CHIP_NO_ERROR)
2333 PRETTY_PRINT_INCDEPTH();
2335 err = ParseData(aReader, aDepth + 1);
2338 PRETTY_PRINT_DECDEPTH();
2341 PRETTY_PRINT("\t%c,", terminating_char);
2343 err = aReader.ExitContainer(type);
2348 ChipLogFunctError(err);
2352 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2353 CHIP_ERROR AttributeDataElement::Parser::CheckSchemaValidity() const
2355 CHIP_ERROR err = CHIP_NO_ERROR;
2356 uint16_t TagPresenceMask = 0;
2357 chip::TLV::TLVReader reader;
2358 uint32_t tagNum = 0;
2360 PRETTY_PRINT("AttributeDataElement =");
2363 // make a copy of the reader
2364 reader.Init(mReader);
2366 while (CHIP_NO_ERROR == (err = reader.Next()))
2368 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
2370 tagNum = chip::TLV::TagNumFromTag(reader.GetTag());
2374 case kCsTag_AttributePath:
2375 // check if this tag has appeared before
2376 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_AttributePath)), err = CHIP_ERROR_INVALID_TLV_TAG);
2377 TagPresenceMask |= (1 << kCsTag_AttributePath);
2378 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2381 AttributePath::Parser path;
2382 err = path.Init(reader);
2385 PRETTY_PRINT_INCDEPTH();
2386 err = path.CheckSchemaValidity();
2388 PRETTY_PRINT_DECDEPTH();
2392 case kCsTag_DataVersion:
2393 // check if this tag has appeared before
2394 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_DataVersion)), err = CHIP_ERROR_INVALID_TLV_TAG);
2395 TagPresenceMask |= (1 << kCsTag_DataVersion);
2396 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2398 #if CHIP_DETAIL_LOGGING
2400 chip::DataVersion version;
2401 err = reader.Get(version);
2404 PRETTY_PRINT("\tDataElementVersion = 0x%" PRIx64 ",", version);
2406 #endif // CHIP_DETAIL_LOGGING
2409 // check if this tag has appeared before
2410 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_Data)), err = CHIP_ERROR_INVALID_TLV_TAG);
2411 TagPresenceMask |= (1 << kCsTag_Data);
2413 err = ParseData(reader, 0);
2416 case kCsTag_MoreClusterDataFlag:
2417 // check if this tag has appeared before
2418 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_MoreClusterDataFlag)), err = CHIP_ERROR_INVALID_TLV_TAG);
2419 TagPresenceMask |= (1 << kCsTag_MoreClusterDataFlag);
2420 VerifyOrExit(chip::TLV::kTLVType_Boolean == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2422 #if CHIP_DETAIL_LOGGING
2425 err = reader.Get(flag);
2428 PRETTY_PRINT("\tMoreClusterDataFlag = %s,", flag ? "true" : "false");
2431 #endif // CHIP_DETAIL_LOGGING
2435 PRETTY_PRINT("\tUnknown tag num %" PRIu32, tagNum);
2443 // if we have exhausted this container
2444 if (CHIP_END_OF_TLV == err)
2446 // check for required fields:
2447 // Either the data or deleted keys should be present.
2448 const uint16_t RequiredFields = (1 << kCsTag_AttributePath) | (1 << kCsTag_DataVersion) | (1 << kCsTag_Data);
2449 if ((TagPresenceMask & RequiredFields) == RequiredFields)
2451 err = CHIP_NO_ERROR;
2455 err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_DATA_ELEMENT;
2460 ChipLogFunctError(err);
2464 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2466 CHIP_ERROR AttributeDataElement::Parser::GetAttributePath(AttributePath::Parser * const apAttributePath) const
2468 CHIP_ERROR err = CHIP_NO_ERROR;
2469 chip::TLV::TLVReader reader;
2471 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_AttributePath), reader);
2474 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2476 err = apAttributePath->Init(reader);
2480 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2485 CHIP_ERROR AttributeDataElement::Parser::GetDataVersion(chip::DataVersion * const apVersion) const
2487 return GetUnsignedInteger(kCsTag_DataVersion, apVersion);
2490 CHIP_ERROR AttributeDataElement::Parser::GetData(chip::TLV::TLVReader * const apReader) const
2492 CHIP_ERROR err = CHIP_NO_ERROR;
2494 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_Data), *apReader);
2498 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2503 CHIP_ERROR AttributeDataElement::Parser::GetMoreClusterDataFlag(bool * const apGetMoreClusterDataFlag) const
2505 return GetSimpleValue(kCsTag_MoreClusterDataFlag, chip::TLV::kTLVType_Boolean, apGetMoreClusterDataFlag);
2508 CHIP_ERROR AttributeDataElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
2510 return InitAnonymousStructure(apWriter);
2513 AttributePath::Builder & AttributeDataElement::Builder::CreateAttributePathBuilder()
2515 // skip if error has already been set
2516 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributePathBuilder.ResetError(mError));
2518 mError = mAttributePathBuilder.Init(mpWriter, kCsTag_AttributePath);
2519 ChipLogFunctError(mError);
2522 // on error, mAttributePathBuilder would be un-/partial initialized and cannot be used to write anything
2523 return mAttributePathBuilder;
2526 AttributeDataElement::Builder & AttributeDataElement::Builder::DataVersion(const chip::DataVersion aDataVersion)
2528 // skip if error has already been set
2529 SuccessOrExit(mError);
2531 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_DataVersion), aDataVersion);
2532 ChipLogFunctError(mError);
2538 AttributeDataElement::Builder & AttributeDataElement::Builder::MoreClusterData(const bool aMoreClusterData)
2540 // skip if error has already been set
2541 SuccessOrExit(mError);
2543 if (aMoreClusterData)
2545 mError = mpWriter->PutBoolean(chip::TLV::ContextTag(kCsTag_MoreClusterDataFlag), true);
2546 ChipLogFunctError(mError);
2553 AttributeDataElement::Builder & AttributeDataElement::Builder::EndOfAttributeDataElement()
2560 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2561 CHIP_ERROR AttributeDataList::Parser::CheckSchemaValidity() const
2563 CHIP_ERROR err = CHIP_NO_ERROR;
2564 size_t NumDataElement = 0;
2565 chip::TLV::TLVReader reader;
2567 PRETTY_PRINT("AttributeDataList =");
2570 // make a copy of the reader
2571 reader.Init(mReader);
2573 while (CHIP_NO_ERROR == (err = reader.Next()))
2575 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
2576 VerifyOrExit(chip::TLV::kTLVType_Structure == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2579 AttributeDataElement::Parser data;
2580 err = data.Init(reader);
2583 PRETTY_PRINT_INCDEPTH();
2584 err = data.CheckSchemaValidity();
2586 PRETTY_PRINT_DECDEPTH();
2595 // if we have exhausted this container
2596 if (CHIP_END_OF_TLV == err)
2598 // if we have at least one data element
2599 if (NumDataElement > 0)
2601 err = CHIP_NO_ERROR;
2606 ChipLogFunctError(err);
2610 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2612 AttributeDataElement::Builder & AttributeDataList::Builder::CreateAttributeDataElementBuilder()
2614 // skip if error has already been set
2615 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributeDataElementBuilder.ResetError(mError));
2617 mError = mAttributeDataElementBuilder.Init(mpWriter);
2618 ChipLogFunctError(mError);
2622 // on error, mAttributeDataElementBuilder would be un-/partial initialized and cannot be used to write anything
2623 return mAttributeDataElementBuilder;
2626 AttributeDataList::Builder & AttributeDataList::Builder::EndOfAttributeDataList()
2633 CHIP_ERROR CommandDataElement::Parser::Init(const chip::TLV::TLVReader & aReader)
2635 CHIP_ERROR err = CHIP_NO_ERROR;
2637 // make a copy of the reader here
2638 mReader.Init(aReader);
2640 VerifyOrExit(chip::TLV::kTLVType_Structure == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2642 // This is just a dummy, as we're not going to exit this container ever
2643 chip::TLV::TLVType OuterContainerType;
2644 err = mReader.EnterContainer(OuterContainerType);
2647 ChipLogFunctError(err);
2652 CommandDataElement::Parser::ParseData(chip::TLV::TLVReader & aReader, int aDepth) const
2654 CHIP_ERROR err = CHIP_NO_ERROR;
2658 PRETTY_PRINT("\tCommandDataElement = ");
2662 if (chip::TLV::IsContextTag(aReader.GetTag()))
2664 PRETTY_PRINT("\t0x%" PRIx32 " = ", chip::TLV::TagNumFromTag(aReader.GetTag()));
2666 else if (chip::TLV::IsProfileTag(aReader.GetTag()))
2668 PRETTY_PRINT("\t0x%" PRIx32 "::0x%" PRIx32 " = ", chip::TLV::ProfileIdFromTag(aReader.GetTag()),
2669 chip::TLV::TagNumFromTag(aReader.GetTag()));
2673 // Anonymous tag, don't print anything
2677 switch (aReader.GetType())
2679 case chip::TLV::kTLVType_Structure:
2680 PRETTY_PRINT("\t{");
2683 case chip::TLV::kTLVType_Array:
2684 PRETTY_PRINT_SAMELINE("[");
2685 PRETTY_PRINT("\t\t");
2688 case chip::TLV::kTLVType_SignedInteger: {
2691 err = aReader.Get(value_s64);
2694 PRETTY_PRINT_SAMELINE("%" PRId64 ", ", value_s64);
2698 case chip::TLV::kTLVType_UnsignedInteger: {
2701 err = aReader.Get(value_u64);
2704 PRETTY_PRINT_SAMELINE("%" PRIu64 ", ", value_u64);
2708 case chip::TLV::kTLVType_FloatingPointNumber: {
2711 err = aReader.Get(value_fp);
2714 PRETTY_PRINT_SAMELINE("%lf, ", value_fp);
2717 case chip::TLV::kTLVType_Boolean: {
2720 err = aReader.Get(value_b);
2723 PRETTY_PRINT_SAMELINE("%s, ", value_b ? "true" : "false");
2727 case chip::TLV::kTLVType_UTF8String: {
2730 err = aReader.GetString(value_s, sizeof(value_s));
2731 VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, );
2733 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
2735 PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
2736 err = CHIP_NO_ERROR;
2740 PRETTY_PRINT_SAMELINE("\"%s\", ", value_s);
2745 case chip::TLV::kTLVType_ByteString: {
2746 uint8_t value_b[256];
2747 uint32_t len, readerLen;
2749 readerLen = aReader.GetLength();
2751 err = aReader.GetBytes(value_b, sizeof(value_b));
2752 VerifyOrExit(err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL, );
2754 PRETTY_PRINT_SAMELINE("[");
2755 PRETTY_PRINT("\t\t");
2757 if (readerLen < sizeof(value_b))
2763 len = sizeof(value_b);
2766 if (err == CHIP_ERROR_BUFFER_TOO_SMALL)
2768 PRETTY_PRINT_SAMELINE("... (byte string too long) ...");
2772 for (size_t i = 0; i < len; i++)
2774 PRETTY_PRINT_SAMELINE("0x%" PRIx8 ", ", value_b[i]);
2778 err = CHIP_NO_ERROR;
2783 case chip::TLV::kTLVType_Null:
2784 PRETTY_PRINT_SAMELINE("NULL");
2788 PRETTY_PRINT_SAMELINE("--");
2792 if (aReader.GetType() == chip::TLV::kTLVType_Structure || aReader.GetType() == chip::TLV::kTLVType_Array)
2794 const char terminating_char = (aReader.GetType() == chip::TLV::kTLVType_Structure) ? '}' : ']';
2795 chip::TLV::TLVType type;
2797 IgnoreUnusedVariable(terminating_char);
2799 err = aReader.EnterContainer(type);
2802 while ((err = aReader.Next()) == CHIP_NO_ERROR)
2804 PRETTY_PRINT_INCDEPTH();
2806 err = ParseData(aReader, aDepth + 1);
2809 PRETTY_PRINT_DECDEPTH();
2812 PRETTY_PRINT("\t%c,", terminating_char);
2814 err = aReader.ExitContainer(type);
2819 ChipLogFunctError(err);
2823 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2824 CHIP_ERROR CommandDataElement::Parser::CheckSchemaValidity() const
2826 CHIP_ERROR err = CHIP_NO_ERROR;
2827 uint16_t TagPresenceMask = 0;
2828 chip::TLV::TLVReader reader;
2829 uint32_t tagNum = 0;
2831 PRETTY_PRINT("CommandDataElement =");
2834 // make a copy of the reader
2835 reader.Init(mReader);
2837 while (CHIP_NO_ERROR == (err = reader.Next()))
2839 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
2841 tagNum = chip::TLV::TagNumFromTag(reader.GetTag());
2845 case kCsTag_CommandPath:
2846 // check if this tag has appeared before
2847 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_CommandPath)), err = CHIP_ERROR_INVALID_TLV_TAG);
2848 TagPresenceMask |= (1 << kCsTag_CommandPath);
2849 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2852 CommandPath::Parser path;
2853 err = path.Init(reader);
2856 PRETTY_PRINT_INCDEPTH();
2857 err = path.CheckSchemaValidity();
2859 PRETTY_PRINT_DECDEPTH();
2864 // check if this tag has appeared before
2865 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_Data)), err = CHIP_ERROR_INVALID_TLV_TAG);
2866 TagPresenceMask |= (1 << kCsTag_Data);
2868 err = ParseData(reader, 0);
2871 case kCsTag_StatusElement:
2872 // check if this tag has appeared before
2873 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_StatusElement)), err = CHIP_ERROR_INVALID_TLV_TAG);
2874 TagPresenceMask |= (1 << kCsTag_StatusElement);
2875 VerifyOrExit(chip::TLV::kTLVType_Structure == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2878 StatusElement::Parser status;
2879 err = status.Init(reader);
2882 PRETTY_PRINT_INCDEPTH();
2883 err = status.CheckSchemaValidity();
2885 PRETTY_PRINT_DECDEPTH();
2890 PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum);
2898 // if we have exhausted this container
2899 if (CHIP_END_OF_TLV == err)
2901 // check for required fields:
2902 const uint16_t RequiredFields = (1 << kCsTag_CommandPath);
2903 if ((TagPresenceMask & RequiredFields) == RequiredFields)
2905 err = CHIP_NO_ERROR;
2909 err = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
2914 ChipLogFunctError(err);
2917 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
2919 CHIP_ERROR CommandDataElement::Parser::GetCommandPath(CommandPath::Parser * const apCommandPath) const
2921 CHIP_ERROR err = CHIP_NO_ERROR;
2922 chip::TLV::TLVReader reader;
2924 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_CommandPath), reader);
2927 VerifyOrExit(chip::TLV::kTLVType_Path == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2929 err = apCommandPath->Init(reader);
2933 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2938 CHIP_ERROR CommandDataElement::Parser::GetData(chip::TLV::TLVReader * const apReader) const
2940 CHIP_ERROR err = CHIP_NO_ERROR;
2942 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_Data), *apReader);
2946 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2951 CHIP_ERROR CommandDataElement::Parser::GetStatusElement(StatusElement::Parser * const apStatusElement) const
2953 CHIP_ERROR err = CHIP_NO_ERROR;
2954 chip::TLV::TLVReader reader;
2956 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_StatusElement), reader);
2959 VerifyOrExit(chip::TLV::kTLVType_Structure == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
2961 err = apStatusElement->Init(reader);
2965 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
2970 CHIP_ERROR CommandDataElement::Builder::Init(chip::TLV::TLVWriter * const apWriter)
2972 return InitAnonymousStructure(apWriter);
2975 CommandPath::Builder & CommandDataElement::Builder::CreateCommandPathBuilder()
2977 // skip if error has already been set
2978 VerifyOrExit(CHIP_NO_ERROR == mError, mCommandPathBuilder.ResetError(mError));
2980 mError = mCommandPathBuilder.Init(mpWriter, kCsTag_CommandPath);
2981 ChipLogFunctError(mError);
2984 // on error, mAttributePathBuilder would be un-/partial initialized and cannot be used to write anything
2985 return mCommandPathBuilder;
2988 StatusElement::Builder & CommandDataElement::Builder::CreateStatusElementBuilder()
2990 // skip if error has already been set
2991 VerifyOrExit(CHIP_NO_ERROR == mError, mStatusElementBuilder.ResetError(mError));
2993 mError = mStatusElementBuilder.Init(mpWriter, kCsTag_StatusElement);
2994 ChipLogFunctError(mError);
2997 // on error, mStatusElementBuilder would be un-/partial initialized and cannot be used to write anything
2998 return mStatusElementBuilder;
3001 CommandDataElement::Builder & CommandDataElement::Builder::EndOfCommandDataElement()
3008 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
3009 CHIP_ERROR CommandList::Parser::CheckSchemaValidity() const
3011 CHIP_ERROR err = CHIP_NO_ERROR;
3012 size_t NumCommands = 0;
3013 chip::TLV::TLVReader reader;
3015 PRETTY_PRINT("CommandList =");
3018 // make a copy of the reader
3019 reader.Init(mReader);
3021 while (CHIP_NO_ERROR == (err = reader.Next()))
3023 VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG);
3024 VerifyOrExit(chip::TLV::kTLVType_Structure == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3027 CommandDataElement::Parser data;
3028 err = data.Init(reader);
3031 PRETTY_PRINT_INCDEPTH();
3032 err = data.CheckSchemaValidity();
3035 PRETTY_PRINT_DECDEPTH();
3044 // if we have exhausted this container
3045 if (CHIP_END_OF_TLV == err)
3047 // if we have at least one data element
3048 if (NumCommands > 0)
3050 err = CHIP_NO_ERROR;
3055 ChipLogFunctError(err);
3059 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
3061 CommandDataElement::Builder & CommandList::Builder::CreateCommandDataElementBuilder()
3063 // skip if error has already been set
3064 VerifyOrExit(CHIP_NO_ERROR == mError, mCommandDataElementBuilder.ResetError(mError));
3066 mError = mCommandDataElementBuilder.Init(mpWriter);
3067 ChipLogFunctError(mError);
3070 // on error, mCommandDataElementBuilder would be un-/partial initialized and cannot be used to write anything
3071 return mCommandDataElementBuilder;
3074 CommandList::Builder & CommandList::Builder::EndOfCommandList()
3080 CHIP_ERROR ReportData::Parser::Init(const chip::TLV::TLVReader & aReader)
3082 CHIP_ERROR err = CHIP_NO_ERROR;
3084 // make a copy of the reader here
3085 mReader.Init(aReader);
3087 VerifyOrExit(chip::TLV::kTLVType_Structure == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3089 // This is just a dummy, as we're not going to exit this container ever
3090 chip::TLV::TLVType OuterContainerType;
3091 err = mReader.EnterContainer(OuterContainerType);
3094 ChipLogFunctError(err);
3099 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
3100 CHIP_ERROR ReportData::Parser::CheckSchemaValidity() const
3102 CHIP_ERROR err = CHIP_NO_ERROR;
3103 uint16_t TagPresenceMask = 0;
3104 chip::TLV::TLVReader reader;
3105 AttributeStatusList::Parser attributeStatusList;
3106 AttributeDataList::Parser attributeDataList;
3107 EventList::Parser eventList;
3109 PRETTY_PRINT("ReportData =");
3112 // make a copy of the reader
3113 reader.Init(mReader);
3115 while (CHIP_NO_ERROR == (err = reader.Next()))
3117 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
3119 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
3121 case kCsTag_RequestResponse:
3122 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_RequestResponse)), err = CHIP_ERROR_INVALID_TLV_TAG);
3123 TagPresenceMask |= (1 << kCsTag_RequestResponse);
3124 VerifyOrExit(chip::TLV::kTLVType_Boolean == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3125 #if CHIP_DETAIL_LOGGING
3127 bool RequestResponse;
3128 err = reader.Get(RequestResponse);
3130 PRETTY_PRINT("\tRequestResponse = %s, ", RequestResponse ? "true" : "false");
3132 #endif // CHIP_DETAIL_LOGGING
3134 case kCsTag_SubscriptionId:
3135 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_SubscriptionId)), err = CHIP_ERROR_INVALID_TLV_TAG);
3136 TagPresenceMask |= (1 << kCsTag_SubscriptionId);
3137 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3138 #if CHIP_DETAIL_LOGGING
3140 uint64_t subscriptionId;
3141 err = reader.Get(subscriptionId);
3143 PRETTY_PRINT("\tSubscriptionId = 0x%" PRIx64 ",", subscriptionId);
3145 #endif // CHIP_DETAIL_LOGGING
3147 case kCsTag_AttributeStatusList:
3148 // check if this tag has appeared before
3149 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_AttributeStatusList)), err = CHIP_ERROR_INVALID_TLV_TAG);
3150 TagPresenceMask |= (1 << kCsTag_AttributeStatusList);
3151 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3152 #if CHIP_DETAIL_LOGGING
3154 attributeStatusList.Init(reader);
3156 PRETTY_PRINT_INCDEPTH();
3157 err = attributeStatusList.CheckSchemaValidity();
3159 PRETTY_PRINT_DECDEPTH();
3161 #endif // CHIP_DETAIL_LOGGING
3163 case kCsTag_AttributeDataList:
3164 // check if this tag has appeared before
3165 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_AttributeDataList)), err = CHIP_ERROR_INVALID_TLV_TAG);
3166 TagPresenceMask |= (1 << kCsTag_AttributeDataList);
3167 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3168 #if CHIP_DETAIL_LOGGING
3170 attributeDataList.Init(reader);
3172 PRETTY_PRINT_INCDEPTH();
3173 err = attributeDataList.CheckSchemaValidity();
3175 PRETTY_PRINT_DECDEPTH();
3177 #endif // CHIP_DETAIL_LOGGING
3179 case kCsTag_EventDataList:
3180 // check if this tag has appeared before
3181 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EventDataList)), err = CHIP_ERROR_INVALID_TLV_TAG);
3182 TagPresenceMask |= (1 << kCsTag_EventDataList);
3183 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3184 #if CHIP_DETAIL_LOGGING
3186 eventList.Init(reader);
3188 PRETTY_PRINT_INCDEPTH();
3189 err = eventList.CheckSchemaValidity();
3191 PRETTY_PRINT_DECDEPTH();
3193 #endif // CHIP_DETAIL_LOGGING
3195 case kCsTag_IsLastReport:
3196 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_IsLastReport)), err = CHIP_ERROR_INVALID_TLV_TAG);
3197 TagPresenceMask |= (1 << kCsTag_IsLastReport);
3198 VerifyOrExit(chip::TLV::kTLVType_Boolean == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3199 #if CHIP_DETAIL_LOGGING
3202 err = reader.Get(isLastReport);
3204 PRETTY_PRINT("\tisLastReport = %s, ", isLastReport ? "true" : "false");
3206 #endif // CHIP_DETAIL_LOGGING
3209 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
3215 // if we have exhausted this container
3216 if (CHIP_END_OF_TLV == err)
3218 err = CHIP_NO_ERROR;
3222 ChipLogFunctError(err);
3226 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
3228 CHIP_ERROR ReportData::Parser::GetRequestResponse(bool * const apRequestResponse) const
3230 return GetSimpleValue(kCsTag_RequestResponse, chip::TLV::kTLVType_Boolean, apRequestResponse);
3233 CHIP_ERROR ReportData::Parser::GetSubscriptionId(uint64_t * const apSubscriptionId) const
3235 return GetUnsignedInteger(kCsTag_SubscriptionId, apSubscriptionId);
3238 CHIP_ERROR ReportData::Parser::GetAttributeStatusList(AttributeStatusList::Parser * const apAttributeStatusList) const
3240 CHIP_ERROR err = CHIP_NO_ERROR;
3241 chip::TLV::TLVReader reader;
3243 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_AttributeStatusList), reader);
3246 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3248 err = apAttributeStatusList->Init(reader);
3252 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
3257 CHIP_ERROR ReportData::Parser::GetAttributeDataList(AttributeDataList::Parser * const apAttributeDataList) const
3259 CHIP_ERROR err = CHIP_NO_ERROR;
3260 chip::TLV::TLVReader reader;
3262 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_AttributeDataList), reader);
3265 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3267 err = apAttributeDataList->Init(reader);
3271 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
3276 CHIP_ERROR ReportData::Parser::GetEventDataList(EventList::Parser * const apEventDataList) const
3278 CHIP_ERROR err = CHIP_NO_ERROR;
3279 chip::TLV::TLVReader reader;
3281 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_EventDataList), reader);
3284 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3286 err = apEventDataList->Init(reader);
3290 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
3295 CHIP_ERROR ReportData::Parser::GetIsLastReport(bool * const apIsLastReport) const
3297 return GetSimpleValue(kCsTag_IsLastReport, chip::TLV::kTLVType_Boolean, apIsLastReport);
3300 CHIP_ERROR ReportData::Builder::Init(chip::TLV::TLVWriter * const apWriter)
3302 return InitAnonymousStructure(apWriter);
3305 ReportData::Builder & ReportData::Builder::RequestResponse(const bool aRequestResponse)
3307 // skip if error has already been set
3308 SuccessOrExit(mError);
3310 mError = mpWriter->PutBoolean(chip::TLV::ContextTag(kCsTag_RequestResponse), aRequestResponse);
3311 ChipLogFunctError(mError);
3317 ReportData::Builder & ReportData::Builder::SubscriptionId(const uint64_t aSubscriptionId)
3319 // skip if error has already been set
3320 SuccessOrExit(mError);
3322 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_SubscriptionId), aSubscriptionId);
3323 ChipLogFunctError(mError);
3329 AttributeStatusList::Builder & ReportData::Builder::CreateAttributeStatusListBuilder()
3331 // skip if error has already been set
3332 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributeStatusListBuilder.ResetError(mError));
3334 mError = mAttributeStatusListBuilder.Init(mpWriter, kCsTag_AttributeStatusList);
3335 ChipLogFunctError(mError);
3338 return mAttributeStatusListBuilder;
3341 AttributeDataList::Builder & ReportData::Builder::CreateAttributeDataListBuilder()
3343 // skip if error has already been set
3344 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributeDataListBuilder.ResetError(mError));
3346 mError = mAttributeDataListBuilder.Init(mpWriter, kCsTag_AttributeDataList);
3347 ChipLogFunctError(mError);
3350 return mAttributeDataListBuilder;
3353 EventList::Builder & ReportData::Builder::CreateEventDataListBuilder()
3355 // skip if error has already been set
3356 VerifyOrExit(CHIP_NO_ERROR == mError, mAttributeDataListBuilder.ResetError(mError));
3358 mError = mEventDataListBuilder.Init(mpWriter, kCsTag_EventDataList);
3359 ChipLogFunctError(mError);
3362 return mEventDataListBuilder;
3365 ReportData::Builder & ReportData::Builder::IsLastReport(const bool aIsLastReport)
3367 // skip if error has already been set
3368 SuccessOrExit(mError);
3370 mError = mpWriter->PutBoolean(chip::TLV::ContextTag(kCsTag_IsLastReport), aIsLastReport);
3371 ChipLogFunctError(mError);
3377 ReportData::Builder & ReportData::Builder::EndOfReportData()
3383 CHIP_ERROR InvokeCommand::Parser::Init(const chip::TLV::TLVReader & aReader)
3385 CHIP_ERROR err = CHIP_NO_ERROR;
3387 // make a copy of the reader here
3388 mReader.Init(aReader);
3390 VerifyOrExit(chip::TLV::kTLVType_Structure == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3392 // This is just a dummy, as we're not going to exit this container ever
3393 chip::TLV::TLVType OuterContainerType;
3394 err = mReader.EnterContainer(OuterContainerType);
3397 ChipLogFunctError(err);
3402 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
3403 CHIP_ERROR InvokeCommand::Parser::CheckSchemaValidity() const
3405 CHIP_ERROR err = CHIP_NO_ERROR;
3406 uint16_t TagPresenceMask = 0;
3407 chip::TLV::TLVReader reader;
3408 CommandList::Parser commandList;
3410 PRETTY_PRINT("InvokeCommand =");
3413 // make a copy of the reader
3414 reader.Init(mReader);
3416 while (CHIP_NO_ERROR == (err = reader.Next()))
3418 const uint64_t tag = reader.GetTag();
3420 if (chip::TLV::ContextTag(kCsTag_CommandList) == tag)
3422 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_CommandList)), err = CHIP_ERROR_INVALID_TLV_TAG);
3423 TagPresenceMask |= (1 << kCsTag_CommandList);
3424 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3426 commandList.Init(reader);
3428 PRETTY_PRINT_INCDEPTH();
3430 err = commandList.CheckSchemaValidity();
3433 PRETTY_PRINT_DECDEPTH();
3437 PRETTY_PRINT("\tUnknown tag 0x%" PRIx64, tag);
3444 // if we have exhausted this container
3445 if (CHIP_END_OF_TLV == err)
3447 // if we have at least the DataList or EventList field
3448 if ((TagPresenceMask & (1 << kCsTag_CommandList)))
3450 err = CHIP_NO_ERROR;
3455 ChipLogFunctError(err);
3459 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
3461 CHIP_ERROR InvokeCommand::Parser::GetCommandList(CommandList::Parser * const apCommandList) const
3463 CHIP_ERROR err = CHIP_NO_ERROR;
3464 chip::TLV::TLVReader reader;
3466 err = mReader.FindElementWithTag(chip::TLV::ContextTag(kCsTag_CommandList), reader);
3469 VerifyOrExit(chip::TLV::kTLVType_Array == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
3471 err = apCommandList->Init(reader);
3475 ChipLogIfFalse((CHIP_NO_ERROR == err) || (CHIP_END_OF_TLV == err));
3480 CHIP_ERROR InvokeCommand::Builder::Init(chip::TLV::TLVWriter * const apWriter)
3482 return InitAnonymousStructure(apWriter);
3485 CommandList::Builder & InvokeCommand::Builder::CreateCommandListBuilder()
3487 // skip if error has already been set
3488 VerifyOrExit(CHIP_NO_ERROR == mError, mCommandListBuilder.ResetError(mError));
3490 mError = mCommandListBuilder.Init(mpWriter, kCsTag_CommandList);
3491 ChipLogFunctError(mError);
3494 // on error, mCommandListBuilder would be un-/partial initialized and cannot be used to write anything
3495 return mCommandListBuilder;
3498 InvokeCommand::Builder & InvokeCommand::Builder::EndOfInvokeCommand()
3505 }; // namespace chip