diff --git a/examples/bridge-app/linux/BUILD.gn b/examples/bridge-app/linux/BUILD.gn index 0f27218e003c55..eac94b9712c3db 100644 --- a/examples/bridge-app/linux/BUILD.gn +++ b/examples/bridge-app/linux/BUILD.gn @@ -22,13 +22,13 @@ executable("chip-bridge-app") { sources = [ "${chip_root}/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h", "Device.cpp", - "Options.cpp", "include/Device.h", "main.cpp", ] deps = [ "${chip_root}/examples/bridge-app/bridge-common", + "${chip_root}/examples/platform/linux:app-main", "${chip_root}/src/lib", ] diff --git a/examples/bridge-app/linux/Options.cpp b/examples/bridge-app/linux/Options.cpp deleted file mode 100644 index e88133e45d86f7..00000000000000 --- a/examples/bridge-app/linux/Options.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Copyright (c) 2021 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Options.h" - -#include -#include - -using namespace chip; -using namespace chip::ArgParser; - -namespace { -LinuxDeviceOptions gDeviceOptions; - -// Follow the code style of command line arguments in case we need to add more options in the future. -enum -{ - kDeviceOption_BleDevice = 0x1000, -}; - -OptionDef sDeviceOptionDefs[] = { { "ble-device", kArgumentRequired, kDeviceOption_BleDevice }, {} }; - -const char * sDeviceOptionHelp = " --ble-device \n" - " The device number for CHIPoBLE, without 'hci' prefix, can be found by hciconfig.\n" - "\n"; - -bool HandleOption(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue) -{ - bool retval = true; - - switch (aIdentifier) - { - - case kDeviceOption_BleDevice: - if (!ParseInt(aValue, LinuxDeviceOptions::GetInstance().mBleDevice)) - { - PrintArgError("%s: invalid value specified for ble device number: %s\n", aProgram, aValue); - retval = false; - } - break; - - default: - PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName); - retval = false; - break; - } - - return (retval); -} - -OptionSet sDeviceOptions = { HandleOption, sDeviceOptionDefs, "GENERAL OPTIONS", sDeviceOptionHelp }; - -OptionSet * sLinuxDeviceOptionSets[] = { &sDeviceOptions, nullptr }; -} // namespace - -CHIP_ERROR ParseArguments(int argc, char * argv[]) -{ - if (!ParseArgs(argv[0], argc, argv, sLinuxDeviceOptionSets)) - { - return CHIP_ERROR_INVALID_ARGUMENT; - } - return CHIP_NO_ERROR; -} - -LinuxDeviceOptions & LinuxDeviceOptions::GetInstance() -{ - return gDeviceOptions; -} diff --git a/examples/bridge-app/linux/include/Options.h b/examples/bridge-app/linux/include/Options.h deleted file mode 100644 index 6d1d5165caeb82..00000000000000 --- a/examples/bridge-app/linux/include/Options.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Copyright (c) 2020 Project CHIP Authors - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Support functions for parsing command-line arguments. - * - */ - -#pragma once - -#include - -#include -#include - -struct LinuxDeviceOptions -{ - chip::SetupPayload payload; - uint32_t mBleDevice = 0; - - static LinuxDeviceOptions & GetInstance(); -}; - -CHIP_ERROR ParseArguments(int argc, char * argv[]); diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp index 02e92e87146693..a5ba5eb83f74c9 100644 --- a/examples/bridge-app/linux/main.cpp +++ b/examples/bridge-app/linux/main.cpp @@ -38,6 +38,7 @@ #include #include +#include "CommissionableInit.h" #include "Device.h" #include "Options.h" #include @@ -51,16 +52,21 @@ using namespace chip::Inet; using namespace chip::Transport; using namespace chip::DeviceLayer; -static const int kNodeLabelSize = 32; +namespace { + +const int kNodeLabelSize = 32; // Current ZCL implementation of Struct uses a max-size array of 254 bytes -static const int kDescriptorAttributeArraySize = 254; -static const int kFixedLabelAttributeArraySize = 254; +const int kDescriptorAttributeArraySize = 254; +const int kFixedLabelAttributeArraySize = 254; // Four attributes in descriptor cluster: DeviceTypeList, ServerList, ClientList, PartsList -static const int kFixedLabelElementsOctetStringSize = 16; +const int kFixedLabelElementsOctetStringSize = 16; + +EndpointId gCurrentEndpointId; +EndpointId gFirstDynamicEndpointId; +Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; -static EndpointId gCurrentEndpointId; -static EndpointId gFirstDynamicEndpointId; -static Device * gDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT]; +// To hold SPAKE2+ verifier, discriminator, passcode +LinuxCommissionableDataProvider gCommissionableDataProvider; // ENDPOINT DEFINITIONS: // ================================================================================= @@ -194,6 +200,8 @@ DECLARE_DYNAMIC_ENDPOINT(bridgedSwitchEndpoint, bridgedSwitchClusters); DataVersion gSwitch1DataVersions[ArraySize(bridgedSwitchClusters)]; DataVersion gSwitch2DataVersions[ArraySize(bridgedSwitchClusters)]; +} // namespace + // REVISION DEFINITIONS: // ================================================================================= @@ -653,22 +661,37 @@ int main(int argc, char * argv[]) err = chip::DeviceLayer::PlatformMgr().InitChipStack(); SuccessOrExit(err); + // Init the commissionable data provider based on command line options + // to handle custom verifiers, discriminators, etc. + err = chip::examples::InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); + SuccessOrExit(err); + DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider); + + err = chip::examples::InitConfigurationManager(reinterpret_cast(ConfigurationMgr()), + LinuxDeviceOptions::GetInstance()); + SuccessOrExit(err); + err = PrintQRCodeContent(); SuccessOrExit(err); chip::DeviceLayer::PlatformMgrImpl().AddEventHandler(EventHandler, 0); - chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr); // Use default device name (CHIP-XXXX) - #if CONFIG_NETWORK_LAYER_BLE + chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(nullptr); // Use default device name (CHIP-XXXX) chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureBle(LinuxDeviceOptions::GetInstance().mBleDevice, false); -#endif - chip::DeviceLayer::ConnectivityMgr().SetBLEAdvertisingEnabled(true); +#endif - // Init ZCL Data Model and CHIP App Server + // Init Data Model and CHIP App Server static chip::CommonCaseDeviceServerInitParams initParams; (void) initParams.InitializeStaticResourcesBeforeServerInit(); + +#if CHIP_DEVICE_ENABLE_PORT_PARAMS + // use a different service port to make testing possible with other sample devices running on same host + initParams.operationalServicePort = LinuxDeviceOptions::GetInstance().securedDevicePort; +#endif + + initParams.interfaceId = LinuxDeviceOptions::GetInstance().interfaceId; chip::Server::GetInstance().Init(initParams); // Initialize device attestation config diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index 0ada93be2049a9..08892c7afe4b2a 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -40,8 +40,6 @@ #include #include -#include -#include #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include "CommissionerMain.h" @@ -69,7 +67,7 @@ #include #include "AppMain.h" -#include "LinuxCommissionableDataProvider.h" +#include "CommissionableInit.h" using namespace chip; using namespace chip::ArgParser; @@ -162,80 +160,6 @@ void SetupSignalHandlers() signal(SIGINT, OnSignalHandler); } -CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options) -{ - chip::Optional setupPasscode; - - if (options.payload.setUpPINCode != 0) - { - setupPasscode.SetValue(options.payload.setUpPINCode); - } - else if (!options.spake2pVerifier.HasValue()) - { - uint32_t defaultTestPasscode = 0; - chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; - VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR); - - ChipLogError(Support, - "*** WARNING: Using temporary passcode %u due to no neither --passcode or --spake2p-verifier-base64 " - "given on command line. This is temporary and will disappear. Please update your scripts " - "to explicitly configure onboarding credentials. ***", - static_cast(defaultTestPasscode)); - setupPasscode.SetValue(defaultTestPasscode); - options.payload.setUpPINCode = defaultTestPasscode; - } - else - { - // Passcode is 0, so will be ignored, and verifier will take over. Onboarding payload - // printed for debug will be invalid, but if the onboarding payload had been given - // properly to the commissioner later, PASE will succeed. - } - - if (options.discriminator.HasValue()) - { - options.payload.discriminator = options.discriminator.Value(); - } - else - { - uint16_t defaultTestDiscriminator = 0; - chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; - VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupDiscriminator(defaultTestDiscriminator) == CHIP_NO_ERROR); - - ChipLogError(Support, - "*** WARNING: Using temporary test discriminator %u due to --discriminator not " - "given on command line. This is temporary and will disappear. Please update your scripts " - "to explicitly configure discriminator. ***", - static_cast(defaultTestDiscriminator)); - options.payload.discriminator = defaultTestDiscriminator; - } - - // Default to minimum PBKDF iterations - uint32_t spake2pIterationCount = chip::Crypto::kSpake2p_Min_PBKDF_Iterations; - if (options.spake2pIterations != 0) - { - spake2pIterationCount = options.spake2pIterations; - } - ChipLogError(Support, "PASE PBKDF iterations set to %u", static_cast(spake2pIterationCount)); - - return provider.Init(options.spake2pVerifier, options.spake2pSalt, spake2pIterationCount, setupPasscode, - options.payload.discriminator); -} - -CHIP_ERROR InitConfigurationManager(ConfigurationManagerImpl & configManager, LinuxDeviceOptions & options) -{ - if (options.payload.vendorID != 0) - { - configManager.StoreVendorId(options.payload.vendorID); - } - - if (options.payload.productID != 0) - { - configManager.StoreProductId(options.payload.productID); - } - - return CHIP_NO_ERROR; -} - void Cleanup() { #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED @@ -305,12 +229,12 @@ int ChipLinuxAppInit(int argc, char ** argv, OptionSet * customOptions) // Init the commissionable data provider based on command line options // to handle custom verifiers, discriminators, etc. - err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); + err = chip::examples::InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); SuccessOrExit(err); DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider); - err = InitConfigurationManager(reinterpret_cast(ConfigurationMgr()), - LinuxDeviceOptions::GetInstance()); + err = chip::examples::InitConfigurationManager(reinterpret_cast(ConfigurationMgr()), + LinuxDeviceOptions::GetInstance()); SuccessOrExit(err); err = GetSetupPayload(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags); @@ -318,15 +242,21 @@ int ChipLinuxAppInit(int argc, char ** argv, OptionSet * customOptions) ConfigurationMgr().LogDeviceConfig(); - PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload); + { + ChipLogProgress(NotSpecified, "==== Onboarding payload for Standard Commissioning Flow ===="); + PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload); + } - // For testing of manual pairing code with custom commissioning flow - err = GetSetupPayload(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags); - SuccessOrExit(err); + { + // For testing of manual pairing code with custom commissioning flow + ChipLogProgress(NotSpecified, "==== Onboarding payload for Custom Commissioning Flows ===="); + err = GetSetupPayload(LinuxDeviceOptions::GetInstance().payload, rendezvousFlags); + SuccessOrExit(err); - LinuxDeviceOptions::GetInstance().payload.commissioningFlow = chip::CommissioningFlow::kCustom; + LinuxDeviceOptions::GetInstance().payload.commissioningFlow = chip::CommissioningFlow::kCustom; - PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload); + PrintOnboardingCodes(LinuxDeviceOptions::GetInstance().payload); + } #if defined(PW_RPC_ENABLED) rpc::Init(); diff --git a/examples/platform/linux/BUILD.gn b/examples/platform/linux/BUILD.gn index 4cb3655e74ee51..d1be2f256b53a5 100644 --- a/examples/platform/linux/BUILD.gn +++ b/examples/platform/linux/BUILD.gn @@ -27,6 +27,8 @@ source_set("app-main") { sources = [ "AppMain.cpp", "AppMain.h", + "CommissionableInit.cpp", + "CommissionableInit.h", "CommissioneeShellCommands.cpp", "CommissioneeShellCommands.h", "CommissionerMain.cpp", diff --git a/examples/platform/linux/CommissionableInit.cpp b/examples/platform/linux/CommissionableInit.cpp new file mode 100644 index 00000000000000..8bb9ed90f42924 --- /dev/null +++ b/examples/platform/linux/CommissionableInit.cpp @@ -0,0 +1,106 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "CommissionableInit.h" + +namespace chip { +namespace examples { + +using namespace chip::DeviceLayer; + +CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options) +{ + chip::Optional setupPasscode; + + if (options.payload.setUpPINCode != 0) + { + setupPasscode.SetValue(options.payload.setUpPINCode); + } + else if (!options.spake2pVerifier.HasValue()) + { + uint32_t defaultTestPasscode = 0; + chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; + VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR); + + ChipLogError(Support, + "*** WARNING: Using temporary passcode %u due to no neither --passcode or --spake2p-verifier-base64 " + "given on command line. This is temporary and will disappear. Please update your scripts " + "to explicitly configure onboarding credentials. ***", + static_cast(defaultTestPasscode)); + setupPasscode.SetValue(defaultTestPasscode); + options.payload.setUpPINCode = defaultTestPasscode; + } + else + { + // Passcode is 0, so will be ignored, and verifier will take over. Onboarding payload + // printed for debug will be invalid, but if the onboarding payload had been given + // properly to the commissioner later, PASE will succeed. + } + + if (options.discriminator.HasValue()) + { + options.payload.discriminator = options.discriminator.Value(); + } + else + { + uint16_t defaultTestDiscriminator = 0; + chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; + VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupDiscriminator(defaultTestDiscriminator) == CHIP_NO_ERROR); + + ChipLogError(Support, + "*** WARNING: Using temporary test discriminator %u due to --discriminator not " + "given on command line. This is temporary and will disappear. Please update your scripts " + "to explicitly configure discriminator. ***", + static_cast(defaultTestDiscriminator)); + options.payload.discriminator = defaultTestDiscriminator; + } + + // Default to minimum PBKDF iterations + uint32_t spake2pIterationCount = chip::Crypto::kSpake2p_Min_PBKDF_Iterations; + if (options.spake2pIterations != 0) + { + spake2pIterationCount = options.spake2pIterations; + } + ChipLogError(Support, "PASE PBKDF iterations set to %u", static_cast(spake2pIterationCount)); + + return provider.Init(options.spake2pVerifier, options.spake2pSalt, spake2pIterationCount, setupPasscode, + options.payload.discriminator); +} + +CHIP_ERROR InitConfigurationManager(ConfigurationManagerImpl & configManager, LinuxDeviceOptions & options) +{ + if (options.payload.vendorID != 0) + { + configManager.StoreVendorId(options.payload.vendorID); + } + + if (options.payload.productID != 0) + { + configManager.StoreProductId(options.payload.productID); + } + + return CHIP_NO_ERROR; +} + +} // namespace examples +} // namespace chip diff --git a/examples/platform/linux/CommissionableInit.h b/examples/platform/linux/CommissionableInit.h new file mode 100644 index 00000000000000..61d63e42dcce60 --- /dev/null +++ b/examples/platform/linux/CommissionableInit.h @@ -0,0 +1,51 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "LinuxCommissionableDataProvider.h" +#include "Options.h" +#include +#include +#include + +namespace chip { +namespace examples { + +/** + * @brief Initialize a LinuxCommissionableDataProvider from Linux common command-line + * options. Handles verifier, passcode, discriminator, etc. + * + * @param provider - provider to initialize from command line arguments + * @param options - LinuxDeviceOptions instance configured via command-line parsing + * @return CHIP_NO_ERROR on success or another CHIP_ERROR value on internal validation errors (likely fatal) + */ +CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options); + +/** + * @brief Initialize a Linux ConfigurationManagerImpl to reflect some command-line configured + * values such as VendorID/ProductID + * + * @param configManager - Linux-specific configuration manager to update + * @param options - LinuxDeviceOptions instance configured via command-line parsing + * @return CHIP_NO_ERROR on success or another CHIP_ERROR value on internal validation errors (likely fatal) + */ +CHIP_ERROR InitConfigurationManager(chip::DeviceLayer::ConfigurationManagerImpl & configManager, LinuxDeviceOptions & options); + +} // namespace examples +} // namespace chip