diff --git a/docs/guides/esp32/README.md b/docs/guides/esp32/README.md index 89d9225cf65dd8..e487a58f318591 100644 --- a/docs/guides/esp32/README.md +++ b/docs/guides/esp32/README.md @@ -17,3 +17,4 @@ example on ESP32 series of SoCs - [RPC Console and Device Tracing](rpc_console.md) - [Matter OTA](ota.md) - [Generating and Using ESP Secure Cert Partition](secure_cert_partition.md) +- [BLE Settings](ble_settings.md) diff --git a/docs/guides/esp32/ble_settings.md b/docs/guides/esp32/ble_settings.md new file mode 100644 index 00000000000000..36178ebece5d71 --- /dev/null +++ b/docs/guides/esp32/ble_settings.md @@ -0,0 +1,32 @@ +# Bluetooth Low Energy (BLE) + +## Nimble: scan response + +The `ConfigureScanResponseData` API is used to configure the scan response data +for advertising in a Bluetooth Low Energy (BLE) application based on the NimBLE +BLE stack. Scan response data is additional data that a BLE peripheral device +can include in its advertising packets to provide more information about itself. +This API allows you to set the scan response data that will be included in the +advertising packets. + +### Usage + +``` +{ + uint8_t scanResponse[31]; // 0x05, 0x09, a, b, c, d + scanResponse[0] = 0x05; + scanResponse[1] = 0x09; + scanResponse[2] = 0x61; + scanResponse[3] = 0x62; + scanResponse[4] = 0x63; + scanResponse[5] = 0x64; + chip::ByteSpan data(scanResponse); + CHIP_ERROR err = chip::DeviceLayer::Internal::BLEMgrImpl().ConfigureScanResponseData(data); + if (err != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Failed to configure scan response, err:%" CHIP_ERROR_FORMAT, err.Format()); + } +} +``` + +Note: Scan response should be configure before `InitServer`. diff --git a/examples/lock-app/silabs/include/LockManager.h b/examples/lock-app/silabs/include/LockManager.h index 901dfdbd06cb04..9adcc863f0aec7 100644 --- a/examples/lock-app/silabs/include/LockManager.h +++ b/examples/lock-app/silabs/include/LockManager.h @@ -143,9 +143,12 @@ class LockManager typedef void (*Callback_fn_completed)(Action_t); void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB); - bool Lock(chip::EndpointId endpointId, const Optional & pin, OperationErrorEnum & err); - bool Unlock(chip::EndpointId endpointId, const Optional & pin, OperationErrorEnum & err); - bool Unbolt(chip::EndpointId endpointId, const Optional & pin, OperationErrorEnum & err); + bool Lock(chip::EndpointId endpointId, const Nullable & fabricIdx, const Nullable & nodeId, + const Optional & pin, OperationErrorEnum & err); + bool Unlock(chip::EndpointId endpointId, const Nullable & fabricIdx, const Nullable & nodeId, + const Optional & pin, OperationErrorEnum & err); + bool Unbolt(chip::EndpointId endpointId, const Nullable & fabricIdx, const Nullable & nodeId, + const Optional & pin, OperationErrorEnum & err); bool GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user); bool SetUser(chip::EndpointId endpointId, uint16_t userIndex, chip::FabricIndex creator, chip::FabricIndex modifier, @@ -183,7 +186,8 @@ class LockManager bool IsValidYeardayScheduleIndex(uint8_t scheduleIndex); bool IsValidHolidayScheduleIndex(uint8_t scheduleIndex); - bool setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin, + bool setLockState(chip::EndpointId endpointId, const Nullable & fabricIdx, + const Nullable & nodeId, DlLockState lockState, const Optional & pin, OperationErrorEnum & err); const char * lockStateToString(DlLockState lockState) const; diff --git a/examples/lock-app/silabs/src/AppTask.cpp b/examples/lock-app/silabs/src/AppTask.cpp index 8afe7d6cc8d9e5..7d86fec80a07d9 100644 --- a/examples/lock-app/silabs/src/AppTask.cpp +++ b/examples/lock-app/silabs/src/AppTask.cpp @@ -352,11 +352,9 @@ void AppTask::UpdateClusterState(intptr_t context) bool unlocked = LockMgr().NextState(); DlLockState newState = unlocked ? DlLockState::kUnlocked : DlLockState::kLocked; - OperationSourceEnum source = OperationSourceEnum::kUnspecified; - // write the new lock value EmberAfStatus status = - DoorLockServer::Instance().SetLockState(1, newState, source) ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE; + DoorLockServer::Instance().SetLockState(1, newState) ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE; if (status != EMBER_ZCL_STATUS_SUCCESS) { diff --git a/examples/lock-app/silabs/src/LockManager.cpp b/examples/lock-app/silabs/src/LockManager.cpp index f3c6dfe748ca35..8190dbddd6141e 100644 --- a/examples/lock-app/silabs/src/LockManager.cpp +++ b/examples/lock-app/silabs/src/LockManager.cpp @@ -288,19 +288,22 @@ void LockManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent) } } -bool LockManager::Lock(chip::EndpointId endpointId, const Optional & pin, OperationErrorEnum & err) +bool LockManager::Lock(chip::EndpointId endpointId, const Nullable & fabricIdx, + const Nullable & nodeId, const Optional & pin, OperationErrorEnum & err) { - return setLockState(endpointId, DlLockState::kLocked, pin, err); + return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kLocked, pin, err); } -bool LockManager::Unlock(chip::EndpointId endpointId, const Optional & pin, OperationErrorEnum & err) +bool LockManager::Unlock(chip::EndpointId endpointId, const Nullable & fabricIdx, + const Nullable & nodeId, const Optional & pin, OperationErrorEnum & err) { - return setLockState(endpointId, DlLockState::kUnlocked, pin, err); + return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlocked, pin, err); } -bool LockManager::Unbolt(chip::EndpointId endpointId, const Optional & pin, OperationErrorEnum & err) +bool LockManager::Unbolt(chip::EndpointId endpointId, const Nullable & fabricIdx, + const Nullable & nodeId, const Optional & pin, OperationErrorEnum & err) { - return setLockState(endpointId, DlLockState::kUnlocked, pin, err); + return setLockState(endpointId, fabricIdx, nodeId, DlLockState::kUnlocked, pin, err); } bool LockManager::GetUser(chip::EndpointId endpointId, uint16_t userIndex, EmberAfPluginDoorLockUserInfo & user) @@ -664,7 +667,8 @@ const char * LockManager::lockStateToString(DlLockState lockState) const return "Unknown"; } -bool LockManager::setLockState(chip::EndpointId endpointId, DlLockState lockState, const Optional & pin, +bool LockManager::setLockState(chip::EndpointId endpointId, const Nullable & fabricIdx, + const Nullable & nodeId, DlLockState lockState, const Optional & pin, OperationErrorEnum & err) { @@ -683,7 +687,8 @@ bool LockManager::setLockState(chip::EndpointId endpointId, DlLockState lockStat ChipLogDetail(Zcl, "Door Lock App: setting door lock state to \"%s\" [endpointId=%d]", lockStateToString(lockState), endpointId); - DoorLockServer::Instance().SetLockState(endpointId, lockState); + DoorLockServer::Instance().SetLockState(endpointId, lockState, OperationSourceEnum::kRemote, NullNullable, NullNullable, + fabricIdx, nodeId); return true; } @@ -708,7 +713,8 @@ bool LockManager::setLockState(chip::EndpointId endpointId, DlLockState lockStat "Lock App: specified PIN code was found in the database, setting lock state to \"%s\" [endpointId=%d]", lockStateToString(lockState), endpointId); - DoorLockServer::Instance().SetLockState(endpointId, lockState); + DoorLockServer::Instance().SetLockState(endpointId, lockState, OperationSourceEnum::kRemote, NullNullable, NullNullable, + fabricIdx, nodeId); return true; } diff --git a/examples/lock-app/silabs/src/ZclCallbacks.cpp b/examples/lock-app/silabs/src/ZclCallbacks.cpp index dc5d60915218ae..12649100df5737 100644 --- a/examples/lock-app/silabs/src/ZclCallbacks.cpp +++ b/examples/lock-app/silabs/src/ZclCallbacks.cpp @@ -66,7 +66,7 @@ bool emberAfPluginDoorLockOnDoorLockCommand(chip::EndpointId endpointId, const N OperationErrorEnum & err) { ChipLogProgress(Zcl, "Door Lock App: Lock Command endpoint=%d", endpointId); - bool status = LockMgr().Lock(endpointId, pinCode, err); + bool status = LockMgr().Lock(endpointId, fabricIdx, nodeId, pinCode, err); if (status == true) { LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::LOCK_ACTION); @@ -79,7 +79,7 @@ bool emberAfPluginDoorLockOnDoorUnlockCommand(chip::EndpointId endpointId, const OperationErrorEnum & err) { ChipLogProgress(Zcl, "Door Lock App: Unlock Command endpoint=%d", endpointId); - bool status = LockMgr().Unlock(endpointId, pinCode, err); + bool status = LockMgr().Unlock(endpointId, fabricIdx, nodeId, pinCode, err); if (status == true) { LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION); @@ -93,7 +93,7 @@ bool emberAfPluginDoorLockOnDoorUnboltCommand(chip::EndpointId endpointId, const OperationErrorEnum & err) { ChipLogProgress(Zcl, "Door Lock App: Unbolt Command endpoint=%d", endpointId); - bool status = LockMgr().Unlock(endpointId, pinCode, err); + bool status = LockMgr().Unlock(endpointId, fabricIdx, nodeId, pinCode, err); if (status == true) { LockMgr().InitiateAction(AppEvent::kEventType_Lock, LockManager::UNLOCK_ACTION); diff --git a/examples/platform/silabs/BaseApplication.cpp b/examples/platform/silabs/BaseApplication.cpp index b0d1dd0ea8a414..cd37c4615fa4bb 100644 --- a/examples/platform/silabs/BaseApplication.cpp +++ b/examples/platform/silabs/BaseApplication.cpp @@ -222,24 +222,7 @@ CHIP_ERROR BaseApplication::Init() ConfigurationMgr().LogDeviceConfig(); - // Create buffer for QR code that can fit max size and null terminator. - char qrCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1]; - chip::MutableCharSpan QRCode(qrCodeBuffer); - - if (Silabs::SilabsDeviceDataProvider::GetDeviceDataProvider().GetSetupPayload(QRCode) == CHIP_NO_ERROR) - { - // Print setup info on LCD if available -#ifdef QR_CODE_ENABLED - slLCD.SetQRCode((uint8_t *) QRCode.data(), QRCode.size()); - slLCD.ShowQRCode(true, true); -#else - PrintQrCodeURL(QRCode); -#endif // QR_CODE_ENABLED - } - else - { - SILABS_LOG("Getting QR code failed!"); - } + OutputQrCode(true /*refreshLCD at init*/); PlatformMgr().AddEventHandler(OnPlatformEvent, 0); #ifdef SL_WIFI @@ -457,6 +440,7 @@ void BaseApplication::ButtonHandler(AppEvent * aEvent) CancelFunctionTimer(); mFunction = kFunction_NoneSelected; + OutputQrCode(false); #ifdef QR_CODE_ENABLED // TOGGLE QRCode/LCD demo UI slLCD.ToggleQRCode(); @@ -700,3 +684,30 @@ void BaseApplication::OnPlatformEvent(const ChipDeviceEvent * event, intptr_t) sIsProvisioned = event->ServiceProvisioningChange.IsServiceProvisioned; } } + +void BaseApplication::OutputQrCode(bool refreshLCD) +{ + (void) refreshLCD; // could be unused + + // Create buffer for the Qr code setup payload that can fit max size and null terminator. + char setupPayloadBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1]; + chip::MutableCharSpan setupPayload(setupPayloadBuffer); + + if (Silabs::SilabsDeviceDataProvider::GetDeviceDataProvider().GetSetupPayload(setupPayload) == CHIP_NO_ERROR) + { + // Print setup info on LCD if available +#ifdef QR_CODE_ENABLED + if (refreshLCD) + { + slLCD.SetQRCode((uint8_t *) setupPayload.data(), setupPayload.size()); + slLCD.ShowQRCode(true, true); + } +#endif // QR_CODE_ENABLED + + PrintQrCodeURL(setupPayload); + } + else + { + SILABS_LOG("Getting QR code failed!"); + } +} diff --git a/examples/platform/silabs/BaseApplication.h b/examples/platform/silabs/BaseApplication.h index 9e99580811293c..b3a9db893183e5 100644 --- a/examples/platform/silabs/BaseApplication.h +++ b/examples/platform/silabs/BaseApplication.h @@ -202,6 +202,15 @@ class BaseApplication static void ScheduleFactoryReset(); static void OnPlatformEvent(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t); + + /** + * @brief Outputs the QRcode payload and URL to the QR code in the logs + * and conditionally on the device LCD. + * + * @param refreshLCD When true, The LCD of the device will be refreshed to show the QR code + */ + static void OutputQrCode(bool refreshLCD); + /********************************************************** * Protected Attributes declaration *********************************************************/ diff --git a/examples/platform/silabs/FreeRTOSConfig.h b/examples/platform/silabs/FreeRTOSConfig.h index 4cad6b1e9803dc..8d3236763f35e6 100644 --- a/examples/platform/silabs/FreeRTOSConfig.h +++ b/examples/platform/silabs/FreeRTOSConfig.h @@ -107,11 +107,15 @@ extern "C" { #include +#ifdef SIWX_917 +extern uint32_t SystemCoreClock; +#else // For EFR32 #include "RTE_Components.h" #include CMSIS_device_header #include "em_assert.h" #include "em_device.h" +#endif #if defined(SL_COMPONENT_CATALOG_PRESENT) #include "sl_component_catalog.h" diff --git a/examples/platform/silabs/MatterConfig.cpp b/examples/platform/silabs/MatterConfig.cpp index 1392dd9dc2b382..36f78aa84839c2 100644 --- a/examples/platform/silabs/MatterConfig.cpp +++ b/examples/platform/silabs/MatterConfig.cpp @@ -48,7 +48,7 @@ using namespace ::chip::DeviceLayer; #include // If building with the EFR32-provided crypto backend, we can use the // opaque keystore -#if CHIP_CRYPTO_PLATFORM +#if CHIP_CRYPTO_PLATFORM && !(defined(SIWX_917)) #include static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeystore; #endif @@ -215,7 +215,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) initParams.testEventTriggerDelegate = &testEventTriggerDelegate; #endif // SILABS_TEST_EVENT_TRIGGER_ENABLED -#if CHIP_CRYPTO_PLATFORM +#if CHIP_CRYPTO_PLATFORM && !(defined(SIWX_917)) // When building with EFR32 crypto, use the opaque key store // instead of the default (insecure) one. gOperationalKeystore.Init(); @@ -255,7 +255,7 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName) } #ifdef SL_WIFI -void SilabsMatterConfig::InitWiFi(void) +CHIP_ERROR SilabsMatterConfig::InitWiFi(void) { #ifdef WF200_WIFI // Start wfx bus communication task. @@ -271,6 +271,7 @@ void SilabsMatterConfig::InitWiFi(void) return CHIP_ERROR_INTERNAL; } #endif /* WF200_WIFI */ + return CHIP_NO_ERROR; } #endif // SL_WIFI diff --git a/examples/platform/silabs/MatterConfig.h b/examples/platform/silabs/MatterConfig.h index 2c565f7caa7321..86c8b7e0a66ba4 100644 --- a/examples/platform/silabs/MatterConfig.h +++ b/examples/platform/silabs/MatterConfig.h @@ -29,7 +29,7 @@ class SilabsMatterConfig private: static CHIP_ERROR InitOpenThread(void); - static void InitWiFi(void); + static CHIP_ERROR InitWiFi(void); static void ConnectivityEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg); static void InitOTARequestorHandler(chip::System::Layer * systemLayer, void * appState); }; diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn index 3fd6164b576ea1..f0600f012e19e7 100644 --- a/examples/platform/silabs/SiWx917/BUILD.gn +++ b/examples/platform/silabs/SiWx917/BUILD.gn @@ -183,9 +183,10 @@ config("siwx917-common-config") { defines += [ "QR_CODE_ENABLED" ] } - if (chip_enable_ota_requestor) { - defines += [ "SILABS_OTA_ENABLED" ] - } + # TODO: Renable once ota is supported + # if (chip_enable_ota_requestor) { + # defines += [ "SILABS_OTA_ENABLED" ] + # } if (enable_heap_monitoring) { defines += [ "HEAP_MONITORING" ] diff --git a/examples/platform/silabs/SiWx917/uart.cpp b/examples/platform/silabs/SiWx917/uart.cpp index 966fe44d7efd25..ac7bb8af3e774a 100644 --- a/examples/platform/silabs/SiWx917/uart.cpp +++ b/examples/platform/silabs/SiWx917/uart.cpp @@ -53,7 +53,7 @@ void ARM_USART_SignalEvent(uint32_t event) case ARM_USART_EVENT_RECEIVE_COMPLETE: #ifdef ENABLE_CHIP_SHELL chip::NotifyShellProcessFromISR(); -#endif; +#endif case ARM_USART_EVENT_TRANSFER_COMPLETE: case ARM_USART_EVENT_TX_COMPLETE: case ARM_USART_EVENT_TX_UNDERFLOW: diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp index cd67ffd59e436f..d291d8154d421f 100644 --- a/src/app/CommandHandler.cpp +++ b/src/app/CommandHandler.cpp @@ -272,7 +272,7 @@ Status CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommandElem ChipLogDetail(DataManagement, "No command " ChipLogFormatMEI " in Cluster " ChipLogFormatMEI " on Endpoint 0x%x", ChipLogValueMEI(concretePath.mCommandId), ChipLogValueMEI(concretePath.mClusterId), concretePath.mEndpointId); - return FallibleAddStatus(concretePath, commandExists) != CHIP_NO_ERROR ? Status::Failure : Status::Success; + return AddStatus(concretePath, commandExists) != CHIP_NO_ERROR ? Status::Failure : Status::Success; } } @@ -287,10 +287,10 @@ Status CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommandElem { if (err != CHIP_ERROR_ACCESS_DENIED) { - return FallibleAddStatus(concretePath, Status::Failure) != CHIP_NO_ERROR ? Status::Failure : Status::Success; + return AddStatus(concretePath, Status::Failure) != CHIP_NO_ERROR ? Status::Failure : Status::Success; } // TODO: when wildcard invokes are supported, handle them to discard rather than fail with status - return FallibleAddStatus(concretePath, Status::UnsupportedAccess) != CHIP_NO_ERROR ? Status::Failure : Status::Success; + return AddStatus(concretePath, Status::UnsupportedAccess) != CHIP_NO_ERROR ? Status::Failure : Status::Success; } } @@ -298,7 +298,7 @@ Status CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommandElem { // TODO: when wildcard invokes are supported, discard a // wildcard-expanded path instead of returning a status. - return FallibleAddStatus(concretePath, Status::NeedsTimedInteraction) != CHIP_NO_ERROR ? Status::Failure : Status::Success; + return AddStatus(concretePath, Status::NeedsTimedInteraction) != CHIP_NO_ERROR ? Status::Failure : Status::Success; } if (CommandIsFabricScoped(concretePath.mClusterId, concretePath.mCommandId)) @@ -312,7 +312,7 @@ Status CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommandElem { // TODO: when wildcard invokes are supported, discard a // wildcard-expanded path instead of returning a status. - return FallibleAddStatus(concretePath, Status::UnsupportedAccess) != CHIP_NO_ERROR ? Status::Failure : Status::Success; + return AddStatus(concretePath, Status::UnsupportedAccess) != CHIP_NO_ERROR ? Status::Failure : Status::Success; } } @@ -337,7 +337,7 @@ Status CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommandElem exit: if (err != CHIP_NO_ERROR) { - return FallibleAddStatus(concretePath, Status::InvalidCommand) != CHIP_NO_ERROR ? Status::Failure : Status::Success; + return AddStatus(concretePath, Status::InvalidCommand) != CHIP_NO_ERROR ? Status::Failure : Status::Success; } // We have handled the error status above and put the error status in response, now return success status so we can process @@ -468,31 +468,31 @@ CHIP_ERROR CommandHandler::AddStatusInternal(const ConcreteCommandPath & aComman return FinishStatus(); } -void CommandHandler::AddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus, - const char * context) +CHIP_ERROR CommandHandler::AddStatus(const ConcreteCommandPath & aCommandPath, const Status aStatus) { - - VerifyOrDie(FallibleAddStatus(aCommandPath, aStatus, context) == CHIP_NO_ERROR); + return AddStatusInternal(aCommandPath, StatusIB(aStatus)); } -CHIP_ERROR CommandHandler::FallibleAddStatus(const ConcreteCommandPath & path, const Protocols::InteractionModel::Status status, - const char * context) +void CommandHandler::AddStatusAndLogIfFailure(const ConcreteCommandPath & aCommandPath, const Status aStatus, const char * aMessage) { - - if (status != Status::Success) + if (aStatus != Status::Success) { - if (context == nullptr) - { - context = "no additional context"; - } - ChipLogError(DataManagement, - "Endpoint=%u Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI " status " ChipLogFormatIMStatus " (%s)", - path.mEndpointId, ChipLogValueMEI(path.mClusterId), ChipLogValueMEI(path.mCommandId), - ChipLogValueIMStatus(status), context); + "Failed to handle on Endpoint=%u Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI + " with " ChipLogFormatIMStatus ": %s", + aCommandPath.mEndpointId, ChipLogValueMEI(aCommandPath.mClusterId), ChipLogValueMEI(aCommandPath.mCommandId), + ChipLogValueIMStatus(aStatus), aMessage); } - return AddStatusInternal(path, StatusIB(status)); + CHIP_ERROR err = AddStatus(aCommandPath, aStatus); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DataManagement, + "Failed to set status on Endpoint=%u Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI + ": %" CHIP_ERROR_FORMAT, + aCommandPath.mEndpointId, ChipLogValueMEI(aCommandPath.mClusterId), ChipLogValueMEI(aCommandPath.mCommandId), + err.Format()); + } } CHIP_ERROR CommandHandler::AddClusterSpecificSuccess(const ConcreteCommandPath & aCommandPath, ClusterStatus aClusterStatus) diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h index 3c9a86c97b6052..bc96583abd7597 100644 --- a/src/app/CommandHandler.h +++ b/src/app/CommandHandler.h @@ -170,20 +170,13 @@ class CommandHandler : public Messaging::ExchangeDelegate */ void OnInvokeCommandRequest(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, System::PacketBufferHandle && payload, bool isTimedInvoke); + CHIP_ERROR AddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus); - /** - * Adds the given command status and returns any failures in adding statuses (e.g. out - * of buffer space) to the caller - */ - CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus, - const char * context = nullptr); - - /** - * Adds a status when the caller is unable to handle any failures. Logging is performed - * and failure to register the status is checked with VerifyOrDie. - */ - void AddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus, - const char * context = nullptr); + // Same as AddStatus, but logs that the command represented by aCommandPath failed with the given + // error status and error message, if aStatus is an error. Errors on AddStatus are just logged + // (since the caller likely can only log and not further add a status). + void AddStatusAndLogIfFailure(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus, + const char * aMessage); CHIP_ERROR AddClusterSpecificSuccess(const ConcreteCommandPath & aCommandPath, ClusterStatus aClusterStatus); @@ -245,9 +238,13 @@ class CommandHandler : public Messaging::ExchangeDelegate template void AddResponse(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData) { - if (AddResponseData(aRequestCommandPath, aData) != CHIP_NO_ERROR) + if (CHIP_NO_ERROR != AddResponseData(aRequestCommandPath, aData)) { - AddStatus(aRequestCommandPath, Protocols::InteractionModel::Status::Failure); + CHIP_ERROR err = AddStatus(aRequestCommandPath, Protocols::InteractionModel::Status::Failure); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DataManagement, "Failed to encode status: %" CHIP_ERROR_FORMAT, err.Format()); + } } } diff --git a/src/app/CommandResponseHelper.h b/src/app/CommandResponseHelper.h index 48d36d1ea82013..a85e92b72cc587 100644 --- a/src/app/CommandResponseHelper.h +++ b/src/app/CommandResponseHelper.h @@ -53,7 +53,7 @@ class CommandResponseHelper CHIP_ERROR Failure(Protocols::InteractionModel::Status aStatus) { - CHIP_ERROR err = mCommandHandler->FallibleAddStatus(mCommandPath, aStatus); + CHIP_ERROR err = mCommandHandler->AddStatus(mCommandPath, aStatus); if (err == CHIP_NO_ERROR) { mSentResponse = true; diff --git a/src/app/DataModelRevision.h b/src/app/DataModelRevision.h index a476b32c93b1c8..47ecb626a13ffa 100644 --- a/src/app/DataModelRevision.h +++ b/src/app/DataModelRevision.h @@ -22,7 +22,10 @@ * * A monotonic number identifying the revision number of the Data Model against * which the Node is certified. + * + * See section 7.1.1. "Revision History" in the "Data Model Specification" + * chapter of the core Matter specification. */ #ifndef CHIP_DEVICE_DATA_MODEL_REVISION -#define CHIP_DEVICE_DATA_MODEL_REVISION 1 +#define CHIP_DEVICE_DATA_MODEL_REVISION 17 #endif diff --git a/src/app/InteractionModelRevision.h b/src/app/InteractionModelRevision.h index 8f38a342969ddd..7e92d7c2d58aba 100644 --- a/src/app/InteractionModelRevision.h +++ b/src/app/InteractionModelRevision.h @@ -24,9 +24,12 @@ * CHIP_DEVICE_INTERACTION_MODEL_REVISION * * A monothonic number identifying the interaction model revision. + * + * See section 8.1.1. "Revision History" in the "Interaction Model + * Specification" chapter of the core Matter specification. */ #ifndef CHIP_DEVICE_INTERACTION_MODEL_REVISION -#define CHIP_DEVICE_INTERACTION_MODEL_REVISION 1 +#define CHIP_DEVICE_INTERACTION_MODEL_REVISION 10 #endif constexpr uint8_t kInteractionModelRevisionTag = 0xFF; diff --git a/src/app/clusters/barrier-control-server/barrier-control-server.cpp b/src/app/clusters/barrier-control-server/barrier-control-server.cpp index 645fc943078355..a7531aee1bcf91 100644 --- a/src/app/clusters/barrier-control-server/barrier-control-server.cpp +++ b/src/app/clusters/barrier-control-server/barrier-control-server.cpp @@ -286,7 +286,10 @@ void emberAfBarrierControlClusterServerTickCallback(EndpointId endpoint) static void sendDefaultResponse(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, Status status) { - commandObj->AddStatus(commandPath, status); + if (commandObj->AddStatus(commandPath, status) != CHIP_NO_ERROR) + { + ChipLogProgress(Zcl, "Failed to send default response"); + } } bool emberAfBarrierControlClusterBarrierControlGoToPercentCallback( diff --git a/src/app/clusters/door-lock-server/door-lock-server.cpp b/src/app/clusters/door-lock-server/door-lock-server.cpp index a9b3cdd4dc106d..ad201e78cf7d2f 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server.cpp @@ -3314,20 +3314,23 @@ bool DoorLockServer::RemoteOperationEnabled(chip::EndpointId endpointId) const mode != OperatingModeEnum::kPrivacy && mode != OperatingModeEnum::kNoRemoteLockUnlock; } -void DoorLockServer::sendClusterResponse(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - EmberAfStatus status) +CHIP_ERROR DoorLockServer::sendClusterResponse(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, EmberAfStatus status) { VerifyOrDie(nullptr != commandObj); + auto err = CHIP_NO_ERROR; auto statusAsInteger = to_underlying(status); if (statusAsInteger == to_underlying(DlStatus::kOccupied) || statusAsInteger == to_underlying(DlStatus::kDuplicate)) { - VerifyOrDie(commandObj->AddClusterSpecificFailure(commandPath, static_cast(status)) == CHIP_NO_ERROR); + err = commandObj->AddClusterSpecificFailure(commandPath, static_cast(status)); } else { - commandObj->AddStatus(commandPath, ToInteractionModelStatus(status)); + err = commandObj->AddStatus(commandPath, ToInteractionModelStatus(status)); } + + return err; } EmberAfDoorLockEndpointContext * DoorLockServer::getContext(chip::EndpointId endpointId) diff --git a/src/app/clusters/door-lock-server/door-lock-server.h b/src/app/clusters/door-lock-server/door-lock-server.h index 70988c17786964..212c374077298f 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.h +++ b/src/app/clusters/door-lock-server/door-lock-server.h @@ -422,8 +422,8 @@ class DoorLockServer bool engageLockout(chip::EndpointId endpointId); - static void sendClusterResponse(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - EmberAfStatus status); + static CHIP_ERROR sendClusterResponse(chip::app::CommandHandler * commandObj, + const chip::app::ConcreteCommandPath & commandPath, EmberAfStatus status); /** * @brief Common handler for LockDoor, UnlockDoor, UnlockWithTimeout commands diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp index 536ac205454862..ef66957d754d68 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp @@ -50,7 +50,11 @@ using Transport::Session; { \ if (!::chip::ChipError::IsSuccess(expr)) \ { \ - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::code, #expr); \ + CHIP_ERROR statusErr = commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::code); \ + if (statusErr != CHIP_NO_ERROR) \ + { \ + ChipLogError(Zcl, "%s: %" CHIP_ERROR_FORMAT, #expr, statusErr.Format()); \ + } \ return true; \ } \ } while (false) diff --git a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp index f4da9238611528..fcd0dfa1353516 100644 --- a/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp +++ b/src/app/clusters/group-key-mgmt-server/group-key-mgmt-server.cpp @@ -414,13 +414,13 @@ bool GetProviderAndFabric(chip::app::CommandHandler * commandObj, const chip::ap if (nullptr == provider) { - commandObj->AddStatus(commandPath, Status::Failure, "Internal consistency error on provider!"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::Failure, "Internal consistency error on provider!"); return false; } if (nullptr == fabric) { - commandObj->AddStatus(commandPath, Status::Failure, "Internal consistency error on access fabric!"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::Failure, "Internal consistency error on access fabric!"); return false; } @@ -460,7 +460,7 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback( Status status = ValidateKeySetWriteArguments(commandData); if (status != Status::Success) { - commandObj->AddStatus(commandPath, status, "Failure to validate KeySet data dependencies."); + commandObj->AddStatusAndLogIfFailure(commandPath, status, "Failure to validate KeySet data dependencies."); return true; } @@ -470,7 +470,8 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback( // supported by the server, because it is ... a new value unrecognized // by a legacy server, then the server SHALL generate a general // constraint error - commandObj->AddStatus(commandPath, Status::ConstraintError, "Received unknown GroupKeySecurityPolicyEnum value"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::ConstraintError, + "Received unknown GroupKeySecurityPolicyEnum value"); return true; } @@ -481,8 +482,8 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback( // any action attempting to set CacheAndSync in the // GroupKeySecurityPolicy field SHALL fail with an INVALID_COMMAND // error. - commandObj->AddStatus(commandPath, Status::InvalidCommand, - "Received a CacheAndSync GroupKeySecurityPolicyEnum when MCSP not supported"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::InvalidCommand, + "Received a CacheAndSync GroupKeySecurityPolicyEnum when MCSP not supported"); return true; } @@ -528,7 +529,7 @@ bool emberAfGroupKeyManagementClusterKeySetWriteCallback( err = provider->SetKeySet(fabric->GetFabricIndex(), compressed_fabric_id, keyset); if (CHIP_ERROR_INVALID_LIST_LENGTH == err) { - commandObj->AddStatus(commandPath, Status::ResourceExhausted, "Not enough space left to add a new KeySet"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::ResourceExhausted, "Not enough space left to add a new KeySet"); return true; } @@ -564,7 +565,7 @@ bool emberAfGroupKeyManagementClusterKeySetReadCallback( if (CHIP_NO_ERROR != provider->GetKeySet(fabricIndex, commandData.groupKeySetID, keyset)) { // KeySet ID not found - commandObj->AddStatus(commandPath, Status::NotFound, "Keyset ID not found in KeySetRead"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::NotFound, "Keyset ID not found in KeySetRead"); return true; } @@ -628,7 +629,8 @@ bool emberAfGroupKeyManagementClusterKeySetRemoveCallback( { // SPEC: This command SHALL fail with an INVALID_COMMAND status code back to the initiator if the GroupKeySetID being // removed is 0, which is the Key Set associated with the Identity Protection Key (IPK). - commandObj->AddStatus(commandPath, Status::InvalidCommand, "Attempted to KeySetRemove the identity protection key!"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::InvalidCommand, + "Attempted to KeySetRemove the identity protection key!"); return true; } @@ -647,7 +649,7 @@ bool emberAfGroupKeyManagementClusterKeySetRemoveCallback( } // Send status response. - commandObj->AddStatus(commandPath, status, "KeySetRemove failed"); + commandObj->AddStatusAndLogIfFailure(commandPath, status, "KeySetRemove failed"); return true; } @@ -699,7 +701,7 @@ bool emberAfGroupKeyManagementClusterKeySetReadAllIndicesCallback( auto keysIt = provider->IterateKeySets(fabricIndex); if (nullptr == keysIt) { - commandObj->AddStatus(commandPath, Status::Failure, "Failed iteration of key set indices!"); + commandObj->AddStatusAndLogIfFailure(commandPath, Status::Failure, "Failed iteration of key set indices!"); return true; } diff --git a/src/app/clusters/groups-server/groups-server.cpp b/src/app/clusters/groups-server/groups-server.cpp index ccb4fb1d439a72..00196ad94c9419 100644 --- a/src/app/clusters/groups-server/groups-server.cpp +++ b/src/app/clusters/groups-server/groups-server.cpp @@ -351,7 +351,11 @@ bool emberAfGroupsClusterAddGroupIfIdentifyingCallback(app::CommandHandler * com status = GroupAdd(fabricIndex, endpointId, groupId, groupName); } - commandObj->AddStatus(commandPath, status); + CHIP_ERROR sendErr = commandObj->AddStatus(commandPath, status); + if (CHIP_NO_ERROR != sendErr) + { + ChipLogDetail(Zcl, "Groups: failed to send %s: %" CHIP_ERROR_FORMAT, "status_response", sendErr.Format()); + } return true; } diff --git a/src/app/clusters/window-covering-server/window-covering-server.cpp b/src/app/clusters/window-covering-server/window-covering-server.cpp index a78a3d138bbd39..2bdd972cd634f7 100644 --- a/src/app/clusters/window-covering-server/window-covering-server.cpp +++ b/src/app/clusters/window-covering-server/window-covering-server.cpp @@ -771,8 +771,7 @@ bool emberAfWindowCoveringClusterStopMotionCallback(app::CommandHandler * comman } } - commandObj->AddStatus(commandPath, Status::Success); - return true; + return CHIP_NO_ERROR == commandObj->AddStatus(commandPath, Status::Success); } /** diff --git a/src/app/tests/TestCommandInteraction.cpp b/src/app/tests/TestCommandInteraction.cpp index 14418aecc2877a..d90ce4d97b3d7c 100644 --- a/src/app/tests/TestCommandInteraction.cpp +++ b/src/app/tests/TestCommandInteraction.cpp @@ -1095,8 +1095,9 @@ void TestCommandInteraction::TestCommandHandlerCommandEncodeExternalFailure(nlTe err = commandHandler.AddResponseData(ConcreteCommandPath(path.mEndpointId, path.mClusterId, path.mCommandId), BadFields()); NL_TEST_ASSERT(apSuite, err != CHIP_NO_ERROR); - commandHandler.AddStatus(ConcreteCommandPath(path.mEndpointId, path.mClusterId, path.mCommandId), - Protocols::InteractionModel::Status::Failure); + err = commandHandler.AddStatus(ConcreteCommandPath(path.mEndpointId, path.mClusterId, path.mCommandId), + Protocols::InteractionModel::Status::Failure); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); err = commandHandler.Finalize(commandPacket); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); diff --git a/src/app/tests/suites/TestCASERecovery.yaml b/src/app/tests/suites/TestCASERecovery.yaml index 69ecf23a9f50fe..ef72e4dff7e512 100644 --- a/src/app/tests/suites/TestCASERecovery.yaml +++ b/src/app/tests/suites/TestCASERecovery.yaml @@ -33,7 +33,7 @@ tests: command: "readAttribute" attribute: "DataModelRevision" response: - value: 1 + value: 17 - label: "Reboot the server" cluster: "SystemCommands" @@ -72,4 +72,4 @@ tests: command: "readAttribute" attribute: "DataModelRevision" response: - value: 1 + value: 17 diff --git a/src/controller/java/BUILD.gn b/src/controller/java/BUILD.gn index e967b0bd007936..a2865ffd326c1c 100644 --- a/src/controller/java/BUILD.gn +++ b/src/controller/java/BUILD.gn @@ -104,7 +104,10 @@ shared_library("jni") { deps += [ "${chip_root}/src/platform/Linux" ] } - cflags = [ "-Wno-unknown-pragmas" ] + cflags = [ + "-Wno-unknown-pragmas", + "-Wconversion", + ] output_dir = "${root_out_dir}/lib/jni" } else { @@ -143,7 +146,10 @@ if (chip_link_tests) { deps += [ "${chip_root}/src/platform/Linux" ] } - cflags = [ "-Wno-unknown-pragmas" ] + cflags = [ + "-Wno-unknown-pragmas", + "-Wconversion", + ] output_dir = "${root_out_dir}/lib/jni" } else { diff --git a/src/controller/java/CHIPDeviceController-JNI.cpp b/src/controller/java/CHIPDeviceController-JNI.cpp index 64c7dac4774785..5d93b3075a2d8b 100644 --- a/src/controller/java/CHIPDeviceController-JNI.cpp +++ b/src/controller/java/CHIPDeviceController-JNI.cpp @@ -340,20 +340,21 @@ JNI_METHOD(jlong, newDeviceController)(JNIEnv * env, jobject self, jobject contr SuccessOrExit(err); { - uint64_t fabricId = env->CallLongMethod(controllerParams, getFabricId); - uint16_t listenPort = env->CallIntMethod(controllerParams, getUdpListenPort); - uint16_t controllerVendorId = env->CallIntMethod(controllerParams, getControllerVendorId); + uint64_t fabricId = static_cast(env->CallLongMethod(controllerParams, getFabricId)); + uint16_t listenPort = static_cast(env->CallIntMethod(controllerParams, getUdpListenPort)); + uint16_t controllerVendorId = static_cast(env->CallIntMethod(controllerParams, getControllerVendorId)); jobject keypairDelegate = env->CallObjectMethod(controllerParams, getKeypairDelegate); jbyteArray rootCertificate = (jbyteArray) env->CallObjectMethod(controllerParams, getRootCertificate); jbyteArray intermediateCertificate = (jbyteArray) env->CallObjectMethod(controllerParams, getIntermediateCertificate); jbyteArray operationalCertificate = (jbyteArray) env->CallObjectMethod(controllerParams, getOperationalCertificate); jbyteArray ipk = (jbyteArray) env->CallObjectMethod(controllerParams, getIpk); - uint16_t failsafeTimerSeconds = env->CallIntMethod(controllerParams, getFailsafeTimerSeconds); - uint16_t caseFailsafeTimerSeconds = env->CallIntMethod(controllerParams, getCASEFailsafeTimerSeconds); + uint16_t failsafeTimerSeconds = static_cast(env->CallIntMethod(controllerParams, getFailsafeTimerSeconds)); + uint16_t caseFailsafeTimerSeconds = + static_cast(env->CallIntMethod(controllerParams, getCASEFailsafeTimerSeconds)); bool attemptNetworkScanWiFi = env->CallBooleanMethod(controllerParams, getAttemptNetworkScanWiFi); bool attemptNetworkScanThread = env->CallBooleanMethod(controllerParams, getAttemptNetworkScanThread); bool skipCommissioningComplete = env->CallBooleanMethod(controllerParams, getSkipCommissioningComplete); - uint64_t adminSubject = env->CallLongMethod(controllerParams, getAdminSubject); + uint64_t adminSubject = static_cast(env->CallLongMethod(controllerParams, getAdminSubject)); jobject countryCodeOptional = env->CallObjectMethod(controllerParams, getCountryCode); jobject regulatoryLocationOptional = env->CallObjectMethod(controllerParams, getRegulatoryLocation); @@ -630,9 +631,9 @@ JNI_METHOD(void, pairDeviceWithAddress) RendezvousParameters rendezvousParams = RendezvousParameters() - .SetDiscriminator(discriminator) + .SetDiscriminator(static_cast(discriminator)) .SetSetupPINCode(static_cast(pinCode)) - .SetPeerAddress(Transport::PeerAddress::UDP(const_cast(addrJniString.c_str()), port)); + .SetPeerAddress(Transport::PeerAddress::UDP(const_cast(addrJniString.c_str()), static_cast(port))); CommissioningParameters commissioningParams = wrapper->GetCommissioningParameters(); if (csrNonce != nullptr) @@ -748,7 +749,7 @@ JNI_METHOD(void, establishPaseConnectionByAddress) RendezvousParameters rendezvousParams = RendezvousParameters() .SetSetupPINCode(static_cast(pinCode)) - .SetPeerAddress(Transport::PeerAddress::UDP(const_cast(addrJniString.c_str()), port)); + .SetPeerAddress(Transport::PeerAddress::UDP(const_cast(addrJniString.c_str()), static_cast(port))); err = wrapper->Controller()->EstablishPASEConnection(deviceId, rendezvousParams); @@ -871,7 +872,7 @@ CHIP_ERROR GetEpochTime(JNIEnv * env, jobject calendar, uint32_t & epochTime) universalTime.Year = static_cast(env->CallIntMethod(calendar, getMethod, yearID)); // The first month of the year in the Gregorian and Julian calendars is JANUARY which is 0. See detailed in // https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#MONTH - universalTime.Month = static_cast(env->CallIntMethod(calendar, getMethod, monthID)) + 1; + universalTime.Month = static_cast(static_cast(env->CallIntMethod(calendar, getMethod, monthID)) + 1u); universalTime.Day = static_cast(env->CallIntMethod(calendar, getMethod, dayID)); universalTime.Hour = static_cast(env->CallIntMethod(calendar, getMethod, hourID)); universalTime.Minute = static_cast(env->CallIntMethod(calendar, getMethod, minuteID)); @@ -1505,7 +1506,7 @@ JNI_METHOD(jboolean, openPairingWindowWithPIN) chip::SetupPayload setupPayload; err = AutoCommissioningWindowOpener::OpenCommissioningWindow( wrapper->Controller(), chipDevice->GetDeviceId(), System::Clock::Seconds16(duration), static_cast(iteration), - discriminator, pinCode, NullOptional, setupPayload); + static_cast(discriminator), pinCode, NullOptional, setupPayload); if (err != CHIP_NO_ERROR) { @@ -1571,7 +1572,7 @@ JNI_METHOD(jboolean, openPairingWindowWithPINCallback) chip::SetupPayload setupPayload; err = AndroidCommissioningWindowOpener::OpenCommissioningWindow( wrapper->Controller(), chipDevice->GetDeviceId(), System::Clock::Seconds16(duration), static_cast(iteration), - discriminator, pinCode, NullOptional, jcallback, setupPayload); + static_cast(discriminator), pinCode, NullOptional, jcallback, setupPayload); if (err != CHIP_NO_ERROR) { @@ -1699,11 +1700,12 @@ JNI_METHOD(void, subscribe) } app::ReadPrepareParams params(device->GetSecureSession().Value()); - params.mMinIntervalFloorSeconds = minInterval; - params.mMaxIntervalCeilingSeconds = maxInterval; + uint16_t aImTimeoutMs = static_cast(imTimeoutMs); + params.mMinIntervalFloorSeconds = static_cast(minInterval); + params.mMaxIntervalCeilingSeconds = static_cast(maxInterval); params.mKeepSubscriptions = (keepSubscriptions != JNI_FALSE); params.mIsFabricFiltered = (isFabricFiltered != JNI_FALSE); - params.mTimeout = imTimeoutMs != 0 ? System::Clock::Milliseconds32(imTimeoutMs) : System::Clock::kZero; + params.mTimeout = aImTimeoutMs != 0 ? System::Clock::Milliseconds32(aImTimeoutMs) : System::Clock::kZero; if (attributePathList != nullptr) { @@ -1857,10 +1859,11 @@ JNI_METHOD(void, write) jint imTimeoutMs) { chip::DeviceLayer::StackLock lock; - CHIP_ERROR err = CHIP_NO_ERROR; - jint listSize = 0; - auto callback = reinterpret_cast(callbackHandle); - app::WriteClient * writeClient; + CHIP_ERROR err = CHIP_NO_ERROR; + jint listSize = 0; + auto callback = reinterpret_cast(callbackHandle); + app::WriteClient * writeClient = nullptr; + uint16_t convertedTimedRequestTimeoutMs = static_cast(timedRequestTimeoutMs); ChipLogDetail(Controller, "IM write() called"); @@ -1870,9 +1873,9 @@ JNI_METHOD(void, write) VerifyOrExit(attributeList != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); SuccessOrExit(err = JniReferences::GetInstance().GetListSize(attributeList, listSize)); - writeClient = Platform::New(device->GetExchangeManager(), callback->GetChunkedWriteCallback(), - timedRequestTimeoutMs != 0 ? Optional(timedRequestTimeoutMs) - : Optional::Missing()); + writeClient = Platform::New( + device->GetExchangeManager(), callback->GetChunkedWriteCallback(), + convertedTimedRequestTimeoutMs != 0 ? Optional(convertedTimedRequestTimeoutMs) : Optional::Missing()); for (uint8_t i = 0; i < listSize; i++) { @@ -1987,24 +1990,25 @@ JNI_METHOD(void, invoke) jint imTimeoutMs) { chip::DeviceLayer::StackLock lock; - CHIP_ERROR err = CHIP_NO_ERROR; - auto callback = reinterpret_cast(callbackHandle); - app::CommandSender * commandSender; - uint32_t endpointId = 0; - uint32_t clusterId = 0; - uint32_t commandId = 0; - jmethodID getEndpointIdMethod = nullptr; - jmethodID getClusterIdMethod = nullptr; - jmethodID getCommandIdMethod = nullptr; - jmethodID getTlvByteArrayMethod = nullptr; - jobject endpointIdObj = nullptr; - jobject clusterIdObj = nullptr; - jobject commandIdObj = nullptr; - jbyteArray tlvBytesObj = nullptr; - jbyte * tlvBytesObjBytes = nullptr; - jsize length = 0; + CHIP_ERROR err = CHIP_NO_ERROR; + auto callback = reinterpret_cast(callbackHandle); + app::CommandSender * commandSender = nullptr; + uint32_t endpointId = 0; + uint32_t clusterId = 0; + uint32_t commandId = 0; + jmethodID getEndpointIdMethod = nullptr; + jmethodID getClusterIdMethod = nullptr; + jmethodID getCommandIdMethod = nullptr; + jmethodID getTlvByteArrayMethod = nullptr; + jobject endpointIdObj = nullptr; + jobject clusterIdObj = nullptr; + jobject commandIdObj = nullptr; + jbyteArray tlvBytesObj = nullptr; + jbyte * tlvBytesObjBytes = nullptr; + jsize length = 0; TLV::TLVReader reader; - TLV::TLVWriter * writer = nullptr; + TLV::TLVWriter * writer = nullptr; + uint16_t convertedTimedRequestTimeoutMs = static_cast(timedRequestTimeoutMs); ChipLogDetail(Controller, "IM invoke() called"); @@ -2058,9 +2062,9 @@ JNI_METHOD(void, invoke) reader.Init(reinterpret_cast(tlvBytesObjBytes), static_cast(length)); reader.Next(); SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(app::CommandDataIB::Tag::kFields), reader)); - - SuccessOrExit(err = commandSender->FinishCommand(timedRequestTimeoutMs != 0 ? Optional(timedRequestTimeoutMs) - : Optional::Missing())); + SuccessOrExit(err = commandSender->FinishCommand(convertedTimedRequestTimeoutMs != 0 + ? Optional(convertedTimedRequestTimeoutMs) + : Optional::Missing())); SuccessOrExit(err = commandSender->SendCommandRequest(device->GetSecureSession().Value(), diff --git a/src/controller/tests/data_model/TestCommands.cpp b/src/controller/tests/data_model/TestCommands.cpp index 0cb30647b6da4e..f9d1e35a900b73 100644 --- a/src/controller/tests/data_model/TestCommands.cpp +++ b/src/controller/tests/data_model/TestCommands.cpp @@ -85,7 +85,8 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip if (DataModel::Decode(aReader, dataRequest) != CHIP_NO_ERROR) { - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::Failure, "Unable to decode the request"); + apCommandObj->AddStatusAndLogIfFailure(aCommandPath, Protocols::InteractionModel::Status::Failure, + "Unable to decode the request"); return; } @@ -115,18 +116,15 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip } else if (responseDirective == kSendMultipleSuccessStatusCodes) { - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::Success, - "No error but testing status success case"); - // TODO: Right now all but the first AddStatus call fail, so this // test is not really testing what it should. - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < 4; ++i) { - (void) apCommandObj->FallibleAddStatus(aCommandPath, Protocols::InteractionModel::Status::Success, - "No error but testing status success case"); + apCommandObj->AddStatusAndLogIfFailure(aCommandPath, Protocols::InteractionModel::Status::Success, + "No error but testing AddStatusAndLogIfFailure in success case"); } // And one failure on the end. - (void) apCommandObj->FallibleAddStatus(aCommandPath, Protocols::InteractionModel::Status::Failure); + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::Failure); } else if (responseDirective == kSendError) { @@ -134,13 +132,11 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, chip } else if (responseDirective == kSendMultipleErrors) { - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::Failure); - // TODO: Right now all but the first AddStatus call fail, so this // test is not really testing what it should. - for (size_t i = 0; i < 3; ++i) + for (size_t i = 0; i < 4; ++i) { - (void) apCommandObj->FallibleAddStatus(aCommandPath, Protocols::InteractionModel::Status::Failure); + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::Failure); } } else if (responseDirective == kSendSuccessStatusCodeWithClusterStatus) diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index cf4ab4c068d465..21ec9e56f737e9 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -163,11 +163,17 @@ - (void)cleanupAfterStartup { // Invalidate our MTRDevice instances before we shut down our secure // sessions and whatnot, so they don't start trying to resubscribe when we - // do the secure session shutdowns. - for (MTRDevice * device in [self.nodeIDToDeviceMap allValues]) { + // do the secure session shutdowns. Since we don't want to hold the lock + // while calling out into arbitrary invalidation code, snapshot the list of + // devices before we start invalidating. + os_unfair_lock_lock(&_deviceMapLock); + NSArray * devices = [self.nodeIDToDeviceMap allValues]; + [self.nodeIDToDeviceMap removeAllObjects]; + os_unfair_lock_unlock(&_deviceMapLock); + + for (MTRDevice * device in devices) { [device invalidate]; } - [self.nodeIDToDeviceMap removeAllObjects]; [self stopBrowseForCommissionables]; [_factory controllerShuttingDown:self]; diff --git a/src/platform/ESP32/BLEManagerImpl.h b/src/platform/ESP32/BLEManagerImpl.h index e7f61785ffa5c8..5cb1421750786a 100644 --- a/src/platform/ESP32/BLEManagerImpl.h +++ b/src/platform/ESP32/BLEManagerImpl.h @@ -71,6 +71,8 @@ struct ble_gatt_char_context #include #endif +#define MAX_SCAN_RSP_DATA_LEN 31 + namespace chip { namespace DeviceLayer { namespace Internal { @@ -132,6 +134,7 @@ class BLEManagerImpl final : public BLEManager, #endif { public: + uint8_t scanResponseBuffer[MAX_SCAN_RSP_DATA_LEN]; BLEManagerImpl() {} #if CONFIG_ENABLE_ESP32_BLE_CONTROLLER CHIP_ERROR ConfigureBle(uint32_t aAdapterId, bool aIsCentral); @@ -140,7 +143,12 @@ class BLEManagerImpl final : public BLEManager, #endif #endif + CHIP_ERROR ConfigureScanResponseData(ByteSpan data); + void ClearScanResponseData(void); + private: + chip::Optional mScanResponse; + // Allow the BLEManager interface class to delegate method calls to // the implementation methods provided by this class. friend BLEManager; diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp index 52e86d4b050a7f..6a9a047ab84db1 100644 --- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp +++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp @@ -1012,6 +1012,25 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void) return err; } +CHIP_ERROR BLEManagerImpl::ConfigureScanResponseData(ByteSpan data) +{ + if (!IsSpanUsable(data) || data.size() > MAX_SCAN_RSP_DATA_LEN) + { + ChipLogError(DeviceLayer, "scan response data is invalid"); + return CHIP_ERROR_INVALID_ARGUMENT; + } + memcpy(scanResponseBuffer, data.data(), data.size()); + ByteSpan scanResponseSpan(scanResponseBuffer); + mScanResponse = chip::Optional(scanResponseSpan); + return CHIP_NO_ERROR; +} + +void BLEManagerImpl::ClearScanResponseData(void) +{ + mScanResponse.ClearValue(); + ChipLogDetail(DeviceLayer, "scan response data is cleared"); +} + void BLEManagerImpl::HandleRXCharWrite(struct ble_gatt_char_context * param) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -1584,6 +1603,15 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void) } } #endif + if (mScanResponse.HasValue()) + { + err = MapBLEError(ble_gap_adv_rsp_set_data(mScanResponse.Value().data(), mScanResponse.Value().size())); + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "ble_gap_adv_rsp_set_data failed: %s", ErrorStr(err)); + return err; + } + } err = MapBLEError(ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL)); if (err == CHIP_NO_ERROR) { diff --git a/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp b/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp index f226caeaaa8395..0eba1701c5dec1 100644 --- a/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp +++ b/src/platform/silabs/platformAbstraction/WiseMcuSpam.cpp @@ -26,6 +26,10 @@ extern "C" void RSI_Board_LED_Toggle(int); extern "C" void RSI_Wakeupsw_config(void); extern "C" void RSI_Wakeupsw_config_gpio0(void); +#if SILABS_LOG_ENABLED +#include "silabs_utils.h" +#endif + namespace chip { namespace DeviceLayer { namespace Silabs { diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index c66cad9e1d95c8..0905fdf3599b2b 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -81101,7 +81101,7 @@ class TestCASERecoverySuite : public TestCommand { uint16_t value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); - VerifyOrReturn(CheckValue("dataModelRevision", value, 1U)); + VerifyOrReturn(CheckValue("dataModelRevision", value, 17U)); } break; case 2: @@ -81124,7 +81124,7 @@ class TestCASERecoverySuite : public TestCommand { uint16_t value; VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); - VerifyOrReturn(CheckValue("dataModelRevision", value, 1U)); + VerifyOrReturn(CheckValue("dataModelRevision", value, 17U)); } break; default: diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index feeeed0da0bc56..e9f65d53c9e541 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -117246,7 +117246,7 @@ class TestCASERecovery : public TestCommandBridge { { id actualValue = value; - VerifyOrReturn(CheckValue("DataModelRevision", actualValue, 1U)); + VerifyOrReturn(CheckValue("DataModelRevision", actualValue, 17U)); } NextTest(); @@ -117315,7 +117315,7 @@ class TestCASERecovery : public TestCommandBridge { { id actualValue = value; - VerifyOrReturn(CheckValue("DataModelRevision", actualValue, 1U)); + VerifyOrReturn(CheckValue("DataModelRevision", actualValue, 17U)); } NextTest();