Line data Source code
1 : /*
2 : * Copyright (c) 2022 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include <app-common/zap-generated/cluster-objects.h>
19 : #include <controller/CommissioningWindowOpener.h>
20 : #include <lib/core/CHIPSafeCasts.h>
21 : #include <lib/support/CHIPMem.h>
22 : #include <protocols/secure_channel/PASESession.h>
23 : #include <setup_payload/ManualSetupPayloadGenerator.h>
24 : #include <setup_payload/QRCodeSetupPayloadGenerator.h>
25 :
26 : using namespace chip::app::Clusters;
27 : using namespace chip::System::Clock;
28 : using namespace chip::Crypto;
29 :
30 : namespace {
31 : // TODO: What should the timed invoke timeout here be?
32 : constexpr uint16_t kTimedInvokeTimeoutMs = 10000;
33 : } // anonymous namespace
34 :
35 : namespace chip {
36 : namespace Controller {
37 :
38 0 : CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId deviceId, Seconds16 timeout,
39 : Callback::Callback<OnOpenBasicCommissioningWindow> * callback)
40 : {
41 0 : VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
42 0 : mSetupPayload = SetupPayload();
43 :
44 : // Basic commissioning does not use the setup payload.
45 :
46 0 : mCommissioningWindowOption = CommissioningWindowOption::kOriginalSetupCode;
47 0 : mBasicCommissioningWindowCallback = callback;
48 0 : mCommissioningWindowCallback = nullptr;
49 0 : mCommissioningWindowVerifierCallback = nullptr;
50 0 : mNodeId = deviceId;
51 0 : mCommissioningWindowTimeout = timeout;
52 :
53 0 : mNextStep = Step::kOpenCommissioningWindow;
54 0 : return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
55 : }
56 :
57 0 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, Seconds16 timeout, uint32_t iteration,
58 : uint16_t discriminator, Optional<uint32_t> setupPIN,
59 : Optional<ByteSpan> salt,
60 : Callback::Callback<OnOpenCommissioningWindow> * callback,
61 : SetupPayload & payload, bool readVIDPIDAttributes)
62 : {
63 0 : return OpenCommissioningWindow(CommissioningWindowPasscodeParams()
64 0 : .SetNodeId(deviceId)
65 0 : .SetTimeout(timeout)
66 0 : .SetIteration(iteration)
67 0 : .SetDiscriminator(discriminator)
68 0 : .SetSetupPIN(setupPIN)
69 0 : .SetSalt(salt)
70 0 : .SetReadVIDPIDAttributes(readVIDPIDAttributes)
71 0 : .SetCallback(callback),
72 0 : payload);
73 : }
74 :
75 4 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowPasscodeParams & params,
76 : SetupPayload & payload)
77 : {
78 4 : VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
79 4 : VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
80 4 : VerifyOrReturnError(params.HasDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT);
81 4 : VerifyOrReturnError(kSpake2p_Min_PBKDF_Iterations <= params.GetIteration() &&
82 : params.GetIteration() <= kSpake2p_Max_PBKDF_Iterations,
83 : CHIP_ERROR_INVALID_ARGUMENT);
84 3 : VerifyOrReturnError(!params.HasSalt() ||
85 : (params.GetSalt().size() >= kSpake2p_Min_PBKDF_Salt_Length &&
86 : params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length),
87 : CHIP_ERROR_INVALID_ARGUMENT);
88 :
89 3 : mSetupPayload = SetupPayload();
90 :
91 3 : if (params.HasSetupPIN())
92 : {
93 2 : VerifyOrReturnError(SetupPayload::IsValidSetupPIN(params.GetSetupPIN()), CHIP_ERROR_INVALID_ARGUMENT);
94 2 : mCommissioningWindowOption = CommissioningWindowOption::kTokenWithProvidedPIN;
95 2 : mSetupPayload.setUpPINCode = params.GetSetupPIN();
96 : }
97 : else
98 : {
99 1 : mCommissioningWindowOption = CommissioningWindowOption::kTokenWithRandomPIN;
100 : }
101 :
102 3 : mSetupPayload.version = 0;
103 3 : mDiscriminator.SetLongValue(params.GetDiscriminator());
104 3 : mSetupPayload.discriminator = mDiscriminator;
105 3 : mSetupPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork);
106 :
107 3 : if (params.HasSalt())
108 : {
109 2 : memcpy(mPBKDFSaltBuffer, params.GetSalt().data(), params.GetSalt().size());
110 2 : mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer, params.GetSalt().size());
111 : }
112 : else
113 : {
114 1 : ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFSaltBuffer, sizeof(mPBKDFSaltBuffer)));
115 1 : mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer);
116 : }
117 3 : mPBKDFIterations = params.GetIteration();
118 :
119 3 : bool randomSetupPIN = !params.HasSetupPIN();
120 3 : ReturnErrorOnFailure(
121 : PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));
122 :
123 3 : payload = mSetupPayload;
124 3 : mCommissioningWindowCallback = params.GetCallback();
125 3 : mBasicCommissioningWindowCallback = nullptr;
126 3 : mCommissioningWindowVerifierCallback = nullptr;
127 3 : mNodeId = params.GetNodeId();
128 3 : mCommissioningWindowTimeout = params.GetTimeout();
129 3 : mTargetEndpointId = params.GetEndpointId();
130 :
131 3 : if (params.GetReadVIDPIDAttributes())
132 : {
133 1 : mNextStep = Step::kReadVID;
134 : }
135 : else
136 : {
137 2 : mNextStep = Step::kOpenCommissioningWindow;
138 : }
139 :
140 3 : return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
141 : }
142 :
143 : #if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
144 : CHIP_ERROR CommissioningWindowOpener::OpenJointCommissioningWindow(const CommissioningWindowPasscodeParams & params,
145 : SetupPayload & payload)
146 : {
147 : mJointCommissioning = true;
148 : return OpenCommissioningWindow(params, payload);
149 : }
150 : #endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
151 :
152 4 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowVerifierParams & params)
153 : {
154 4 : VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
155 4 : VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
156 4 : VerifyOrReturnError(params.HasDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT);
157 4 : VerifyOrReturnError(kSpake2p_Min_PBKDF_Iterations <= params.GetIteration() &&
158 : params.GetIteration() <= kSpake2p_Max_PBKDF_Iterations,
159 : CHIP_ERROR_INVALID_ARGUMENT);
160 3 : VerifyOrReturnError(params.GetSalt().size() >= kSpake2p_Min_PBKDF_Salt_Length &&
161 : params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length,
162 : CHIP_ERROR_INVALID_ARGUMENT);
163 2 : memcpy(mPBKDFSaltBuffer, params.GetSalt().data(), params.GetSalt().size());
164 2 : mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer, params.GetSalt().size());
165 :
166 2 : ReturnErrorOnFailure(mVerifier.Deserialize(params.GetVerifier()));
167 1 : mCommissioningWindowVerifierCallback = params.GetCallback();
168 1 : mBasicCommissioningWindowCallback = nullptr;
169 1 : mCommissioningWindowCallback = nullptr;
170 1 : mNodeId = params.GetNodeId();
171 1 : mCommissioningWindowTimeout = params.GetTimeout();
172 1 : mPBKDFIterations = params.GetIteration();
173 1 : mCommissioningWindowOption = CommissioningWindowOption::kTokenWithProvidedPIN;
174 1 : mDiscriminator.SetLongValue(params.GetDiscriminator());
175 1 : mTargetEndpointId = params.GetEndpointId();
176 :
177 1 : mNextStep = Step::kOpenCommissioningWindow;
178 :
179 1 : return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
180 : }
181 :
182 0 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowInternal(Messaging::ExchangeManager & exchangeMgr,
183 : const SessionHandle & sessionHandle)
184 : {
185 0 : ChipLogProgress(Controller, "OpenCommissioningWindow for device ID 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));
186 :
187 0 : ClusterBase cluster(exchangeMgr, sessionHandle, mTargetEndpointId);
188 :
189 0 : if (mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode)
190 : {
191 : Spake2pVerifierSerialized serializedVerifier;
192 0 : MutableByteSpan serializedVerifierSpan(serializedVerifier);
193 0 : ReturnErrorOnFailure(mVerifier.Serialize(serializedVerifierSpan));
194 :
195 : #if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
196 : if (mJointCommissioning == false)
197 : {
198 : #endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
199 0 : AdministratorCommissioning::Commands::OpenCommissioningWindow::Type request;
200 0 : request.commissioningTimeout = mCommissioningWindowTimeout.count();
201 0 : request.PAKEPasscodeVerifier = serializedVerifierSpan;
202 0 : request.discriminator = mDiscriminator.GetLongValue();
203 0 : request.iterations = mPBKDFIterations;
204 0 : request.salt = mPBKDFSalt;
205 :
206 0 : ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
207 : OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
208 : #if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
209 : }
210 : else
211 : {
212 : mJointCommissioning = false; // Reset the flag for next use
213 :
214 : JointFabricAdministrator::Commands::OpenJointCommissioningWindow::Type request;
215 : request.commissioningTimeout = mCommissioningWindowTimeout.count();
216 : request.PAKEPasscodeVerifier = serializedVerifierSpan;
217 : request.discriminator = mDiscriminator.GetLongValue();
218 : request.iterations = mPBKDFIterations;
219 : request.salt = mPBKDFSalt;
220 :
221 : ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
222 : OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
223 : }
224 : #endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
225 : }
226 : else
227 : {
228 0 : AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type request;
229 0 : request.commissioningTimeout = mCommissioningWindowTimeout.count();
230 0 : ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
231 : OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
232 : }
233 :
234 0 : return CHIP_NO_ERROR;
235 0 : }
236 :
237 0 : void CommissioningWindowOpener::OnPIDReadResponse(void * context, uint16_t value)
238 : {
239 0 : ChipLogProgress(Controller, "Received PID for the device. Value %d", value);
240 0 : auto * self = static_cast<CommissioningWindowOpener *>(context);
241 0 : self->mSetupPayload.productID = value;
242 :
243 0 : self->mNextStep = Step::kOpenCommissioningWindow;
244 :
245 0 : CHIP_ERROR err = self->mController->GetConnectedDevice(self->mNodeId, &self->mDeviceConnected, &self->mDeviceConnectionFailure);
246 0 : if (err != CHIP_NO_ERROR)
247 : {
248 0 : OnOpenCommissioningWindowFailure(context, err);
249 : }
250 0 : }
251 :
252 0 : void CommissioningWindowOpener::OnVIDReadResponse(void * context, VendorId value)
253 : {
254 0 : ChipLogProgress(Controller, "Received VID for the device. Value %d", to_underlying(value));
255 :
256 0 : auto * self = static_cast<CommissioningWindowOpener *>(context);
257 :
258 0 : self->mSetupPayload.vendorID = value;
259 :
260 0 : self->mNextStep = Step::kReadPID;
261 0 : CHIP_ERROR err = self->mController->GetConnectedDevice(self->mNodeId, &self->mDeviceConnected, &self->mDeviceConnectionFailure);
262 0 : if (err != CHIP_NO_ERROR)
263 : {
264 0 : OnOpenCommissioningWindowFailure(context, err);
265 : }
266 0 : }
267 :
268 0 : void CommissioningWindowOpener::OnVIDPIDReadFailureResponse(void * context, CHIP_ERROR error)
269 : {
270 0 : ChipLogProgress(Controller, "Failed to read VID/PID for the device. error %" CHIP_ERROR_FORMAT, error.Format());
271 0 : OnOpenCommissioningWindowFailure(context, error);
272 0 : }
273 :
274 0 : void CommissioningWindowOpener::OnOpenCommissioningWindowSuccess(void * context, const chip::app::DataModel::NullObjectType &)
275 : {
276 0 : ChipLogProgress(Controller, "Successfully opened pairing window on the device");
277 0 : auto * self = static_cast<CommissioningWindowOpener *>(context);
278 0 : self->mNextStep = Step::kAcceptCommissioningStart;
279 0 : if (self->mCommissioningWindowCallback != nullptr)
280 : {
281 : char payloadBuffer[QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
282 :
283 0 : MutableCharSpan manualCode(payloadBuffer);
284 0 : CHIP_ERROR err = ManualSetupPayloadGenerator(self->mSetupPayload).payloadDecimalStringRepresentation(manualCode);
285 0 : if (err == CHIP_NO_ERROR)
286 : {
287 0 : ChipLogProgress(Controller, "Manual pairing code: [%s]", payloadBuffer);
288 : }
289 : else
290 : {
291 0 : ChipLogError(Controller, "Unable to generate manual code for setup payload: %" CHIP_ERROR_FORMAT, err.Format());
292 : }
293 :
294 0 : MutableCharSpan QRCode(payloadBuffer);
295 0 : err = QRCodeBasicSetupPayloadGenerator(self->mSetupPayload).payloadBase38Representation(QRCode);
296 0 : if (err == CHIP_NO_ERROR)
297 : {
298 0 : ChipLogProgress(Controller, "SetupQRCode: [%s]", payloadBuffer);
299 : }
300 : else
301 : {
302 0 : ChipLogError(Controller, "Unable to generate QR code for setup payload: %" CHIP_ERROR_FORMAT, err.Format());
303 : }
304 :
305 0 : self->mCommissioningWindowCallback->mCall(self->mCommissioningWindowCallback->mContext, self->mNodeId, CHIP_NO_ERROR,
306 0 : self->mSetupPayload);
307 : // Don't touch `self` anymore; it might have been destroyed by the callee.
308 : }
309 0 : else if (self->mCommissioningWindowVerifierCallback != nullptr)
310 : {
311 0 : self->mCommissioningWindowVerifierCallback->mCall(self->mCommissioningWindowVerifierCallback->mContext, self->mNodeId,
312 : CHIP_NO_ERROR);
313 : // Don't touch `self` anymore; it might have been destroyed by the callee.
314 : }
315 0 : else if (self->mBasicCommissioningWindowCallback != nullptr)
316 : {
317 0 : self->mBasicCommissioningWindowCallback->mCall(self->mBasicCommissioningWindowCallback->mContext, self->mNodeId,
318 : CHIP_NO_ERROR);
319 : // Don't touch `self` anymore; it might have been destroyed by the callee.
320 : }
321 0 : }
322 :
323 0 : void CommissioningWindowOpener::OnOpenCommissioningWindowFailure(void * context, CHIP_ERROR error)
324 : {
325 0 : ChipLogError(Controller, "Failed to open pairing window on the device. Status %" CHIP_ERROR_FORMAT, error.Format());
326 0 : auto * self = static_cast<CommissioningWindowOpener *>(context);
327 0 : self->mNextStep = Step::kAcceptCommissioningStart;
328 0 : if (self->mCommissioningWindowCallback != nullptr)
329 : {
330 0 : self->mCommissioningWindowCallback->mCall(self->mCommissioningWindowCallback->mContext, self->mNodeId, error,
331 0 : SetupPayload());
332 : }
333 0 : else if (self->mCommissioningWindowVerifierCallback != nullptr)
334 : {
335 0 : self->mCommissioningWindowVerifierCallback->mCall(self->mCommissioningWindowVerifierCallback->mContext, self->mNodeId,
336 : error);
337 : }
338 0 : else if (self->mBasicCommissioningWindowCallback != nullptr)
339 : {
340 0 : self->mBasicCommissioningWindowCallback->mCall(self->mBasicCommissioningWindowCallback->mContext, self->mNodeId, error);
341 : }
342 0 : }
343 :
344 0 : void CommissioningWindowOpener::OnDeviceConnectedCallback(void * context, Messaging::ExchangeManager & exchangeMgr,
345 : const SessionHandle & sessionHandle)
346 : {
347 0 : auto * self = static_cast<CommissioningWindowOpener *>(context);
348 :
349 : #if CHIP_ERROR_LOGGING
350 0 : const char * messageIfError = nullptr;
351 : #endif // CHIP_ERROR_LOGGING
352 0 : CHIP_ERROR err = CHIP_NO_ERROR;
353 :
354 0 : switch (self->mNextStep)
355 : {
356 0 : case Step::kReadVID: {
357 0 : ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);
358 0 : err = cluster.ReadAttribute<BasicInformation::Attributes::VendorID::TypeInfo>(context, OnVIDReadResponse,
359 : OnVIDPIDReadFailureResponse);
360 : #if CHIP_ERROR_LOGGING
361 0 : messageIfError = "Could not read VID for opening commissioning window";
362 : #endif // CHIP_ERROR_LOGGING
363 0 : break;
364 0 : }
365 0 : case Step::kReadPID: {
366 0 : ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);
367 0 : err = cluster.ReadAttribute<BasicInformation::Attributes::ProductID::TypeInfo>(context, OnPIDReadResponse,
368 : OnVIDPIDReadFailureResponse);
369 : #if CHIP_ERROR_LOGGING
370 0 : messageIfError = "Could not read PID for opening commissioning window";
371 : #endif // CHIP_ERROR_LOGGING
372 0 : break;
373 0 : }
374 0 : case Step::kOpenCommissioningWindow: {
375 0 : err = self->OpenCommissioningWindowInternal(exchangeMgr, sessionHandle);
376 : #if CHIP_ERROR_LOGGING
377 0 : messageIfError = "Could not connect to open commissioning window";
378 : #endif // CHIP_ERROR_LOGGING
379 0 : break;
380 : }
381 0 : case Step::kAcceptCommissioningStart: {
382 0 : err = CHIP_ERROR_INCORRECT_STATE;
383 : #if CHIP_ERROR_LOGGING
384 0 : messageIfError = "Just got a connected device; how can we be done?";
385 : #endif // CHIP_ERROR_LOGGING
386 0 : break;
387 : }
388 : }
389 :
390 0 : if (err != CHIP_NO_ERROR)
391 : {
392 0 : ChipLogError(Controller, "%s: %" CHIP_ERROR_FORMAT, messageIfError, err.Format());
393 0 : OnOpenCommissioningWindowFailure(context, err);
394 : }
395 0 : }
396 :
397 0 : void CommissioningWindowOpener::OnDeviceConnectionFailureCallback(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
398 : {
399 0 : OnOpenCommissioningWindowFailure(context, error);
400 0 : }
401 :
402 0 : AutoCommissioningWindowOpener::AutoCommissioningWindowOpener(DeviceController * controller) :
403 0 : CommissioningWindowOpener(controller), mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
404 0 : mOnOpenBasicCommissioningWindowCallback(OnOpenBasicCommissioningWindowResponse, this)
405 0 : {}
406 :
407 0 : CHIP_ERROR AutoCommissioningWindowOpener::OpenBasicCommissioningWindow(DeviceController * controller, NodeId deviceId,
408 : Seconds16 timeout)
409 : {
410 : // Not using Platform::New because we want to keep our constructor private.
411 0 : auto * opener = new (std::nothrow) AutoCommissioningWindowOpener(controller);
412 0 : if (opener == nullptr)
413 : {
414 0 : return CHIP_ERROR_NO_MEMORY;
415 : }
416 :
417 0 : CHIP_ERROR err = opener->CommissioningWindowOpener::OpenBasicCommissioningWindow(
418 : deviceId, timeout, &opener->mOnOpenBasicCommissioningWindowCallback);
419 0 : if (err != CHIP_NO_ERROR)
420 : {
421 0 : delete opener;
422 : }
423 : // Else will clean up when the callback is called.
424 0 : return err;
425 : }
426 :
427 0 : CHIP_ERROR AutoCommissioningWindowOpener::OpenCommissioningWindow(DeviceController * controller, NodeId deviceId, Seconds16 timeout,
428 : uint32_t iteration, uint16_t discriminator,
429 : Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
430 : SetupPayload & payload, bool readVIDPIDAttributes)
431 : {
432 : // Not using Platform::New because we want to keep our constructor private.
433 0 : auto * opener = new (std::nothrow) AutoCommissioningWindowOpener(controller);
434 0 : if (opener == nullptr)
435 : {
436 0 : return CHIP_ERROR_NO_MEMORY;
437 : }
438 :
439 0 : CHIP_ERROR err = opener->CommissioningWindowOpener::OpenCommissioningWindow(
440 : deviceId, timeout, iteration, discriminator, setupPIN, salt, &opener->mOnOpenCommissioningWindowCallback, payload,
441 : readVIDPIDAttributes);
442 0 : if (err != CHIP_NO_ERROR)
443 : {
444 0 : delete opener;
445 : }
446 : // Else will clean up when the callback is called.
447 0 : return err;
448 : }
449 :
450 0 : void AutoCommissioningWindowOpener::OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status,
451 : chip::SetupPayload payload)
452 : {
453 0 : auto * self = static_cast<AutoCommissioningWindowOpener *>(context);
454 0 : delete self;
455 0 : }
456 0 : void AutoCommissioningWindowOpener::OnOpenBasicCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status)
457 : {
458 0 : auto * self = static_cast<AutoCommissioningWindowOpener *>(context);
459 0 : delete self;
460 0 : }
461 :
462 : } // namespace Controller
463 : } // namespace chip
|