Skip to content

Commit ca06856

Browse files
silabs-aydoganerzr
authored andcommitted
uic: zpc: SWPROT-9247: Implement "Get NLS Nodes" SAPI command
(cherry picked from commit d14526c3dcd81d6feec8b52f09eee3dbb5d05910) Forwarded: #11 Signed-off-by: Philippe Coval <[email protected]>
1 parent 4ba0765 commit ca06856

File tree

4 files changed

+324
-0
lines changed

4 files changed

+324
-0
lines changed

applications/zpc/components/zwave_api/include/zwapi_protocol_controller.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ extern "C" {
309309
#define MULTI_DEST_MASK_OFFSET_MASK 0xE0
310310
///@}
311311

312+
/// Each increase in offset in nodeID is reflected in this value multiplied by 8
313+
#define GET_NLS_NODES_OFFSET_GRANULARITY_IN_BYTES 128
314+
312315
typedef struct _ZW_MULTI_DEST_ {
313316
/// - bit 5-7 states the nodeId-1 (offset 0, 32, 64, 96... - translates into
314317
/// respectively nodeID 1, 33, 65, 97...), which is represented by the
@@ -1050,6 +1053,17 @@ sl_status_t zwapi_enable_node_nls(const zwave_node_id_t nodeId);
10501053
*/
10511054
sl_status_t zwapi_get_node_nls(const zwave_node_id_t nodeId, uint8_t* nls_state);
10521055

1056+
/**
1057+
* @brief Get the NLS State of the nodes of a network in the controller NVM
1058+
*
1059+
* @param list_length Length of the node list in bytes
1060+
* @param node_list List of nodes with NLS state
1061+
*
1062+
* @returns SL_STATUS_OK or SL_STATUS_FAIL
1063+
*/
1064+
sl_status_t zwapi_get_nls_nodes(uint16_t *list_length,
1065+
zwave_nodemask_t node_list);
1066+
10531067
/**
10541068
* @brief Sends TX status, TX report and session ID of the ongoing protocol command class encryption
10551069
* session to the Z-Wave API module.

applications/zpc/components/zwave_api/src/zwapi_func_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ typedef enum
219219
#define FUNC_ID_ZW_GET_NODE_NLS_STATE 0x6B
220220
#define FUNC_ID_ZW_REQUEST_PROTOCOL_CC_ENCRYPTION 0x6C
221221
#define FUNC_ID_ZW_SEND_PROTOCOL_DATA 0xAC
222+
#define FUNC_ID_ZW_GET_NLS_NODES 0xC0
222223

223224
#define FUNC_ID_TIMER_START 0x70
224225
#define FUNC_ID_TIMER_RESTART 0x71

applications/zpc/components/zwave_api/src/zwapi_protocol_controller.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,63 @@ sl_status_t zwapi_get_node_nls(
833833
return SL_STATUS_FAIL;
834834
}
835835

836+
sl_status_t zwapi_get_nls_nodes(uint16_t *list_length,
837+
zwave_nodemask_t node_list)
838+
{
839+
uint8_t more_nodes = 1;
840+
uint8_t start_offset = 0;
841+
sl_status_t command_status = SL_STATUS_OK;
842+
*list_length = 0;
843+
844+
while (more_nodes > 0) {
845+
uint8_t response_length = 0;
846+
uint8_t index = 0;
847+
uint8_t request_buffer[REQUEST_BUFFER_SIZE] = {0};
848+
uint8_t response_buffer[FRAME_LENGTH_MAX] = {0};
849+
uint8_t received_nodelist_length = 0;
850+
request_buffer[index++] = start_offset;
851+
852+
command_status = zwapi_send_command_with_response(FUNC_ID_ZW_GET_NLS_NODES,
853+
request_buffer,
854+
index,
855+
response_buffer,
856+
&response_length);
857+
858+
if (command_status == SL_STATUS_OK) {
859+
more_nodes = response_buffer[IDX_DATA];
860+
start_offset = response_buffer[IDX_DATA + 1];
861+
received_nodelist_length = response_buffer[IDX_DATA + 2];
862+
*list_length += received_nodelist_length;
863+
const uint8_t *p = &response_buffer[IDX_DATA + 3];
864+
for (uint8_t i = 0; i < received_nodelist_length; i++) {
865+
if ((i + (start_offset * GET_NLS_NODES_OFFSET_GRANULARITY_IN_BYTES)) // NOSONAR
866+
> sizeof(zwave_nodemask_t)) {
867+
sl_log_debug(LOG_TAG,
868+
"Z-Wave API get NLS node list index of bound\n");
869+
return SL_STATUS_FAIL;
870+
}
871+
node_list[i + start_offset * GET_NLS_NODES_OFFSET_GRANULARITY_IN_BYTES]
872+
= *p;
873+
p++;
874+
}
875+
start_offset++;
876+
} else {
877+
sl_log_debug(LOG_TAG,
878+
"Z-Wave API get NLS node list retrieve error, %d",
879+
command_status);
880+
return SL_STATUS_FAIL;
881+
}
882+
}
883+
884+
// Buffer is shifted due to misalignement between zwave stack and ZPC.
885+
// It will be addressed in SWPROT-9279.
886+
memmove(&node_list[ZW_LR_NODEMASK_OFFSET - 1],
887+
&node_list[ZW_MAX_NODEMASK_LENGTH - 1],
888+
ZW_LR_MAX_NODEMASK_LENGTH - ZW_LR_NODEMASK_OFFSET);
889+
890+
return SL_STATUS_OK;
891+
}
892+
836893
sl_status_t zwapi_transfer_protocol_cc(
837894
const zwave_node_id_t srcNode,
838895
const uint8_t decryptionKey,

applications/zpc/components/zwave_api/test/zwapi_protocol_controller_test.c

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "zwapi_init_mock.h"
2020
#include "zwapi_utils.h"
2121

22+
#include <string.h>
23+
2224
/// Setup the test suite (called once before all test_xxx functions are called)
2325
void suiteSetUp() {}
2426

@@ -92,6 +94,256 @@ void test_zwapi_get_node_nls(void)
9294
TEST_ASSERT_EQUAL(nls_enabled, node_nls_state);
9395
}
9496

97+
void test_zwapi_get_nls_nodes_frame_0_reduced(void)
98+
{
99+
// clang-format off
100+
uint8_t response_buffer[3 + 6] = {0x00}; /* frame 0 */
101+
memset(response_buffer, 0, sizeof(response_buffer));
102+
response_buffer[0] = 0x09; /* length = len(payload) + 3 */
103+
response_buffer[1] = 0x01; /* type: response */
104+
response_buffer[2] = FUNC_ID_ZW_GET_NLS_NODES; /* cmd */
105+
response_buffer[3] = 0x00; /* more nodes flag: no */
106+
response_buffer[4] = 0x00; /* start offset */
107+
response_buffer[5] = 0x03; /* list length */
108+
response_buffer[6] = 0xF2; /* nodes 2, 5, 6, 7, 8 */
109+
response_buffer[7] = 0x01; /* nodes 9 */
110+
response_buffer[8] = 0x80; /* nodes 24 */
111+
uint8_t response_buffer_length = sizeof(response_buffer);
112+
uint8_t request_buffer[] = {0x00 /* start offset */};
113+
uint8_t request_buffer_length = sizeof(request_buffer);
114+
uint8_t expected_list_length = response_buffer[5];
115+
// clang-format on
116+
117+
zwapi_session_send_frame_with_response_ExpectAndReturn(
118+
FUNC_ID_ZW_GET_NLS_NODES,
119+
request_buffer,
120+
request_buffer_length,
121+
response_buffer,
122+
&response_buffer_length,
123+
SL_STATUS_OK);
124+
zwapi_session_send_frame_with_response_IgnoreArg_response_buf();
125+
zwapi_session_send_frame_with_response_IgnoreArg_response_len();
126+
zwapi_session_send_frame_with_response_ReturnMemThruPtr_response_buf(
127+
response_buffer,
128+
response_buffer_length);
129+
zwapi_session_send_frame_with_response_ReturnThruPtr_response_len(
130+
&response_buffer_length);
131+
132+
uint16_t list_length = 0;
133+
zwave_nodemask_t node_list;
134+
memset(&node_list, 0, sizeof(zwave_nodemask_t));
135+
// verify API call
136+
TEST_ASSERT_EQUAL(SL_STATUS_OK, zwapi_get_nls_nodes(&list_length, node_list));
137+
// verify list length
138+
TEST_ASSERT_EQUAL(expected_list_length, list_length);
139+
// verify NLS enabled nodes
140+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(2, node_list));
141+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(5, node_list));
142+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(6, node_list));
143+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(7, node_list));
144+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(8, node_list));
145+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(9, node_list));
146+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(24, node_list));
147+
}
148+
149+
void test_zwapi_get_nls_nodes_frame_0_full(void)
150+
{
151+
// clang-format off
152+
uint8_t response_buffer[128 + 6] = {0x00}; /* frame 0 */
153+
memset(response_buffer, 0, sizeof(response_buffer));
154+
response_buffer[0] = 0x86; /* length = len(payload) + 3 */
155+
response_buffer[1] = 0x01; /* type: response */
156+
response_buffer[2] = FUNC_ID_ZW_GET_NLS_NODES; /* cmd */
157+
response_buffer[3] = 0x00; /* more nodes flag: no */
158+
response_buffer[4] = 0x00; /* start offset */
159+
response_buffer[5] = 0x80; /* list length */
160+
response_buffer[125 + 6] = 0x01; /* nodes 1024 */
161+
response_buffer[127 + 6] = 0x80; /* nodes 1047 (last node ID of the frame 0) */
162+
uint8_t response_buffer_length = sizeof(response_buffer);
163+
uint8_t request_buffer[] = {0x00 /* start offset */};
164+
uint8_t request_buffer_length = sizeof(request_buffer);
165+
uint8_t expected_list_length = response_buffer[5];
166+
// clang-format on
167+
168+
zwapi_session_send_frame_with_response_ExpectAndReturn(
169+
FUNC_ID_ZW_GET_NLS_NODES,
170+
request_buffer,
171+
request_buffer_length,
172+
response_buffer,
173+
&response_buffer_length,
174+
SL_STATUS_OK);
175+
zwapi_session_send_frame_with_response_IgnoreArg_response_buf();
176+
zwapi_session_send_frame_with_response_IgnoreArg_response_len();
177+
zwapi_session_send_frame_with_response_ReturnMemThruPtr_response_buf(
178+
response_buffer,
179+
response_buffer_length);
180+
zwapi_session_send_frame_with_response_ReturnThruPtr_response_len(
181+
&response_buffer_length);
182+
183+
uint16_t list_length = 0;
184+
zwave_nodemask_t node_list;
185+
memset(&node_list, 0, sizeof(zwave_nodemask_t));
186+
// verify API call
187+
TEST_ASSERT_EQUAL(SL_STATUS_OK, zwapi_get_nls_nodes(&list_length, node_list));
188+
// verify list length
189+
TEST_ASSERT_EQUAL(expected_list_length, list_length);
190+
// verify NLS enabled nodes
191+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1024, node_list));
192+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1047, node_list));
193+
}
194+
195+
void test_zwapi_get_nls_nodes_frame_0_full_frame_1_reduced(void)
196+
{
197+
// clang-format off
198+
uint8_t response_buffer1[128 + 6] = {0x00}; /* frame 0 */
199+
uint8_t response_buffer2[29 + 6] = {0x00}; /* frame 1 */
200+
memset(response_buffer1, 0, sizeof(response_buffer1));
201+
memset(response_buffer2, 0, sizeof(response_buffer2));
202+
response_buffer1[0] = 0x86; /* length = len(payload) + 3 */
203+
response_buffer1[1] = 0x01; /* type: response */
204+
response_buffer1[2] = FUNC_ID_ZW_GET_NLS_NODES; /* cmd */
205+
response_buffer1[3] = 0x80; /* more nodes flag: yes */
206+
response_buffer1[4] = 0x00; /* start offset */
207+
response_buffer1[5] = 0x80; /* list length */
208+
response_buffer1[29 + 6] = 0x01; /* nodes 256 (first LR node ID) */
209+
response_buffer1[127 + 6] = 0x80; /* nodes 1047 (last node ID of the frame 0) */
210+
response_buffer2[0] = 0x22; /* length = len(payload) + 6 */
211+
response_buffer2[1] = 0x01; /* type: response */
212+
response_buffer2[2] = FUNC_ID_ZW_GET_NLS_NODES; /* cmd */
213+
response_buffer2[3] = 0x00; /* more nodes flag: no */
214+
response_buffer2[4] = 0x01; /* start offset */
215+
response_buffer2[5] = 0x1C; /* list length */
216+
response_buffer2[0 + 6] = 0x01; /* nodes 1048 (first node ID of the frame 1) */
217+
response_buffer2[27 + 6] = 0x80; /* nodes 1271 */
218+
uint8_t response_buffer1_length = sizeof(response_buffer1);
219+
uint8_t response_buffer2_length = sizeof(response_buffer2);
220+
uint8_t request_buffer1[] = {0x00 /* start offset */};
221+
uint8_t request_buffer1_length = sizeof(request_buffer1);
222+
uint8_t request_buffer2[] = {0x01 /* start offset */};
223+
uint8_t request_buffer2_length = sizeof(request_buffer2);
224+
uint8_t expected_list_length = response_buffer1[5] + response_buffer2[5];
225+
// clang-format on
226+
227+
zwapi_session_send_frame_with_response_ExpectAndReturn(
228+
FUNC_ID_ZW_GET_NLS_NODES,
229+
request_buffer1,
230+
request_buffer1_length,
231+
response_buffer1,
232+
&response_buffer1_length,
233+
SL_STATUS_OK);
234+
zwapi_session_send_frame_with_response_IgnoreArg_response_buf();
235+
zwapi_session_send_frame_with_response_IgnoreArg_response_len();
236+
zwapi_session_send_frame_with_response_ReturnMemThruPtr_response_buf(
237+
response_buffer1,
238+
response_buffer1_length);
239+
zwapi_session_send_frame_with_response_ReturnThruPtr_response_len(
240+
&response_buffer1_length);
241+
242+
zwapi_session_send_frame_with_response_ExpectAndReturn(
243+
FUNC_ID_ZW_GET_NLS_NODES,
244+
request_buffer2,
245+
request_buffer2_length,
246+
response_buffer2,
247+
&response_buffer2_length,
248+
SL_STATUS_OK);
249+
zwapi_session_send_frame_with_response_IgnoreArg_response_buf();
250+
zwapi_session_send_frame_with_response_IgnoreArg_response_len();
251+
zwapi_session_send_frame_with_response_ReturnMemThruPtr_response_buf(
252+
response_buffer2,
253+
response_buffer2_length);
254+
zwapi_session_send_frame_with_response_ReturnThruPtr_response_len(
255+
&response_buffer2_length);
256+
257+
uint16_t list_length = 0;
258+
zwave_nodemask_t node_list;
259+
memset(&node_list, 0, sizeof(zwave_nodemask_t));
260+
// verify API call
261+
TEST_ASSERT_EQUAL(SL_STATUS_OK, zwapi_get_nls_nodes(&list_length, node_list));
262+
// verify list length
263+
TEST_ASSERT_EQUAL(expected_list_length, list_length);
264+
// verify NLS enabled nodes
265+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(256, node_list));
266+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1047, node_list));
267+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1048, node_list));
268+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1271, node_list));
269+
}
270+
271+
void test_zwapi_get_nls_nodes_frame_0_full_frame_1_full(void)
272+
{
273+
// clang-format off
274+
uint8_t response_buffer1[128 + 6] = {0x00}; /* frame 0 */
275+
uint8_t response_buffer2[29 + 6] = {0x00}; /* frame 1 */
276+
memset(response_buffer1, 0, sizeof(response_buffer1));
277+
memset(response_buffer2, 0, sizeof(response_buffer2));
278+
response_buffer1[0] = 0x86; /* length = len(payload) + 3 */
279+
response_buffer1[1] = 0x01; /* type: response */
280+
response_buffer1[2] = FUNC_ID_ZW_GET_NLS_NODES; /* cmd */
281+
response_buffer1[3] = 0x80; /* more nodes flag: yes */
282+
response_buffer1[4] = 0x00; /* start offset */
283+
response_buffer1[5] = 0x80; /* list length */
284+
response_buffer1[29 + 6] = 0x01; /* nodes 256 (first LR node ID) */
285+
response_buffer1[127 + 6] = 0x80; /* nodes 1047 (last node ID of the frame 0) */
286+
response_buffer2[0] = 0x23; /* length = len(payload) + 6 */
287+
response_buffer2[1] = 0x01; /* type: response */
288+
response_buffer2[2] = FUNC_ID_ZW_GET_NLS_NODES; /* cmd */
289+
response_buffer2[3] = 0x00; /* more nodes flag: no */
290+
response_buffer2[4] = 0x01; /* start offset */
291+
response_buffer2[5] = 0x1D; /* list length */
292+
response_buffer2[0 + 6] = 0x01; /* nodes 1048 (first node ID of the frame 1) */
293+
response_buffer2[28 + 6] = 0x80; /* nodes 1279 (last LR node ID) */
294+
uint8_t response_buffer1_length = sizeof(response_buffer1);
295+
uint8_t response_buffer2_length = sizeof(response_buffer2);
296+
uint8_t request_buffer1[] = {0x00 /* start offset */};
297+
uint8_t request_buffer1_length = sizeof(request_buffer1);
298+
uint8_t request_buffer2[] = {0x01 /* start offset */};
299+
uint8_t request_buffer2_length = sizeof(request_buffer2);
300+
uint8_t expected_list_length = response_buffer1[5] + response_buffer2[5];
301+
// clang-format on
302+
303+
zwapi_session_send_frame_with_response_ExpectAndReturn(
304+
FUNC_ID_ZW_GET_NLS_NODES,
305+
request_buffer1,
306+
request_buffer1_length,
307+
response_buffer1,
308+
&response_buffer1_length,
309+
SL_STATUS_OK);
310+
zwapi_session_send_frame_with_response_IgnoreArg_response_buf();
311+
zwapi_session_send_frame_with_response_IgnoreArg_response_len();
312+
zwapi_session_send_frame_with_response_ReturnMemThruPtr_response_buf(
313+
response_buffer1,
314+
response_buffer1_length);
315+
zwapi_session_send_frame_with_response_ReturnThruPtr_response_len(
316+
&response_buffer1_length);
317+
318+
zwapi_session_send_frame_with_response_ExpectAndReturn(
319+
FUNC_ID_ZW_GET_NLS_NODES,
320+
request_buffer2,
321+
request_buffer2_length,
322+
response_buffer2,
323+
&response_buffer2_length,
324+
SL_STATUS_OK);
325+
zwapi_session_send_frame_with_response_IgnoreArg_response_buf();
326+
zwapi_session_send_frame_with_response_IgnoreArg_response_len();
327+
zwapi_session_send_frame_with_response_ReturnMemThruPtr_response_buf(
328+
response_buffer2,
329+
response_buffer2_length);
330+
zwapi_session_send_frame_with_response_ReturnThruPtr_response_len(
331+
&response_buffer2_length);
332+
333+
uint16_t list_length = 0;
334+
zwave_nodemask_t node_list;
335+
memset(&node_list, 0, sizeof(zwave_nodemask_t));
336+
// verify API call
337+
TEST_ASSERT_EQUAL(SL_STATUS_OK, zwapi_get_nls_nodes(&list_length, node_list));
338+
// verify list length
339+
TEST_ASSERT_EQUAL(expected_list_length, list_length);
340+
// verify NLS enabled nodes
341+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(256, node_list));
342+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1047, node_list));
343+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1048, node_list));
344+
TEST_ASSERT_EQUAL(1, ZW_IS_NODE_IN_MASK(1279, node_list));
345+
}
346+
95347
void test_zwapi_transfer_protocol_cc(void)
96348
{
97349
zwave_node_id_t node_id = 2;

0 commit comments

Comments
 (0)