diff --git a/src/controller/AutoCommissioner.cpp b/src/controller/AutoCommissioner.cpp index 72470edec40edc..f34a2d055f26c3 100644 --- a/src/controller/AutoCommissioner.cpp +++ b/src/controller/AutoCommissioner.cpp @@ -392,6 +392,13 @@ CommissioningStage AutoCommissioner::GetNextCommissioningStageInternal(Commissio } return CommissioningStage::kFindOperational; case CommissioningStage::kFindOperational: + if (mParams.GetIcdRegistrationStrategy() != IcdRegistrationStrategy::kIgnore) + { + return CommissioningStage::kIcdDiscovery; + } + return CommissioningStage::kSendComplete; + case CommissioningStage::kIcdDiscovery: + // TODO(#29385): Register to the ICD. return CommissioningStage::kSendComplete; case CommissioningStage::kSendComplete: return CommissioningStage::kCleanup; @@ -705,6 +712,15 @@ CHIP_ERROR AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, Commissio case CommissioningStage::kFindOperational: mOperationalDeviceProxy = report.Get().operationalProxy; break; + case CommissioningStage::kIcdDiscovery: { + IcdInfo icdInfo = report.Get(); + if (icdInfo.isIcd) + { + mNeedIcdRegistraion = true; + ChipLogDetail(Controller, "AutoCommissioner: Device is ICD"); + } + break; + } case CommissioningStage::kCleanup: ReleasePAI(); ReleaseDAC(); diff --git a/src/controller/AutoCommissioner.h b/src/controller/AutoCommissioner.h index 66dafeef6851cb..e1459188043b68 100644 --- a/src/controller/AutoCommissioner.h +++ b/src/controller/AutoCommissioner.h @@ -106,6 +106,8 @@ class AutoCommissioner : public CommissioningDelegate ReadCommissioningInfo mDeviceCommissioningInfo; bool mNeedsDST = false; + bool mNeedIcdRegistraion = false; + // TODO: Why were the nonces statically allocated, but the certs dynamically allocated? uint8_t * mDAC = nullptr; uint16_t mDACLen = 0; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 9a59e89837329b..b3c21dccad65af 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -1880,6 +1880,9 @@ void DeviceCommissioner::OnDone(app::ReadClient *) case CommissioningStage::kCheckForMatchingFabric: ParseFabrics(); break; + case CommissioningStage::kIcdDiscovery: + ParseIcdInfo(); + break; default: // We're not trying to read anything here, just exit break; @@ -2175,6 +2178,43 @@ void DeviceCommissioner::ParseFabrics() CommissioningStageComplete(return_err, report); } +void DeviceCommissioner::ParseIcdInfo() +{ + CHIP_ERROR err; + IcdInfo info; + IcdManagement::Attributes::FeatureMap::TypeInfo::DecodableType featureMap; + + err = mAttributeCache->Get(kRootEndpointId, featureMap); + if (err == CHIP_NO_ERROR) + { + info.isIcd = true; + info.checkInProtocolSupport = !!(featureMap & 0x1); + } + else if (err == CHIP_ERROR_IM_STATUS_CODE_RECEIVED) + { + app::StatusIB statusIB; + err = mAttributeCache->GetStatus( + app::ConcreteAttributePath(kRootEndpointId, IcdManagement::Id, IcdManagement::Attributes::FeatureMap::Id), statusIB); + if (err != CHIP_NO_ERROR) + { + CommissioningStageComplete(err); + return; + } + if (statusIB.mStatus == Protocols::InteractionModel::Status::UnsupportedCluster) + { + info.isIcd = false; + } + else + { + err = statusIB.ToChipError(); + } + } + + CommissioningDelegate::CommissioningReport report; + report.Set(info); + CommissioningStageComplete(err, report); +} + void DeviceCommissioner::OnArmFailSafe(void * context, const GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data) { @@ -2782,6 +2822,14 @@ void DeviceCommissioner::PerformCommissioningStep(DeviceProxy * proxy, Commissio ); } break; + case CommissioningStage::kIcdDiscovery: { + app::AttributePathParams readPaths[1]; + // Read all the feature maps for all the networking clusters on any endpoint to determine what is supported + readPaths[0] = + app::AttributePathParams(app::Clusters::IcdManagement::Id, app::Clusters::IcdManagement::Attributes::FeatureMap::Id); + SendCommissioningReadRequest(proxy, timeout, readPaths, 1); + } + break; case CommissioningStage::kSendComplete: { GeneralCommissioning::Commands::CommissioningComplete::Type request; SendCommand(proxy, request, OnCommissioningCompleteResponse, OnBasicFailure, endpoint, timeout); diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index a83ca98fca5f3d..c9737518cf310a 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -938,6 +938,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController, void ParseFabrics(); // Called by ParseCommissioningInfo void ParseTimeSyncInfo(ReadCommissioningInfo & info); + void ParseIcdInfo(); #endif // CHIP_CONFIG_ENABLE_READ_CLIENT static CHIP_ERROR diff --git a/src/controller/CommissioningDelegate.cpp b/src/controller/CommissioningDelegate.cpp index 7100ee0865b392..d549a1c595e7e3 100644 --- a/src/controller/CommissioningDelegate.cpp +++ b/src/controller/CommissioningDelegate.cpp @@ -137,6 +137,10 @@ const char * StageToString(CommissioningStage stage) return "FindOperational"; break; + case kIcdDiscovery: + return "ICDDiscovery"; + break; + case kSendComplete: return "SendComplete"; break; diff --git a/src/controller/CommissioningDelegate.h b/src/controller/CommissioningDelegate.h index 47ca12166ec8bf..8759d062c3eb28 100644 --- a/src/controller/CommissioningDelegate.h +++ b/src/controller/CommissioningDelegate.h @@ -59,8 +59,12 @@ enum CommissioningStage : uint8_t kWiFiNetworkEnable, ///< Send ConnectNetwork (0x31:6) command to the device for the WiFi network kThreadNetworkEnable, ///< Send ConnectNetwork (0x31:6) command to the device for the Thread network kFindOperational, ///< Perform operational discovery and establish a CASE session with the device - kSendComplete, ///< Send CommissioningComplete (0x30:4) command to the device - kCleanup, ///< Call delegates with status, free memory, clear timers and state + /// Optional steps for ICD + kIcdDiscovery, ///< Check whether the device is an ICD + /// TODO(#29384): Finish ICD registration implementation in commissioner + /// End of optional steps for ICD + kSendComplete, ///< Send CommissioningComplete (0x30:4) command to the device + kCleanup, ///< Call delegates with status, free memory, clear timers and state /// Send ScanNetworks (0x31:0) command to the device. /// ScanNetworks can happen anytime after kArmFailsafe. /// However, the cirque tests fail if it is earlier in the list @@ -71,6 +75,13 @@ enum CommissioningStage : uint8_t kNeedsNetworkCreds, }; +enum IcdRegistrationStrategy +{ + kIgnore, ///< Do not check whether the device is an ICD during commissioning + kBeforeComplete, ///< Do commissioner self-registration or external controller registration, + ///< Controller should provide a ICDKey manager for generating symmetric key +}; + const char * StageToString(CommissioningStage stage); struct WiFiCredentials @@ -493,6 +504,13 @@ class CommissioningParameters return *this; } + IcdRegistrationStrategy GetIcdRegistrationStrategy() const { return mIcdRegistrationStrategy; } + CommissioningParameters & SetIcdRegistrationStrategy(IcdRegistrationStrategy icdRegistrationStrategy) + { + mIcdRegistrationStrategy = icdRegistrationStrategy; + return *this; + } + // Clear all members that depend on some sort of external buffer. Can be // used to make sure that we are not holding any dangling pointers. void ClearExternalBufferDependentValues() @@ -550,7 +568,8 @@ class CommissioningParameters Optional mAttemptWiFiNetworkScan; Optional mAttemptThreadNetworkScan; // This automatically gets set to false when a ThreadOperationalDataset is set Optional mSkipCommissioningComplete; - bool mCheckForMatchingFabric = false; + IcdRegistrationStrategy mIcdRegistrationStrategy = IcdRegistrationStrategy::kIgnore; + bool mCheckForMatchingFabric = false; }; struct RequestedCertificate @@ -632,6 +651,13 @@ struct ReadCommissioningInfo uint8_t maxTimeZoneSize = 1; uint8_t maxDSTSize = 1; }; + +struct IcdInfo +{ + bool isIcd = false; + bool checkInProtocolSupport = false; +}; + struct MatchingFabricInfo { NodeId nodeId = kUndefinedNodeId; @@ -694,7 +720,7 @@ class CommissioningDelegate */ struct CommissioningReport : Variant + NetworkCommissioningStatusInfo, MatchingFabricInfo, TimeZoneResponseInfo, IcdInfo> { CommissioningReport() : stageCompleted(CommissioningStage::kError) {} CommissioningStage stageCompleted;