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 AttributePath parser and builder in CHIP interaction model
24 #include "AttributePath.h"
25 #include "MessageDefHelper.h"
32 using namespace chip::TLV;
36 CHIP_ERROR AttributePath::Parser::Init(const chip::TLV::TLVReader & aReader)
38 CHIP_ERROR err = CHIP_NO_ERROR;
40 // make a copy of the reader here
41 mReader.Init(aReader);
43 VerifyOrExit(chip::TLV::kTLVType_List == mReader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
45 // This is just a dummy, as we're not going to exit this container ever
46 chip::TLV::TLVType dummyContainerType;
47 // enter into the Path
48 err = mReader.EnterContainer(dummyContainerType);
52 ChipLogFunctError(err);
57 #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
58 CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const
60 CHIP_ERROR err = CHIP_NO_ERROR;
61 uint16_t TagPresenceMask = 0;
62 chip::TLV::TLVReader reader;
64 PRETTY_PRINT("AttributePath =");
67 // make a copy of the Path reader
70 while (CHIP_NO_ERROR == (err = reader.Next()))
72 VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG);
73 switch (chip::TLV::TagNumFromTag(reader.GetTag()))
76 // check if this tag has appeared before
77 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NodeId)), err = CHIP_ERROR_INVALID_TLV_TAG);
78 TagPresenceMask |= (1 << kCsTag_NodeId);
79 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
81 #if CHIP_DETAIL_LOGGING
85 PRETTY_PRINT("\tNodeId = 0x%" PRIx64 ",", nodeId);
87 #endif // CHIP_DETAIL_LOGGING
89 case kCsTag_EndpointId:
90 // check if this tag has appeared before
91 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EndpointId)), err = CHIP_ERROR_INVALID_TLV_TAG);
92 TagPresenceMask |= (1 << kCsTag_EndpointId);
93 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
94 #if CHIP_DETAIL_LOGGING
97 reader.Get(endpointId);
98 PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId);
100 #endif // CHIP_DETAIL_LOGGING
102 case kCsTag_ClusterId:
103 // check if this tag has appeared before
104 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ClusterId)), err = CHIP_ERROR_INVALID_TLV_TAG);
105 TagPresenceMask |= (1 << kCsTag_ClusterId);
106 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
108 #if CHIP_DETAIL_LOGGING
109 if (chip::TLV::kTLVType_UnsignedInteger == reader.GetType())
111 chip::ClusterId clusterId;
112 reader.Get(clusterId);
113 PRETTY_PRINT("\tClusterId = 0x%" PRIx32 ",", clusterId);
115 #endif // CHIP_DETAIL_LOGGING
118 // check if this tag has appeared before
119 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_FieldId)), err = CHIP_ERROR_INVALID_TLV_TAG);
120 TagPresenceMask |= (1 << kCsTag_FieldId);
121 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
122 #if CHIP_DETAIL_LOGGING
125 reader.Get(fieldTag);
126 PRETTY_PRINT("\tFieldTag = 0x%" PRIx8 ",", fieldTag);
128 #endif // CHIP_DETAIL_LOGGING
130 case kCsTag_ListIndex:
131 // check if this tag has appeared before
132 VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ListIndex)), err = CHIP_ERROR_INVALID_TLV_TAG);
133 TagPresenceMask |= (1 << kCsTag_ListIndex);
134 VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
135 #if CHIP_DETAIL_LOGGING
136 if (chip::TLV::kTLVType_UnsignedInteger == reader.GetType())
139 reader.Get(listIndex);
140 PRETTY_PRINT("\tListIndex = 0x%" PRIx16 ",", listIndex);
142 #endif // CHIP_DETAIL_LOGGING
145 ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG);
151 // if we have exhausted this container
152 if (CHIP_END_OF_TLV == err)
154 // check for required fields:
155 const uint16_t RequiredFields = (1 << kCsTag_EndpointId) | (1 << kCsTag_ClusterId);
157 if ((TagPresenceMask & RequiredFields) == RequiredFields)
163 err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH;
169 ChipLogFunctError(err);
173 #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK
175 CHIP_ERROR AttributePath::Parser::GetNodeId(chip::NodeId * const apNodeId) const
177 return GetUnsignedInteger(kCsTag_NodeId, apNodeId);
180 CHIP_ERROR AttributePath::Parser::GetEndpointId(chip::EndpointId * const apEndpointId) const
182 return GetUnsignedInteger(kCsTag_EndpointId, apEndpointId);
185 CHIP_ERROR AttributePath::Parser::GetClusterId(chip::ClusterId * const apClusterId) const
187 return GetUnsignedInteger(kCsTag_ClusterId, apClusterId);
190 CHIP_ERROR AttributePath::Parser::GetFieldId(uint8_t * const apFieldId) const
192 return GetUnsignedInteger(kCsTag_FieldId, apFieldId);
195 CHIP_ERROR AttributePath::Parser::GetListIndex(uint16_t * const apListIndex) const
197 return GetUnsignedInteger(kCsTag_ListIndex, apListIndex);
200 CHIP_ERROR AttributePath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const uint64_t aTag)
203 mError = mpWriter->StartContainer(aTag, chip::TLV::kTLVType_List, mOuterContainerType);
204 SuccessOrExit(mError);
207 ChipLogFunctError(mError);
211 CHIP_ERROR AttributePath::Builder::Init(chip::TLV::TLVWriter * const apWriter)
213 return _Init(apWriter, chip::TLV::AnonymousTag);
216 CHIP_ERROR AttributePath::Builder::Init(chip::TLV::TLVWriter * const apWriter, const uint8_t aContextTagToUse)
218 return _Init(apWriter, chip::TLV::ContextTag(aContextTagToUse));
221 AttributePath::Builder & AttributePath::Builder::NodeId(const uint64_t aNodeId)
223 // skip if error has already been set
224 SuccessOrExit(mError);
226 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NodeId), aNodeId);
227 ChipLogFunctError(mError);
234 AttributePath::Builder & AttributePath::Builder::EndpointId(const chip::EndpointId aEndpointId)
236 // skip if error has already been set
237 SuccessOrExit(mError);
239 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EndpointId), aEndpointId);
240 ChipLogFunctError(mError);
246 AttributePath::Builder & AttributePath::Builder::ClusterId(const chip::ClusterId aClusterId)
248 // skip if error has already been set
249 SuccessOrExit(mError);
251 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ClusterId), aClusterId);
252 ChipLogFunctError(mError);
258 AttributePath::Builder & AttributePath::Builder::FieldId(const uint8_t aFieldId)
260 // skip if error has already been set
261 SuccessOrExit(mError);
263 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_FieldId), aFieldId);
264 ChipLogFunctError(mError);
270 AttributePath::Builder & AttributePath::Builder::ListIndex(const uint16_t aListIndex)
272 // skip if error has already been set
273 SuccessOrExit(mError);
275 mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ListIndex), aListIndex);
276 ChipLogFunctError(mError);
282 AttributePath::Builder & AttributePath::Builder::EndOfAttributePath()