Coverage Report

Created: 2026-08-14 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/connectedhomeip/examples/platform/linux/AppMain.cpp
Line
Count
Source
1
/*
2
 *
3
 *    Copyright (c) 2021-2022 Project CHIP Authors
4
 *    All rights reserved.
5
 *
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
9
 *
10
 *        http://www.apache.org/licenses/LICENSE-2.0
11
 *
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.
17
 */
18
19
#include <string>
20
21
#include <platform/CHIPDeviceLayer.h>
22
#include <platform/PlatformManager.h>
23
24
#include <app/InteractionModelEngine.h>
25
#include <app/clusters/network-commissioning/network-commissioning.h>
26
#include <app/server/Dnssd.h>
27
#include <app/server/Server.h>
28
#include <app/util/endpoint-config-api.h>
29
#include <crypto/CHIPCryptoPAL.h>
30
#include <data-model-providers/codegen/Instance.h>
31
#include <lib/core/CHIPError.h>
32
#include <lib/core/NodeId.h>
33
#include <lib/core/Optional.h>
34
#include <lib/support/logging/CHIPLogging.h>
35
#include <setup_payload/OnboardingCodesUtil.h>
36
37
#include <credentials/DeviceAttestationCredsProvider.h>
38
39
#include <lib/support/CHIPMem.h>
40
#include <lib/support/CHIPMemString.h>
41
#include <lib/support/CodeUtils.h>
42
#include <lib/support/ScopedMemoryBuffer.h>
43
#include <lib/support/TestGroupData.h>
44
#include <platform/CHIPDeviceEvent.h>
45
#include <platform/ConnectivityManager.h>
46
#include <platform/OpenThread/GenericNetworkCommissioningThreadDriver.h>
47
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
48
#include <setup_payload/SetupPayload.h>
49
50
#include <platform/CommissionableDataProvider.h>
51
#include <platform/DiagnosticDataProvider.h>
52
#include <platform/RuntimeOptionsProvider.h>
53
54
#include <AllClustersExampleDeviceInfoProviderImpl.h>
55
#include <DeviceInfoProviderImpl.h>
56
57
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
58
#include "CommissionerMain.h"
59
#include <ControllerShellCommands.h>
60
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
61
62
#ifndef CHIP_LINUX_APP_START_COMMISSIONER_AT_BOOT
63
#define CHIP_LINUX_APP_START_COMMISSIONER_AT_BOOT 1
64
#endif
65
66
#if defined(ENABLE_CHIP_SHELL)
67
#include <CommissioneeShellCommands.h>
68
#include <lib/shell/Engine.h> // nogncheck
69
#include <thread>
70
#endif
71
72
#if defined(PW_RPC_ENABLED)
73
#include <Rpc.h>
74
#endif
75
76
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
77
#include "TraceDecoder.h"
78
#include "TraceHandlers.h"
79
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
80
81
#if ENABLE_TRACING
82
#include <TracingCommandLineArgument.h> // nogncheck
83
#endif
84
85
#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_DIAGNOSTIC_TRIGGER
86
#include <app/clusters/software-diagnostics-server/SoftwareDiagnosticsTestEventTriggerHandler.h>
87
#endif
88
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_DIAGNOSTIC_TRIGGER
89
#include <app/clusters/wifi-network-diagnostics-server/WiFiDiagnosticsTestEventTriggerHandler.h>
90
#endif
91
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
92
#include <app/clusters/ota-requestor/OTATestEventTriggerHandler.h>
93
#endif
94
#if CHIP_DEVICE_CONFIG_ENABLE_SMOKE_CO_TRIGGER
95
#include <app/clusters/smoke-co-alarm-server/SmokeCOTestEventTriggerHandler.h>
96
#endif
97
#if CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER
98
#include <app/clusters/boolean-state-configuration-server/BooleanStateConfigurationTestEventTriggerHandler.h>
99
#endif
100
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_PRICE_TRIGGER
101
#include <app/clusters/commodity-price-server/CommodityPriceTestEventTriggerHandler.h>
102
#endif
103
#if CHIP_DEVICE_CONFIG_ENABLE_ELECTRICAL_GRID_CONDITIONS_TRIGGER
104
#include <app/clusters/electrical-grid-conditions-server/ElectricalGridConditionsTestEventTriggerHandler.h>
105
#endif
106
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_TARIFF_TRIGGER
107
#include <app/clusters/commodity-tariff-server/CommodityTariffTestEventTriggerHandler.h>
108
#endif
109
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
110
#include <app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h>
111
#endif
112
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
113
#include <app/clusters/electrical-energy-measurement-server/EnergyReportingTestEventTriggerHandler.h>
114
#endif
115
#if CHIP_DEVICE_CONFIG_ENABLE_METER_IDENTIFICATION_TRIGGER
116
#include <app/clusters/meter-identification-server/MeterIdentificationTestEventTriggerHandler.h>
117
#endif
118
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
119
#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
120
#endif
121
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
122
#include <app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h>
123
#endif
124
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_METERING_TRIGGER
125
#include <app/clusters/commodity-metering-server/CommodityMeteringTestEventTriggerHandler.h>
126
#endif
127
#if CHIP_CONFIG_ENABLE_ICD_SERVER
128
#include <app/icd/server/ICDManager.h> // nogncheck
129
#endif
130
#include <app/TestEventTriggerDelegate.h>
131
132
#include <signal.h>
133
134
#include "AppMain.h"
135
#include "CommissionableInit.h"
136
137
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
138
#include "ExampleAccessRestrictionProvider.h"
139
#endif
140
141
#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
142
#include <app/server/TermsAndConditionsManager.h> // nogncheck
143
#endif
144
145
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
146
#include <platform/Darwin/NetworkCommissioningDriver.h>
147
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
148
#include <platform/Darwin/WiFi/NetworkCommissioningWiFiDriver.h>
149
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
150
#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN
151
152
#if CHIP_DEVICE_LAYER_TARGET_LINUX
153
#include <platform/Linux/NetworkCommissioningDriver.h>
154
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
155
156
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
157
#include <inet/EndPointStateOpenThread.h>
158
#include <openthread-system.h>
159
#include <openthread/instance.h>
160
#endif
161
162
using namespace chip;
163
using namespace chip::ArgParser;
164
using namespace chip::Credentials;
165
using namespace chip::DeviceLayer;
166
using namespace chip::Inet;
167
using namespace chip::Transport;
168
using namespace chip::app::Clusters;
169
using namespace chip::Access;
170
using namespace chip::Platform;
171
172
// Network comissioning implementation
173
namespace {
174
// If secondaryNetworkCommissioningEndpoint has a value and both Thread and WiFi
175
// are enabled, we put the WiFi network commissioning cluster on
176
// secondaryNetworkCommissioningEndpoint.
177
Optional<EndpointId> sSecondaryNetworkCommissioningEndpoint;
178
179
#if CHIP_DEVICE_LAYER_TARGET_LINUX
180
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
181
#define CHIP_APP_MAIN_HAS_THREAD_DRIVER 1
182
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
183
DeviceLayer::NetworkCommissioning::GenericThreadDriver sThreadDriver;
184
#else
185
DeviceLayer::NetworkCommissioning::LinuxThreadDriver sThreadDriver;
186
#endif
187
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
188
189
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
190
#define CHIP_APP_MAIN_HAS_WIFI_DRIVER 1
191
DeviceLayer::NetworkCommissioning::LinuxWiFiDriver sWiFiDriver;
192
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
193
194
#define CHIP_APP_MAIN_HAS_ETHERNET_DRIVER 1
195
DeviceLayer::NetworkCommissioning::LinuxEthernetDriver sEthernetDriver;
196
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
197
198
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
199
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
200
#define CHIP_APP_MAIN_HAS_WIFI_DRIVER 1
201
DeviceLayer::NetworkCommissioning::DarwinWiFiDriver sWiFiDriver;
202
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
203
204
#define CHIP_APP_MAIN_HAS_ETHERNET_DRIVER 1
205
DeviceLayer::NetworkCommissioning::DarwinEthernetDriver sEthernetDriver;
206
#endif // CHIP_DEVICE_LAYER_TARGET_DARWIN
207
208
#ifndef CHIP_APP_MAIN_HAS_THREAD_DRIVER
209
#define CHIP_APP_MAIN_HAS_THREAD_DRIVER 0
210
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
211
212
#ifndef CHIP_APP_MAIN_HAS_WIFI_DRIVER
213
#define CHIP_APP_MAIN_HAS_WIFI_DRIVER 0
214
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
215
216
#ifndef CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
217
#define CHIP_APP_MAIN_HAS_ETHERNET_DRIVER 0
218
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
219
220
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
221
app::Clusters::NetworkCommissioning::Instance sThreadNetworkCommissioningInstance(kRootEndpointId, &sThreadDriver);
222
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
223
224
#if CHIP_APP_MAIN_HAS_WIFI_DRIVER
225
// The WiFi network commissioning instance cannot be constructed until we know
226
// whether we have an sSecondaryNetworkCommissioningEndpoint.
227
Optional<app::Clusters::NetworkCommissioning::Instance> sWiFiNetworkCommissioningInstance;
228
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
229
230
#if CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
231
app::Clusters::NetworkCommissioning::Instance sEthernetNetworkCommissioningInstance(kRootEndpointId, &sEthernetDriver);
232
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
233
234
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
235
auto exampleAccessRestrictionProvider = std::make_unique<ExampleAccessRestrictionProvider>();
236
#endif
237
238
void EnableThreadNetworkCommissioning()
239
0
{
240
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
241
    SuccessOrDie(sThreadNetworkCommissioningInstance.Init());
242
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
243
0
}
244
245
void EnableWiFiNetworkCommissioning(EndpointId endpoint)
246
0
{
247
0
#if CHIP_APP_MAIN_HAS_WIFI_DRIVER
248
0
    sWiFiNetworkCommissioningInstance.Emplace(endpoint, &sWiFiDriver);
249
0
    SuccessOrDie(sWiFiNetworkCommissioningInstance.Value().Init());
250
0
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
251
0
}
252
253
void InitNetworkCommissioning()
254
0
{
255
0
    if (sSecondaryNetworkCommissioningEndpoint.HasValue())
256
0
    {
257
        // Enable secondary endpoint only when we need it, this should be applied to all platforms.
258
0
        emberAfEndpointEnableDisable(sSecondaryNetworkCommissioningEndpoint.Value(), false);
259
0
    }
260
261
0
    bool isThreadEnabled = false;
262
#if CHIP_APP_MAIN_HAS_THREAD_DRIVER
263
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
264
    isThreadEnabled = LinuxDeviceOptions::GetInstance().mThreadNodeId > 0;
265
#else
266
    isThreadEnabled = LinuxDeviceOptions::GetInstance().mThread;
267
#endif
268
#endif // CHIP_APP_MAIN_HAS_THREAD_DRIVER
269
270
0
    bool isWiFiEnabled = false;
271
0
#if CHIP_APP_MAIN_HAS_WIFI_DRIVER
272
0
    isWiFiEnabled = LinuxDeviceOptions::GetInstance().mWiFi;
273
274
    // On Linux, command-line indicates whether Wi-Fi is supported since determining it from
275
    // the OS level is not easily portable.
276
0
#if CHIP_DEVICE_LAYER_TARGET_LINUX
277
0
    sWiFiDriver.Set5gSupport(LinuxDeviceOptions::GetInstance().wifiSupports5g);
278
0
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
279
280
0
#endif // CHIP_APP_MAIN_HAS_WIFI_DRIVER
281
282
0
    if (isThreadEnabled && isWiFiEnabled)
283
0
    {
284
0
        if (sSecondaryNetworkCommissioningEndpoint.HasValue())
285
0
        {
286
0
            EnableThreadNetworkCommissioning();
287
0
            EnableWiFiNetworkCommissioning(sSecondaryNetworkCommissioningEndpoint.Value());
288
            // Only enable secondary endpoint for network commissioning cluster when both WiFi and Thread are enabled.
289
0
            emberAfEndpointEnableDisable(sSecondaryNetworkCommissioningEndpoint.Value(), true);
290
0
        }
291
0
        else
292
0
        {
293
            // Just use the Thread one.
294
0
            EnableThreadNetworkCommissioning();
295
0
        }
296
0
    }
297
0
    else if (isThreadEnabled)
298
0
    {
299
0
        EnableThreadNetworkCommissioning();
300
0
    }
301
0
    else if (isWiFiEnabled)
302
0
    {
303
0
        EnableWiFiNetworkCommissioning(kRootEndpointId);
304
0
    }
305
0
    else
306
0
    {
307
0
#if CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
308
0
        TEMPORARY_RETURN_IGNORED sEthernetNetworkCommissioningInstance.Init();
309
0
#if CHIP_DEVICE_LAYER_TARGET_LINUX
310
0
        DeviceLayer::ConnectivityMgrImpl().UpdateEthernetNetworkingStatus();
311
0
#endif // CHIP_DEVICE_LAYER_TARGET_LINUX
312
0
#endif // CHIP_APP_MAIN_HAS_ETHERNET_DRIVER
313
0
    }
314
0
}
315
316
} // anonymous namespace
317
318
#if defined(ENABLE_CHIP_SHELL)
319
using chip::Shell::Engine;
320
#endif
321
322
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
323
/*
324
 * The device shall check every kWiFiStartCheckTimeUsec whether Wi-Fi management
325
 * has been fully initialized. If after kWiFiStartCheckAttempts Wi-Fi management
326
 * still hasn't been initialized, the device configuration is reset, and device
327
 * needs to be paired again.
328
 */
329
static constexpr useconds_t kWiFiStartCheckTimeUsec = WIFI_START_CHECK_TIME_USEC;
330
static constexpr uint8_t kWiFiStartCheckAttempts    = WIFI_START_CHECK_ATTEMPTS;
331
#endif
332
333
namespace {
334
AppMainLoopImplementation * gMainLoopImplementation = nullptr;
335
336
// To hold SPAKE2+ verifier, discriminator, passcode
337
LinuxCommissionableDataProvider gCommissionableDataProvider;
338
339
chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
340
chip::DeviceLayer::AllClustersExampleDeviceInfoProviderImpl gAllClustersExampleDeviceInfoProvider;
341
342
void EventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
343
0
{
344
0
    (void) arg;
345
0
    if (event->Type == DeviceLayer::DeviceEventType::kCHIPoBLEConnectionEstablished)
346
0
    {
347
0
        ChipLogProgress(DeviceLayer, "Receive kCHIPoBLEConnectionEstablished");
348
0
    }
349
0
    else if ((event->Type == chip::DeviceLayer::DeviceEventType::kInternetConnectivityChange))
350
0
    {
351
        // Restart the server on connectivity change
352
0
        app::DnssdServer::Instance().StartServer();
353
0
    }
354
0
}
355
356
void StopMainEventLoop()
357
0
{
358
0
    if (gMainLoopImplementation != nullptr)
359
0
    {
360
0
        gMainLoopImplementation->SignalSafeStopMainLoop();
361
0
    }
362
0
    else
363
0
    {
364
0
        Server::GetInstance().GenerateShutDownEvent();
365
0
        TEMPORARY_RETURN_IGNORED SystemLayer().ScheduleLambda([]() { TEMPORARY_RETURN_IGNORED PlatformMgr().StopEventLoopTask(); });
366
0
    }
367
0
}
368
369
void Cleanup()
370
0
{
371
0
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
372
0
    chip::trace::DeInitTrace();
373
0
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
374
375
    // TODO(16968): Lifecycle management of storage-using components like GroupDataProvider, etc
376
0
}
377
378
void StopSignalHandler(int /* signal */)
379
0
{
380
#if defined(ENABLE_CHIP_SHELL)
381
    Engine::Root().StopMainLoop();
382
#endif
383
0
    StopMainEventLoop();
384
0
}
385
386
} // namespace
387
388
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
389
static bool EnsureWiFiIsStarted()
390
0
{
391
0
    for (int cnt = 0; cnt < kWiFiStartCheckAttempts; cnt++)
392
0
    {
393
0
        if (DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted())
394
0
        {
395
0
            return true;
396
0
        }
397
398
0
        usleep(kWiFiStartCheckTimeUsec);
399
0
    }
400
401
0
    return DeviceLayer::ConnectivityMgrImpl().IsWiFiManagementStarted();
402
0
}
403
#endif
404
405
class SampleTestEventTriggerHandler : public TestEventTriggerHandler
406
{
407
    /// NOTE: If you copy this for NON-STANDARD CLUSTERS OR USAGES, please use the reserved range FFFF_FFFF_<VID_HEX>_xxxx for your
408
    /// trigger codes. NOTE: Standard codes are <CLUSTER_ID_HEX>_xxxx_xxxx_xxxx.
409
    static constexpr uint64_t kSampleTestEventTriggerAlwaysSuccess = static_cast<uint64_t>(0xFFFF'FFFF'FFF1'0000ull);
410
411
public:
412
    CHIP_ERROR HandleEventTrigger(uint64_t eventTrigger) override
413
0
    {
414
0
        ChipLogProgress(Support, "Saw TestEventTrigger: " ChipLogFormatX64, ChipLogValueX64(eventTrigger));
415
416
0
        if (eventTrigger == kSampleTestEventTriggerAlwaysSuccess)
417
0
        {
418
            // Do nothing, successfully
419
0
            ChipLogProgress(Support, "Handling \"Always success\" internal test event");
420
0
            return CHIP_NO_ERROR;
421
0
        }
422
423
0
        return CHIP_ERROR_INVALID_ARGUMENT;
424
0
    }
425
};
426
427
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
428
/*
429
    Get the freq_list from args.
430
    Format:
431
        "freq_list=[freq#1],[freq#2]...[freq#n]"
432
            [freq#1] - [freq#n]: frequence number, separated by ','
433
*/
434
static uint16_t WiFiPAFGet_FreqList(const char * args, std::unique_ptr<uint16_t[]> & freq_list)
435
0
{
436
0
    const char hdstr[] = "freq_list=";
437
0
    std::vector<uint16_t> freq_vect;
438
0
    const std::string argstrn(args);
439
0
    auto pos = argstrn.find(hdstr);
440
0
    if (pos == std::string::npos)
441
0
    {
442
0
        return 0;
443
0
    }
444
0
    std::string nums = argstrn.substr(pos + strlen(hdstr));
445
0
    std::stringstream ss(nums);
446
0
    std::string item;
447
0
    while (std::getline(ss, item, ','))
448
0
    {
449
0
        freq_vect.push_back(std::stoi(item));
450
0
    }
451
0
    uint16_t freq_size = freq_vect.size();
452
0
    freq_list          = std::make_unique<uint16_t[]>(freq_size);
453
0
    for (int i = 0; i < freq_size; i++)
454
0
    {
455
0
        freq_list.get()[i] = freq_vect[i];
456
0
    }
457
0
    return freq_size;
458
0
}
459
#endif
460
461
// Wrapper for DeviceInstanceInfoProvider that allows the example app to set
462
// attribute values from the command-line, provide hardcoded values, or fall
463
// back to the default DeviceInstanceInfoProvider.
464
class ExampleDeviceInstanceInfoProvider : public DeviceInstanceInfoProvider
465
{
466
public:
467
0
    void Init(DeviceInstanceInfoProvider * defaultProvider) { mDefaultProvider = defaultProvider; }
468
469
    CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override
470
0
    {
471
        // Check if it was set from the command line or fall back to default provider.
472
0
        if (mVendorName.has_value())
473
0
        {
474
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mVendorName.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
475
0
            CopyString(buf, bufSize, mVendorName.value().c_str());
476
0
            return CHIP_NO_ERROR;
477
0
        }
478
479
0
        return mDefaultProvider->GetVendorName(buf, bufSize);
480
0
    }
481
482
0
    CHIP_ERROR GetVendorId(uint16_t & vendorId) override { return mDefaultProvider->GetVendorId(vendorId); }
483
484
    CHIP_ERROR GetProductName(char * buf, size_t bufSize) override
485
0
    {
486
        // Check if it was set from the command line or fall back to default provider.
487
0
        if (mProductName.has_value())
488
0
        {
489
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mProductName.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
490
0
            CopyString(buf, bufSize, mProductName.value().c_str());
491
0
            return CHIP_NO_ERROR;
492
0
        }
493
494
0
        return mDefaultProvider->GetProductName(buf, bufSize);
495
0
    }
496
497
0
    CHIP_ERROR GetProductId(uint16_t & productId) override { return mDefaultProvider->GetProductId(productId); }
498
0
    CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override { return mDefaultProvider->GetPartNumber(buf, bufSize); }
499
0
    CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override { return mDefaultProvider->GetProductURL(buf, bufSize); }
500
0
    CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override { return mDefaultProvider->GetProductLabel(buf, bufSize); }
501
502
    CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override
503
0
    {
504
        // Check if it was set from the command line or fall back to default provider.
505
0
        if (mSerialNumber.has_value())
506
0
        {
507
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mSerialNumber.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
508
0
            CopyString(buf, bufSize, mSerialNumber.value().c_str());
509
0
            return CHIP_NO_ERROR;
510
0
        }
511
512
0
        return mDefaultProvider->GetSerialNumber(buf, bufSize);
513
0
    }
514
515
    CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override
516
0
    {
517
0
        return mDefaultProvider->GetManufacturingDate(year, month, day);
518
0
    }
519
    CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override
520
0
    {
521
0
        return mDefaultProvider->GetHardwareVersion(hardwareVersion);
522
0
    }
523
    CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override
524
0
    {
525
        // Check if it was set from the command line or fall back to default provider.
526
0
        if (mHardwareVersionString.has_value())
527
0
        {
528
0
            VerifyOrReturnError(CanFitInNullTerminatedString(mHardwareVersionString.value(), bufSize), CHIP_ERROR_BUFFER_TOO_SMALL);
529
0
            CopyString(buf, bufSize, mHardwareVersionString.value().c_str());
530
0
            return CHIP_NO_ERROR;
531
0
        }
532
533
0
        return mDefaultProvider->GetHardwareVersionString(buf, bufSize);
534
0
    }
535
536
    CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override
537
0
    {
538
0
        return mDefaultProvider->GetRotatingDeviceIdUniqueId(uniqueIdSpan);
539
0
    }
540
541
    CHIP_ERROR GetProductFinish(chip::app::Clusters::BasicInformation::ProductFinishEnum * finish) override
542
0
    {
543
        // Our example device claims to have a Satin finish for now.  We can make
544
        // this configurable as needed.
545
0
        *finish = chip::app::Clusters::BasicInformation::ProductFinishEnum::kSatin;
546
0
        return CHIP_NO_ERROR;
547
0
    }
548
549
    CHIP_ERROR GetProductPrimaryColor(chip::app::Clusters::BasicInformation::ColorEnum * primaryColor) override
550
0
    {
551
        // Our example device claims to have a nice purple color for now.  We can
552
        // make this configurable as needed.
553
0
        *primaryColor = chip::app::Clusters::BasicInformation::ColorEnum::kPurple;
554
0
        return CHIP_NO_ERROR;
555
0
    }
556
557
    // Once an attribute has been set with one of these Set methods, the
558
    // corresponding Get method will return the stored value instead of getting
559
    // the value from the default provider.
560
0
    void SetVendorName(const std::string & buf) { mVendorName = buf; }
561
0
    void SetProductName(const std::string & buf) { mProductName = buf; }
562
0
    void SetSerialNumber(const std::string & buf) { mSerialNumber = buf; }
563
0
    void SetHardwareVersionString(const std::string & buf) { mHardwareVersionString = buf; }
564
565
private:
566
    DeviceInstanceInfoProvider * mDefaultProvider;
567
568
    // Values of basic information cluster attributes that may be set from the command-line.
569
    // When GetX is called, if this has a value it will be returned instead of getting the
570
    // value from the default provider.
571
    std::optional<std::string> mVendorName;
572
    std::optional<std::string> mProductName;
573
    std::optional<std::string> mSerialNumber;
574
    std::optional<std::string> mHardwareVersionString;
575
576
    static inline bool CanFitInNullTerminatedString(const std::string & candidate, size_t bufSizeIncludingNull)
577
0
    {
578
0
        return bufSizeIncludingNull >= (candidate.size() + 1);
579
0
    }
580
};
581
582
ExampleDeviceInstanceInfoProvider gExampleDeviceInstanceInfoProvider;
583
584
int ChipLinuxAppInit(int argc, char * const argv[], OptionSet * customOptions,
585
                     const Optional<EndpointId> secondaryNetworkCommissioningEndpoint)
586
0
{
587
0
    CHIP_ERROR err            = CHIP_NO_ERROR;
588
0
    bool isAllClustersVariant = (std::string(argv[0]).find("all-clusters") != std::string::npos);
589
0
    DeviceInstanceInfoProvider * defaultDeviceInstanceInfoProvider = nullptr;
590
591
0
#if CONFIG_NETWORK_LAYER_BLE
592
0
    RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kBLE;
593
#else  // CONFIG_NETWORK_LAYER_BLE
594
    RendezvousInformationFlags rendezvousFlags = RendezvousInformationFlag::kOnNetwork;
595
#endif // CONFIG_NETWORK_LAYER_BLE
596
597
#ifdef CONFIG_RENDEZVOUS_MODE
598
    rendezvousFlags = static_cast<RendezvousInformationFlags>(CONFIG_RENDEZVOUS_MODE);
599
#endif
600
601
0
    err = Platform::MemoryInit();
602
0
    SuccessOrExit(err);
603
604
0
    err = ParseArguments(argc, argv, customOptions);
605
0
    SuccessOrExit(err);
606
607
0
#if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
608
0
    if (LinuxDeviceOptions::GetInstance().mWiFiPAF)
609
0
    {
610
0
        rendezvousFlags.Set(RendezvousInformationFlag::kWiFiPAF);
611
0
    }
612
0
#endif
613
614
0
    sSecondaryNetworkCommissioningEndpoint = secondaryNetworkCommissioningEndpoint;
615
616
0
#ifdef CHIP_CONFIG_KVS_PATH
617
0
    if (LinuxDeviceOptions::GetInstance().KVS == nullptr)
618
0
    {
619
0
        err = DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(CHIP_CONFIG_KVS_PATH);
620
0
    }
621
0
    else
622
0
    {
623
0
        err = DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(LinuxDeviceOptions::GetInstance().KVS);
624
0
    }
625
0
    SuccessOrExit(err);
626
0
#endif
627
628
#if defined(ENABLE_CHIP_SHELL)
629
    /* Block SIGINT and SIGTERM. Other threads created by the main thread
630
     * will inherit the signal mask. Then we can explicitly unblock signals
631
     * in the shell thread to handle them, so the read(stdin) call can be
632
     * interrupted by a signal. */
633
    sigset_t set;
634
    sigemptyset(&set);
635
    sigaddset(&set, SIGINT);
636
    sigaddset(&set, SIGTERM);
637
    pthread_sigmask(SIG_BLOCK, &set, nullptr);
638
#endif
639
640
0
    err = DeviceLayer::PlatformMgr().InitChipStack();
641
0
    SuccessOrExit(err);
642
643
    // Init the commissionable data provider based on command line options
644
    // to handle custom verifiers, discriminators, etc.
645
0
    err = chip::examples::InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance());
646
0
    SuccessOrExit(err);
647
0
    DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider);
648
649
0
    err = chip::examples::InitConfigurationManager(reinterpret_cast<ConfigurationManagerImpl &>(ConfigurationMgr()),
650
0
                                                   LinuxDeviceOptions::GetInstance());
651
0
    SuccessOrExit(err);
652
653
0
    if (LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.HasValue())
654
0
    {
655
0
        rendezvousFlags = LinuxDeviceOptions::GetInstance().payload.rendezvousInformation.Value();
656
0
    }
657
658
0
    err = GetPayloadContents(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags);
659
0
    SuccessOrExit(err);
660
661
    // We need to set DeviceInfoProvider before Server::Init to set up the storage of DeviceInfoProvider properly.
662
0
    if (isAllClustersVariant)
663
0
    {
664
0
        DeviceLayer::SetDeviceInfoProvider(&gAllClustersExampleDeviceInfoProvider);
665
0
    }
666
0
    else
667
0
    {
668
0
        DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
669
0
    }
670
671
0
    ConfigurationMgr().LogDeviceConfig();
672
673
0
    {
674
0
        ChipLogProgress(NotSpecified, "==== Onboarding payload for Standard Commissioning Flow ====");
675
0
        PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload);
676
0
    }
677
678
#if defined(PW_RPC_ENABLED)
679
    rpc::Init(LinuxDeviceOptions::GetInstance().rpcServerPort);
680
    ChipLogProgress(NotSpecified, "PW_RPC initialized.");
681
#endif // defined(PW_RPC_ENABLED)
682
683
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::PlatformMgrImpl().AddEventHandler(EventHandler, 0);
684
685
0
#if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
686
0
    if (LinuxDeviceOptions::GetInstance().traceStreamFilename.HasValue())
687
0
    {
688
0
        const char * traceFilename = LinuxDeviceOptions::GetInstance().traceStreamFilename.Value().c_str();
689
0
        auto traceStream           = new chip::trace::TraceStreamFile(traceFilename);
690
0
        chip::trace::AddTraceStream(traceStream);
691
0
    }
692
0
    else if (LinuxDeviceOptions::GetInstance().traceStreamToLogEnabled)
693
0
    {
694
0
        auto traceStream = new chip::trace::TraceStreamLog();
695
0
        chip::trace::AddTraceStream(traceStream);
696
0
    }
697
698
0
    if (LinuxDeviceOptions::GetInstance().traceStreamDecodeEnabled)
699
0
    {
700
0
        chip::trace::TraceDecoderOptions options;
701
0
        options.mEnableProtocolInteractionModelResponse = false;
702
703
0
        chip::trace::TraceDecoder * decoder = new chip::trace::TraceDecoder();
704
0
        decoder->SetOptions(options);
705
0
        chip::trace::AddTraceStream(decoder);
706
0
    }
707
0
    chip::trace::InitTrace();
708
0
#endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
709
710
0
#if CONFIG_NETWORK_LAYER_BLE
711
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr); // Use default device name (CHIP-XXXX)
712
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(LinuxDeviceOptions::GetInstance().mBleDevice, false);
713
0
    TEMPORARY_RETURN_IGNORED DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true);
714
0
#endif
715
716
0
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
717
0
    if (LinuxDeviceOptions::GetInstance().mWiFi)
718
0
    {
719
        // Start WiFi management in Concurrent mode
720
0
        DeviceLayer::ConnectivityMgrImpl().StartWiFiManagement();
721
0
        if (!EnsureWiFiIsStarted())
722
0
        {
723
0
            ChipLogError(NotSpecified, "Wi-Fi Management taking too long to start - device configuration will be reset.");
724
0
        }
725
0
    }
726
0
#endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
727
0
#if CHIP_DEVICE_CONFIG_ENABLE_WPA && CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF && CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
728
0
    if (LinuxDeviceOptions::GetInstance().mWiFi && LinuxDeviceOptions::GetInstance().mWiFiPAF)
729
0
    {
730
0
        ChipLogProgress(WiFiPAF, "WiFi-PAF: initialzing");
731
0
        if (EnsureWiFiIsStarted())
732
0
        {
733
0
            ChipLogProgress(WiFiPAF, "Wi-Fi Management started");
734
0
            DeviceLayer::ConnectivityManager::WiFiPAFAdvertiseParam args;
735
736
0
            args.freq_list_len = WiFiPAFGet_FreqList(LinuxDeviceOptions::GetInstance().mWiFiPAFExtCmds, args.freq_list);
737
0
            DeviceLayer::ConnectivityMgr().WiFiPAFSetParam(args);
738
0
        }
739
0
    }
740
0
#endif
741
742
#if CHIP_ENABLE_OPENTHREAD
743
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
744
    if (LinuxDeviceOptions::GetInstance().mThreadNodeId)
745
    {
746
        std::string nodeid  = std::to_string(LinuxDeviceOptions::GetInstance().mThreadNodeId);
747
        std::string logfile = "--log-file=thread.log";
748
        char * args[]       = { argv[0], logfile.data(), nodeid.data() };
749
750
        otSysInit(MATTER_ARRAY_SIZE(args), args);
751
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().InitThreadStack());
752
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().StartThreadTask());
753
        ChipLogProgress(NotSpecified, "Thread initialized.");
754
    }
755
#else
756
    if (LinuxDeviceOptions::GetInstance().mThread)
757
    {
758
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().InitThreadStack());
759
        SuccessOrExit(err = DeviceLayer::ThreadStackMgrImpl().StartThreadTask());
760
        ChipLogProgress(NotSpecified, "Thread initialized.");
761
    }
762
#endif
763
#endif
764
765
#if CHIP_CONFIG_ENABLE_ICD_SERVER
766
    if (LinuxDeviceOptions::GetInstance().icdActiveModeDurationMs.HasValue() ||
767
        LinuxDeviceOptions::GetInstance().icdIdleModeDurationMs.HasValue() ||
768
        LinuxDeviceOptions::GetInstance().shortIdleModeDurationS.has_value())
769
    {
770
        // Convert icdIdleModeDurationMs to seconds for SetModeDurations api
771
        std::optional<System::Clock::Seconds32> tmpIdleModeDuration = std::nullopt;
772
        if (LinuxDeviceOptions::GetInstance().icdIdleModeDurationMs.HasValue())
773
            tmpIdleModeDuration = std::chrono::duration_cast<System::Clock::Seconds32>(
774
                LinuxDeviceOptions::GetInstance().icdIdleModeDurationMs.Value());
775
776
        err = Server::GetInstance().GetICDManager().SetModeDurations(
777
            LinuxDeviceOptions::GetInstance().icdActiveModeDurationMs.std_optional(), tmpIdleModeDuration,
778
            LinuxDeviceOptions::GetInstance().shortIdleModeDurationS);
779
780
        if (err != CHIP_NO_ERROR)
781
        {
782
            ChipLogError(NotSpecified, "Invalid arguments to set ICD mode durations");
783
            SuccessOrExit(err);
784
        }
785
    }
786
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
787
788
    // Initialize the ExampleDeviceInstanceInfoProvider.
789
0
    defaultDeviceInstanceInfoProvider = GetDeviceInstanceInfoProvider();
790
0
    if (defaultDeviceInstanceInfoProvider != &gExampleDeviceInstanceInfoProvider)
791
0
    {
792
0
        gExampleDeviceInstanceInfoProvider.Init(defaultDeviceInstanceInfoProvider);
793
0
        SetDeviceInstanceInfoProvider(&gExampleDeviceInstanceInfoProvider);
794
0
    }
795
796
    // Command line arguments to set attributes of the basic information cluster.
797
0
    if (LinuxDeviceOptions::GetInstance().vendorName.HasValue())
798
0
        gExampleDeviceInstanceInfoProvider.SetVendorName(LinuxDeviceOptions::GetInstance().vendorName.Value());
799
800
0
    if (LinuxDeviceOptions::GetInstance().productName.HasValue())
801
0
        gExampleDeviceInstanceInfoProvider.SetProductName(LinuxDeviceOptions::GetInstance().productName.Value());
802
803
0
    if (LinuxDeviceOptions::GetInstance().serialNumber.HasValue())
804
0
        gExampleDeviceInstanceInfoProvider.SetSerialNumber(LinuxDeviceOptions::GetInstance().serialNumber.Value());
805
806
0
    if (LinuxDeviceOptions::GetInstance().hardwareVersionString.HasValue())
807
0
        gExampleDeviceInstanceInfoProvider.SetHardwareVersionString(
808
0
            LinuxDeviceOptions::GetInstance().hardwareVersionString.Value());
809
810
0
exit:
811
0
    if (err != CHIP_NO_ERROR)
812
0
    {
813
0
        ChipLogProgress(NotSpecified, "Failed to init Linux App: %s ", ErrorStr(err));
814
0
        Cleanup();
815
816
        // End the program with non zero error code to indicate a error.
817
0
        return 1;
818
0
    }
819
0
    return 0;
820
0
}
821
822
struct LinuxCommonCaseDeviceServerInitParams final : public chip::CommonCaseDeviceServerInitParams
823
{
824
    LinuxCommonCaseDeviceServerInitParams()
825
0
    {
826
0
        SuccessOrDie(InitializeStaticResourcesBeforeServerInit());
827
0
        dataModelProvider = app::CodegenDataModelProviderInstance(persistentStorageDelegate);
828
0
    }
829
};
830
831
chip::CommonCaseDeviceServerInitParams & ChipLinuxDefaultServerInitParams()
832
0
{
833
0
    static LinuxCommonCaseDeviceServerInitParams sInitParams;
834
0
    return sInitParams;
835
0
}
836
837
void ChipLinuxAppMainLoop(chip::ServerInitParams & initParams, AppMainLoopImplementation * impl)
838
0
{
839
0
    gMainLoopImplementation = impl;
840
841
#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
842
    if (LinuxDeviceOptions::GetInstance().tcVersion.HasValue() && LinuxDeviceOptions::GetInstance().tcRequired.HasValue())
843
    {
844
        uint16_t version  = LinuxDeviceOptions::GetInstance().tcVersion.Value();
845
        uint16_t required = LinuxDeviceOptions::GetInstance().tcRequired.Value();
846
        Optional<app::TermsAndConditions> requiredAcknowledgements(app::TermsAndConditions(required, version));
847
        SuccessOrDie(
848
            app::TermsAndConditionsManager::GetInstance().Init(initParams.persistentStorageDelegate, requiredAcknowledgements));
849
    }
850
#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED
851
852
#if defined(ENABLE_CHIP_SHELL)
853
    Engine::Root().Init();
854
    Shell::RegisterCommissioneeCommands();
855
    std::thread shellThread([]() {
856
        sigset_t set;
857
        sigemptyset(&set);
858
        sigaddset(&set, SIGINT);
859
        sigaddset(&set, SIGTERM);
860
        // Unblock SIGINT and SIGTERM, so that the shell thread can handle
861
        // them - we need read() call to be interrupted.
862
        pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
863
        Engine::Root().RunMainLoop();
864
        StopMainEventLoop();
865
    });
866
#endif
867
0
    initParams.operationalServicePort        = CHIP_PORT;
868
0
    initParams.userDirectedCommissioningPort = CHIP_UDC_PORT;
869
870
0
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE || CHIP_DEVICE_ENABLE_PORT_PARAMS
871
    // use a different service port to make testing possible with other sample devices running on same host
872
0
    initParams.operationalServicePort        = LinuxDeviceOptions::GetInstance().securedDevicePort;
873
0
    initParams.userDirectedCommissioningPort = LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort;
874
0
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
875
876
#if CHIP_DEVICE_CONFIG_ENABLE_PORT_RETRY
877
    // Enable automatic port retry to handle port conflicts
878
    initParams.portRetryCount = CHIP_DEVICE_CONFIG_PORT_RETRY_COUNT;
879
#endif
880
881
#if ENABLE_TRACING
882
    chip::CommandLineApp::TracingSetup tracing_setup;
883
884
    for (const auto & trace_destination : LinuxDeviceOptions::GetInstance().traceTo)
885
    {
886
        tracing_setup.EnableTracingFor(trace_destination.c_str());
887
    }
888
#endif
889
890
0
    initParams.interfaceId = LinuxDeviceOptions::GetInstance().interfaceId;
891
892
0
    if (LinuxDeviceOptions::GetInstance().mCSRResponseOptions.csrExistingKeyPair)
893
0
    {
894
0
        SuccessOrDie(LinuxDeviceOptions::GetInstance().mCSRResponseOptions.badCsrOperationalKeyStoreForTest.Init(
895
0
            initParams.persistentStorageDelegate));
896
0
        initParams.operationalKeystore = &LinuxDeviceOptions::GetInstance().mCSRResponseOptions.badCsrOperationalKeyStoreForTest;
897
0
    }
898
899
    // For general testing of TestEventTrigger, we have a common "core" event trigger delegate.
900
0
    static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate;
901
0
    static SampleTestEventTriggerHandler sTestEventTriggerHandler;
902
0
    VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(LinuxDeviceOptions::GetInstance().testEventTriggerEnableKey)) ==
903
0
                CHIP_NO_ERROR);
904
0
    VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sTestEventTriggerHandler) == CHIP_NO_ERROR);
905
906
#if CHIP_DEVICE_CONFIG_ENABLE_SOFTWARE_DIAGNOSTIC_TRIGGER
907
    static SoftwareDiagnosticsTestEventTriggerHandler sSoftwareDiagnosticsTestEventTriggerHandler;
908
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sSoftwareDiagnosticsTestEventTriggerHandler));
909
#endif
910
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_DIAGNOSTIC_TRIGGER
911
    static WiFiDiagnosticsTestEventTriggerHandler sWiFiDiagnosticsTestEventTriggerHandler;
912
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sWiFiDiagnosticsTestEventTriggerHandler));
913
#endif
914
#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR
915
    // We want to allow triggering OTA queries if OTA requestor is enabled
916
    static OTATestEventTriggerHandler sOtaTestEventTriggerHandler;
917
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler));
918
#endif
919
#if CHIP_DEVICE_CONFIG_ENABLE_SMOKE_CO_TRIGGER
920
    static SmokeCOTestEventTriggerHandler sSmokeCOTestEventTriggerHandler;
921
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sSmokeCOTestEventTriggerHandler));
922
#endif
923
#if CHIP_DEVICE_CONFIG_ENABLE_BOOLEAN_STATE_CONFIGURATION_TRIGGER
924
    static BooleanStateConfigurationTestEventTriggerHandler sBooleanStateConfigurationTestEventTriggerHandler;
925
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sBooleanStateConfigurationTestEventTriggerHandler));
926
#endif
927
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_PRICE_TRIGGER
928
    static CommodityPriceTestEventTriggerHandler sCommodityPriceTestEventTriggerHandler;
929
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sCommodityPriceTestEventTriggerHandler));
930
#endif
931
#if CHIP_DEVICE_CONFIG_ENABLE_ELECTRICAL_GRID_CONDITIONS_TRIGGER
932
    static ElectricalGridConditionsTestEventTriggerHandler sElectricalGridConditionsTestEventTriggerHandler;
933
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sElectricalGridConditionsTestEventTriggerHandler));
934
#endif
935
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_TARIFF_TRIGGER
936
    static CommodityTariffTestEventTriggerHandler sCommodityTariffTestEventTriggerHandler;
937
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sCommodityTariffTestEventTriggerHandler));
938
#endif
939
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
940
    static EnergyEvseTestEventTriggerHandler sEnergyEvseTestEventTriggerHandler;
941
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sEnergyEvseTestEventTriggerHandler));
942
#endif
943
#if CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
944
    static EnergyReportingTestEventTriggerHandler sEnergyReportingTestEventTriggerHandler;
945
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sEnergyReportingTestEventTriggerHandler));
946
#endif
947
#if CHIP_DEVICE_CONFIG_ENABLE_METER_IDENTIFICATION_TRIGGER
948
    static MeterIdentificationTestEventTriggerHandler sMeterIdentificationTestEventTriggerHandler;
949
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sMeterIdentificationTestEventTriggerHandler));
950
#endif
951
#if CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
952
    static WaterHeaterManagementTestEventTriggerHandler sWaterHeaterManagementTestEventTriggerHandler;
953
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sWaterHeaterManagementTestEventTriggerHandler));
954
#endif
955
#if CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
956
    static DeviceEnergyManagementTestEventTriggerHandler sDeviceEnergyManagementTestEventTriggerHandler;
957
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&sDeviceEnergyManagementTestEventTriggerHandler));
958
#endif
959
#if CHIP_DEVICE_CONFIG_ENABLE_COMMODITY_METERING_TRIGGER
960
    static CommodityMeteringTestEventTriggerHandler CommodityMeteringTestEventTriggerHandler;
961
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&CommodityMeteringTestEventTriggerHandler));
962
#endif
963
#if CHIP_CONFIG_ENABLE_ICD_SERVER
964
    SuccessOrDie(sTestEventTriggerDelegate.AddHandler(&Server::GetInstance().GetICDManager()));
965
#endif
966
967
0
    initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate;
968
969
0
    chip::app::RuntimeOptionsProvider::Instance().SetSimulateNoInternalTime(
970
0
        LinuxDeviceOptions::GetInstance().mSimulateNoInternalTime);
971
972
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
973
    initParams.accessRestrictionProvider = exampleAccessRestrictionProvider.get();
974
#endif
975
976
#if CHIP_SYSTEM_CONFIG_USE_OPENTHREAD_ENDPOINT
977
    chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
978
    nativeParams.lockCb                = []() { chip::DeviceLayer::ThreadStackMgr().LockThreadStack(); };
979
    nativeParams.unlockCb              = []() { chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack(); };
980
    nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
981
    initParams.endpointNativeParams    = static_cast<void *>(&nativeParams);
982
#endif
983
0
    if (LinuxDeviceOptions::GetInstance().payload.commissioningFlow == CommissioningFlow::kUserActionRequired)
984
0
    {
985
0
        initParams.advertiseCommissionableIfNoFabrics = false;
986
0
    }
987
988
    // Set DAC provider before server init because Operational Credentials may snapshot
989
    // the provider during cluster construction.
990
0
    SetDeviceAttestationCredentialsProvider(LinuxDeviceOptions::GetInstance().dacProvider);
991
992
    // Init ZCL Data Model and CHIP App Server
993
0
    CHIP_ERROR err = Server::GetInstance().Init(initParams);
994
0
    if (err != CHIP_NO_ERROR)
995
0
    {
996
0
        ChipLogError(AppServer, "Server init failed: %" CHIP_ERROR_FORMAT, err.Format());
997
0
        chipDie();
998
0
    }
999
1000
#if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
1001
    if (LinuxDeviceOptions::GetInstance().commissioningArlEntries.HasValue())
1002
    {
1003
        SuccessOrDie(exampleAccessRestrictionProvider->SetCommissioningEntries(
1004
            LinuxDeviceOptions::GetInstance().commissioningArlEntries.Value()));
1005
    }
1006
1007
    if (LinuxDeviceOptions::GetInstance().arlEntries.HasValue())
1008
    {
1009
        // This example use of the ARL feature proactively installs the provided entries on fabric index 1
1010
        SuccessOrDie(exampleAccessRestrictionProvider->SetEntries(1, LinuxDeviceOptions::GetInstance().arlEntries.Value()));
1011
    }
1012
#endif
1013
1014
0
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
1015
    // Set ReadHandler Capacity for Subscriptions
1016
0
    chip::app::InteractionModelEngine::GetInstance()->SetHandlerCapacityForSubscriptions(
1017
0
        LinuxDeviceOptions::GetInstance().subscriptionCapacity);
1018
0
    chip::app::InteractionModelEngine::GetInstance()->SetForceHandlerQuota(true);
1019
0
#if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1020
    // Set subscription time resumption retry interval seconds
1021
0
    chip::app::InteractionModelEngine::GetInstance()->SetSubscriptionTimeoutResumptionRetryIntervalSeconds(
1022
0
        LinuxDeviceOptions::GetInstance().subscriptionResumptionRetryIntervalSec);
1023
0
#endif // CHIP_CONFIG_PERSIST_SUBSCRIPTIONS && CHIP_CONFIG_SUBSCRIPTION_TIMEOUT_RESUMPTION
1024
0
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
1025
1026
    // Now that the server has started and we are done with our startup logging,
1027
    // log our discovery/onboarding information again so it's not lost in the
1028
    // noise.
1029
0
    ConfigurationMgr().LogDeviceConfig();
1030
1031
0
    PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload);
1032
1033
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1034
#if CHIP_LINUX_APP_START_COMMISSIONER_AT_BOOT
1035
    ChipLogProgress(AppServer, "Starting commissioner");
1036
    VerifyOrReturn(InitCommissioner(LinuxDeviceOptions::GetInstance().securedCommissionerPort,
1037
                                    LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort,
1038
                                    LinuxDeviceOptions::GetInstance().commissionerFabricId) == CHIP_NO_ERROR);
1039
    ChipLogProgress(AppServer, "Started commissioner");
1040
#endif // CHIP_LINUX_APP_START_COMMISSIONER_AT_BOOT
1041
#if defined(ENABLE_CHIP_SHELL)
1042
    Shell::RegisterControllerCommands();
1043
#endif // defined(ENABLE_CHIP_SHELL)
1044
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1045
1046
0
    InitNetworkCommissioning();
1047
1048
0
    ApplicationInit();
1049
1050
#if CHIP_DEVICE_LAYER_TARGET_DARWIN
1051
#if CHIP_SYSTEM_CONFIG_USE_DISPATCH
1052
    auto & platformMgr = chip::DeviceLayer::PlatformMgrImpl();
1053
    platformMgr.RegisterSignalHandler(SIGINT, ^{
1054
        StopSignalHandler(SIGINT);
1055
    });
1056
1057
    platformMgr.RegisterSignalHandler(SIGTERM, ^{
1058
        StopSignalHandler(SIGTERM);
1059
    });
1060
#else
1061
    // NOTE: For some reason, on Darwin, the signal handler is not called if the signal is
1062
    //       registered with sigaction() call and TSAN is enabled. The problem seems to be
1063
    //       related with the dispatch_semaphore_wait() function in the RunEventLoop() method.
1064
    //       If this call is commented out, the signal handler is called as expected...
1065
    // NOLINTBEGIN(bugprone-signal-handler)
1066
    signal(SIGINT, StopSignalHandler);
1067
    signal(SIGTERM, StopSignalHandler);
1068
    // NOLINTEND(bugprone-signal-handler)
1069
#endif
1070
#else
1071
0
    struct sigaction sa                        = {};
1072
0
    sa.sa_handler                              = StopSignalHandler;
1073
0
    sa.sa_flags                                = SA_RESETHAND;
1074
0
    sigaction(SIGINT, &sa, nullptr);
1075
0
    sigaction(SIGTERM, &sa, nullptr);
1076
0
#endif
1077
1078
    // This message is used as a marker for when the application process has started.
1079
    // See: scripts/tests/chiptest/test_definition.py
1080
    // TODO: A cleaner and more generic mechanism needs to be developed as a follow-up.
1081
    // Currently other places (OTA, TV) also scrape logs for information and a better way should be
1082
    // possible.
1083
0
    ChipLogProgress(DeviceLayer, "===== APP STATUS: Starting event loop =====");
1084
0
    if (impl != nullptr)
1085
0
    {
1086
0
        impl->RunMainLoop();
1087
0
    }
1088
0
    else
1089
0
    {
1090
0
        DeviceLayer::PlatformMgr().RunEventLoop();
1091
0
    }
1092
0
    gMainLoopImplementation = nullptr;
1093
1094
0
    ApplicationShutdown();
1095
1096
#if defined(ENABLE_CHIP_SHELL)
1097
    shellThread.join();
1098
#endif
1099
1100
#if CHIP_DEVICE_LAYER_TARGET_DARWIN && CHIP_SYSTEM_CONFIG_USE_DISPATCH
1101
    platformMgr.UnregisterAllSignalHandlers();
1102
#endif
1103
1104
0
    Server::GetInstance().Shutdown();
1105
1106
#if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1107
    ShutdownCommissioner();
1108
#endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
1109
1110
0
    DeviceLayer::PlatformMgr().Shutdown();
1111
1112
#if ENABLE_TRACING
1113
    tracing_setup.StopTracing();
1114
#endif
1115
1116
0
    Cleanup();
1117
0
}