diff --git a/applications/zpc/components/zwave/zwave_controller/src/zwave_controller_callbacks.c b/applications/zpc/components/zwave/zwave_controller/src/zwave_controller_callbacks.c
index d92b3da52..e1f9dedd0 100644
--- a/applications/zpc/components/zwave/zwave_controller/src/zwave_controller_callbacks.c
+++ b/applications/zpc/components/zwave/zwave_controller/src/zwave_controller_callbacks.c
@@ -313,23 +313,11 @@ void zwave_controller_on_frame_received(
frame_length);
//If no transport plugins needs the frame parse it on to upper layers
if (status == SL_STATUS_NOT_FOUND) {
- // Check if the frame is a protocol CC
- if (frame_data[0] == ZWAVE_CMD_CLASS_PROTOCOL || frame_data[0] == ZWAVE_CMD_CLASS_PROTOCOL_LR)
- {
- ZWAVE_CONTROLLER_DISPATCH_CALLBACKS(on_protocol_frame_received,
- connection_info,
- rx_options,
- frame_data,
- frame_length);
- }
- else
- {
- ZWAVE_CONTROLLER_DISPATCH_CALLBACKS(on_application_frame_received,
- connection_info,
- rx_options,
- frame_data,
- frame_length);
- }
+ ZWAVE_CONTROLLER_DISPATCH_CALLBACKS(on_application_frame_received,
+ connection_info,
+ rx_options,
+ frame_data,
+ frame_length);
}
}
diff --git a/applications/zpc/components/zwave/zwave_controller/test/zwave_controller_callbacks_test.c b/applications/zpc/components/zwave/zwave_controller/test/zwave_controller_callbacks_test.c
index 98d5eb83e..81beafdd6 100644
--- a/applications/zpc/components/zwave/zwave_controller/test/zwave_controller_callbacks_test.c
+++ b/applications/zpc/components/zwave/zwave_controller/test/zwave_controller_callbacks_test.c
@@ -98,15 +98,6 @@ static void zwave_controller_on_protocol_cc_encryption_request(
zwave_controller_on_protocol_cc_encryption_request_count += 1;
}
-static void zwave_controller_on_protocol_frame_received(
- const zwave_controller_connection_info_t *connection_info,
- const zwave_rx_receive_options_t *rx_options,
- const uint8_t *frame_data,
- uint16_t frame_length)
-{
- zwave_controller_on_protocol_frame_received_count += 1;
-}
-
static void zwave_controller_on_node_event_test(zwave_node_id_t node_id)
{
zwave_controller_on_node_event_test_call_count += 1;
@@ -344,74 +335,6 @@ void test_zwave_controller_on_protocol_cc_encryption_request_received()
callbacks.on_protocol_cc_encryption_request = NULL;
}
-void test_zwave_controller_on_controller_protocol_frames()
-{
- // We need to inject a valid frame, as this will go through the transports
- zwave_controller_on_frame_received(&info,
- &rx_options,
- protocol_frame_data,
- sizeof(protocol_frame_data));
- TEST_ASSERT_EQUAL(0, zwave_controller_on_protocol_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_rx_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_application_frame_received_count);
-
- callbacks.on_rx_frame_received
- = &zwave_controller_on_rx_frame_received_callback;
- callbacks.on_application_frame_received
- = &zwave_controller_on_application_frame_received;
- callbacks.on_protocol_frame_received
- = &zwave_controller_on_protocol_frame_received;
- TEST_ASSERT_EQUAL(SL_STATUS_OK,
- zwave_controller_register_callbacks(&callbacks));
-
- zwave_controller_on_frame_received(&info,
- &rx_options,
- protocol_frame_data,
- sizeof(protocol_frame_data));
- TEST_ASSERT_EQUAL(1, zwave_controller_on_protocol_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_application_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_rx_frame_received_count);
-
- // remove these callbacks:
- callbacks.on_rx_frame_received = NULL;
- callbacks.on_application_frame_received = NULL;
- callbacks.on_protocol_frame_received = NULL;
-}
-
-void test_zwave_controller_on_controller_protocol_lr_frames()
-{
- // We need to inject a valid frame, as this will go through the transports
- zwave_controller_on_frame_received(&info,
- &rx_options,
- protocol_lr_frame_data,
- sizeof(protocol_lr_frame_data));
- TEST_ASSERT_EQUAL(0, zwave_controller_on_protocol_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_rx_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_application_frame_received_count);
-
- callbacks.on_rx_frame_received
- = &zwave_controller_on_rx_frame_received_callback;
- callbacks.on_application_frame_received
- = &zwave_controller_on_application_frame_received;
- callbacks.on_protocol_frame_received
- = &zwave_controller_on_protocol_frame_received;
- TEST_ASSERT_EQUAL(SL_STATUS_OK,
- zwave_controller_register_callbacks(&callbacks));
-
- zwave_controller_on_frame_received(&info,
- &rx_options,
- protocol_lr_frame_data,
- sizeof(protocol_lr_frame_data));
- TEST_ASSERT_EQUAL(1, zwave_controller_on_protocol_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_application_frame_received_count);
- TEST_ASSERT_EQUAL(0, zwave_controller_on_rx_frame_received_count);
-
- // remove these callbacks:
- callbacks.on_rx_frame_received = NULL;
- callbacks.on_application_frame_received = NULL;
- callbacks.on_protocol_frame_received = NULL;
-}
-
void test_zwave_controller_on_network_address_update()
{
// Nothing happens with no callback registered
diff --git a/applications/zpc/components/zwave/zwave_transports/s2/CMakeLists.txt b/applications/zpc/components/zwave/zwave_transports/s2/CMakeLists.txt
index a2e9a15df..120e81bd6 100644
--- a/applications/zpc/components/zwave/zwave_transports/s2/CMakeLists.txt
+++ b/applications/zpc/components/zwave/zwave_transports/s2/CMakeLists.txt
@@ -18,7 +18,7 @@ set(KEYSTORE_SOURCES "src/zwave_s2_keystore.c")
add_library(
zwave_s2
src/zwave_s2_fixt.c ${KEYSTORE_SOURCES} src/zwave_s2_network.c
- src/zwave_s2_printf.c src/zwave_s2_process.c src/zwave_s2_transport.c src/zwave_s2_protocol_cc_encryption.c)
+ src/zwave_s2_printf.c src/zwave_s2_process.c src/zwave_s2_transport.c)
set(DEFAULT_ZW-LIBS2_PATH libs/zw-libs2)
if(EXISTS ${ZW-LIBS2_LOCATION})
@@ -40,13 +40,12 @@ target_include_directories(
zwave_s2
PUBLIC include
PRIVATE ${ZW-LIBS2_PATH}/include src)
-
install(TARGETS zwave_s2 LIBRARY DESTINATION lib)
target_link_libraries(
zwave_s2
PUBLIC zwave_s2_nonce_management unify
- PRIVATE s2_controller zwave_controller zwave_s0 zpc_attribute_store)
+ PRIVATE s2_controller zwave_controller zwave_s0 zpc_attribute_store zpc_utils)
target_compile_definitions(zwave_s2 PRIVATE ZIPGW ZW_CONTROLLER)
diff --git a/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_process.c b/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_process.c
index c5507c60e..96f710007 100644
--- a/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_process.c
+++ b/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_process.c
@@ -22,7 +22,6 @@
#include "zwave_s2_keystore_int.h"
#include "zwave_s2_network.h"
#include "zwave_s2_transport.h"
-#include "zwave_s2_protocol_cc_encryption.h"
#define LOG_TAG "zwave_s2_process"
@@ -86,7 +85,6 @@ static void zwave_s2_init()
.on_network_address_update = zwave_s2_on_network_address_update,
.on_new_network_entered = zwave_s2_on_new_network_entered,
.on_multicast_group_deleted = zwave_s2_on_on_multicast_group_deleted,
- .on_protocol_cc_encryption_request = zwave_s2_on_protocol_cc_encryption_request,
};
zwave_controller_register_callbacks(&callbacks);
diff --git a/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_protocol_cc_encryption.c b/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_protocol_cc_encryption.c
deleted file mode 100644
index 5dc7d34f7..000000000
--- a/applications/zpc/components/zwave/zwave_transports/s2/src/zwave_s2_protocol_cc_encryption.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/******************************************************************************
- * # License
- * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
- ******************************************************************************
- * The licensor of this software is Silicon Laboratories Inc. Your use of this
- * software is governed by the terms of Silicon Labs Master Software License
- * Agreement (MSLA) available at
- * www.silabs.com/about-us/legal/master-software-license-agreement. This
- * software is distributed to you in Source Code format and is governed by the
- * sections of the MSLA applicable to Source Code.
- *
- *****************************************************************************/
-#include "zwave_controller_transport.h"
-#include "zwave_controller_transport_internal.h"
-#include "sl_log.h"
-#include "zwave_controller.h"
-#include "zwave_s2_internal.h"
-#include "zwave_s2_transport.h"
-#include "zwave_s2_protocol_cc_encryption.h"
-#include "zwave_tx_scheme_selector.h"
-
-#define LOG_TAG "zwave_s2_protocol_cc_encryption"
-
-protocol_metadata_t metadata = {0};
-
-static void on_send_protocol_data_callback_received(uint8_t status, const zwapi_tx_report_t *tx_info, void *user)
-{
- protocol_metadata_t *metadata = (protocol_metadata_t *)user;
-
- if (status == TRANSMIT_COMPLETE_FAIL || status == TRANSMIT_COMPLETE_VERIFIED) {
- zwave_controller_request_protocol_cc_encryption_callback(status, tx_info, metadata->session_id);
- } else {
- sl_log_debug(LOG_TAG, "Send Protocol Data callback, status: %d", status);
- }
-}
-
-void zwave_s2_on_protocol_cc_encryption_request(
- const zwave_node_id_t destination_node_id,
- const uint8_t payload_length,
- const uint8_t *const payload,
- const uint8_t protocol_metadata_length,
- const uint8_t *const protocol_metadata,
- const uint8_t use_supervision,
- const uint8_t session_id)
-{
- zwave_controller_connection_info_t connection_info = {0};
- zwave_tx_options_t tx_options = {0};
- uint8_t number_of_expected_responses = 1;
- uint32_t discard_timeout_ms = 5000;
- sl_status_t ret = SL_STATUS_OK;
- zwave_tx_session_id_t tx_session_id = NULL;
-
- zwave_tx_scheme_get_node_connection_info(destination_node_id, 0, &connection_info);
- zwave_tx_scheme_get_node_tx_options(
- ZWAVE_TX_QOS_MAX_PRIORITY,
- number_of_expected_responses,
- discard_timeout_ms,
- &tx_options);
-
- // Other TX options are set in the transport layer in `S2_send_frame`
- tx_options.transport.is_protocol_frame = true;
-
- metadata.session_id = session_id;
- metadata.data_length = protocol_metadata_length;
- memcpy(metadata.data, protocol_metadata, protocol_metadata_length);
-
- // Following command will trigger a "Send Protocol Data" command and the callback
- // provided to this function will be triggered when the callback data frame of
- // the "Send Protocol Data" command is received.
- ret = zwave_tx_send_data(&connection_info,
- payload_length,
- payload,
- &tx_options,
- on_send_protocol_data_callback_received,
- (void *)&metadata,
- &tx_session_id);
- if (ret != SL_STATUS_OK) {
- sl_log_error(LOG_TAG, "Unable to send S2 data. Error code %d.", ret);
- }
-}
diff --git a/applications/zpc/components/zwave/zwave_transports/s2/test/CMakeLists.txt b/applications/zpc/components/zwave/zwave_transports/s2/test/CMakeLists.txt
index 52abf038e..64e1107bc 100644
--- a/applications/zpc/components/zwave/zwave_transports/s2/test/CMakeLists.txt
+++ b/applications/zpc/components/zwave/zwave_transports/s2/test/CMakeLists.txt
@@ -65,21 +65,6 @@ target_add_unittest(
zpc_attribute_store_test_helper
zwave_network_management_mock)
-# ####################### S2 Protocol CC Encryption test ##################################
-target_add_unittest(
- zwave_s2
- NAME
- zwave_s2_protocol_cc_encryption_test
- SOURCES
- zwave_s2_protocol_cc_encryption_test.c
- DEPENDS
- zwave_controller ## Non-mock, we use the real thing here
- libs2_mock
- zwave_api_mock
- uic_contiki_stub
- zwave_tx_mock
- zwave_network_management_mock)
-
# ####################### S2 Nonce Management test ##################################
target_add_unittest(
zwave_s2_nonce_management
diff --git a/applications/zpc/components/zwave/zwave_transports/s2/test/zwave_s2_protocol_cc_encryption_test.c b/applications/zpc/components/zwave/zwave_transports/s2/test/zwave_s2_protocol_cc_encryption_test.c
deleted file mode 100644
index b90d6f0d8..000000000
--- a/applications/zpc/components/zwave/zwave_transports/s2/test/zwave_s2_protocol_cc_encryption_test.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/******************************************************************************
- * # License
- * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
- ******************************************************************************
- * The licensor of this software is Silicon Laboratories Inc. Your use of this
- * software is governed by the terms of Silicon Labs Master Software License
- * Agreement (MSLA) available at
- * www.silabs.com/about-us/legal/master-software-license-agreement. This
- * software is distributed to you in Source Code format and is governed by the
- * sections of the MSLA applicable to Source Code.
- *
- *****************************************************************************/
-#include
-
-#include "contiki_test_helper.h"
-
-#include "zwave_s2_protocol_cc_encryption.h"
-
-#include "zwave_controller_connection_info.h"
-
-#include "zwave_tx_mock.h"
-
-#include "sl_log.h"
-#include "sl_status.h"
-
-#include "unity.h"
-
-/// Setup the test suite (called once before all test_xxx functions are called)
-void suiteSetUp() {}
-
-/// Teardown the test suite (called once after all test_xxx functions are called)
-int suiteTearDown(int num_failures)
-{
- return num_failures;
-}
-
-void setUp()
-{
- contiki_test_helper_init();
-}
-
-void tearDown() {}
-
-void test_zwave_s2_on_protocol_cc_encryption_request_happy_case()
-{
- zwave_node_id_t destination_node_id = 2;
- uint8_t payload[] = {0x01, 0x02, 0x03};
- uint8_t payload_length = sizeof(payload);
- uint8_t protocol_metadata[] = {0xA1, 0xA2, 0xA3};
- uint8_t protocol_metadata_length = sizeof(protocol_metadata);
- uint8_t use_supervision = 1;
- uint8_t session_id = 1;
- zwave_controller_connection_info_t connection_info = {0};
- zwave_tx_options_t tx_options = {0};
- zwave_tx_session_id_t tx_session_id = NULL;
- protocol_metadata_t metadata = {0};
-
- // Expected TX options
- tx_options.transport.is_protocol_frame = true;
- tx_options.number_of_responses = 1;
- tx_options.discard_timeout_ms = 5000;
- tx_options.qos_priority = ZWAVE_TX_QOS_MAX_PRIORITY;
-
- // Expected connection info
- connection_info.encapsulation = ZWAVE_CONTROLLER_ENCAPSULATION_NONE;
- connection_info.local.node_id = 0;
- connection_info.remote.node_id = 2;
-
- // Expected protocol metadata
- metadata.session_id = session_id;
- metadata.data_length = protocol_metadata_length;
- memcpy(metadata.data, protocol_metadata, protocol_metadata_length);
-
- zwave_tx_send_data_ExpectWithArrayAndReturn(&connection_info,
- sizeof(connection_info),
- payload_length,
- payload,
- sizeof(payload),
- &tx_options,
- sizeof(tx_options),
- NULL,
- (void *)&metadata,
- sizeof(protocol_metadata_t),
- &tx_session_id,
- sizeof(zwave_tx_session_id_t),
- SL_STATUS_OK);
- zwave_tx_send_data_IgnoreArg_on_send_complete();
-
- zwave_s2_on_protocol_cc_encryption_request(destination_node_id,
- payload_length,
- payload,
- protocol_metadata_length,
- protocol_metadata,
- use_supervision,
- session_id);
-}
diff --git a/applications/zpc/components/zwave_command_classes/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/CMakeLists.txt
index c59c6587e..99c75db5f 100644
--- a/applications/zpc/components/zwave_command_classes/CMakeLists.txt
+++ b/applications/zpc/components/zwave_command_classes/CMakeLists.txt
@@ -62,7 +62,8 @@ add_library(
src/zwave_command_classes_fixt.c
src/zwave_command_classes_utils.c
src/zwave_command_class_inclusion_controller.cpp
- src/zwave_command_class_transport_service.c)
+ src/zwave_command_class_transport_service.c
+ src/zwave_command_class_protocol.c)
install(TARGETS zwave_command_classes LIBRARY DESTINATION lib)
target_include_directories(
diff --git a/applications/zpc/components/zwave/zwave_transports/s2/include/zwave_s2_protocol_cc_encryption.h b/applications/zpc/components/zwave_command_classes/include/zwave_command_class_protocol.h
similarity index 50%
rename from applications/zpc/components/zwave/zwave_transports/s2/include/zwave_s2_protocol_cc_encryption.h
rename to applications/zpc/components/zwave_command_classes/include/zwave_command_class_protocol.h
index db257f59f..2dd8dd55b 100644
--- a/applications/zpc/components/zwave/zwave_transports/s2/include/zwave_s2_protocol_cc_encryption.h
+++ b/applications/zpc/components/zwave_command_classes/include/zwave_command_class_protocol.h
@@ -11,40 +11,34 @@
*
*****************************************************************************/
-/**
- * @defgroup zwave_s2_protocol_cc_encryption Security 2 Protocol Command Class Encryption
- * @ingroup zwave_transports
- * @brief Protocol Command Class Encryption implementation for Z-Wave S2
- *
- * @{
- */
-
-#ifndef ZWAVE_S2_PROTOCOL_CC_ENCRYPTION_H
-#define ZWAVE_S2_PROTOCOL_CC_ENCRYPTION_H
+#ifndef ZWAVE_COMMAND_CLASS_PROTOCOL_H
+#define ZWAVE_COMMAND_CLASS_PROTOCOL_H
-#include
#include "sl_status.h"
-#include "zwave_node_id_definitions.h"
+#include "zwave_controller_connection_info.h"
+#include "zwave_rx.h"
+#include "zwave_tx.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
- * @brief Triggered when a Protocol CC Encryption Request is received.
*
- * This callback has to be registered to the Z-Wave Controller callbacks.
+ * @brief Setup fixture for the Protocol Command Class.
*
- * @param destination_node_id Destination node ID.
- * @param payload_length Length of the payload to be encrypted.
- * @param payload Payload to be encrypted.
- * @param protocol_metadata_length Length of the protocol metadata.
- * @param protocol_metadata Protocol metadata.
- * @param use_supervision Whether to use supervision.
- * @param session_id Session ID.
+ * This setup will register the Protocol command handler
+ * to the Z-Wave CC framework,
*
+ * @returns SL_STATUS_OK if successful
+ * @returns SL_STATUS_FAIL if an error occurred
*/
-void zwave_s2_on_protocol_cc_encryption_request(
+sl_status_t zwave_command_class_protocol_init(void);
+
+/**
+ * @brief
+ */
+void zwave_on_protocol_cc_encryption_request(
const zwave_node_id_t destination_node_id,
const uint8_t payload_length,
const uint8_t *const payload,
@@ -57,6 +51,4 @@ void zwave_s2_on_protocol_cc_encryption_request(
}
#endif
-#endif //ZWAVE_S2_PROTOCOL_CC_ENCRYPTION_H
-/** @} end zwave_s2_protocol_cc_encryption */
-
+#endif //ZWAVE_COMMAND_CLASS_PROTOCOL_H
\ No newline at end of file
diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_protocol.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_protocol.c
new file mode 100644
index 000000000..4f8a64ef7
--- /dev/null
+++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_protocol.c
@@ -0,0 +1,217 @@
+/******************************************************************************
+ * # License
+ * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+
+// Attribute store helpers
+#include "attribute_store_defined_attribute_types.h"
+#include "attribute_store_helper.h"
+
+// Includes from other components
+#include "sl_log.h"
+#include "attribute_store.h"
+#include "attribute_resolver.h"
+#include "zwave_unid.h"
+#include "ZW_classcmd.h"
+#include "zwave_tx.h"
+#include "zwave_controller_keyset.h"
+#include "zwave_controller_utils.h"
+#include "zwave_utils.h"
+#include "zwave_command_handler.h"
+#include "zwave_command_class_indices.h"
+#include "zwapi_protocol_controller.h"
+#include "zwave_command_class_protocol.h"
+#include "zwave_command_class_supervision.h"
+#include "zwave_tx_scheme_selector.h"
+
+// Generic includes
+#include "assert.h"
+#include "string.h"
+
+// Log tag
+#define LOG_TAG "zwave_command_class_protocol"
+
+protocol_metadata_t metadata = {0};
+
+static zwave_controller_callbacks_t zwave_command_class_protocol_callbacks = {
+ .on_protocol_cc_encryption_request = zwave_on_protocol_cc_encryption_request
+};
+
+static void on_send_protocol_data_callback_received(uint8_t status, const zwapi_tx_report_t *tx_info, void *user)
+{
+ protocol_metadata_t *metadata = (protocol_metadata_t *)user;
+
+ if (status == TRANSMIT_COMPLETE_FAIL || status == TRANSMIT_COMPLETE_VERIFIED) {
+ zwave_controller_request_protocol_cc_encryption_callback(status, tx_info, metadata->session_id);
+ } else {
+ sl_log_debug(LOG_TAG, "Send Protocol Data callback, status: %d", status);
+ }
+}
+
+void zwave_on_protocol_cc_encryption_request(
+ const zwave_node_id_t destination_node_id,
+ const uint8_t payload_length,
+ const uint8_t *const payload,
+ const uint8_t protocol_metadata_length,
+ const uint8_t *const protocol_metadata,
+ const uint8_t use_supervision,
+ const uint8_t session_id)
+{
+ zwave_controller_connection_info_t connection_info = {0};
+ zwave_tx_options_t tx_options = {0};
+ uint8_t number_of_expected_responses = 1;
+ uint32_t discard_timeout_ms = 5000;
+ // sl_status_t ret = SL_STATUS_OK;
+ zwave_tx_session_id_t tx_session_id = NULL;
+
+ zwave_tx_scheme_get_node_connection_info(destination_node_id, 0, &connection_info);
+ zwave_tx_scheme_get_node_tx_options(
+ ZWAVE_TX_QOS_MAX_PRIORITY,
+ number_of_expected_responses,
+ discard_timeout_ms,
+ &tx_options);
+
+ // Other TX options are set in the transport layer in `S2_send_frame`
+ tx_options.transport.is_protocol_frame = true;
+
+ metadata.session_id = session_id;
+ metadata.data_length = protocol_metadata_length;
+ memcpy(metadata.data, protocol_metadata, protocol_metadata_length);
+
+ if (use_supervision)
+ {
+ zwave_command_class_supervision_send_data(
+ &connection_info,
+ payload_length,
+ payload,
+ &tx_options,
+ &on_send_protocol_data_callback_received,
+ (void *)&metadata,
+ &tx_session_id);
+ } else {
+ zwave_tx_send_data(
+ &connection_info,
+ payload_length,
+ payload,
+ &tx_options,
+ &on_send_protocol_data_callback_received,
+ (void *)&metadata,
+ &tx_session_id);
+ }
+}
+
+sl_status_t zwave_command_class_protocol_support_handler(
+ const zwave_controller_connection_info_t *connection,
+ const uint8_t *frame_data,
+ uint16_t frame_length)
+{
+ // Frame too short, it should have not come here.
+ if (frame_length <= COMMAND_INDEX) {
+ return SL_STATUS_NOT_SUPPORTED;
+ }
+
+ sl_log_info(LOG_TAG, "Protocol command received from NodeID %d:%d",
+ connection->remote.node_id, connection->remote.endpoint_id);
+
+ sl_status_t status =
+ zwapi_transfer_protocol_cc(
+ connection->remote.node_id,
+ zwave_controller_get_key_from_encapsulation(connection->encapsulation),
+ frame_length,
+ frame_data);
+
+ switch (status) {
+ case SL_STATUS_OK:
+ sl_log_info(LOG_TAG,
+ "Command from NodeID %d:%d was handled successfully.",
+ connection->remote.node_id,
+ connection->remote.endpoint_id);
+ break;
+
+ case SL_STATUS_FAIL:
+ sl_log_warning(LOG_TAG,
+ "Command from NodeID %d:%d had an error during handling. "
+ "Not all parameters were accepted",
+ connection->remote.node_id,
+ connection->remote.endpoint_id);
+ break;
+
+ case SL_STATUS_BUSY:
+ // This should not happen, or if it happens, we should be able to return
+ // an application busy message or similar.
+ sl_log_warning(LOG_TAG,
+ "Frame handler is busy and could not handle frame from "
+ "NodeID %d:%d correctly.",
+ connection->remote.node_id,
+ connection->remote.endpoint_id);
+ break;
+
+ case SL_STATUS_NOT_SUPPORTED:
+ sl_log_warning(
+ LOG_TAG,
+ "Command from NodeID %d:%d got rejected because it is not supported. "
+ "It was possibly also rejected due to security filtering",
+ connection->remote.node_id,
+ connection->remote.endpoint_id);
+ break;
+
+ default:
+ sl_log_warning(
+ LOG_TAG,
+ "Command from NodeID %d:%d had an unexpected return status: 0x%04X\n",
+ connection->remote.node_id,
+ connection->remote.endpoint_id,
+ status);
+ break;
+ }
+ return status;
+}
+
+sl_status_t zwave_command_class_protocol_init()
+{
+ zwave_command_handler_t handler_protocol = { 0 };
+ handler_protocol.support_handler = &zwave_command_class_protocol_support_handler;
+ handler_protocol.control_handler = NULL;
+ handler_protocol.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NONE;
+ handler_protocol.command_class = ZWAVE_CMD_CLASS_PROTOCOL;
+ handler_protocol.version = 1;
+ handler_protocol.command_class_name = "Protocol";
+ handler_protocol.manual_security_validation = false;
+
+ if(SL_STATUS_OK != zwave_controller_register_callbacks(&zwave_command_class_protocol_callbacks))
+ {
+ sl_log_error(LOG_TAG, "Failed to register callbacks for Protocol Command Class");
+ return SL_STATUS_FAIL;
+ }
+
+ if(SL_STATUS_OK != zwave_command_handler_register_handler(handler_protocol))
+ {
+ sl_log_error(LOG_TAG, "Failed to register Protocol Command Class");
+ return SL_STATUS_FAIL;
+ }
+
+ zwave_command_handler_t handler_protocol_lr = { 0 };
+ handler_protocol_lr.support_handler = &zwave_command_class_protocol_support_handler;
+ handler_protocol_lr.control_handler = NULL;
+ handler_protocol_lr.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NONE;
+ handler_protocol_lr.command_class = ZWAVE_CMD_CLASS_PROTOCOL_LR;
+ handler_protocol_lr.version = 1;
+ handler_protocol_lr.command_class_name = "Protocol LR";
+ handler_protocol_lr.manual_security_validation = false;
+
+ if (SL_STATUS_OK != zwave_command_handler_register_handler(handler_protocol_lr))
+ {
+ sl_log_error(LOG_TAG, "Failed to register Protocol Command Class");
+ return SL_STATUS_FAIL;
+ }
+
+ return SL_STATUS_OK;
+}
\ No newline at end of file
diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_supervision.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_supervision.c
index c7d716c60..f9ee011bb 100644
--- a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_supervision.c
+++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_supervision.c
@@ -503,10 +503,17 @@ sl_status_t zwave_command_class_supervision_send_data(
supervision_tx_options.number_of_responses = tx_options->number_of_responses;
supervision_tx_options.number_of_responses += 1;
- intptr_t user_parameter = (intptr_t)INVALID_SUPERVISION_ID;
- if (connection->remote.is_multicast == false) {
- user_parameter = (intptr_t)supervision_id;
+ intptr_t user_parameter;
+ if (!tx_options->transport.is_protocol_frame)
+ {
+ user_parameter = (intptr_t)INVALID_SUPERVISION_ID;
+ if (connection->remote.is_multicast == false) {
+ user_parameter = (intptr_t)supervision_id;
+ }
+ } else {
+ user_parameter = (intptr_t) user;
}
+
sl_status_t zwave_tx_status = zwave_tx_send_data(
connection,
supervision_frame_size,
diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c
index 32d1c1522..a20c668f3 100644
--- a/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c
+++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c
@@ -59,6 +59,7 @@
#include "zwave_command_class_indicator_control.h"
#include "zwave_command_class_manufacturer_specific_control.h"
#include "zwave_command_class_humidity_control_mode.h"
+#include "zwave_command_class_protocol.h"
// Generic includes
#include
@@ -129,6 +130,7 @@ sl_status_t zwave_command_classes_init()
status |= zwave_command_class_version_init();
status |= zwave_command_class_wake_up_init();
status |= zwave_command_class_zwave_plus_info_init();
+ status |= zwave_command_class_protocol_init();
// Auto-generated handlers with overrides
status |= zwave_command_class_indicator_control_init();
diff --git a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt
index 63b79e147..bfb7362ff 100644
--- a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt
+++ b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt
@@ -884,3 +884,18 @@ target_add_unittest(
uic_attribute_resolver_mock
zpc_attribute_resolver_mock
uic_dotdot_mqtt_mock)
+
+target_add_unittest(
+ zwave_command_classes
+ NAME
+ zwave_command_class_protocol_test
+ SOURCES
+ zwave_command_class_protocol_test.c
+ DEPENDS
+ zwave_command_class_test_helpers
+ zwave_controller_mock
+ zwave_command_handler_mock
+ zwave_api_mock
+ zwave_tx_mock
+ zwave_tx_scheme_selector_mock
+)
diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_protocol_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_protocol_test.c
new file mode 100644
index 000000000..fcdaf3388
--- /dev/null
+++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_protocol_test.c
@@ -0,0 +1,220 @@
+/******************************************************************************
+ * # License
+ * Copyright 2021 Silicon Laboratories Inc. www.silabs.com
+ ******************************************************************************
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is distributed to you in Source Code format and is governed by the
+ * sections of the MSLA applicable to Source Code.
+ *
+ *****************************************************************************/
+
+// Generic includes
+#include
+
+// Test includes
+#include "unity.h"
+
+// Interface includes
+#include "attribute_store_defined_attribute_types.h"
+#include "zwave_command_class_wake_up_types.h"
+#include "ZW_classcmd.h"
+#include "zwave_command_class_protocol.h"
+#include "zwave_controller_utils.h"
+
+// Includes from other components
+#include "sl_log.h"
+#include "zwave_controller_connection_info.h"
+#include "zwave_tx_groups.h"
+
+// Mock includes
+#include "zwave_command_handler_mock.h"
+#include "zwave_tx_scheme_selector_mock.h"
+#include "attribute_store_mock.h"
+#include "attribute_store_helper_mock.h"
+#include "attribute_resolver_mock.h"
+#include "zwapi_protocol_controller_mock.h"
+#include "zwave_controller_keyset_mock.h"
+#include "zwave_tx_mock.h"
+#include "zwave_controller_callbacks_mock.h"
+
+#define LOG_TAG "zwave_command_class_protocol_test"
+
+static zwave_command_handler_t protocol_handler = {};
+
+static sl_status_t zwave_command_handler_register_handler_stub(
+ zwave_command_handler_t new_command_class_handler, int cmock_num_calls)
+{
+ protocol_handler = new_command_class_handler;
+
+ TEST_ASSERT_EQUAL(ZWAVE_CONTROLLER_ENCAPSULATION_NONE,
+ protocol_handler.minimal_scheme);
+ TEST_ASSERT_TRUE(ZWAVE_CMD_CLASS_PROTOCOL ==protocol_handler.command_class
+ || ZWAVE_CMD_CLASS_PROTOCOL_LR == protocol_handler.command_class);
+ TEST_ASSERT_EQUAL(1, protocol_handler.version);
+ TEST_ASSERT_NULL(protocol_handler.control_handler);
+ TEST_ASSERT_NOT_NULL(protocol_handler.support_handler);
+ TEST_ASSERT_FALSE(protocol_handler.manual_security_validation);
+
+ return SL_STATUS_OK;
+}
+
+static sl_status_t zwave_controller_register_callback_stub(
+ const zwave_controller_callbacks_t *callback, int cmock_num_calls)
+{
+ TEST_ASSERT_NOT_NULL(callback);
+ TEST_ASSERT_NOT_NULL(callback->on_protocol_cc_encryption_request);
+
+ return SL_STATUS_OK;
+}
+
+void suiteSetUp() {}
+
+int suiteTearDown(int num_failures)
+{
+ return num_failures;
+}
+
+void setUp()
+{
+ // Handler registration
+ zwave_command_handler_register_handler_Stub(
+ &zwave_command_handler_register_handler_stub);
+
+ zwave_controller_register_callbacks_Stub(
+ &zwave_controller_register_callback_stub);
+
+ zwave_command_class_protocol_init();
+}
+
+void tearDown() {}
+
+void test_zwave_command_class_protocol_init()
+{
+ // Call the function
+ TEST_ASSERT_EQUAL(SL_STATUS_OK, zwave_command_class_protocol_init());
+}
+
+void test_zwave_command_class_protocol_handler(void)
+{
+ uint8_t test_frame_data[5] = { 0};
+
+ test_frame_data[0] = ZWAVE_CMD_CLASS_PROTOCOL;
+
+ zwave_controller_connection_info_t connection = { 0 };
+ connection.encapsulation = ZWAVE_CONTROLLER_ENCAPSULATION_SECURITY_2_AUTHENTICATED;
+ connection.remote.node_id = 2;
+ connection.local.node_id = 1;
+
+ // Test with wrong command length
+ TEST_ASSERT_EQUAL(
+ SL_STATUS_NOT_SUPPORTED,
+ protocol_handler.support_handler(&connection,
+ test_frame_data,
+ 1)); // wrong length
+
+ // Test with correct length
+ zwave_controller_get_key_from_encapsulation_ExpectAndReturn(ZWAVE_CONTROLLER_ENCAPSULATION_SECURITY_2_AUTHENTICATED, ZWAVE_CONTROLLER_S2_AUTHENTICATED_KEY);
+
+ zwapi_transfer_protocol_cc_ExpectAndReturn(2,
+ ZWAVE_CONTROLLER_S2_AUTHENTICATED_KEY,
+ 5,
+ (uint8_t*) &test_frame_data,
+ SL_STATUS_OK);
+
+ TEST_ASSERT_EQUAL(
+ SL_STATUS_OK,
+ protocol_handler.support_handler(&connection,
+ test_frame_data,
+ sizeof(test_frame_data)));
+}
+
+void test_zwave_s2_on_protocol_cc_encryption_request_happy_case()
+{
+ zwave_node_id_t destination_node_id = 2;
+ uint8_t payload[] = {0x01, 0x02, 0x03};
+ uint8_t payload_length = sizeof(payload) / sizeof(payload[0]);
+ uint8_t protocol_metadata[] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7};
+ uint8_t protocol_metadata_length = sizeof(protocol_metadata) / sizeof(protocol_metadata[0]);
+ uint8_t use_supervision = 0;
+ uint8_t session_id = 1;
+ zwave_controller_connection_info_t connection_info = {0};
+ zwave_tx_options_t tx_options = {0};
+ zwave_tx_session_id_t tx_session_id = NULL;
+ protocol_metadata_t metadata = {0};
+
+ // Expected TX options
+ tx_options.transport.is_protocol_frame = true;
+
+ // Expected protocol metadata
+ metadata.session_id = session_id;
+ metadata.data_length = protocol_metadata_length;
+ memcpy(metadata.data, protocol_metadata, protocol_metadata_length);
+
+ zwave_tx_scheme_get_node_connection_info_Expect(destination_node_id, 0, NULL);
+ zwave_tx_scheme_get_node_connection_info_IgnoreArg_connection_info();
+ zwave_tx_scheme_get_node_tx_options_Expect(ZWAVE_TX_QOS_MAX_PRIORITY, 1, 5000, NULL);
+ zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
+
+ zwave_tx_send_data_ExpectWithArrayAndReturn(&connection_info,
+ sizeof(connection_info),
+ payload_length,
+ payload,
+ sizeof(payload),
+ &tx_options,
+ sizeof(tx_options),
+ NULL,
+ (void *)&metadata,
+ sizeof(protocol_metadata_t),
+ &tx_session_id,
+ sizeof(zwave_tx_session_id_t),
+ SL_STATUS_OK);
+ zwave_tx_send_data_IgnoreArg_on_send_complete();
+
+ zwave_on_protocol_cc_encryption_request(destination_node_id,
+ payload_length,
+ payload,
+ protocol_metadata_length,
+ protocol_metadata,
+ use_supervision,
+ session_id);
+
+ // Test with supervision
+ use_supervision = 1;
+
+ zwave_tx_scheme_get_node_connection_info_Expect(destination_node_id, 0, NULL);
+ zwave_tx_scheme_get_node_connection_info_IgnoreArg_connection_info();
+ zwave_tx_scheme_get_node_tx_options_Expect(ZWAVE_TX_QOS_MAX_PRIORITY, 1, 5000, NULL);
+ zwave_tx_scheme_get_node_tx_options_IgnoreArg_tx_options();
+
+ uint16_t supervision_frame_size = 4 + payload_length; // sizeof(frame) - SUPERVISION_ENCAPSULATED_COMMAND_MAXIMUM_SIZE
+ tx_options.number_of_responses += 1; // supervision get expects 1 frame in response
+
+ zwave_tx_send_data_ExpectWithArrayAndReturn(&connection_info,
+ sizeof(connection_info),
+ supervision_frame_size,
+ payload,
+ sizeof(payload),
+ &tx_options,
+ sizeof(tx_options),
+ NULL,
+ (void *)&metadata,
+ sizeof(protocol_metadata_t),
+ &tx_session_id,
+ sizeof(zwave_tx_session_id_t),
+ SL_STATUS_OK);
+ zwave_tx_send_data_IgnoreArg_on_send_complete();
+ zwave_tx_send_data_IgnoreArg_data();
+ zwave_tx_send_data_IgnoreArg_user();
+
+ zwave_on_protocol_cc_encryption_request(destination_node_id,
+ payload_length,
+ payload,
+ protocol_metadata_length,
+ protocol_metadata,
+ use_supervision,
+ session_id);
+}
+
diff --git a/applications/zpc/components/zwave_command_handler/src/zwave_command_handler.cpp b/applications/zpc/components/zwave_command_handler/src/zwave_command_handler.cpp
index 1717c1c04..a2f213b83 100644
--- a/applications/zpc/components/zwave_command_handler/src/zwave_command_handler.cpp
+++ b/applications/zpc/components/zwave_command_handler/src/zwave_command_handler.cpp
@@ -53,7 +53,7 @@ std::multiset
static zwave_controller_callbacks_t zwave_command_handler_callbacks = {
.on_new_network_entered = zwave_command_handler_on_new_network_entered,
.on_application_frame_received = zwave_command_handler_on_frame_received,
- .on_protocol_frame_received = zwave_command_handler_on_protocol_frame_received
+ .on_protocol_frame_received = zwave_command_handler_on_protocol_frame_received,
};
///////////////////////////////////////////////////////////////////////////////
diff --git a/applications/zpc/main.c b/applications/zpc/main.c
index 0c41e3e75..8ce055310 100644
--- a/applications/zpc/main.c
+++ b/applications/zpc/main.c
@@ -204,6 +204,7 @@ static uic_fixt_shutdown_step_t uic_fixt_shutdown_steps_list[]
{&dotdot_mapper_teardown, "DotDot mapper"},
{NULL, "Terminator"}};
+
int main(int argc, char **argv)
{
attribute_mapper_config_init(); //TODO how do we want to do this