1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <zephyr/shell/shell.h>
9 #include <zephyr/bluetooth/mesh.h>
10 
11 #include "mesh/net.h"
12 #include "mesh/access.h"
13 #include "utils.h"
14 #include <zephyr/bluetooth/mesh/shell.h>
15 
16 #define CID_NVAL 0xffff
17 
18 /* Default net & app key values, unless otherwise specified */
19 extern const uint8_t bt_mesh_shell_default_key[16];
20 
cmd_reset(const struct shell * sh,size_t argc,char * argv[])21 static int cmd_reset(const struct shell *sh, size_t argc, char *argv[])
22 {
23 	int err;
24 	bool reset = false;
25 
26 	err = bt_mesh_cfg_cli_node_reset(bt_mesh_shell_target_ctx.net_idx,
27 					 bt_mesh_shell_target_ctx.dst, &reset);
28 	if (err) {
29 		shell_error(sh, "Unable to send Remote Node Reset (err %d)", err);
30 		return 0;
31 	}
32 
33 	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
34 		struct bt_mesh_cdb_node *node = bt_mesh_cdb_node_get(bt_mesh_shell_target_ctx.dst);
35 
36 		if (node) {
37 			bt_mesh_cdb_node_del(node, true);
38 		}
39 	}
40 
41 	shell_print(sh, "Remote node reset complete");
42 
43 	return 0;
44 }
45 
cmd_timeout(const struct shell * sh,size_t argc,char * argv[])46 static int cmd_timeout(const struct shell *sh, size_t argc, char *argv[])
47 {
48 	int32_t timeout_ms;
49 	int err = 0;
50 
51 	if (argc == 2) {
52 		int32_t timeout_s = shell_strtol(argv[1], 0, &err);
53 
54 		if (err) {
55 			shell_warn(sh, "Unable to parse input string argument");
56 			return err;
57 		}
58 
59 		if (timeout_s < 0 || timeout_s > (INT32_MAX / 1000)) {
60 			timeout_ms = SYS_FOREVER_MS;
61 		} else {
62 			timeout_ms = timeout_s * MSEC_PER_SEC;
63 		}
64 
65 		bt_mesh_cfg_cli_timeout_set(timeout_ms);
66 	}
67 
68 	timeout_ms = bt_mesh_cfg_cli_timeout_get();
69 	if (timeout_ms == SYS_FOREVER_MS) {
70 		shell_print(sh, "Message timeout: forever");
71 	} else {
72 		shell_print(sh, "Message timeout: %u seconds", timeout_ms / 1000);
73 	}
74 
75 	return 0;
76 }
77 
cmd_get_comp(const struct shell * sh,size_t argc,char * argv[])78 static int cmd_get_comp(const struct shell *sh, size_t argc, char *argv[])
79 {
80 	NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_RX_SDU_MAX);
81 	struct bt_mesh_comp_p0_elem elem;
82 	struct bt_mesh_comp_p0 comp;
83 	uint8_t page = 0x00;
84 	int err = 0;
85 
86 	if (argc > 1) {
87 		page = shell_strtoul(argv[1], 0, &err);
88 		if (err) {
89 			shell_warn(sh, "Unable to parse input string argument");
90 			return err;
91 		}
92 	}
93 
94 	err = bt_mesh_cfg_cli_comp_data_get(bt_mesh_shell_target_ctx.net_idx,
95 					bt_mesh_shell_target_ctx.dst, page, &page, &buf);
96 	if (err) {
97 		shell_error(sh, "Getting composition failed (err %d)", err);
98 		return 0;
99 	}
100 
101 	if (page != 0 && page != 128 &&
102 	    ((page != 1 && page != 129) || !IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1)) &&
103 	    ((page != 2 && page != 130) || !IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2))) {
104 		shell_print(sh, "Got page %d. No parser available.", page);
105 		return 0;
106 	}
107 
108 	if (page == 0 || page == 128) {
109 		err = bt_mesh_comp_p0_get(&comp, &buf);
110 
111 		if (err) {
112 			shell_error(sh, "Couldn't parse Composition data (err %d)",
113 				    err);
114 			return 0;
115 		}
116 
117 		shell_print(sh, "Got Composition Data for 0x%04x, page: %d:",
118 			    bt_mesh_shell_target_ctx.dst, page);
119 		shell_print(sh, "\tCID      0x%04x", comp.cid);
120 		shell_print(sh, "\tPID      0x%04x", comp.pid);
121 		shell_print(sh, "\tVID      0x%04x", comp.vid);
122 		shell_print(sh, "\tCRPL     0x%04x", comp.crpl);
123 		shell_print(sh, "\tFeatures 0x%04x", comp.feat);
124 
125 		while (bt_mesh_comp_p0_elem_pull(&comp, &elem)) {
126 			int i;
127 
128 			shell_print(sh, "\tElement @ 0x%04x:", elem.loc);
129 
130 			if (elem.nsig) {
131 				shell_print(sh, "\t\tSIG Models:");
132 			} else {
133 				shell_print(sh, "\t\tNo SIG Models");
134 			}
135 
136 			for (i = 0; i < elem.nsig; i++) {
137 				uint16_t mod_id = bt_mesh_comp_p0_elem_mod(&elem, i);
138 
139 				shell_print(sh, "\t\t\t0x%04x", mod_id);
140 			}
141 
142 			if (elem.nvnd) {
143 				shell_print(sh, "\t\tVendor Models:");
144 			} else {
145 				shell_print(sh, "\t\tNo Vendor Models");
146 			}
147 
148 			for (i = 0; i < elem.nvnd; i++) {
149 				struct bt_mesh_mod_id_vnd mod =
150 					bt_mesh_comp_p0_elem_mod_vnd(&elem, i);
151 
152 				shell_print(sh, "\t\t\tCompany 0x%04x: 0x%04x",
153 					    mod.company, mod.id);
154 			}
155 		}
156 	}
157 
158 	if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_1) && (page == 1 || page == 129)) {
159 		/* size of 32 is chosen arbitrary, as sufficient for testing purposes */
160 		NET_BUF_SIMPLE_DEFINE(p1_buf, 32);
161 		NET_BUF_SIMPLE_DEFINE(p1_item_buf, 32);
162 		struct bt_mesh_comp_p1_elem p1_elem = { ._buf = &p1_buf };
163 		struct bt_mesh_comp_p1_model_item mod_item = { ._buf = &p1_item_buf };
164 		struct bt_mesh_comp_p1_ext_item ext_item = { 0 };
165 		int mod_idx = 1;
166 
167 		if (!buf.len) {
168 			shell_error(sh, "Composition data empty");
169 			return 0;
170 		}
171 		shell_print(sh,
172 			    "Got Composition Data for 0x%04x, page: %d:",
173 			    bt_mesh_shell_target_ctx.dst, page);
174 
175 		while (bt_mesh_comp_p1_elem_pull(&buf, &p1_elem)) {
176 			int i, j;
177 
178 			shell_print(sh, "\tElement #%d description", mod_idx);
179 
180 			for (i = 0; i < p1_elem.nsig; i++) {
181 				if (bt_mesh_comp_p1_item_pull(&p1_elem, &mod_item)) {
182 					shell_print(sh, "\t\tSIG Model Item #%d:", i+1);
183 					if (mod_item.cor_present) {
184 						shell_print(sh,
185 							    "\t\t\tWith Corresponding ID %u",
186 							    mod_item.cor_id);
187 					} else {
188 						shell_print(sh,
189 							    "\t\t\tWithout Corresponding ID");
190 					}
191 					shell_print(sh,
192 						    "\t\t\tWith %u Extended Model Item(s)",
193 						    mod_item.ext_item_cnt);
194 				}
195 				for (j = 0; j < mod_item.ext_item_cnt; j++) {
196 					bt_mesh_comp_p1_pull_ext_item(&mod_item,
197 								      &ext_item);
198 					shell_print(sh,
199 						    "\t\t\t\tExtended Item #%d:", j+1);
200 					if (ext_item.type == SHORT) {
201 						shell_print(sh,
202 							    "\t\t\t\t\toffset: %u",
203 							    ext_item.short_item.elem_offset);
204 						shell_print(sh,
205 							    "\t\t\t\t\tindex: %u",
206 							    ext_item.short_item.mod_item_idx);
207 					} else {
208 						shell_print(sh,
209 							    "\t\t\t\t\toffset: %u",
210 							    ext_item.long_item.elem_offset);
211 						shell_print(sh,
212 							    "\t\t\t\t\tindex: %u",
213 							    ext_item.long_item.mod_item_idx);
214 					}
215 				}
216 			}
217 			for (i = 0; i < p1_elem.nvnd; i++) {
218 				if (bt_mesh_comp_p1_item_pull(&p1_elem, &mod_item)) {
219 					shell_print(sh, "\t\tVendor Model Item #%d:", i+1);
220 					if (mod_item.cor_present) {
221 						shell_print(sh,
222 							    "\t\t\tWith Corresponding ID %u",
223 							    mod_item.cor_id);
224 					} else {
225 						shell_print(sh,
226 							    "\t\t\tWithout Corresponding ID");
227 					}
228 					shell_print(sh,
229 						    "\t\t\tWith %u Extended Model Item(s)",
230 						    mod_item.ext_item_cnt);
231 				}
232 				for (j = 0; j < mod_item.ext_item_cnt; j++) {
233 					bt_mesh_comp_p1_pull_ext_item(&mod_item,
234 								      &ext_item);
235 					shell_print(sh,
236 						    "\t\t\t\tExtended Item #%d:", j+1);
237 					if (ext_item.type == SHORT) {
238 						shell_print(sh,
239 							    "\t\t\t\t\toffset: %u",
240 							    ext_item.short_item.elem_offset);
241 						shell_print(sh,
242 							    "\t\t\t\t\tindex: %u",
243 							    ext_item.short_item.mod_item_idx);
244 					} else {
245 						shell_print(sh,
246 							    "\t\t\t\t\toffset: %u",
247 							    ext_item.long_item.elem_offset);
248 						shell_print(sh,
249 							    "\t\t\t\t\tindex: %u",
250 							    ext_item.long_item.mod_item_idx);
251 					}
252 				}
253 			}
254 			mod_idx++;
255 		}
256 	}
257 
258 	if (IS_ENABLED(CONFIG_BT_MESH_COMP_PAGE_2) && (page == 2 || page == 130)) {
259 		/* size of 32 is chosen arbitrary, as sufficient for testing purposes */
260 		NET_BUF_SIMPLE_DEFINE(p2_elem_offset_buf, 32);
261 		NET_BUF_SIMPLE_DEFINE(p2_data_buf, 32);
262 		struct bt_mesh_comp_p2_record p2_elem = {
263 			.elem_buf = &p2_elem_offset_buf,
264 			.data_buf = &p2_data_buf
265 		};
266 
267 		if (!buf.len) {
268 			shell_error(sh, "Composition data empty");
269 			return 0;
270 		}
271 		shell_print(sh, "Got Composition Data for 0x%04x, page: %d:",
272 			    bt_mesh_shell_target_ctx.dst, page);
273 
274 		while (bt_mesh_comp_p2_record_pull(&buf, &p2_elem)) {
275 
276 			shell_print(sh, "\tMesh Profile id: %04x ", p2_elem.id);
277 			shell_print(sh, "\t\tVersion: %d.%d.%d ", p2_elem.version.x,
278 				    p2_elem.version.y, p2_elem.version.z);
279 			shell_print(sh, "\t\tElement offsets:");
280 
281 			while (p2_elem.elem_buf->len) {
282 				shell_print(sh, "\t\t\t%d ",
283 					    net_buf_simple_pull_u8(p2_elem.elem_buf));
284 			}
285 
286 			if (p2_elem.data_buf->len) {
287 				shell_print(sh, "\t\t%d bytes of additional data is available",
288 					    p2_elem.data_buf->len);
289 			}
290 		}
291 	}
292 
293 	if (buf.len) {
294 		shell_print(sh, "\t\t...truncated data!");
295 	}
296 
297 	return 0;
298 }
299 
cmd_beacon(const struct shell * sh,size_t argc,char * argv[])300 static int cmd_beacon(const struct shell *sh, size_t argc, char *argv[])
301 {
302 	uint8_t status;
303 	int err = 0;
304 
305 	if (argc < 2) {
306 		err = bt_mesh_cfg_cli_beacon_get(bt_mesh_shell_target_ctx.net_idx,
307 					     bt_mesh_shell_target_ctx.dst, &status);
308 	} else {
309 		uint8_t val = shell_strtobool(argv[1], 0, &err);
310 
311 		if (err) {
312 			shell_warn(sh, "Unable to parse input string argument");
313 			return err;
314 		}
315 
316 		err = bt_mesh_cfg_cli_beacon_set(bt_mesh_shell_target_ctx.net_idx,
317 					     bt_mesh_shell_target_ctx.dst, val, &status);
318 	}
319 
320 	if (err) {
321 		shell_error(sh, "Unable to send Beacon Get/Set message (err %d)", err);
322 		return 0;
323 	}
324 
325 	shell_print(sh, "Beacon state is 0x%02x", status);
326 
327 	return 0;
328 }
329 
cmd_ttl(const struct shell * sh,size_t argc,char * argv[])330 static int cmd_ttl(const struct shell *sh, size_t argc, char *argv[])
331 {
332 	uint8_t ttl;
333 	int err = 0;
334 
335 	if (argc < 2) {
336 		err = bt_mesh_cfg_cli_ttl_get(bt_mesh_shell_target_ctx.net_idx,
337 					  bt_mesh_shell_target_ctx.dst, &ttl);
338 	} else {
339 		uint8_t val = shell_strtoul(argv[1], 0, &err);
340 
341 		if (err) {
342 			shell_warn(sh, "Unable to parse input string argument");
343 			return err;
344 		}
345 
346 		err = bt_mesh_cfg_cli_ttl_set(bt_mesh_shell_target_ctx.net_idx,
347 					  bt_mesh_shell_target_ctx.dst, val, &ttl);
348 	}
349 
350 	if (err) {
351 		shell_error(sh, "Unable to send Default TTL Get/Set (err %d)", err);
352 		return 0;
353 	}
354 
355 	shell_print(sh, "Default TTL is 0x%02x", ttl);
356 
357 	return 0;
358 }
359 
cmd_friend(const struct shell * sh,size_t argc,char * argv[])360 static int cmd_friend(const struct shell *sh, size_t argc, char *argv[])
361 {
362 	uint8_t frnd;
363 	int err = 0;
364 
365 	if (argc < 2) {
366 		err = bt_mesh_cfg_cli_friend_get(bt_mesh_shell_target_ctx.net_idx,
367 					     bt_mesh_shell_target_ctx.dst, &frnd);
368 	} else {
369 		uint8_t val = shell_strtobool(argv[1], 0, &err);
370 
371 		if (err) {
372 			shell_warn(sh, "Unable to parse input string argument");
373 			return err;
374 		}
375 
376 		err = bt_mesh_cfg_cli_friend_set(bt_mesh_shell_target_ctx.net_idx,
377 					     bt_mesh_shell_target_ctx.dst, val, &frnd);
378 	}
379 
380 	if (err) {
381 		shell_error(sh, "Unable to send Friend Get/Set (err %d)", err);
382 		return 0;
383 	}
384 
385 	shell_print(sh, "Friend is set to 0x%02x", frnd);
386 
387 	return 0;
388 }
389 
cmd_gatt_proxy(const struct shell * sh,size_t argc,char * argv[])390 static int cmd_gatt_proxy(const struct shell *sh, size_t argc, char *argv[])
391 {
392 	uint8_t proxy;
393 	int err = 0;
394 
395 	if (argc < 2) {
396 		err = bt_mesh_cfg_cli_gatt_proxy_get(bt_mesh_shell_target_ctx.net_idx,
397 						 bt_mesh_shell_target_ctx.dst, &proxy);
398 	} else {
399 		uint8_t val = shell_strtobool(argv[1], 0, &err);
400 
401 		if (err) {
402 			shell_warn(sh, "Unable to parse input string argument");
403 			return err;
404 		}
405 
406 		err = bt_mesh_cfg_cli_gatt_proxy_set(bt_mesh_shell_target_ctx.net_idx,
407 						 bt_mesh_shell_target_ctx.dst, val, &proxy);
408 	}
409 
410 	if (err) {
411 		shell_print(sh, "Unable to send GATT Proxy Get/Set (err %d)", err);
412 		return 0;
413 	}
414 
415 	shell_print(sh, "GATT Proxy is set to 0x%02x", proxy);
416 
417 	return 0;
418 }
419 
cmd_polltimeout_get(const struct shell * sh,size_t argc,char * argv[])420 static int cmd_polltimeout_get(const struct shell *sh, size_t argc, char *argv[])
421 {
422 	uint16_t lpn_address;
423 	int32_t poll_timeout;
424 	int err = 0;
425 
426 	lpn_address = shell_strtoul(argv[1], 0, &err);
427 	if (err) {
428 		shell_warn(sh, "Unable to parse input string argument");
429 		return err;
430 	}
431 
432 	err = bt_mesh_cfg_cli_lpn_timeout_get(bt_mesh_shell_target_ctx.net_idx,
433 					  bt_mesh_shell_target_ctx.dst, lpn_address, &poll_timeout);
434 	if (err) {
435 		shell_error(sh, "Unable to send LPN PollTimeout Get (err %d)", err);
436 		return 0;
437 	}
438 
439 	shell_print(sh, "PollTimeout value %d", poll_timeout);
440 
441 	return 0;
442 }
443 
cmd_net_transmit(const struct shell * sh,size_t argc,char * argv[])444 static int cmd_net_transmit(const struct shell *sh, size_t argc, char *argv[])
445 {
446 	uint8_t transmit;
447 	int err = 0;
448 
449 	if (argc < 2) {
450 		err = bt_mesh_cfg_cli_net_transmit_get(bt_mesh_shell_target_ctx.net_idx,
451 						   bt_mesh_shell_target_ctx.dst, &transmit);
452 	} else {
453 		if (argc != 3) {
454 			shell_warn(sh, "Wrong number of input arguments"
455 					"(2 arguments are required)");
456 			return -EINVAL;
457 		}
458 
459 		uint8_t count, interval, new_transmit;
460 
461 		count = shell_strtoul(argv[1], 0, &err);
462 		interval = shell_strtoul(argv[2], 0, &err);
463 		if (err) {
464 			shell_warn(sh, "Unable to parse input string argument");
465 			return err;
466 		}
467 
468 		new_transmit = BT_MESH_TRANSMIT(count, interval);
469 
470 		err = bt_mesh_cfg_cli_net_transmit_set(bt_mesh_shell_target_ctx.net_idx,
471 						   bt_mesh_shell_target_ctx.dst, new_transmit,
472 						   &transmit);
473 	}
474 
475 	if (err) {
476 		shell_error(sh, "Unable to send network transmit Get/Set (err %d)", err);
477 		return 0;
478 	}
479 
480 	shell_print(sh, "Transmit 0x%02x (count %u interval %ums)", transmit,
481 		    BT_MESH_TRANSMIT_COUNT(transmit), BT_MESH_TRANSMIT_INT(transmit));
482 
483 	return 0;
484 }
485 
cmd_relay(const struct shell * sh,size_t argc,char * argv[])486 static int cmd_relay(const struct shell *sh, size_t argc, char *argv[])
487 {
488 	uint8_t relay, transmit;
489 	int err = 0;
490 
491 	if (argc < 2) {
492 		err = bt_mesh_cfg_cli_relay_get(bt_mesh_shell_target_ctx.net_idx,
493 					    bt_mesh_shell_target_ctx.dst, &relay, &transmit);
494 	} else {
495 		uint8_t count, interval, new_transmit;
496 		uint8_t val = shell_strtobool(argv[1], 0, &err);
497 
498 		if (val) {
499 			if (argc > 2) {
500 				count = shell_strtoul(argv[2], 0, &err);
501 			} else {
502 				count = 2U;
503 			}
504 
505 			if (argc > 3) {
506 				interval = shell_strtoul(argv[3], 0, &err);
507 			} else {
508 				interval = 20U;
509 			}
510 
511 			new_transmit = BT_MESH_TRANSMIT(count, interval);
512 		} else {
513 			new_transmit = 0U;
514 		}
515 
516 		if (err) {
517 			shell_warn(sh, "Unable to parse input string argument");
518 			return err;
519 		}
520 
521 		err = bt_mesh_cfg_cli_relay_set(bt_mesh_shell_target_ctx.net_idx,
522 					    bt_mesh_shell_target_ctx.dst, val, new_transmit, &relay,
523 					    &transmit);
524 	}
525 
526 	if (err) {
527 		shell_error(sh, "Unable to send Relay Get/Set (err %d)", err);
528 		return 0;
529 	}
530 
531 	shell_print(sh, "Relay is 0x%02x, Transmit 0x%02x (count %u interval %ums)", relay,
532 		    transmit, BT_MESH_TRANSMIT_COUNT(transmit), BT_MESH_TRANSMIT_INT(transmit));
533 
534 	return 0;
535 }
536 
cmd_net_key_add(const struct shell * sh,size_t argc,char * argv[])537 static int cmd_net_key_add(const struct shell *sh, size_t argc, char *argv[])
538 {
539 	bool has_key_val = (argc > 2);
540 	uint8_t key_val[16];
541 	uint16_t key_net_idx;
542 	uint8_t status;
543 	int err = 0;
544 
545 	key_net_idx = shell_strtoul(argv[1], 0, &err);
546 	if (err) {
547 		shell_warn(sh, "Unable to parse input string argument");
548 		return err;
549 	}
550 
551 	if (has_key_val) {
552 		size_t len;
553 
554 		len = hex2bin(argv[2], strlen(argv[2]), key_val, sizeof(key_val));
555 		(void)memset(key_val + len, 0, sizeof(key_val) - len);
556 	} else {
557 		memcpy(key_val, bt_mesh_shell_default_key, sizeof(key_val));
558 	}
559 
560 	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
561 		struct bt_mesh_cdb_subnet *subnet;
562 
563 		subnet = bt_mesh_cdb_subnet_get(key_net_idx);
564 		if (subnet) {
565 			if (has_key_val) {
566 				shell_error(sh, "Subnet 0x%03x already has a value", key_net_idx);
567 				return 0;
568 			}
569 
570 			if (bt_mesh_cdb_subnet_key_export(subnet, 0, key_val)) {
571 				shell_error(sh, "Unable to export subnet key from cdb 0x%03x",
572 					    key_net_idx);
573 				return 0;
574 			}
575 		} else {
576 			subnet = bt_mesh_cdb_subnet_alloc(key_net_idx);
577 			if (!subnet) {
578 				shell_error(sh, "No space for subnet in cdb");
579 				return 0;
580 			}
581 
582 			if (bt_mesh_cdb_subnet_key_import(subnet, 0, key_val)) {
583 				shell_error(sh, "Unable to import subnet key into cdb 0x%03x",
584 					    key_net_idx);
585 				return 0;
586 			}
587 			bt_mesh_cdb_subnet_store(subnet);
588 		}
589 	}
590 
591 	err = bt_mesh_cfg_cli_net_key_add(bt_mesh_shell_target_ctx.net_idx,
592 				      bt_mesh_shell_target_ctx.dst, key_net_idx, key_val, &status);
593 	if (err) {
594 		shell_print(sh, "Unable to send NetKey Add (err %d)", err);
595 		return 0;
596 	}
597 
598 	if (status) {
599 		shell_print(sh, "NetKeyAdd failed with status 0x%02x", status);
600 	} else {
601 		shell_print(sh, "NetKey added with NetKey Index 0x%03x", key_net_idx);
602 	}
603 
604 	return 0;
605 }
606 
cmd_net_key_update(const struct shell * sh,size_t argc,char * argv[])607 static int cmd_net_key_update(const struct shell *sh, size_t argc, char *argv[])
608 {
609 	bool has_key_val = (argc > 2);
610 	uint8_t key_val[16];
611 	uint16_t key_net_idx;
612 	uint8_t status;
613 	int err = 0;
614 
615 	key_net_idx = shell_strtoul(argv[1], 0, &err);
616 	if (err) {
617 		shell_warn(sh, "Unable to parse input string argument");
618 		return err;
619 	}
620 
621 	if (has_key_val) {
622 		size_t len;
623 
624 		len = hex2bin(argv[2], strlen(argv[2]), key_val, sizeof(key_val));
625 		(void)memset(key_val + len, 0, sizeof(key_val) - len);
626 	} else {
627 		memcpy(key_val, bt_mesh_shell_default_key, sizeof(key_val));
628 	}
629 
630 	err = bt_mesh_cfg_cli_net_key_update(bt_mesh_shell_target_ctx.net_idx,
631 					 bt_mesh_shell_target_ctx.dst, key_net_idx, key_val,
632 					 &status);
633 	if (err) {
634 		shell_print(sh, "Unable to send NetKey Update (err %d)", err);
635 		return 0;
636 	}
637 
638 	if (status) {
639 		shell_print(sh, "NetKeyUpdate failed with status 0x%02x", status);
640 	} else {
641 		shell_print(sh, "NetKey updated with NetKey Index 0x%03x", key_net_idx);
642 	}
643 
644 	return 0;
645 }
646 
cmd_net_key_get(const struct shell * sh,size_t argc,char * argv[])647 static int cmd_net_key_get(const struct shell *sh, size_t argc, char *argv[])
648 {
649 	uint16_t keys[16];
650 	size_t cnt;
651 	int err, i;
652 
653 	cnt = ARRAY_SIZE(keys);
654 
655 	err = bt_mesh_cfg_cli_net_key_get(bt_mesh_shell_target_ctx.net_idx,
656 				      bt_mesh_shell_target_ctx.dst, keys, &cnt);
657 	if (err) {
658 		shell_print(sh, "Unable to send NetKeyGet (err %d)", err);
659 		return 0;
660 	}
661 
662 	shell_print(sh, "NetKeys known by 0x%04x:", bt_mesh_shell_target_ctx.dst);
663 	for (i = 0; i < cnt; i++) {
664 		shell_print(sh, "\t0x%03x", keys[i]);
665 	}
666 
667 	return 0;
668 }
669 
cmd_net_key_del(const struct shell * sh,size_t argc,char * argv[])670 static int cmd_net_key_del(const struct shell *sh, size_t argc, char *argv[])
671 {
672 	uint16_t key_net_idx;
673 	uint8_t status;
674 	int err = 0;
675 
676 	key_net_idx = shell_strtoul(argv[1], 0, &err);
677 	if (err) {
678 		shell_warn(sh, "Unable to parse input string argument");
679 		return err;
680 	}
681 
682 	err = bt_mesh_cfg_cli_net_key_del(bt_mesh_shell_target_ctx.net_idx,
683 				      bt_mesh_shell_target_ctx.dst, key_net_idx, &status);
684 	if (err) {
685 		shell_print(sh, "Unable to send NetKeyDel (err %d)", err);
686 		return 0;
687 	}
688 
689 	if (status) {
690 		shell_print(sh, "NetKeyDel failed with status 0x%02x", status);
691 	} else {
692 		shell_print(sh, "NetKey 0x%03x deleted", key_net_idx);
693 	}
694 
695 	return 0;
696 }
697 
cmd_app_key_add(const struct shell * sh,size_t argc,char * argv[])698 static int cmd_app_key_add(const struct shell *sh, size_t argc, char *argv[])
699 {
700 	uint8_t key_val[16];
701 	uint16_t key_net_idx, key_app_idx;
702 	bool has_key_val = (argc > 3);
703 	uint8_t status;
704 	int err = 0;
705 
706 	key_net_idx = shell_strtoul(argv[1], 0, &err);
707 	key_app_idx = shell_strtoul(argv[2], 0, &err);
708 	if (err) {
709 		shell_warn(sh, "Unable to parse input string argument");
710 		return err;
711 	}
712 
713 	if (has_key_val) {
714 		size_t len;
715 
716 		len = hex2bin(argv[3], strlen(argv[3]), key_val, sizeof(key_val));
717 		(void)memset(key_val + len, 0, sizeof(key_val) - len);
718 	} else {
719 		memcpy(key_val, bt_mesh_shell_default_key, sizeof(key_val));
720 	}
721 
722 	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
723 		struct bt_mesh_cdb_app_key *app_key;
724 
725 		app_key = bt_mesh_cdb_app_key_get(key_app_idx);
726 		if (app_key) {
727 			if (has_key_val) {
728 				shell_error(sh, "App key 0x%03x already has a value", key_app_idx);
729 				return 0;
730 			}
731 
732 			if (bt_mesh_cdb_app_key_export(app_key, 0, key_val)) {
733 				shell_error(sh, "Unable to export app key 0x%03x from cdb",
734 					    key_app_idx);
735 				return 0;
736 			}
737 		} else {
738 			app_key = bt_mesh_cdb_app_key_alloc(key_net_idx, key_app_idx);
739 			if (!app_key) {
740 				shell_error(sh, "No space for app key in cdb");
741 				return 0;
742 			}
743 
744 			if (bt_mesh_cdb_app_key_import(app_key, 0, key_val)) {
745 				shell_error(sh, "Unable to import app key 0x%03x into cdb",
746 					    key_app_idx);
747 				return 0;
748 			}
749 			bt_mesh_cdb_app_key_store(app_key);
750 		}
751 	}
752 
753 	err = bt_mesh_cfg_cli_app_key_add(bt_mesh_shell_target_ctx.net_idx,
754 				      bt_mesh_shell_target_ctx.dst, key_net_idx, key_app_idx,
755 				      key_val, &status);
756 	if (err) {
757 		shell_error(sh, "Unable to send App Key Add (err %d)", err);
758 		return 0;
759 	}
760 
761 	if (status) {
762 		shell_print(sh, "AppKeyAdd failed with status 0x%02x", status);
763 	} else {
764 		shell_print(sh, "AppKey added, NetKeyIndex 0x%04x AppKeyIndex 0x%04x", key_net_idx,
765 			    key_app_idx);
766 	}
767 
768 	return 0;
769 }
770 
cmd_app_key_upd(const struct shell * sh,size_t argc,char * argv[])771 static int cmd_app_key_upd(const struct shell *sh, size_t argc, char *argv[])
772 {
773 	uint8_t key_val[16];
774 	uint16_t key_net_idx, key_app_idx;
775 	bool has_key_val = (argc > 3);
776 	uint8_t status;
777 	int err = 0;
778 
779 	key_net_idx = shell_strtoul(argv[1], 0, &err);
780 	key_app_idx = shell_strtoul(argv[2], 0, &err);
781 	if (err) {
782 		shell_warn(sh, "Unable to parse input string argument");
783 		return err;
784 	}
785 
786 	if (has_key_val) {
787 		size_t len;
788 
789 		len = hex2bin(argv[3], strlen(argv[3]), key_val, sizeof(key_val));
790 		(void)memset(key_val + len, 0, sizeof(key_val) - len);
791 	} else {
792 		memcpy(key_val, bt_mesh_shell_default_key, sizeof(key_val));
793 	}
794 
795 	err = bt_mesh_cfg_cli_app_key_update(bt_mesh_shell_target_ctx.net_idx,
796 					 bt_mesh_shell_target_ctx.dst, key_net_idx, key_app_idx,
797 					 key_val, &status);
798 	if (err) {
799 		shell_error(sh, "Unable to send App Key Update (err %d)", err);
800 		return 0;
801 	}
802 
803 	if (status) {
804 		shell_print(sh, "AppKey update failed with status 0x%02x", status);
805 	} else {
806 		shell_print(sh, "AppKey updated, NetKeyIndex 0x%04x AppKeyIndex 0x%04x",
807 			    key_net_idx, key_app_idx);
808 	}
809 
810 	return 0;
811 }
812 
cmd_app_key_get(const struct shell * sh,size_t argc,char * argv[])813 static int cmd_app_key_get(const struct shell *sh, size_t argc, char *argv[])
814 {
815 	uint16_t net_idx;
816 	uint16_t keys[16];
817 	size_t cnt;
818 	uint8_t status;
819 	int err = 0;
820 	int i;
821 
822 	cnt = ARRAY_SIZE(keys);
823 	net_idx = shell_strtoul(argv[1], 0, &err);
824 	if (err) {
825 		shell_warn(sh, "Unable to parse input string argument");
826 		return err;
827 	}
828 
829 	err = bt_mesh_cfg_cli_app_key_get(bt_mesh_shell_target_ctx.net_idx,
830 				      bt_mesh_shell_target_ctx.dst, net_idx, &status, keys, &cnt);
831 	if (err) {
832 		shell_print(sh, "Unable to send AppKeyGet (err %d)", err);
833 		return 0;
834 	}
835 
836 	if (status) {
837 		shell_print(sh, "AppKeyGet failed with status 0x%02x", status);
838 		return 0;
839 	}
840 
841 	shell_print(sh, "AppKeys for NetKey 0x%03x known by 0x%04x:", net_idx,
842 		    bt_mesh_shell_target_ctx.dst);
843 	for (i = 0; i < cnt; i++) {
844 		shell_print(sh, "\t0x%03x", keys[i]);
845 	}
846 
847 	return 0;
848 }
849 
cmd_node_id(const struct shell * sh,size_t argc,char * argv[])850 static int cmd_node_id(const struct shell *sh, size_t argc, char *argv[])
851 {
852 	uint16_t net_idx;
853 	uint8_t status, identify;
854 	int err = 0;
855 
856 	net_idx = shell_strtoul(argv[1], 0, &err);
857 	if (err) {
858 		shell_warn(sh, "Unable to parse input string argument");
859 		return err;
860 	}
861 
862 	if (argc <= 2) {
863 		err = bt_mesh_cfg_cli_node_identity_get(bt_mesh_shell_target_ctx.net_idx,
864 						    bt_mesh_shell_target_ctx.dst, net_idx, &status,
865 						    &identify);
866 		if (err) {
867 			shell_print(sh, "Unable to send Node Identify Get (err %d)", err);
868 			return 0;
869 		}
870 	} else {
871 		uint8_t new_identify = shell_strtoul(argv[2], 0, &err);
872 
873 		if (err) {
874 			shell_warn(sh, "Unable to parse input string argument");
875 			return err;
876 		}
877 
878 		err = bt_mesh_cfg_cli_node_identity_set(bt_mesh_shell_target_ctx.net_idx,
879 						    bt_mesh_shell_target_ctx.dst, net_idx,
880 						    new_identify, &status, &identify);
881 		if (err) {
882 			shell_print(sh, "Unable to send Node Identify Set (err %d)", err);
883 			return 0;
884 		}
885 	}
886 
887 	if (status) {
888 		shell_print(sh, "Node Identify Get/Set failed with status 0x%02x", status);
889 	} else {
890 		shell_print(sh, "Node Identify Get/Set successful with identify 0x%02x", identify);
891 	}
892 
893 	return 0;
894 }
895 
cmd_app_key_del(const struct shell * sh,size_t argc,char * argv[])896 static int cmd_app_key_del(const struct shell *sh, size_t argc, char *argv[])
897 {
898 	uint16_t key_net_idx, key_app_idx;
899 	uint8_t status;
900 	int err = 0;
901 
902 	key_net_idx = shell_strtoul(argv[1], 0, &err);
903 	key_app_idx = shell_strtoul(argv[2], 0, &err);
904 	if (err) {
905 		shell_warn(sh, "Unable to parse input string argument");
906 		return err;
907 	}
908 
909 	err = bt_mesh_cfg_cli_app_key_del(bt_mesh_shell_target_ctx.net_idx,
910 				      bt_mesh_shell_target_ctx.dst, key_net_idx, key_app_idx,
911 				      &status);
912 	if (err) {
913 		shell_error(sh, "Unable to send App Key del(err %d)", err);
914 		return 0;
915 	}
916 
917 	if (status) {
918 		shell_print(sh, "AppKeyDel failed with status 0x%02x", status);
919 	} else {
920 		shell_print(sh, "AppKey deleted, NetKeyIndex 0x%04x AppKeyIndex 0x%04x",
921 			    key_net_idx, key_app_idx);
922 	}
923 
924 	return 0;
925 }
926 
cmd_mod_app_bind(const struct shell * sh,size_t argc,char * argv[])927 static int cmd_mod_app_bind(const struct shell *sh, size_t argc, char *argv[])
928 {
929 	uint16_t elem_addr, mod_app_idx, mod_id, cid;
930 	uint8_t status;
931 	int err = 0;
932 
933 	elem_addr = shell_strtoul(argv[1], 0, &err);
934 	mod_app_idx = shell_strtoul(argv[2], 0, &err);
935 	mod_id = shell_strtoul(argv[3], 0, &err);
936 	if (err) {
937 		shell_warn(sh, "Unable to parse input string argument");
938 		return err;
939 	}
940 
941 	if (argc > 4) {
942 		cid = shell_strtoul(argv[4], 0, &err);
943 		if (err) {
944 			shell_warn(sh, "Unable to parse input string argument");
945 			return err;
946 		}
947 
948 		err = bt_mesh_cfg_cli_mod_app_bind_vnd(bt_mesh_shell_target_ctx.net_idx,
949 						   bt_mesh_shell_target_ctx.dst, elem_addr,
950 						   mod_app_idx, mod_id, cid, &status);
951 	} else {
952 		err = bt_mesh_cfg_cli_mod_app_bind(bt_mesh_shell_target_ctx.net_idx,
953 					       bt_mesh_shell_target_ctx.dst, elem_addr, mod_app_idx,
954 					       mod_id, &status);
955 	}
956 
957 	if (err) {
958 		shell_error(sh, "Unable to send Model App Bind (err %d)", err);
959 		return 0;
960 	}
961 
962 	if (status) {
963 		shell_print(sh, "Model App Bind failed with status 0x%02x", status);
964 	} else {
965 		shell_print(sh, "AppKey successfully bound");
966 	}
967 
968 	return 0;
969 }
970 
cmd_mod_app_unbind(const struct shell * sh,size_t argc,char * argv[])971 static int cmd_mod_app_unbind(const struct shell *sh, size_t argc, char *argv[])
972 {
973 	uint16_t elem_addr, mod_app_idx, mod_id, cid;
974 	uint8_t status;
975 	int err = 0;
976 
977 	elem_addr = shell_strtoul(argv[1], 0, &err);
978 	mod_app_idx = shell_strtoul(argv[2], 0, &err);
979 	mod_id = shell_strtoul(argv[3], 0, &err);
980 	if (err) {
981 		shell_warn(sh, "Unable to parse input string argument");
982 		return err;
983 	}
984 
985 	if (argc > 4) {
986 		cid = shell_strtoul(argv[4], 0, &err);
987 		if (err) {
988 			shell_warn(sh, "Unable to parse input string argument");
989 			return err;
990 		}
991 
992 		err = bt_mesh_cfg_cli_mod_app_unbind_vnd(bt_mesh_shell_target_ctx.net_idx,
993 						     bt_mesh_shell_target_ctx.dst, elem_addr,
994 						     mod_app_idx, mod_id, cid, &status);
995 	} else {
996 		err = bt_mesh_cfg_cli_mod_app_unbind(bt_mesh_shell_target_ctx.net_idx,
997 						 bt_mesh_shell_target_ctx.dst, elem_addr,
998 						 mod_app_idx, mod_id, &status);
999 	}
1000 
1001 	if (err) {
1002 		shell_error(sh, "Unable to send Model App Unbind (err %d)", err);
1003 		return 0;
1004 	}
1005 
1006 	if (status) {
1007 		shell_print(sh, "Model App Unbind failed with status 0x%02x", status);
1008 	} else {
1009 		shell_print(sh, "AppKey successfully unbound");
1010 	}
1011 
1012 	return 0;
1013 }
1014 
cmd_mod_app_get(const struct shell * sh,size_t argc,char * argv[])1015 static int cmd_mod_app_get(const struct shell *sh, size_t argc, char *argv[])
1016 {
1017 	uint16_t elem_addr, mod_id, cid;
1018 	uint16_t apps[16];
1019 	uint8_t status;
1020 	size_t cnt;
1021 	int err = 0;
1022 	int i;
1023 
1024 	cnt = ARRAY_SIZE(apps);
1025 	elem_addr = shell_strtoul(argv[1], 0, &err);
1026 	mod_id = shell_strtoul(argv[2], 0, &err);
1027 	if (err) {
1028 		shell_warn(sh, "Unable to parse input string argument");
1029 		return err;
1030 	}
1031 
1032 	if (argc > 3) {
1033 		cid = shell_strtoul(argv[3], 0, &err);
1034 		if (err) {
1035 			shell_warn(sh, "Unable to parse input string argument");
1036 			return err;
1037 		}
1038 
1039 		err = bt_mesh_cfg_cli_mod_app_get_vnd(bt_mesh_shell_target_ctx.net_idx,
1040 						  bt_mesh_shell_target_ctx.dst, elem_addr, mod_id,
1041 						  cid, &status, apps, &cnt);
1042 	} else {
1043 		err = bt_mesh_cfg_cli_mod_app_get(bt_mesh_shell_target_ctx.net_idx,
1044 					      bt_mesh_shell_target_ctx.dst, elem_addr, mod_id,
1045 					      &status, apps, &cnt);
1046 	}
1047 
1048 	if (err) {
1049 		shell_error(sh, "Unable to send Model App Get (err %d)", err);
1050 		return 0;
1051 	}
1052 
1053 	if (status) {
1054 		shell_print(sh, "Model App Get failed with status 0x%02x", status);
1055 	} else {
1056 		shell_print(sh, "Apps bound to Element 0x%04x, Model 0x%04x %s:", elem_addr, mod_id,
1057 			    argc > 3 ? argv[3] : "(SIG)");
1058 
1059 		if (!cnt) {
1060 			shell_print(sh, "\tNone.");
1061 		}
1062 
1063 		for (i = 0; i < cnt; i++) {
1064 			shell_print(sh, "\t0x%04x", apps[i]);
1065 		}
1066 	}
1067 
1068 	return 0;
1069 }
1070 
cmd_mod_sub_add(const struct shell * sh,size_t argc,char * argv[])1071 static int cmd_mod_sub_add(const struct shell *sh, size_t argc, char *argv[])
1072 {
1073 	uint16_t elem_addr, sub_addr, mod_id, cid;
1074 	uint8_t status;
1075 	int err = 0;
1076 
1077 	elem_addr = shell_strtoul(argv[1], 0, &err);
1078 	sub_addr = shell_strtoul(argv[2], 0, &err);
1079 	mod_id = shell_strtoul(argv[3], 0, &err);
1080 	if (err) {
1081 		shell_warn(sh, "Unable to parse input string argument");
1082 		return err;
1083 	}
1084 
1085 	if (argc > 4) {
1086 		cid = shell_strtoul(argv[4], 0, &err);
1087 		if (err) {
1088 			shell_warn(sh, "Unable to parse input string argument");
1089 			return err;
1090 		}
1091 
1092 		err = bt_mesh_cfg_cli_mod_sub_add_vnd(bt_mesh_shell_target_ctx.net_idx,
1093 						  bt_mesh_shell_target_ctx.dst, elem_addr, sub_addr,
1094 						  mod_id, cid, &status);
1095 	} else {
1096 		err = bt_mesh_cfg_cli_mod_sub_add(bt_mesh_shell_target_ctx.net_idx,
1097 					      bt_mesh_shell_target_ctx.dst, elem_addr, sub_addr,
1098 					      mod_id, &status);
1099 	}
1100 
1101 	if (err) {
1102 		shell_error(sh, "Unable to send Model Subscription Add (err %d)", err);
1103 		return 0;
1104 	}
1105 
1106 	if (status) {
1107 		shell_print(sh, "Model Subscription Add failed with status 0x%02x", status);
1108 	} else {
1109 		shell_print(sh, "Model subscription was successful");
1110 	}
1111 
1112 	return 0;
1113 }
1114 
cmd_mod_sub_del(const struct shell * sh,size_t argc,char * argv[])1115 static int cmd_mod_sub_del(const struct shell *sh, size_t argc, char *argv[])
1116 {
1117 	uint16_t elem_addr, sub_addr, mod_id, cid;
1118 	uint8_t status;
1119 	int err = 0;
1120 
1121 	elem_addr = shell_strtoul(argv[1], 0, &err);
1122 	sub_addr = shell_strtoul(argv[2], 0, &err);
1123 	mod_id = shell_strtoul(argv[3], 0, &err);
1124 	if (err) {
1125 		shell_warn(sh, "Unable to parse input string argument");
1126 		return err;
1127 	}
1128 
1129 	if (argc > 4) {
1130 		cid = shell_strtoul(argv[4], 0, &err);
1131 		if (err) {
1132 			shell_warn(sh, "Unable to parse input string argument");
1133 			return err;
1134 		}
1135 
1136 		err = bt_mesh_cfg_cli_mod_sub_del_vnd(bt_mesh_shell_target_ctx.net_idx,
1137 						  bt_mesh_shell_target_ctx.dst, elem_addr, sub_addr,
1138 						  mod_id, cid, &status);
1139 	} else {
1140 		err = bt_mesh_cfg_cli_mod_sub_del(bt_mesh_shell_target_ctx.net_idx,
1141 					      bt_mesh_shell_target_ctx.dst, elem_addr, sub_addr,
1142 					      mod_id, &status);
1143 	}
1144 
1145 	if (err) {
1146 		shell_error(sh, "Unable to send Model Subscription Delete (err %d)", err);
1147 		return 0;
1148 	}
1149 
1150 	if (status) {
1151 		shell_print(sh, "Model Subscription Delete failed with status 0x%02x", status);
1152 	} else {
1153 		shell_print(sh, "Model subscription deletion was successful");
1154 	}
1155 
1156 	return 0;
1157 }
1158 
cmd_mod_sub_add_va(const struct shell * sh,size_t argc,char * argv[])1159 static int cmd_mod_sub_add_va(const struct shell *sh, size_t argc, char *argv[])
1160 {
1161 	uint16_t elem_addr, sub_addr, mod_id, cid;
1162 	uint8_t label[16];
1163 	uint8_t status;
1164 	size_t len;
1165 	int err = 0;
1166 
1167 	elem_addr = shell_strtoul(argv[1], 0, &err);
1168 
1169 	len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
1170 	(void)memset(label + len, 0, sizeof(label) - len);
1171 
1172 	mod_id = shell_strtoul(argv[3], 0, &err);
1173 	if (err) {
1174 		shell_warn(sh, "Unable to parse input string argument");
1175 		return err;
1176 	}
1177 
1178 	if (argc > 4) {
1179 		cid = shell_strtoul(argv[4], 0, &err);
1180 		if (err) {
1181 			shell_warn(sh, "Unable to parse input string argument");
1182 			return err;
1183 		}
1184 
1185 		err = bt_mesh_cfg_cli_mod_sub_va_add_vnd(bt_mesh_shell_target_ctx.net_idx,
1186 						     bt_mesh_shell_target_ctx.dst, elem_addr, label,
1187 						     mod_id, cid, &sub_addr, &status);
1188 	} else {
1189 		err = bt_mesh_cfg_cli_mod_sub_va_add(bt_mesh_shell_target_ctx.net_idx,
1190 						 bt_mesh_shell_target_ctx.dst, elem_addr, label,
1191 						 mod_id, &sub_addr, &status);
1192 	}
1193 
1194 	if (err) {
1195 		shell_error(sh, "Unable to send Mod Sub VA Add (err %d)", err);
1196 		return 0;
1197 	}
1198 
1199 	if (status) {
1200 		shell_print(sh, "Mod Sub VA Add failed with status 0x%02x", status);
1201 	} else {
1202 		shell_print(sh, "0x%04x subscribed to Label UUID %s (va 0x%04x)", elem_addr,
1203 			    argv[2], sub_addr);
1204 	}
1205 
1206 	return 0;
1207 }
1208 
cmd_mod_sub_del_va(const struct shell * sh,size_t argc,char * argv[])1209 static int cmd_mod_sub_del_va(const struct shell *sh, size_t argc, char *argv[])
1210 {
1211 	uint16_t elem_addr, sub_addr, mod_id, cid;
1212 	uint8_t label[16];
1213 	uint8_t status;
1214 	size_t len;
1215 	int err = 0;
1216 
1217 	elem_addr = shell_strtoul(argv[1], 0, &err);
1218 
1219 	len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
1220 	(void)memset(label + len, 0, sizeof(label) - len);
1221 
1222 	mod_id = shell_strtoul(argv[3], 0, &err);
1223 	if (err) {
1224 		shell_warn(sh, "Unable to parse input string argument");
1225 		return err;
1226 	}
1227 
1228 	if (argc > 4) {
1229 		cid = shell_strtoul(argv[4], 0, &err);
1230 		if (err) {
1231 			shell_warn(sh, "Unable to parse input string argument");
1232 			return err;
1233 		}
1234 
1235 		err = bt_mesh_cfg_cli_mod_sub_va_del_vnd(bt_mesh_shell_target_ctx.net_idx,
1236 						     bt_mesh_shell_target_ctx.dst, elem_addr, label,
1237 						     mod_id, cid, &sub_addr, &status);
1238 	} else {
1239 		err = bt_mesh_cfg_cli_mod_sub_va_del(bt_mesh_shell_target_ctx.net_idx,
1240 						 bt_mesh_shell_target_ctx.dst, elem_addr, label,
1241 						 mod_id, &sub_addr, &status);
1242 	}
1243 
1244 	if (err) {
1245 		shell_error(sh, "Unable to send Model Subscription Delete (err %d)", err);
1246 		return 0;
1247 	}
1248 
1249 	if (status) {
1250 		shell_print(sh, "Model Subscription Delete failed with status 0x%02x", status);
1251 	} else {
1252 		shell_print(sh, "0x%04x unsubscribed from Label UUID %s (va 0x%04x)", elem_addr,
1253 			    argv[2], sub_addr);
1254 	}
1255 
1256 	return 0;
1257 }
1258 
cmd_mod_sub_ow(const struct shell * sh,size_t argc,char * argv[])1259 static int cmd_mod_sub_ow(const struct shell *sh, size_t argc, char *argv[])
1260 {
1261 	uint16_t elem_addr, sub_addr, mod_id, cid;
1262 	uint8_t status;
1263 	int err = 0;
1264 
1265 	elem_addr = shell_strtoul(argv[1], 0, &err);
1266 	sub_addr = shell_strtoul(argv[2], 0, &err);
1267 	mod_id = shell_strtoul(argv[3], 0, &err);
1268 	if (err) {
1269 		shell_warn(sh, "Unable to parse input string argument");
1270 		return err;
1271 	}
1272 
1273 	if (argc > 4) {
1274 		cid = shell_strtoul(argv[4], 0, &err);
1275 		if (err) {
1276 			shell_warn(sh, "Unable to parse input string argument");
1277 			return err;
1278 		}
1279 
1280 		err = bt_mesh_cfg_cli_mod_sub_overwrite_vnd(bt_mesh_shell_target_ctx.net_idx,
1281 							bt_mesh_shell_target_ctx.dst, elem_addr,
1282 							sub_addr, mod_id, cid, &status);
1283 	} else {
1284 		err = bt_mesh_cfg_cli_mod_sub_overwrite(bt_mesh_shell_target_ctx.net_idx,
1285 						    bt_mesh_shell_target_ctx.dst, elem_addr,
1286 						    sub_addr, mod_id, &status);
1287 	}
1288 
1289 	if (err) {
1290 		shell_error(sh, "Unable to send Model Subscription Overwrite (err %d)", err);
1291 		return 0;
1292 	}
1293 
1294 	if (status) {
1295 		shell_print(sh, "Model Subscription Overwrite failed with status 0x%02x", status);
1296 	} else {
1297 		shell_print(sh, "Model subscription overwrite was successful");
1298 	}
1299 
1300 	return 0;
1301 }
1302 
cmd_mod_sub_ow_va(const struct shell * sh,size_t argc,char * argv[])1303 static int cmd_mod_sub_ow_va(const struct shell *sh, size_t argc, char *argv[])
1304 {
1305 	uint16_t elem_addr, sub_addr, mod_id, cid;
1306 	uint8_t label[16];
1307 	uint8_t status;
1308 	size_t len;
1309 	int err = 0;
1310 
1311 	elem_addr = shell_strtoul(argv[1], 0, &err);
1312 
1313 	len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
1314 	(void)memset(label + len, 0, sizeof(label) - len);
1315 
1316 	mod_id = shell_strtoul(argv[3], 0, &err);
1317 	if (err) {
1318 		shell_warn(sh, "Unable to parse input string argument");
1319 		return err;
1320 	}
1321 
1322 	if (argc > 4) {
1323 		cid = shell_strtoul(argv[4], 0, &err);
1324 		if (err) {
1325 			shell_warn(sh, "Unable to parse input string argument");
1326 			return err;
1327 		}
1328 
1329 		err = bt_mesh_cfg_cli_mod_sub_va_overwrite_vnd(bt_mesh_shell_target_ctx.net_idx,
1330 							   bt_mesh_shell_target_ctx.dst, elem_addr,
1331 							   label, mod_id, cid, &sub_addr, &status);
1332 	} else {
1333 		err = bt_mesh_cfg_cli_mod_sub_va_overwrite(bt_mesh_shell_target_ctx.net_idx,
1334 						       bt_mesh_shell_target_ctx.dst, elem_addr,
1335 						       label, mod_id, &sub_addr, &status);
1336 	}
1337 
1338 	if (err) {
1339 		shell_error(sh, "Unable to send Mod Sub VA Overwrite (err %d)", err);
1340 		return 0;
1341 	}
1342 
1343 	if (status) {
1344 		shell_print(sh, "Mod Sub VA Overwrite failed with status 0x%02x", status);
1345 	} else {
1346 		shell_print(sh, "0x%04x overwrite to Label UUID %s (va 0x%04x)", elem_addr, argv[2],
1347 			    sub_addr);
1348 	}
1349 
1350 	return 0;
1351 }
1352 
cmd_mod_sub_del_all(const struct shell * sh,size_t argc,char * argv[])1353 static int cmd_mod_sub_del_all(const struct shell *sh, size_t argc, char *argv[])
1354 {
1355 	uint16_t elem_addr, mod_id, cid;
1356 	uint8_t status;
1357 	int err = 0;
1358 
1359 	elem_addr = shell_strtoul(argv[1], 0, &err);
1360 	mod_id = shell_strtoul(argv[2], 0, &err);
1361 	if (err) {
1362 		shell_warn(sh, "Unable to parse input string argument");
1363 		return err;
1364 	}
1365 
1366 	if (argc > 3) {
1367 		cid = shell_strtoul(argv[3], 0, &err);
1368 		if (err) {
1369 			shell_warn(sh, "Unable to parse input string argument");
1370 			return err;
1371 		}
1372 
1373 		err = bt_mesh_cfg_cli_mod_sub_del_all_vnd(bt_mesh_shell_target_ctx.net_idx,
1374 						      bt_mesh_shell_target_ctx.dst, elem_addr,
1375 						      mod_id, cid, &status);
1376 	} else {
1377 		err = bt_mesh_cfg_cli_mod_sub_del_all(bt_mesh_shell_target_ctx.net_idx,
1378 						  bt_mesh_shell_target_ctx.dst, elem_addr, mod_id,
1379 						  &status);
1380 	}
1381 
1382 	if (err) {
1383 		shell_error(sh, "Unable to send Model Subscription Delete All (err %d)", err);
1384 		return 0;
1385 	}
1386 
1387 	if (status) {
1388 		shell_print(sh, "Model Subscription Delete All failed with status 0x%02x", status);
1389 	} else {
1390 		shell_print(sh, "Model subscription deletion all was successful");
1391 	}
1392 
1393 	return 0;
1394 }
1395 
cmd_mod_sub_get(const struct shell * sh,size_t argc,char * argv[])1396 static int cmd_mod_sub_get(const struct shell *sh, size_t argc, char *argv[])
1397 {
1398 	uint16_t elem_addr, mod_id, cid;
1399 	uint16_t subs[16];
1400 	uint8_t status;
1401 	size_t cnt;
1402 	int err = 0;
1403 	int i;
1404 
1405 	cnt = ARRAY_SIZE(subs);
1406 	elem_addr = shell_strtoul(argv[1], 0, &err);
1407 	mod_id = shell_strtoul(argv[2], 0, &err);
1408 	if (err) {
1409 		shell_warn(sh, "Unable to parse input string argument");
1410 		return err;
1411 	}
1412 
1413 	if (argc > 3) {
1414 		cid = shell_strtoul(argv[3], 0, &err);
1415 		if (err) {
1416 			shell_warn(sh, "Unable to parse input string argument");
1417 			return err;
1418 		}
1419 
1420 		err = bt_mesh_cfg_cli_mod_sub_get_vnd(bt_mesh_shell_target_ctx.net_idx,
1421 						  bt_mesh_shell_target_ctx.dst, elem_addr, mod_id,
1422 						  cid, &status, subs, &cnt);
1423 	} else {
1424 		err = bt_mesh_cfg_cli_mod_sub_get(bt_mesh_shell_target_ctx.net_idx,
1425 					      bt_mesh_shell_target_ctx.dst, elem_addr, mod_id,
1426 					      &status, subs, &cnt);
1427 	}
1428 
1429 	if (err) {
1430 		shell_error(sh, "Unable to send Model Subscription Get (err %d)", err);
1431 		return 0;
1432 	}
1433 
1434 	if (status) {
1435 		shell_print(sh, "Model Subscription Get failed with status 0x%02x", status);
1436 	} else {
1437 		shell_print(sh,
1438 			    "Model Subscriptions for Element 0x%04x, Model 0x%04x %s:", elem_addr,
1439 			    mod_id, argc > 3 ? argv[3] : "(SIG)");
1440 
1441 		if (!cnt) {
1442 			shell_print(sh, "\tNone.");
1443 		}
1444 
1445 		for (i = 0; i < cnt; i++) {
1446 			shell_print(sh, "\t0x%04x", subs[i]);
1447 		}
1448 	}
1449 
1450 	return 0;
1451 }
1452 
cmd_krp(const struct shell * sh,size_t argc,char * argv[])1453 static int cmd_krp(const struct shell *sh, size_t argc, char *argv[])
1454 {
1455 	uint8_t status, phase;
1456 	uint16_t key_net_idx;
1457 	int err = 0;
1458 
1459 	key_net_idx = shell_strtoul(argv[1], 0, &err);
1460 	if (err) {
1461 		shell_warn(sh, "Unable to parse input string argument");
1462 		return err;
1463 	}
1464 
1465 	if (argc < 3) {
1466 		err = bt_mesh_cfg_cli_krp_get(bt_mesh_shell_target_ctx.net_idx,
1467 					  bt_mesh_shell_target_ctx.dst, key_net_idx, &status,
1468 					  &phase);
1469 	} else {
1470 		uint16_t trans = shell_strtoul(argv[2], 0, &err);
1471 
1472 		if (err) {
1473 			shell_warn(sh, "Unable to parse input string argument");
1474 			return err;
1475 		}
1476 
1477 		err = bt_mesh_cfg_cli_krp_set(bt_mesh_shell_target_ctx.net_idx,
1478 					  bt_mesh_shell_target_ctx.dst, key_net_idx, trans, &status,
1479 					  &phase);
1480 	}
1481 
1482 	if (err) {
1483 		shell_error(sh, "Unable to send key refresh phase Get/Set (err %d)", err);
1484 		return 0;
1485 	}
1486 
1487 	shell_print(sh, "Key refresh phase Get/Set with status 0x%02x and phase 0x%02x", status,
1488 		    phase);
1489 
1490 	return 0;
1491 }
1492 
mod_pub_get(const struct shell * sh,uint16_t addr,uint16_t mod_id,uint16_t cid)1493 static int mod_pub_get(const struct shell *sh, uint16_t addr, uint16_t mod_id, uint16_t cid)
1494 {
1495 	struct bt_mesh_cfg_cli_mod_pub pub;
1496 	uint8_t status;
1497 	int err;
1498 
1499 	if (cid == CID_NVAL) {
1500 		err = bt_mesh_cfg_cli_mod_pub_get(bt_mesh_shell_target_ctx.net_idx,
1501 					      bt_mesh_shell_target_ctx.dst, addr, mod_id, &pub,
1502 					      &status);
1503 	} else {
1504 		err = bt_mesh_cfg_cli_mod_pub_get_vnd(bt_mesh_shell_target_ctx.net_idx,
1505 						  bt_mesh_shell_target_ctx.dst, addr, mod_id, cid,
1506 						  &pub, &status);
1507 	}
1508 
1509 	if (err) {
1510 		shell_error(sh, "Model Publication Get failed (err %d)", err);
1511 		return 0;
1512 	}
1513 
1514 	if (status) {
1515 		shell_print(sh, "Model Publication Get failed (status 0x%02x)", status);
1516 		return 0;
1517 	}
1518 
1519 	shell_print(sh,
1520 		    "Model Publication for Element 0x%04x, Model 0x%04x:\n"
1521 		    "\tPublish Address:                0x%04x\n"
1522 		    "\tAppKeyIndex:                    0x%04x\n"
1523 		    "\tCredential Flag:                %u\n"
1524 		    "\tPublishTTL:                     %u\n"
1525 		    "\tPublishPeriod:                  0x%02x\n"
1526 		    "\tPublishRetransmitCount:         %u\n"
1527 		    "\tPublishRetransmitInterval:      %ums",
1528 		    addr, mod_id, pub.addr, pub.app_idx, pub.cred_flag, pub.ttl, pub.period,
1529 		    BT_MESH_PUB_TRANSMIT_COUNT(pub.transmit),
1530 		    BT_MESH_PUB_TRANSMIT_INT(pub.transmit));
1531 
1532 	return 0;
1533 }
1534 
mod_pub_set(const struct shell * sh,uint16_t addr,bool is_va,uint16_t mod_id,uint16_t cid,char * argv[])1535 static int mod_pub_set(const struct shell *sh, uint16_t addr, bool is_va, uint16_t mod_id,
1536 		       uint16_t cid, char *argv[])
1537 {
1538 	struct bt_mesh_cfg_cli_mod_pub pub;
1539 	uint8_t status, count, res_step, steps;
1540 	uint16_t interval;
1541 	uint8_t uuid[16];
1542 	uint8_t len;
1543 	int err = 0;
1544 
1545 	if (!is_va) {
1546 		pub.addr = shell_strtoul(argv[0], 0, &err);
1547 		pub.uuid = NULL;
1548 	} else {
1549 		len = hex2bin(argv[0], strlen(argv[0]), uuid, sizeof(uuid));
1550 		memset(uuid + len, 0, sizeof(uuid) - len);
1551 		pub.uuid = (const uint8_t *)&uuid;
1552 	}
1553 
1554 	pub.app_idx = shell_strtoul(argv[1], 0, &err);
1555 	pub.cred_flag = shell_strtobool(argv[2], 0, &err);
1556 	pub.ttl = shell_strtoul(argv[3], 0, &err);
1557 	res_step = shell_strtoul(argv[4], 0, &err);
1558 	steps = shell_strtoul(argv[5], 0, &err);
1559 	if ((res_step > 3) || (steps > 0x3F)) {
1560 		shell_print(sh, "Invalid period");
1561 		return -EINVAL;
1562 	}
1563 
1564 	pub.period = (steps << 2) + res_step;
1565 	count = shell_strtoul(argv[6], 0, &err);
1566 	if (count > 7) {
1567 		shell_print(sh, "Invalid retransmit count");
1568 		return -EINVAL;
1569 	}
1570 
1571 	interval = shell_strtoul(argv[7], 0, &err);
1572 	if (err) {
1573 		shell_warn(sh, "Unable to parse input string argument");
1574 		return err;
1575 	}
1576 
1577 	if (interval > (31 * 50) || (interval % 50)) {
1578 		shell_print(sh, "Invalid retransmit interval %u", interval);
1579 		return -EINVAL;
1580 	}
1581 
1582 	pub.transmit = BT_MESH_PUB_TRANSMIT(count, interval);
1583 
1584 	if (cid == CID_NVAL) {
1585 		err = bt_mesh_cfg_cli_mod_pub_set(bt_mesh_shell_target_ctx.net_idx,
1586 					      bt_mesh_shell_target_ctx.dst, addr, mod_id, &pub,
1587 					      &status);
1588 	} else {
1589 		err = bt_mesh_cfg_cli_mod_pub_set_vnd(bt_mesh_shell_target_ctx.net_idx,
1590 						  bt_mesh_shell_target_ctx.dst, addr, mod_id, cid,
1591 						  &pub, &status);
1592 	}
1593 
1594 	if (err) {
1595 		shell_error(sh, "Model Publication Set failed (err %d)", err);
1596 		return 0;
1597 	}
1598 
1599 	if (status) {
1600 		shell_print(sh, "Model Publication Set failed (status 0x%02x)", status);
1601 	} else {
1602 		shell_print(sh, "Model Publication successfully set");
1603 	}
1604 
1605 	return 0;
1606 }
1607 
cmd_mod_pub(const struct shell * sh,size_t argc,char * argv[])1608 static int cmd_mod_pub(const struct shell *sh, size_t argc, char *argv[])
1609 {
1610 	int err = 0;
1611 	uint16_t addr, mod_id, cid;
1612 
1613 	addr = shell_strtoul(argv[1], 0, &err);
1614 	mod_id = shell_strtoul(argv[2], 0, &err);
1615 
1616 	argc -= 3;
1617 	argv += 3;
1618 
1619 	if (argc == 1 || argc == 9) {
1620 		cid = shell_strtoul(argv[0], 0, &err);
1621 		argc--;
1622 		argv++;
1623 	} else {
1624 		cid = CID_NVAL;
1625 	}
1626 
1627 	if (err) {
1628 		shell_warn(sh, "Unable to parse input string argument");
1629 		return err;
1630 	}
1631 
1632 	if (argc > 0) {
1633 		if (argc < 7) {
1634 			shell_warn(sh, "Invalid number of argument");
1635 			return -EINVAL;
1636 		}
1637 
1638 		return mod_pub_set(sh, addr, false, mod_id, cid, argv);
1639 	} else {
1640 		return mod_pub_get(sh, addr, mod_id, cid);
1641 	}
1642 }
1643 
cmd_mod_pub_va(const struct shell * sh,size_t argc,char * argv[])1644 static int cmd_mod_pub_va(const struct shell *sh, size_t argc, char *argv[])
1645 {
1646 	int err = 0;
1647 	uint16_t addr, mod_id, cid = CID_NVAL;
1648 
1649 	addr = shell_strtoul(argv[1], 0, &err);
1650 	mod_id = shell_strtoul(argv[9], 0, &err);
1651 
1652 	if (argc > 10) {
1653 		cid = shell_strtoul(argv[10], 0, &err);
1654 	}
1655 
1656 	if (err) {
1657 		shell_warn(sh, "Unable to parse input string argument");
1658 		return err;
1659 	}
1660 
1661 	argv += 2;
1662 
1663 	return mod_pub_set(sh, addr, true, mod_id, cid, argv);
1664 }
1665 
hb_sub_print(const struct shell * sh,struct bt_mesh_cfg_cli_hb_sub * sub)1666 static void hb_sub_print(const struct shell *sh, struct bt_mesh_cfg_cli_hb_sub *sub)
1667 {
1668 	shell_print(sh,
1669 		    "Heartbeat Subscription:\n"
1670 		    "\tSource:      0x%04x\n"
1671 		    "\tDestination: 0x%04x\n"
1672 		    "\tPeriodLog:   0x%02x\n"
1673 		    "\tCountLog:    0x%02x\n"
1674 		    "\tMinHops:     %u\n"
1675 		    "\tMaxHops:     %u",
1676 		    sub->src, sub->dst, sub->period, sub->count, sub->min, sub->max);
1677 }
1678 
hb_sub_get(const struct shell * sh,size_t argc,char * argv[])1679 static int hb_sub_get(const struct shell *sh, size_t argc, char *argv[])
1680 {
1681 	struct bt_mesh_cfg_cli_hb_sub sub;
1682 	uint8_t status;
1683 	int err;
1684 
1685 	err = bt_mesh_cfg_cli_hb_sub_get(bt_mesh_shell_target_ctx.net_idx,
1686 					 bt_mesh_shell_target_ctx.dst, &sub, &status);
1687 	if (err) {
1688 		shell_error(sh, "Heartbeat Subscription Get failed (err %d)", err);
1689 		return 0;
1690 	}
1691 
1692 	if (status) {
1693 		shell_print(sh, "Heartbeat Subscription Get failed (status 0x%02x)", status);
1694 	} else {
1695 		hb_sub_print(sh, &sub);
1696 	}
1697 
1698 	return 0;
1699 }
1700 
hb_sub_set(const struct shell * sh,size_t argc,char * argv[])1701 static int hb_sub_set(const struct shell *sh, size_t argc, char *argv[])
1702 {
1703 	struct bt_mesh_cfg_cli_hb_sub sub;
1704 	uint8_t status;
1705 	int err = 0;
1706 
1707 	sub.src = shell_strtoul(argv[1], 0, &err);
1708 	sub.dst = shell_strtoul(argv[2], 0, &err);
1709 	sub.period = shell_strtoul(argv[3], 0, &err);
1710 	if (err) {
1711 		shell_warn(sh, "Unable to parse input string argument");
1712 		return err;
1713 	}
1714 
1715 	err = bt_mesh_cfg_cli_hb_sub_set(bt_mesh_shell_target_ctx.net_idx,
1716 					 bt_mesh_shell_target_ctx.dst, &sub, &status);
1717 	if (err) {
1718 		shell_error(sh, "Heartbeat Subscription Set failed (err %d)", err);
1719 		return 0;
1720 	}
1721 
1722 	if (status) {
1723 		shell_print(sh, "Heartbeat Subscription Set failed (status 0x%02x)", status);
1724 	} else {
1725 		hb_sub_print(sh, &sub);
1726 	}
1727 
1728 	return 0;
1729 }
1730 
cmd_hb_sub(const struct shell * sh,size_t argc,char * argv[])1731 static int cmd_hb_sub(const struct shell *sh, size_t argc, char *argv[])
1732 {
1733 	if (argc > 1) {
1734 		if (argc < 4) {
1735 			shell_warn(sh, "Invalid number of argument");
1736 			return -EINVAL;
1737 		}
1738 
1739 		return hb_sub_set(sh, argc, argv);
1740 	} else {
1741 		return hb_sub_get(sh, argc, argv);
1742 	}
1743 }
1744 
hb_pub_get(const struct shell * sh,size_t argc,char * argv[])1745 static int hb_pub_get(const struct shell *sh, size_t argc, char *argv[])
1746 {
1747 	struct bt_mesh_cfg_cli_hb_pub pub;
1748 	uint8_t status;
1749 	int err;
1750 
1751 	err = bt_mesh_cfg_cli_hb_pub_get(bt_mesh_shell_target_ctx.net_idx,
1752 					 bt_mesh_shell_target_ctx.dst, &pub, &status);
1753 	if (err) {
1754 		shell_error(sh, "Heartbeat Publication Get failed (err %d)", err);
1755 		return 0;
1756 	}
1757 
1758 	if (status) {
1759 		shell_print(sh, "Heartbeat Publication Get failed (status 0x%02x)", status);
1760 		return 0;
1761 	}
1762 
1763 	shell_print(sh, "Heartbeat publication:");
1764 	shell_print(sh, "\tdst 0x%04x count 0x%02x period 0x%02x", pub.dst, pub.count, pub.period);
1765 	shell_print(sh, "\tttl 0x%02x feat 0x%04x net_idx 0x%04x", pub.ttl, pub.feat, pub.net_idx);
1766 
1767 	return 0;
1768 }
1769 
hb_pub_set(const struct shell * sh,size_t argc,char * argv[])1770 static int hb_pub_set(const struct shell *sh, size_t argc, char *argv[])
1771 {
1772 	struct bt_mesh_cfg_cli_hb_pub pub;
1773 	uint8_t status;
1774 	int err = 0;
1775 
1776 	pub.dst = shell_strtoul(argv[1], 0, &err);
1777 	pub.count = shell_strtoul(argv[2], 0, &err);
1778 	pub.period = shell_strtoul(argv[3], 0, &err);
1779 	pub.ttl = shell_strtoul(argv[4], 0, &err);
1780 	pub.feat = shell_strtoul(argv[5], 0, &err);
1781 	pub.net_idx = shell_strtoul(argv[6], 0, &err);
1782 	if (err) {
1783 		shell_warn(sh, "Unable to parse input string argument");
1784 		return err;
1785 	}
1786 
1787 	err = bt_mesh_cfg_cli_hb_pub_set(bt_mesh_shell_target_ctx.net_idx,
1788 					 bt_mesh_shell_target_ctx.dst, &pub, &status);
1789 	if (err) {
1790 		shell_error(sh, "Heartbeat Publication Set failed (err %d)", err);
1791 		return 0;
1792 	}
1793 
1794 	if (status) {
1795 		shell_print(sh, "Heartbeat Publication Set failed (status 0x%02x)", status);
1796 	} else {
1797 		shell_print(sh, "Heartbeat publication successfully set");
1798 	}
1799 
1800 	return 0;
1801 }
1802 
cmd_hb_pub(const struct shell * sh,size_t argc,char * argv[])1803 static int cmd_hb_pub(const struct shell *sh, size_t argc, char *argv[])
1804 {
1805 	if (argc > 1) {
1806 		if (argc < 7) {
1807 			shell_warn(sh, "Invalid number of argument");
1808 			return -EINVAL;
1809 		}
1810 
1811 		return hb_pub_set(sh, argc, argv);
1812 	} else {
1813 		return hb_pub_get(sh, argc, argv);
1814 	}
1815 }
1816 
1817 SHELL_STATIC_SUBCMD_SET_CREATE(model_cmds,
1818 	SHELL_CMD_ARG(app-bind, NULL, "<Addr> <AppKeyIdx> <MID> [CID]",
1819 		      cmd_mod_app_bind, 4, 1),
1820 	SHELL_CMD_ARG(app-get, NULL, "<ElemAddr> <MID> [CID]", cmd_mod_app_get,
1821 		      3, 1),
1822 	SHELL_CMD_ARG(app-unbind, NULL, "<Addr> <AppKeyIdx> <MID> [CID]",
1823 		      cmd_mod_app_unbind, 4, 1),
1824 	SHELL_CMD_ARG(pub, NULL,
1825 		      "<Addr> <MID> [CID] [<PubAddr> "
1826 		      "<AppKeyIdx> <Cred(off, on)> <TTL> <PerRes> <PerSteps> <Count> "
1827 		      "<Int(ms)>]",
1828 		      cmd_mod_pub, 3, 1 + 8),
1829 	SHELL_CMD_ARG(pub-va, NULL,
1830 		      "<Addr> <UUID(1-16 hex)> "
1831 		      "<AppKeyIdx> <Cred(off, on)> <TTL> <PerRes> <PerSteps> <Count> "
1832 		      "<Int(ms)> <MID> [CID]",
1833 		      cmd_mod_pub_va, 11, 1),
1834 	SHELL_CMD_ARG(sub-add, NULL, "<ElemAddr> <SubAddr> <MID> [CID]",
1835 		      cmd_mod_sub_add, 4, 1),
1836 	SHELL_CMD_ARG(sub-del, NULL, "<ElemAddr> <SubAddr> <MID> [CID]",
1837 		      cmd_mod_sub_del, 4, 1),
1838 	SHELL_CMD_ARG(sub-add-va, NULL,
1839 		      "<ElemAddr> <LabelUUID(1-16 hex)> <MID> [CID]", cmd_mod_sub_add_va, 4, 1),
1840 	SHELL_CMD_ARG(sub-del-va, NULL,
1841 		      "<ElemAddr> <LabelUUID(1-16 hex)> <MID> [CID]", cmd_mod_sub_del_va, 4, 1),
1842 	SHELL_CMD_ARG(sub-ow, NULL, "<ElemAddr> <SubAddr> <MID> [CID]",
1843 		      cmd_mod_sub_ow, 4, 1),
1844 	SHELL_CMD_ARG(sub-ow-va, NULL, "<ElemAddr> <LabelUUID(1-16 hex)> <MID> [CID]",
1845 		      cmd_mod_sub_ow_va, 4, 1),
1846 	SHELL_CMD_ARG(sub-del-all, NULL, "<ElemAddr> <MID> [CID]",
1847 		      cmd_mod_sub_del_all, 3, 1),
1848 	SHELL_CMD_ARG(sub-get, NULL, "<ElemAddr> <MID> [CID]", cmd_mod_sub_get,
1849 		      3, 1),
1850 	SHELL_SUBCMD_SET_END);
1851 
1852 SHELL_STATIC_SUBCMD_SET_CREATE(netkey_cmds,
1853 	SHELL_CMD_ARG(add, NULL, "<NetKeyIdx> [Key(1-16 hex)]", cmd_net_key_add, 2, 1),
1854 	SHELL_CMD_ARG(upd, NULL, "<NetKeyIdx> [Key(1-16 hex)]", cmd_net_key_update, 2, 1),
1855 	SHELL_CMD_ARG(get, NULL, NULL, cmd_net_key_get, 1, 0),
1856 	SHELL_CMD_ARG(del, NULL, "<NetKeyIdx>", cmd_net_key_del, 2, 0),
1857 	SHELL_SUBCMD_SET_END);
1858 
1859 SHELL_STATIC_SUBCMD_SET_CREATE(appkey_cmds,
1860 	SHELL_CMD_ARG(add, NULL, "<NetKeyIdx> <AppKeyIdx> [Key(1-16 hex)]", cmd_app_key_add,
1861 		      3, 1),
1862 	SHELL_CMD_ARG(upd, NULL, "<NetKeyIdx> <AppKeyIdx> [Key(1-16 hex)]", cmd_app_key_upd,
1863 		      3, 1),
1864 	SHELL_CMD_ARG(del, NULL, "<NetKeyIdx> <AppKeyIdx>", cmd_app_key_del, 3, 0),
1865 	SHELL_CMD_ARG(get, NULL, "<NetKeyIdx>", cmd_app_key_get, 2, 0),
1866 	SHELL_SUBCMD_SET_END);
1867 
1868 
1869 SHELL_STATIC_SUBCMD_SET_CREATE(
1870 	cfg_cli_cmds,
1871 	/* Configuration Client Model operations */
1872 	SHELL_CMD_ARG(reset, NULL, NULL, cmd_reset, 1, 0),
1873 	SHELL_CMD_ARG(timeout, NULL, "[Timeout(s)]", cmd_timeout, 1, 1),
1874 	SHELL_CMD_ARG(get-comp, NULL, "[Page]", cmd_get_comp, 1, 1),
1875 	SHELL_CMD_ARG(beacon, NULL, "[Val(off, on)]", cmd_beacon, 1, 1),
1876 	SHELL_CMD_ARG(ttl, NULL, "[TTL]", cmd_ttl, 1, 1),
1877 	SHELL_CMD_ARG(friend, NULL, "[Val(off, on)]", cmd_friend, 1, 1),
1878 	SHELL_CMD_ARG(gatt-proxy, NULL, "[Val(off, on)]", cmd_gatt_proxy, 1, 1),
1879 	SHELL_CMD_ARG(relay, NULL, "[<Val(off, on)> [<Count> [Int(ms)]]]", cmd_relay,
1880 		      1, 3),
1881 	SHELL_CMD_ARG(node-id, NULL, "<NetKeyIdx> [Identify]", cmd_node_id, 2, 1),
1882 	SHELL_CMD_ARG(polltimeout-get, NULL, "<LPNAddr>", cmd_polltimeout_get, 2, 0),
1883 	SHELL_CMD_ARG(net-transmit-param, NULL, "[<Count> <Int(ms)>]",
1884 		      cmd_net_transmit, 1, 2),
1885 	SHELL_CMD_ARG(krp, NULL, "<NetKeyIdx> [Phase]", cmd_krp, 2, 1),
1886 	SHELL_CMD_ARG(hb-sub, NULL, "[<Src> <Dst> <Per>]", cmd_hb_sub, 1, 3),
1887 	SHELL_CMD_ARG(hb-pub, NULL, "[<Dst> <Count> <Per> <TTL> <Features> <NetKeyIdx>]",
1888 		      cmd_hb_pub, 1, 6),
1889 	SHELL_CMD(appkey, &appkey_cmds, "Appkey config commands", bt_mesh_shell_mdl_cmds_help),
1890 	SHELL_CMD(netkey, &netkey_cmds, "Netkey config commands", bt_mesh_shell_mdl_cmds_help),
1891 	SHELL_CMD(model, &model_cmds, "Model config commands", bt_mesh_shell_mdl_cmds_help),
1892 	SHELL_SUBCMD_SET_END);
1893 
1894 SHELL_SUBCMD_ADD((mesh, models), cfg, &cfg_cli_cmds, "Config Cli commands",
1895 		 bt_mesh_shell_mdl_cmds_help, 1, 1);
1896