1 /*
2  * Copyright (c) 2017 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <ctype.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/sys/printk.h>
11 #include <zephyr/sys/util.h>
12 
13 #include <zephyr/shell/shell.h>
14 #include <zephyr/settings/settings.h>
15 
16 #include <zephyr/bluetooth/bluetooth.h>
17 #include <zephyr/bluetooth/mesh.h>
18 #include <zephyr/bluetooth/mesh/shell.h>
19 
20 /* Private includes for raw Network & Transport layer access */
21 #include "mesh/mesh.h"
22 #include "mesh/net.h"
23 #include "mesh/rpl.h"
24 #include "mesh/transport.h"
25 #include "mesh/foundation.h"
26 #include "mesh/settings.h"
27 #include "mesh/access.h"
28 #include "mesh/prov.h"
29 #include "common/bt_shell_private.h"
30 #include "utils.h"
31 #include "dfu.h"
32 #include "blob.h"
33 
34 #define CID_NVAL   0xffff
35 #define COMPANY_ID_LF 0x05F1
36 #define COMPANY_ID_NORDIC_SEMI 0x05F9
37 
38 struct bt_mesh_shell_target bt_mesh_shell_target_ctx = {
39 	.dst = BT_MESH_ADDR_UNASSIGNED,
40 };
41 
42 /* Default net, app & dev key values, unless otherwise specified */
43 const uint8_t bt_mesh_shell_default_key[16] = {
44 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
45 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
46 };
47 
48 #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE)
49 static uint8_t cur_faults[BT_MESH_SHELL_CUR_FAULTS_MAX];
50 static uint8_t reg_faults[BT_MESH_SHELL_CUR_FAULTS_MAX * 2];
51 
get_faults(uint8_t * faults,uint8_t faults_size,uint8_t * dst,uint8_t * count)52 static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
53 {
54 	uint8_t i, limit = *count;
55 
56 	for (i = 0U, *count = 0U; i < faults_size && *count < limit; i++) {
57 		if (faults[i]) {
58 			*dst++ = faults[i];
59 			(*count)++;
60 		}
61 	}
62 }
63 
fault_get_cur(const struct bt_mesh_model * model,uint8_t * test_id,uint16_t * company_id,uint8_t * faults,uint8_t * fault_count)64 static int fault_get_cur(const struct bt_mesh_model *model, uint8_t *test_id,
65 			 uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
66 {
67 	bt_shell_print("Sending current faults");
68 
69 	*test_id = 0x00;
70 	*company_id = BT_COMP_ID_LF;
71 
72 	get_faults(cur_faults, sizeof(cur_faults), faults, fault_count);
73 
74 	return 0;
75 }
76 
fault_get_reg(const struct bt_mesh_model * model,uint16_t cid,uint8_t * test_id,uint8_t * faults,uint8_t * fault_count)77 static int fault_get_reg(const struct bt_mesh_model *model, uint16_t cid,
78 			 uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
79 {
80 	if (cid != CONFIG_BT_COMPANY_ID) {
81 		bt_shell_print("Faults requested for unknown Company ID 0x%04x", cid);
82 		return -EINVAL;
83 	}
84 
85 	bt_shell_print("Sending registered faults");
86 
87 	*test_id = 0x00;
88 
89 	get_faults(reg_faults, sizeof(reg_faults), faults, fault_count);
90 
91 	return 0;
92 }
93 
fault_clear(const struct bt_mesh_model * model,uint16_t cid)94 static int fault_clear(const struct bt_mesh_model *model, uint16_t cid)
95 {
96 	if (cid != CONFIG_BT_COMPANY_ID) {
97 		return -EINVAL;
98 	}
99 
100 	(void)memset(reg_faults, 0, sizeof(reg_faults));
101 
102 	return 0;
103 }
104 
fault_test(const struct bt_mesh_model * model,uint8_t test_id,uint16_t cid)105 static int fault_test(const struct bt_mesh_model *model, uint8_t test_id,
106 		      uint16_t cid)
107 {
108 	if (cid != CONFIG_BT_COMPANY_ID) {
109 		return -EINVAL;
110 	}
111 
112 	if (test_id != 0x00) {
113 		return -EINVAL;
114 	}
115 
116 	return 0;
117 }
118 
attention_on(const struct bt_mesh_model * model)119 static void attention_on(const struct bt_mesh_model *model)
120 {
121 	bt_shell_print("Attention On");
122 }
123 
attention_off(const struct bt_mesh_model * model)124 static void attention_off(const struct bt_mesh_model *model)
125 {
126 	bt_shell_print("Attention Off");
127 }
128 
129 static const struct bt_mesh_health_srv_cb health_srv_cb = {
130 	.fault_get_cur = fault_get_cur,
131 	.fault_get_reg = fault_get_reg,
132 	.fault_clear = fault_clear,
133 	.fault_test = fault_test,
134 	.attn_on = attention_on,
135 	.attn_off = attention_off,
136 };
137 #endif /* CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE */
138 
139 #if defined(CONFIG_BT_MESH_LARGE_COMP_DATA_SRV)
140 static const uint8_t health_tests[] = {
141 	BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_LF, 6, 0x01, 0x02, 0x03, 0x04, 0x34, 0x15),
142 	BT_MESH_HEALTH_TEST_INFO(COMPANY_ID_NORDIC_SEMI, 3, 0x01, 0x02, 0x03),
143 };
144 
145 const struct bt_mesh_models_metadata_entry health_srv_meta[] = {
146 	BT_MESH_HEALTH_TEST_INFO_METADATA(health_tests),
147 	BT_MESH_MODELS_METADATA_END,
148 };
149 #endif
150 
151 struct bt_mesh_health_srv bt_mesh_shell_health_srv = {
152 #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE)
153 	.cb = &health_srv_cb,
154 #endif
155 };
156 
157 #if defined(CONFIG_BT_MESH_SHELL_HEALTH_CLI)
show_faults(uint8_t test_id,uint16_t cid,uint8_t * faults,size_t fault_count)158 static void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count)
159 {
160 	size_t i;
161 
162 	if (!fault_count) {
163 		bt_shell_print("Health Test ID 0x%02x Company ID 0x%04x: no faults",
164 			       test_id, cid);
165 		return;
166 	}
167 
168 	bt_shell_print("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:",
169 		       test_id, cid, fault_count);
170 
171 	for (i = 0; i < fault_count; i++) {
172 		bt_shell_print("\t0x%02x", faults[i]);
173 	}
174 }
175 
health_current_status(struct bt_mesh_health_cli * cli,uint16_t addr,uint8_t test_id,uint16_t cid,uint8_t * faults,size_t fault_count)176 static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
177 				  uint8_t test_id, uint16_t cid, uint8_t *faults,
178 				  size_t fault_count)
179 {
180 	bt_shell_print("Health Current Status from 0x%04x", addr);
181 	show_faults(test_id, cid, faults, fault_count);
182 }
183 
health_fault_status(struct bt_mesh_health_cli * cli,uint16_t addr,uint8_t test_id,uint16_t cid,uint8_t * faults,size_t fault_count)184 static void health_fault_status(struct bt_mesh_health_cli *cli, uint16_t addr,
185 				uint8_t test_id, uint16_t cid, uint8_t *faults,
186 				size_t fault_count)
187 {
188 	bt_shell_print("Health Fault Status from 0x%04x", addr);
189 	show_faults(test_id, cid, faults, fault_count);
190 }
191 
health_attention_status(struct bt_mesh_health_cli * cli,uint16_t addr,uint8_t attention)192 static void health_attention_status(struct bt_mesh_health_cli *cli,
193 				    uint16_t addr, uint8_t attention)
194 {
195 	bt_shell_print("Health Attention Status from 0x%04x: %u", addr, attention);
196 }
197 
health_period_status(struct bt_mesh_health_cli * cli,uint16_t addr,uint8_t period)198 static void health_period_status(struct bt_mesh_health_cli *cli, uint16_t addr,
199 				 uint8_t period)
200 {
201 	bt_shell_print("Health Fast Period Divisor Status from 0x%04x: %u", addr, period);
202 }
203 
204 struct bt_mesh_health_cli bt_mesh_shell_health_cli = {
205 	.current_status = health_current_status,
206 	.fault_status = health_fault_status,
207 	.attention_status = health_attention_status,
208 	.period_status = health_period_status,
209 };
210 #endif /* CONFIG_BT_MESH_SHELL_HEALTH_CLI */
211 
cmd_init(const struct shell * sh,size_t argc,char * argv[])212 static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
213 {
214 	shell_print(sh, "Mesh shell initialized");
215 
216 #if defined(CONFIG_BT_MESH_SHELL_DFU_CLI) || defined(CONFIG_BT_MESH_SHELL_DFU_SRV)
217 	bt_mesh_shell_dfu_cmds_init();
218 #endif
219 #if defined(CONFIG_BT_MESH_SHELL_BLOB_CLI) || defined(CONFIG_BT_MESH_SHELL_BLOB_SRV) || \
220 	defined(CONFIG_BT_MESH_SHELL_BLOB_IO_FLASH)
221 	bt_mesh_shell_blob_cmds_init();
222 #endif
223 
224 	if (IS_ENABLED(CONFIG_BT_MESH_RPR_SRV)) {
225 		bt_mesh_prov_enable(BT_MESH_PROV_REMOTE);
226 	}
227 
228 	return 0;
229 }
230 
cmd_reset(const struct shell * sh,size_t argc,char * argv[])231 static int cmd_reset(const struct shell *sh, size_t argc, char *argv[])
232 {
233 #if defined(CONFIG_BT_MESH_CDB)
234 	bt_mesh_cdb_clear();
235 #endif
236 	bt_mesh_reset();
237 	shell_print(sh, "Local node reset complete");
238 
239 	return 0;
240 }
241 
242 #if defined(CONFIG_BT_MESH_SHELL_LOW_POWER)
cmd_lpn(const struct shell * sh,size_t argc,char * argv[])243 static int cmd_lpn(const struct shell *sh, size_t argc, char *argv[])
244 {
245 	static bool enabled;
246 	bool onoff;
247 	int err = 0;
248 
249 	if (argc < 2) {
250 		shell_print(sh, "%s", enabled ? "enabled" : "disabled");
251 		return 0;
252 	}
253 
254 	onoff = shell_strtobool(argv[1], 0, &err);
255 	if (err) {
256 		shell_warn(sh, "Unable to parse input string argument");
257 		return err;
258 	}
259 
260 	if (onoff) {
261 		if (enabled) {
262 			shell_print(sh, "LPN already enabled");
263 			return 0;
264 		}
265 
266 		err = bt_mesh_lpn_set(true);
267 		if (err) {
268 			shell_error(sh, "Enabling LPN failed (err %d)", err);
269 		} else {
270 			enabled = true;
271 		}
272 	} else {
273 		if (!enabled) {
274 			shell_print(sh, "LPN already disabled");
275 			return 0;
276 		}
277 
278 		err = bt_mesh_lpn_set(false);
279 		if (err) {
280 			shell_error(sh, "Enabling LPN failed (err %d)", err);
281 		} else {
282 			enabled = false;
283 		}
284 	}
285 
286 	return 0;
287 }
288 
cmd_poll(const struct shell * sh,size_t argc,char * argv[])289 static int cmd_poll(const struct shell *sh, size_t argc, char *argv[])
290 {
291 	int err;
292 
293 	err = bt_mesh_lpn_poll();
294 	if (err) {
295 		shell_error(sh, "Friend Poll failed (err %d)", err);
296 	}
297 
298 	return 0;
299 }
300 
lpn_established(uint16_t net_idx,uint16_t friend_addr,uint8_t queue_size,uint8_t recv_win)301 static void lpn_established(uint16_t net_idx, uint16_t friend_addr,
302 					uint8_t queue_size, uint8_t recv_win)
303 {
304 	bt_shell_print("Friendship (as LPN) established to "
305 		       "Friend 0x%04x Queue Size %d Receive Window %d",
306 		       friend_addr, queue_size, recv_win);
307 }
308 
lpn_terminated(uint16_t net_idx,uint16_t friend_addr)309 static void lpn_terminated(uint16_t net_idx, uint16_t friend_addr)
310 {
311 	bt_shell_print("Friendship (as LPN) lost with Friend 0x%04x", friend_addr);
312 }
313 
314 BT_MESH_LPN_CB_DEFINE(lpn_cb) = {
315 	.established = lpn_established,
316 	.terminated = lpn_terminated,
317 };
318 #endif /* CONFIG_BT_MESH_SHELL_LOW_POWER */
319 
320 #if defined(CONFIG_BT_MESH_SHELL_GATT_PROXY)
321 #if defined(CONFIG_BT_MESH_GATT_PROXY)
cmd_ident(const struct shell * sh,size_t argc,char * argv[])322 static int cmd_ident(const struct shell *sh, size_t argc, char *argv[])
323 {
324 	int err;
325 
326 	err = bt_mesh_proxy_identity_enable();
327 	if (err) {
328 		shell_error(sh, "Failed advertise using Node Identity (err "
329 			    "%d)", err);
330 	}
331 
332 	return 0;
333 }
334 #endif /* CONFIG_BT_MESH_GATT_PROXY */
335 
336 #if defined(CONFIG_BT_MESH_PROXY_CLIENT)
cmd_proxy_connect(const struct shell * sh,size_t argc,char * argv[])337 static int cmd_proxy_connect(const struct shell *sh, size_t argc,
338 			     char *argv[])
339 {
340 	uint16_t net_idx;
341 	int err = 0;
342 
343 	net_idx = shell_strtoul(argv[1], 0, &err);
344 	if (err) {
345 		shell_warn(sh, "Unable to parse input string argument");
346 		return err;
347 	}
348 
349 	err = bt_mesh_proxy_connect(net_idx);
350 	if (err) {
351 		shell_error(sh, "Proxy connect failed (err %d)", err);
352 	}
353 
354 	return 0;
355 }
356 
cmd_proxy_disconnect(const struct shell * sh,size_t argc,char * argv[])357 static int cmd_proxy_disconnect(const struct shell *sh, size_t argc,
358 				char *argv[])
359 {
360 	uint16_t net_idx;
361 	int err = 0;
362 
363 	net_idx = shell_strtoul(argv[1], 0, &err);
364 	if (err) {
365 		shell_warn(sh, "Unable to parse input string argument");
366 		return err;
367 	}
368 
369 	err = bt_mesh_proxy_disconnect(net_idx);
370 	if (err) {
371 		shell_error(sh, "Proxy disconnect failed (err %d)", err);
372 	}
373 
374 	return 0;
375 }
376 #endif /* CONFIG_BT_MESH_PROXY_CLIENT */
377 
378 #if defined(CONFIG_BT_MESH_PROXY_SOLICITATION)
cmd_proxy_solicit(const struct shell * sh,size_t argc,char * argv[])379 static int cmd_proxy_solicit(const struct shell *sh, size_t argc,
380 			     char *argv[])
381 {
382 	uint16_t net_idx;
383 	int err = 0;
384 
385 	net_idx = shell_strtoul(argv[1], 0, &err);
386 	if (err) {
387 		shell_warn(sh, "Unable to parse input string argument");
388 		return err;
389 	}
390 
391 	err = bt_mesh_proxy_solicit(net_idx);
392 	if (err) {
393 		shell_error(sh, "Failed to advertise solicitation PDU (err %d)",
394 			    err);
395 	}
396 
397 	return err;
398 }
399 #endif /* CONFIG_BT_MESH_PROXY_SOLICITATION */
400 #endif /* CONFIG_BT_MESH_SHELL_GATT_PROXY */
401 
402 #if defined(CONFIG_BT_MESH_SHELL_PROV)
ascii_decimal_to_le_bytes(const char * ascii_str,uint8_t * out,size_t * out_len)403 static int ascii_decimal_to_le_bytes(const char *ascii_str, uint8_t *out, size_t *out_len)
404 {
405 	size_t len = 0;
406 
407 	for (const char *p = ascii_str; *p; ++p) {
408 		if (!isdigit((unsigned char)*p)) {
409 			return -EINVAL; /* Invalid character */
410 		}
411 
412 		uint16_t carry = *p - '0';
413 
414 		/* If this is the first digit and it's 0, we need at least one byte */
415 		if (len == 0) {
416 			out[0] = carry;
417 			len = 1;
418 			continue;
419 		}
420 
421 		/* Multiply current result by 10 and add new digit */
422 		for (size_t i = 0; i < len; ++i) {
423 			uint16_t value = out[i] * 10 + carry;
424 
425 			out[i] = value & 0xFF;
426 			carry = value >> 8;
427 		}
428 
429 		/* Handle overflow to next byte */
430 		if (carry != 0) {
431 			if (len >= PROV_IO_OOB_SIZE_MAX) {
432 				return -EOVERFLOW; /* Overflow */
433 			}
434 			out[len++] = carry;
435 		}
436 	}
437 
438 	*out_len = len;
439 	return 0;
440 }
441 
cmd_input_num(const struct shell * sh,size_t argc,char * argv[])442 static int cmd_input_num(const struct shell *sh, size_t argc, char *argv[])
443 {
444 	int err = 0;
445 	uint8_t result[PROV_IO_OOB_SIZE_MAX] = {0};
446 	size_t result_len;
447 
448 	err = ascii_decimal_to_le_bytes(argv[1], result, &result_len);
449 	if (err) {
450 		shell_warn(sh, err == -EINVAL ? "The input string symbol is not a digit"
451 					      : "Overflow in input string argument");
452 		return err;
453 	}
454 
455 	err = bt_mesh_input_numeric(result, result_len);
456 	if (err) {
457 		shell_error(sh, "Numeric input failed (err %d)", err);
458 	}
459 
460 	return 0;
461 }
462 
cmd_input_str(const struct shell * sh,size_t argc,char * argv[])463 static int cmd_input_str(const struct shell *sh, size_t argc, char *argv[])
464 {
465 	int err = bt_mesh_input_string(argv[1]);
466 
467 	if (err) {
468 		shell_error(sh, "String input failed (err %d)", err);
469 	}
470 
471 	return 0;
472 }
473 
bearer2str(bt_mesh_prov_bearer_t bearer)474 static const char *bearer2str(bt_mesh_prov_bearer_t bearer)
475 {
476 	switch (bearer) {
477 	case BT_MESH_PROV_ADV:
478 		return "PB-ADV";
479 	case BT_MESH_PROV_GATT:
480 		return "PB-GATT";
481 	case BT_MESH_PROV_REMOTE:
482 		return "PB-REMOTE";
483 	default:
484 		return "unknown";
485 	}
486 }
487 
488 #if defined(CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE)
489 static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
490 
prov_complete(uint16_t net_idx,uint16_t addr)491 static void prov_complete(uint16_t net_idx, uint16_t addr)
492 {
493 
494 	bt_shell_print("Local node provisioned, net_idx 0x%04x address 0x%04x", net_idx, addr);
495 
496 	bt_mesh_shell_target_ctx.net_idx = net_idx;
497 	bt_mesh_shell_target_ctx.dst = addr;
498 }
499 
reprovisioned(uint16_t addr)500 static void reprovisioned(uint16_t addr)
501 {
502 	bt_shell_print("Local node re-provisioned, new address 0x%04x", addr);
503 
504 	if (bt_mesh_shell_target_ctx.dst == bt_mesh_primary_addr()) {
505 		bt_mesh_shell_target_ctx.dst = addr;
506 	}
507 }
508 
prov_node_added(uint16_t net_idx,uint8_t uuid[16],uint16_t addr,uint8_t num_elem)509 static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
510 			    uint8_t num_elem)
511 {
512 	bt_shell_print("Node provisioned, net_idx 0x%04x address 0x%04x elements %d",
513 		       net_idx, addr, num_elem);
514 
515 	bt_mesh_shell_target_ctx.net_idx = net_idx;
516 	bt_mesh_shell_target_ctx.dst = addr;
517 }
518 
519 #if defined(CONFIG_BT_MESH_PROVISIONER)
520 static const char * const output_meth_string[] = {
521 	"Blink",
522 	"Beep",
523 	"Vibrate",
524 	"Display Number",
525 	"Display String",
526 };
527 
528 static const char *const input_meth_string[] = {
529 	"Push",
530 	"Twist",
531 	"Enter Number",
532 	"Enter String",
533 };
534 
capabilities(const struct bt_mesh_dev_capabilities * cap)535 static void capabilities(const struct bt_mesh_dev_capabilities *cap)
536 {
537 	bt_shell_print("Provisionee capabilities:");
538 	bt_shell_print("\tStatic OOB is %ssupported", cap->oob_type & 1 ? "" : "not ");
539 
540 	bt_shell_print("\tAvailable output actions (%d bytes max):%s", cap->output_size,
541 		       cap->output_actions ? "" : "\n\t\tNone");
542 	for (int i = 0; i < ARRAY_SIZE(output_meth_string); i++) {
543 		if (cap->output_actions & BIT(i)) {
544 			bt_shell_print("\t\t%s", output_meth_string[i]);
545 		}
546 	}
547 
548 	bt_shell_print("\tAvailable input actions (%d bytes max):%s", cap->input_size,
549 		       cap->input_actions ? "" : "\n\t\tNone");
550 	for (int i = 0; i < ARRAY_SIZE(input_meth_string); i++) {
551 		if (cap->input_actions & BIT(i)) {
552 			bt_shell_print("\t\t%s", input_meth_string[i]);
553 		}
554 	}
555 }
556 #endif
557 
prov_input_complete(void)558 static void prov_input_complete(void)
559 {
560 	bt_shell_print("Input complete");
561 }
562 
prov_reset(void)563 static void prov_reset(void)
564 {
565 	bt_shell_print("The local node has been reset and needs reprovisioning");
566 }
567 
binary_to_ascii_digits(const uint8_t * in,size_t in_len,char * out_str)568 static void binary_to_ascii_digits(const uint8_t *in, size_t in_len, char *out_str)
569 {
570 	uint8_t temp[PROV_IO_OOB_SIZE_MAX];
571 	size_t digit_count = 0;
572 
573 	__ASSERT(in_len <= sizeof(temp), "Output numeric exceeds maximum");
574 	memcpy(temp, in, in_len);
575 
576 	while (in_len > 0) {
577 		uint16_t remainder = 0;
578 
579 		/* Divide the number in `temp` by 10, store quotient back in `temp` */
580 		for (ssize_t i = in_len - 1; i >= 0; --i) {
581 			uint16_t acc = ((uint16_t)remainder << 8) | temp[i];
582 
583 			temp[i] = acc / 10;
584 			remainder = acc % 10;
585 		}
586 
587 		/* Store ASCII digit */
588 		out_str[digit_count++] = '0' + remainder;
589 
590 		/* Trim leading zeros */
591 		while (in_len > 0 && temp[in_len - 1] == 0) {
592 			in_len--;
593 		}
594 	}
595 
596 	/* Digits are in reverse order, reverse them to get correct string */
597 	sys_mem_swap(out_str, digit_count);
598 
599 	/* Null-terminate the string */
600 	out_str[digit_count] = '\0';
601 }
602 
output_numeric(bt_mesh_output_action_t action,uint8_t * numeric,size_t len)603 static int output_numeric(bt_mesh_output_action_t action, uint8_t *numeric, size_t len)
604 {
605 	char oob_string[PROV_IO_OOB_SIZE_MAX + 1];
606 
607 	binary_to_ascii_digits(numeric, len, oob_string);
608 
609 	switch (action) {
610 	case BT_MESH_BLINK:
611 		bt_shell_print("OOB blink Number: %s", oob_string);
612 		break;
613 	case BT_MESH_BEEP:
614 		bt_shell_print("OOB beep Number: %s", oob_string);
615 		break;
616 	case BT_MESH_VIBRATE:
617 		bt_shell_print("OOB vibrate Number: %s", oob_string);
618 		break;
619 	case BT_MESH_DISPLAY_NUMBER:
620 		bt_shell_print("OOB display Number: %s", oob_string);
621 		break;
622 	default:
623 		bt_shell_error("Unknown Output action %u (number %s) requested!", action,
624 			       oob_string);
625 		return -EINVAL;
626 	}
627 
628 	return 0;
629 }
630 
631 #if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY
output_number(bt_mesh_output_action_t action,uint32_t number)632 static int output_number(bt_mesh_output_action_t action, uint32_t number)
633 {
634 	return output_numeric(action, (uint8_t *)&number, sizeof(number));
635 }
636 #endif
637 
output_string(const char * str)638 static int output_string(const char *str)
639 {
640 	bt_shell_print("OOB String: %s", str);
641 	return 0;
642 }
643 
input(bt_mesh_input_action_t act,uint8_t size)644 static int input(bt_mesh_input_action_t act, uint8_t size)
645 {
646 
647 	switch (act) {
648 	case BT_MESH_ENTER_NUMBER:
649 		bt_shell_print("Enter a number (max %u digits) with: Input-num <num>", size);
650 		break;
651 	case BT_MESH_ENTER_STRING:
652 		bt_shell_print("Enter a string (max %u chars) with: Input-str <str>", size);
653 		break;
654 	case BT_MESH_TWIST:
655 		bt_shell_print("\"Twist\" a number (max %u digits) with: Input-num <num>", size);
656 		break;
657 	case BT_MESH_PUSH:
658 		bt_shell_print("\"Push\" a number (max %u digits) with: Input-num <num>", size);
659 		break;
660 	default:
661 		bt_shell_error("Unknown Input action %u (size %u) requested!", act, size);
662 		return -EINVAL;
663 	}
664 
665 	return 0;
666 }
667 
link_open(bt_mesh_prov_bearer_t bearer)668 static void link_open(bt_mesh_prov_bearer_t bearer)
669 {
670 	bt_shell_print("Provisioning link opened on %s", bearer2str(bearer));
671 }
672 
link_close(bt_mesh_prov_bearer_t bearer)673 static void link_close(bt_mesh_prov_bearer_t bearer)
674 {
675 	bt_shell_print("Provisioning link closed on %s", bearer2str(bearer));
676 }
677 
678 static uint8_t static_val[32];
679 
680 struct bt_mesh_prov bt_mesh_shell_prov = {
681 	.uuid = dev_uuid,
682 	.link_open = link_open,
683 	.link_close = link_close,
684 	.complete = prov_complete,
685 	.reprovisioned = reprovisioned,
686 	.node_added = prov_node_added,
687 	.reset = prov_reset,
688 	.static_val = NULL,
689 	.static_val_len = 0,
690 	.output_size = 6,
691 	.output_actions = (BT_MESH_BLINK | BT_MESH_BEEP | BT_MESH_VIBRATE | BT_MESH_DISPLAY_NUMBER |
692 			   BT_MESH_DISPLAY_STRING),
693 #if defined CONFIG_BT_MESH_PROV_OOB_API_LEGACY
694 	.output_number = output_number,
695 #else
696 	.output_numeric = output_numeric,
697 #endif
698 	.output_string = output_string,
699 	.input_size = 6,
700 	.input_actions =
701 		(BT_MESH_ENTER_NUMBER | BT_MESH_ENTER_STRING | BT_MESH_TWIST | BT_MESH_PUSH),
702 	.input = input,
703 	.input_complete = prov_input_complete,
704 #if defined(CONFIG_BT_MESH_PROVISIONER)
705 	.capabilities = capabilities
706 #endif
707 };
708 
cmd_static_oob(const struct shell * sh,size_t argc,char * argv[])709 static int cmd_static_oob(const struct shell *sh, size_t argc, char *argv[])
710 {
711 	if (argc < 2) {
712 		bt_mesh_shell_prov.static_val = NULL;
713 		bt_mesh_shell_prov.static_val_len = 0U;
714 	} else {
715 		bt_mesh_shell_prov.static_val_len = hex2bin(argv[1], strlen(argv[1]),
716 					      static_val, 32);
717 		if (bt_mesh_shell_prov.static_val_len) {
718 			bt_mesh_shell_prov.static_val = static_val;
719 		} else {
720 			bt_mesh_shell_prov.static_val = NULL;
721 		}
722 	}
723 
724 	if (bt_mesh_shell_prov.static_val) {
725 		shell_print(sh, "Static OOB value set (length %u)",
726 			    bt_mesh_shell_prov.static_val_len);
727 	} else {
728 		shell_print(sh, "Static OOB value cleared");
729 	}
730 
731 	return 0;
732 }
733 
cmd_uuid(const struct shell * sh,size_t argc,char * argv[])734 static int cmd_uuid(const struct shell *sh, size_t argc, char *argv[])
735 {
736 	uint8_t uuid[16];
737 	size_t len;
738 
739 	if (argc < 2) {
740 		char uuid_hex_str[32 + 1];
741 
742 		bin2hex(dev_uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
743 
744 		bt_shell_print("Device UUID: %s", uuid_hex_str);
745 		return 0;
746 	}
747 
748 	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
749 	if (len < 1) {
750 		return -EINVAL;
751 	}
752 
753 	memcpy(dev_uuid, uuid, len);
754 	(void)memset(dev_uuid + len, 0, sizeof(dev_uuid) - len);
755 
756 	shell_print(sh, "Device UUID set");
757 
758 	return 0;
759 }
760 
print_unprovisioned_beacon(uint8_t uuid[16],bt_mesh_prov_oob_info_t oob_info,uint32_t * uri_hash)761 static void print_unprovisioned_beacon(uint8_t uuid[16],
762 				       bt_mesh_prov_oob_info_t oob_info,
763 				       uint32_t *uri_hash)
764 {
765 	char uuid_hex_str[32 + 1];
766 
767 	bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
768 
769 	bt_shell_print("PB-ADV UUID %s, OOB Info 0x%04x, URI Hash 0x%x",
770 		       uuid_hex_str, oob_info,
771 		       (uri_hash == NULL ? 0 : *uri_hash));
772 }
773 
774 #if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
pb_gatt_unprovisioned(uint8_t uuid[16],bt_mesh_prov_oob_info_t oob_info)775 static void pb_gatt_unprovisioned(uint8_t uuid[16],
776 				  bt_mesh_prov_oob_info_t oob_info)
777 {
778 	char uuid_hex_str[32 + 1];
779 
780 	bin2hex(uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
781 
782 	bt_shell_print("PB-GATT UUID %s, OOB Info 0x%04x", uuid_hex_str, oob_info);
783 }
784 #endif
785 
cmd_beacon_listen(const struct shell * sh,size_t argc,char * argv[])786 static int cmd_beacon_listen(const struct shell *sh, size_t argc,
787 			     char *argv[])
788 {
789 	int err = 0;
790 	bool val = shell_strtobool(argv[1], 0, &err);
791 
792 	if (err) {
793 		shell_warn(sh, "Unable to parse input string argument");
794 		return err;
795 	}
796 
797 	if (!bt_mesh_is_provisioned()) {
798 		shell_error(sh, "Not yet provisioned");
799 		return -EINVAL;
800 	}
801 
802 	if (val) {
803 		bt_mesh_shell_prov.unprovisioned_beacon = print_unprovisioned_beacon;
804 #if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
805 		bt_mesh_shell_prov.unprovisioned_beacon_gatt = pb_gatt_unprovisioned;
806 #endif
807 	} else {
808 		bt_mesh_shell_prov.unprovisioned_beacon = NULL;
809 		bt_mesh_shell_prov.unprovisioned_beacon_gatt = NULL;
810 	}
811 
812 	return 0;
813 }
814 #endif /* CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE */
815 
816 #if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
cmd_provision_gatt(const struct shell * sh,size_t argc,char * argv[])817 static int cmd_provision_gatt(const struct shell *sh, size_t argc,
818 			      char *argv[])
819 {
820 	static uint8_t uuid[16];
821 	uint8_t attention_duration;
822 	uint16_t net_idx;
823 	uint16_t addr;
824 	size_t len;
825 	int err = 0;
826 
827 	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
828 	(void)memset(uuid + len, 0, sizeof(uuid) - len);
829 
830 	net_idx = shell_strtoul(argv[2], 0, &err);
831 	addr = shell_strtoul(argv[3], 0, &err);
832 	attention_duration = shell_strtoul(argv[4], 0, &err);
833 	if (err) {
834 		shell_warn(sh, "Unable to parse input string argument");
835 		return err;
836 	}
837 
838 	err = bt_mesh_provision_gatt(uuid, net_idx, addr, attention_duration);
839 	if (err) {
840 		shell_error(sh, "Provisioning failed (err %d)", err);
841 	}
842 
843 	return 0;
844 }
845 #endif /* CONFIG_BT_MESH_PB_GATT_CLIENT */
846 
847 #if defined(CONFIG_BT_MESH_PROVISIONEE)
cmd_pb(bt_mesh_prov_bearer_t bearer,const struct shell * sh,size_t argc,char * argv[])848 static int cmd_pb(bt_mesh_prov_bearer_t bearer, const struct shell *sh,
849 		  size_t argc, char *argv[])
850 {
851 	int err = 0;
852 	bool onoff;
853 
854 	if (argc < 2) {
855 		return -EINVAL;
856 	}
857 
858 	onoff = shell_strtobool(argv[1], 0, &err);
859 	if (err) {
860 		shell_warn(sh, "Unable to parse input string argument");
861 		return err;
862 	}
863 
864 	if (onoff) {
865 		err = bt_mesh_prov_enable(bearer);
866 		if (err) {
867 			shell_error(sh, "Failed to enable %s (err %d)",
868 				    bearer2str(bearer), err);
869 		} else {
870 			shell_print(sh, "%s enabled", bearer2str(bearer));
871 		}
872 	} else {
873 		err = bt_mesh_prov_disable(bearer);
874 		if (err) {
875 			shell_error(sh, "Failed to disable %s (err %d)",
876 				    bearer2str(bearer), err);
877 		} else {
878 			shell_print(sh, "%s disabled", bearer2str(bearer));
879 		}
880 	}
881 
882 	return 0;
883 }
884 
885 #if defined(CONFIG_BT_MESH_PB_ADV)
cmd_pb_adv(const struct shell * sh,size_t argc,char * argv[])886 static int cmd_pb_adv(const struct shell *sh, size_t argc, char *argv[])
887 {
888 	return cmd_pb(BT_MESH_PROV_ADV, sh, argc, argv);
889 }
890 #endif /* CONFIG_BT_MESH_PB_ADV */
891 
892 #if defined(CONFIG_BT_MESH_PB_GATT)
cmd_pb_gatt(const struct shell * sh,size_t argc,char * argv[])893 static int cmd_pb_gatt(const struct shell *sh, size_t argc, char *argv[])
894 {
895 	return cmd_pb(BT_MESH_PROV_GATT, sh, argc, argv);
896 }
897 #endif /* CONFIG_BT_MESH_PB_GATT */
898 #endif /* CONFIG_BT_MESH_PROVISIONEE */
899 
900 #if defined(CONFIG_BT_MESH_PROVISIONER)
cmd_remote_pub_key_set(const struct shell * sh,size_t argc,char * argv[])901 static int cmd_remote_pub_key_set(const struct shell *sh, size_t argc, char *argv[])
902 {
903 	size_t len;
904 	uint8_t pub_key[64];
905 	int err = 0;
906 
907 	len = hex2bin(argv[1], strlen(argv[1]), pub_key, sizeof(pub_key));
908 	if (len < 1) {
909 		shell_warn(sh, "Unable to parse input string argument");
910 		return -EINVAL;
911 	}
912 
913 	err = bt_mesh_prov_remote_pub_key_set(pub_key);
914 
915 	if (err) {
916 		shell_error(sh, "Setting remote pub key failed (err %d)", err);
917 	}
918 
919 	return 0;
920 }
921 
cmd_auth_method_set_input(const struct shell * sh,size_t argc,char * argv[])922 static int cmd_auth_method_set_input(const struct shell *sh, size_t argc, char *argv[])
923 {
924 	int err = 0;
925 	bt_mesh_input_action_t action = shell_strtoul(argv[1], 10, &err);
926 	uint8_t size = shell_strtoul(argv[2], 10, &err);
927 
928 	if (err) {
929 		shell_warn(sh, "Unable to parse input string argument");
930 		return err;
931 	}
932 
933 	err = bt_mesh_auth_method_set_input(action, size);
934 	if (err) {
935 		shell_error(sh, "Setting input OOB authentication action failed (err %d)", err);
936 	}
937 
938 	return 0;
939 }
940 
cmd_auth_method_set_output(const struct shell * sh,size_t argc,char * argv[])941 static int cmd_auth_method_set_output(const struct shell *sh, size_t argc, char *argv[])
942 {
943 	int err = 0;
944 	bt_mesh_output_action_t action = shell_strtoul(argv[1], 10, &err);
945 	uint8_t size = shell_strtoul(argv[2], 10, &err);
946 
947 	if (err) {
948 		shell_warn(sh, "Unable to parse input string argument");
949 		return err;
950 	}
951 
952 	err = bt_mesh_auth_method_set_output(action, size);
953 	if (err) {
954 		shell_error(sh, "Setting output OOB authentication action failed (err %d)", err);
955 	}
956 	return 0;
957 }
958 
cmd_auth_method_set_static(const struct shell * sh,size_t argc,char * argv[])959 static int cmd_auth_method_set_static(const struct shell *sh, size_t argc, char *argv[])
960 {
961 	size_t len;
962 	uint8_t static_oob_auth[32];
963 	int err = 0;
964 
965 	len = hex2bin(argv[1], strlen(argv[1]), static_oob_auth, sizeof(static_oob_auth));
966 	if (len < 1) {
967 		shell_warn(sh, "Unable to parse input string argument");
968 		return -EINVAL;
969 	}
970 
971 	err = bt_mesh_auth_method_set_static(static_oob_auth, len);
972 	if (err) {
973 		shell_error(sh, "Setting static OOB authentication failed (err %d)", err);
974 	}
975 	return 0;
976 }
977 
cmd_auth_method_set_none(const struct shell * sh,size_t argc,char * argv[])978 static int cmd_auth_method_set_none(const struct shell *sh, size_t argc, char *argv[])
979 {
980 	int err = bt_mesh_auth_method_set_none();
981 
982 	if (err) {
983 		shell_error(sh, "Disabling authentication failed (err %d)", err);
984 	}
985 	return 0;
986 }
987 
cmd_provision_adv(const struct shell * sh,size_t argc,char * argv[])988 static int cmd_provision_adv(const struct shell *sh, size_t argc,
989 			     char *argv[])
990 {
991 	uint8_t uuid[16];
992 	uint8_t attention_duration;
993 	uint16_t net_idx;
994 	uint16_t addr;
995 	size_t len;
996 	int err = 0;
997 
998 	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
999 	(void)memset(uuid + len, 0, sizeof(uuid) - len);
1000 
1001 	net_idx = shell_strtoul(argv[2], 0, &err);
1002 	addr = shell_strtoul(argv[3], 0, &err);
1003 	attention_duration = shell_strtoul(argv[4], 0, &err);
1004 	if (err) {
1005 		shell_warn(sh, "Unable to parse input string argument");
1006 		return err;
1007 	}
1008 
1009 	err = bt_mesh_provision_adv(uuid, net_idx, addr, attention_duration);
1010 	if (err) {
1011 		shell_error(sh, "Provisioning failed (err %d)", err);
1012 	}
1013 
1014 	return 0;
1015 }
1016 #endif /* CONFIG_BT_MESH_PROVISIONER */
1017 
cmd_provision_local(const struct shell * sh,size_t argc,char * argv[])1018 static int cmd_provision_local(const struct shell *sh, size_t argc, char *argv[])
1019 {
1020 	uint8_t net_key[16];
1021 	uint16_t net_idx, addr;
1022 	uint32_t iv_index;
1023 	int err = 0;
1024 
1025 	net_idx = shell_strtoul(argv[1], 0, &err);
1026 	addr = shell_strtoul(argv[2], 0, &err);
1027 
1028 	if (argc > 3) {
1029 		iv_index = shell_strtoul(argv[3], 0, &err);
1030 	} else {
1031 		iv_index = 0U;
1032 	}
1033 
1034 	if (err) {
1035 		shell_warn(sh, "Unable to parse input string argument");
1036 		return err;
1037 	}
1038 
1039 	memcpy(net_key, bt_mesh_shell_default_key, sizeof(net_key));
1040 
1041 	if (IS_ENABLED(CONFIG_BT_MESH_CDB)) {
1042 		struct bt_mesh_cdb_subnet *sub;
1043 
1044 		sub = bt_mesh_cdb_subnet_get(net_idx);
1045 		if (!sub) {
1046 			shell_error(sh, "No cdb entry for subnet 0x%03x", net_idx);
1047 			return 0;
1048 		}
1049 
1050 		if (bt_mesh_cdb_subnet_key_export(sub, SUBNET_KEY_TX_IDX(sub), net_key)) {
1051 			shell_error(sh, "Unable to export key for subnet 0x%03x", net_idx);
1052 			return 0;
1053 		}
1054 	}
1055 
1056 	err = bt_mesh_provision(net_key, net_idx, 0, iv_index, addr, bt_mesh_shell_default_key);
1057 	if (err) {
1058 		shell_error(sh, "Provisioning failed (err %d)", err);
1059 	}
1060 
1061 	return 0;
1062 }
1063 
cmd_comp_change(const struct shell * sh,size_t argc,char * argv[])1064 static int cmd_comp_change(const struct shell *sh, size_t argc, char *argv[])
1065 {
1066 	bt_mesh_comp_change_prepare();
1067 	return 0;
1068 }
1069 #endif /* CONFIG_BT_MESH_SHELL_PROV */
1070 
1071 #if defined(CONFIG_BT_MESH_SHELL_TEST)
cmd_net_send(const struct shell * sh,size_t argc,char * argv[])1072 static int cmd_net_send(const struct shell *sh, size_t argc, char *argv[])
1073 {
1074 	NET_BUF_SIMPLE_DEFINE(msg, 32);
1075 
1076 	struct bt_mesh_msg_ctx ctx = BT_MESH_MSG_CTX_INIT(bt_mesh_shell_target_ctx.net_idx,
1077 							  bt_mesh_shell_target_ctx.app_idx,
1078 							  bt_mesh_shell_target_ctx.dst,
1079 							  BT_MESH_TTL_DEFAULT);
1080 	struct bt_mesh_net_tx tx = {
1081 		.ctx = &ctx,
1082 		.src = bt_mesh_primary_addr(),
1083 	};
1084 
1085 	size_t len;
1086 	int err;
1087 
1088 	len = hex2bin(argv[1], strlen(argv[1]),
1089 		      msg.data, net_buf_simple_tailroom(&msg) - 4);
1090 	net_buf_simple_add(&msg, len);
1091 
1092 	err = bt_mesh_trans_send(&tx, &msg, NULL, NULL);
1093 	if (err) {
1094 		shell_error(sh, "Failed to send (err %d)", err);
1095 	}
1096 
1097 	return 0;
1098 }
1099 
1100 #if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
cmd_iv_update(const struct shell * sh,size_t argc,char * argv[])1101 static int cmd_iv_update(const struct shell *sh, size_t argc, char *argv[])
1102 {
1103 	if (bt_mesh_iv_update()) {
1104 		shell_print(sh, "Transitioned to IV Update In Progress "
1105 			    "state");
1106 	} else {
1107 		shell_print(sh, "Transitioned to IV Update Normal state");
1108 	}
1109 
1110 	shell_print(sh, "IV Index is 0x%08x", bt_mesh.iv_index);
1111 
1112 	return 0;
1113 }
1114 
cmd_iv_update_test(const struct shell * sh,size_t argc,char * argv[])1115 static int cmd_iv_update_test(const struct shell *sh, size_t argc,
1116 			      char *argv[])
1117 {
1118 	int err = 0;
1119 	bool enable;
1120 
1121 	enable = shell_strtobool(argv[1], 0, &err);
1122 	if (err) {
1123 		shell_warn(sh, "Unable to parse input string argument");
1124 		return err;
1125 	}
1126 
1127 	if (enable) {
1128 		shell_print(sh, "Enabling IV Update test mode");
1129 	} else {
1130 		shell_print(sh, "Disabling IV Update test mode");
1131 	}
1132 
1133 	bt_mesh_iv_update_test(enable);
1134 
1135 	return 0;
1136 }
1137 #endif /* CONFIG_BT_MESH_IV_UPDATE_TEST */
1138 
cmd_rpl_clear(const struct shell * sh,size_t argc,char * argv[])1139 static int cmd_rpl_clear(const struct shell *sh, size_t argc, char *argv[])
1140 {
1141 	bt_mesh_rpl_clear();
1142 	return 0;
1143 }
1144 
1145 #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE)
primary_element(void)1146 static const struct bt_mesh_elem *primary_element(void)
1147 {
1148 	const struct bt_mesh_comp *comp = bt_mesh_comp_get();
1149 
1150 	if (comp) {
1151 		return &comp->elem[0];
1152 	}
1153 
1154 	return NULL;
1155 }
1156 
cmd_add_fault(const struct shell * sh,size_t argc,char * argv[])1157 static int cmd_add_fault(const struct shell *sh, size_t argc, char *argv[])
1158 {
1159 	uint8_t fault_id;
1160 	uint8_t i;
1161 	const struct bt_mesh_elem *elem;
1162 	int err = 0;
1163 
1164 	elem = primary_element();
1165 	if (elem == NULL) {
1166 		shell_print(sh, "Element not found!");
1167 		return -EINVAL;
1168 	}
1169 
1170 	fault_id = shell_strtoul(argv[1], 0, &err);
1171 	if (err) {
1172 		shell_warn(sh, "Unable to parse input string argument");
1173 		return err;
1174 	}
1175 
1176 	if (!fault_id) {
1177 		shell_print(sh, "The Fault ID must be non-zero!");
1178 		return -EINVAL;
1179 	}
1180 
1181 	for (i = 0U; i < sizeof(cur_faults); i++) {
1182 		if (!cur_faults[i]) {
1183 			cur_faults[i] = fault_id;
1184 			break;
1185 		}
1186 	}
1187 
1188 	if (i == sizeof(cur_faults)) {
1189 		shell_print(sh, "Fault array is full. Use \"del-fault\" to "
1190 			    "clear it");
1191 		return 0;
1192 	}
1193 
1194 	for (i = 0U; i < sizeof(reg_faults); i++) {
1195 		if (!reg_faults[i]) {
1196 			reg_faults[i] = fault_id;
1197 			break;
1198 		}
1199 	}
1200 
1201 	if (i == sizeof(reg_faults)) {
1202 		shell_print(sh, "No space to store more registered faults");
1203 	}
1204 
1205 	bt_mesh_health_srv_fault_update(elem);
1206 
1207 	return 0;
1208 }
1209 
cmd_del_fault(const struct shell * sh,size_t argc,char * argv[])1210 static int cmd_del_fault(const struct shell *sh, size_t argc, char *argv[])
1211 {
1212 	uint8_t fault_id;
1213 	uint8_t i;
1214 	const struct bt_mesh_elem *elem;
1215 	int err = 0;
1216 
1217 	elem = primary_element();
1218 	if (elem == NULL) {
1219 		shell_print(sh, "Element not found!");
1220 		return -EINVAL;
1221 	}
1222 
1223 	if (argc < 2) {
1224 		(void)memset(cur_faults, 0, sizeof(cur_faults));
1225 		shell_print(sh, "All current faults cleared");
1226 		bt_mesh_health_srv_fault_update(elem);
1227 		return 0;
1228 	}
1229 
1230 	fault_id = shell_strtoul(argv[1], 0, &err);
1231 	if (err) {
1232 		shell_warn(sh, "Unable to parse input string argument");
1233 		return err;
1234 	}
1235 
1236 	if (!fault_id) {
1237 		shell_print(sh, "The Fault ID must be non-zero!");
1238 		return -EINVAL;
1239 	}
1240 
1241 	for (i = 0U; i < sizeof(cur_faults); i++) {
1242 		if (cur_faults[i] == fault_id) {
1243 			cur_faults[i] = 0U;
1244 			shell_print(sh, "Fault cleared");
1245 		}
1246 	}
1247 
1248 	bt_mesh_health_srv_fault_update(elem);
1249 
1250 	return 0;
1251 }
1252 #endif /* CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE */
1253 #endif /* CONFIG_BT_MESH_SHELL_TEST */
1254 
1255 #if defined(CONFIG_BT_MESH_SHELL_CDB)
cmd_cdb_create(const struct shell * sh,size_t argc,char * argv[])1256 static int cmd_cdb_create(const struct shell *sh, size_t argc,
1257 			  char *argv[])
1258 {
1259 	uint8_t net_key[16];
1260 	size_t len;
1261 	int err;
1262 
1263 	if (argc < 2) {
1264 		bt_rand(net_key, 16);
1265 	} else {
1266 		len = hex2bin(argv[1], strlen(argv[1]), net_key,
1267 			      sizeof(net_key));
1268 		memset(net_key + len, 0, sizeof(net_key) - len);
1269 	}
1270 
1271 	err = bt_mesh_cdb_create(net_key);
1272 	if (err < 0) {
1273 		shell_print(sh, "Failed to create CDB (err %d)", err);
1274 	}
1275 
1276 	return 0;
1277 }
1278 
cmd_cdb_clear(const struct shell * sh,size_t argc,char * argv[])1279 static int cmd_cdb_clear(const struct shell *sh, size_t argc,
1280 			 char *argv[])
1281 {
1282 	bt_mesh_cdb_clear();
1283 
1284 	shell_print(sh, "Cleared CDB");
1285 
1286 	return 0;
1287 }
1288 
cdb_print_nodes(const struct shell * sh)1289 static void cdb_print_nodes(const struct shell *sh)
1290 {
1291 	char key_hex_str[32 + 1], uuid_hex_str[32 + 1];
1292 	struct bt_mesh_cdb_node *node;
1293 	int i, total = 0;
1294 	bool configured;
1295 	uint8_t dev_key[16];
1296 
1297 	shell_print(sh, "Address  Elements  Flags  %-32s  DevKey", "UUID");
1298 
1299 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.nodes); ++i) {
1300 		node = &bt_mesh_cdb.nodes[i];
1301 		if (node->addr == BT_MESH_ADDR_UNASSIGNED) {
1302 			continue;
1303 		}
1304 
1305 		configured = atomic_test_bit(node->flags,
1306 					     BT_MESH_CDB_NODE_CONFIGURED);
1307 
1308 		total++;
1309 		bin2hex(node->uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));
1310 		if (bt_mesh_cdb_node_key_export(node, dev_key)) {
1311 			shell_error(sh, "Unable to export key for node 0x%04x", node->addr);
1312 			continue;
1313 		}
1314 		bin2hex(dev_key, 16, key_hex_str, sizeof(key_hex_str));
1315 		shell_print(sh, "0x%04x   %-8d  %-5s  %s  %s", node->addr,
1316 			    node->num_elem, configured ? "C" : "-",
1317 			    uuid_hex_str, key_hex_str);
1318 	}
1319 
1320 	shell_print(sh, "> Total nodes: %d", total);
1321 }
1322 
cdb_print_subnets(const struct shell * sh)1323 static void cdb_print_subnets(const struct shell *sh)
1324 {
1325 	struct bt_mesh_cdb_subnet *subnet;
1326 	char key_hex_str[32 + 1];
1327 	int i, total = 0;
1328 	uint8_t net_key[16];
1329 
1330 	shell_print(sh, "NetIdx  NetKey");
1331 
1332 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) {
1333 		subnet = &bt_mesh_cdb.subnets[i];
1334 		if (subnet->net_idx == BT_MESH_KEY_UNUSED) {
1335 			continue;
1336 		}
1337 
1338 		if (bt_mesh_cdb_subnet_key_export(subnet, 0, net_key)) {
1339 			shell_error(sh, "Unable to export key for subnet 0x%03x",
1340 					subnet->net_idx);
1341 			continue;
1342 		}
1343 
1344 		total++;
1345 		bin2hex(net_key, 16, key_hex_str, sizeof(key_hex_str));
1346 		shell_print(sh, "0x%03x   %s", subnet->net_idx, key_hex_str);
1347 	}
1348 
1349 	shell_print(sh, "> Total subnets: %d", total);
1350 }
1351 
cdb_print_app_keys(const struct shell * sh)1352 static void cdb_print_app_keys(const struct shell *sh)
1353 {
1354 	struct bt_mesh_cdb_app_key *key;
1355 	char key_hex_str[32 + 1];
1356 	int i, total = 0;
1357 	uint8_t app_key[16];
1358 
1359 	shell_print(sh, "NetIdx  AppIdx  AppKey");
1360 
1361 	for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) {
1362 		key = &bt_mesh_cdb.app_keys[i];
1363 		if (key->net_idx == BT_MESH_KEY_UNUSED) {
1364 			continue;
1365 		}
1366 
1367 		if (bt_mesh_cdb_app_key_export(key, 0, app_key)) {
1368 			shell_error(sh, "Unable to export app key 0x%03x", key->app_idx);
1369 			continue;
1370 		}
1371 
1372 		total++;
1373 		bin2hex(app_key, 16, key_hex_str, sizeof(key_hex_str));
1374 		shell_print(sh, "0x%03x   0x%03x   %s", key->net_idx, key->app_idx, key_hex_str);
1375 	}
1376 
1377 	shell_print(sh, "> Total app-keys: %d", total);
1378 }
1379 
cmd_cdb_show(const struct shell * sh,size_t argc,char * argv[])1380 static int cmd_cdb_show(const struct shell *sh, size_t argc,
1381 			char *argv[])
1382 {
1383 	if (!atomic_test_bit(bt_mesh_cdb.flags, BT_MESH_CDB_VALID)) {
1384 		shell_print(sh, "No valid networks");
1385 		return 0;
1386 	}
1387 
1388 	shell_print(sh, "Mesh Network Information");
1389 	shell_print(sh, "========================");
1390 
1391 	cdb_print_nodes(sh);
1392 	shell_print(sh, "---");
1393 	cdb_print_subnets(sh);
1394 	shell_print(sh, "---");
1395 	cdb_print_app_keys(sh);
1396 
1397 	return 0;
1398 }
1399 
cmd_cdb_node_add(const struct shell * sh,size_t argc,char * argv[])1400 static int cmd_cdb_node_add(const struct shell *sh, size_t argc,
1401 			    char *argv[])
1402 {
1403 	struct bt_mesh_cdb_node *node;
1404 	uint8_t uuid[16], dev_key[16];
1405 	uint16_t addr, net_idx;
1406 	uint8_t num_elem;
1407 	size_t len;
1408 	int err = 0;
1409 
1410 	len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
1411 	memset(uuid + len, 0, sizeof(uuid) - len);
1412 
1413 	addr = shell_strtoul(argv[2], 0, &err);
1414 	num_elem = shell_strtoul(argv[3], 0, &err);
1415 	net_idx = shell_strtoul(argv[4], 0, &err);
1416 	if (err) {
1417 		shell_warn(sh, "Unable to parse input string argument");
1418 		return err;
1419 	}
1420 
1421 	if (argc < 6) {
1422 		bt_rand(dev_key, 16);
1423 	} else {
1424 		len = hex2bin(argv[5], strlen(argv[5]), dev_key,
1425 			      sizeof(dev_key));
1426 		memset(dev_key + len, 0, sizeof(dev_key) - len);
1427 	}
1428 
1429 	node = bt_mesh_cdb_node_alloc(uuid, addr, num_elem, net_idx);
1430 	if (node == NULL) {
1431 		shell_print(sh, "Failed to allocate node");
1432 		return 0;
1433 	}
1434 
1435 	err = bt_mesh_cdb_node_key_import(node, dev_key);
1436 	if (err) {
1437 		shell_warn(sh, "Unable to import device key into cdb");
1438 		return err;
1439 	}
1440 
1441 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
1442 		bt_mesh_cdb_node_store(node);
1443 	}
1444 
1445 	shell_print(sh, "Added node 0x%04x", node->addr);
1446 
1447 	return 0;
1448 }
1449 
cmd_cdb_node_del(const struct shell * sh,size_t argc,char * argv[])1450 static int cmd_cdb_node_del(const struct shell *sh, size_t argc,
1451 			    char *argv[])
1452 {
1453 	struct bt_mesh_cdb_node *node;
1454 	uint16_t addr;
1455 	int err = 0;
1456 
1457 	addr = shell_strtoul(argv[1], 0, &err);
1458 	if (err) {
1459 		shell_warn(sh, "Unable to parse input string argument");
1460 		return err;
1461 	}
1462 
1463 	node = bt_mesh_cdb_node_get(addr);
1464 	if (node == NULL) {
1465 		shell_print(sh, "No node with address 0x%04x", addr);
1466 		return 0;
1467 	}
1468 
1469 	bt_mesh_cdb_node_del(node, true);
1470 
1471 	shell_print(sh, "Deleted node 0x%04x", addr);
1472 
1473 	return 0;
1474 }
1475 
cmd_cdb_subnet_add(const struct shell * sh,size_t argc,char * argv[])1476 static int cmd_cdb_subnet_add(const struct shell *sh, size_t argc,
1477 			     char *argv[])
1478 {
1479 	struct bt_mesh_cdb_subnet *sub;
1480 	uint8_t net_key[16];
1481 	uint16_t net_idx;
1482 	size_t len;
1483 	int err = 0;
1484 
1485 	net_idx = shell_strtoul(argv[1], 0, &err);
1486 	if (err) {
1487 		shell_warn(sh, "Unable to parse input string argument");
1488 		return err;
1489 	}
1490 
1491 	if (argc < 3) {
1492 		bt_rand(net_key, 16);
1493 	} else {
1494 		len = hex2bin(argv[2], strlen(argv[2]), net_key,
1495 			      sizeof(net_key));
1496 		memset(net_key + len, 0, sizeof(net_key) - len);
1497 	}
1498 
1499 	sub = bt_mesh_cdb_subnet_alloc(net_idx);
1500 	if (sub == NULL) {
1501 		shell_print(sh, "Could not add subnet");
1502 		return 0;
1503 	}
1504 
1505 	if (bt_mesh_cdb_subnet_key_import(sub, 0, net_key)) {
1506 		shell_error(sh, "Unable to import key for subnet 0x%03x", net_idx);
1507 		return 0;
1508 	}
1509 
1510 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
1511 		bt_mesh_cdb_subnet_store(sub);
1512 	}
1513 
1514 	shell_print(sh, "Added Subnet 0x%03x", net_idx);
1515 
1516 	return 0;
1517 }
1518 
cmd_cdb_subnet_del(const struct shell * sh,size_t argc,char * argv[])1519 static int cmd_cdb_subnet_del(const struct shell *sh, size_t argc,
1520 			     char *argv[])
1521 {
1522 	struct bt_mesh_cdb_subnet *sub;
1523 	uint16_t net_idx;
1524 	int err = 0;
1525 
1526 	net_idx = shell_strtoul(argv[1], 0, &err);
1527 	if (err) {
1528 		shell_warn(sh, "Unable to parse input string argument");
1529 		return err;
1530 	}
1531 
1532 	sub = bt_mesh_cdb_subnet_get(net_idx);
1533 	if (sub == NULL) {
1534 		shell_print(sh, "No subnet with NetIdx 0x%03x", net_idx);
1535 		return 0;
1536 	}
1537 
1538 	bt_mesh_cdb_subnet_del(sub, true);
1539 
1540 	shell_print(sh, "Deleted subnet 0x%03x", net_idx);
1541 
1542 	return 0;
1543 }
1544 
cmd_cdb_app_key_add(const struct shell * sh,size_t argc,char * argv[])1545 static int cmd_cdb_app_key_add(const struct shell *sh, size_t argc,
1546 			      char *argv[])
1547 {
1548 	struct bt_mesh_cdb_app_key *key;
1549 	uint16_t net_idx, app_idx;
1550 	uint8_t app_key[16];
1551 	size_t len;
1552 	int err = 0;
1553 
1554 	net_idx = shell_strtoul(argv[1], 0, &err);
1555 	app_idx = shell_strtoul(argv[2], 0, &err);
1556 	if (err) {
1557 		shell_warn(sh, "Unable to parse input string argument");
1558 		return err;
1559 	}
1560 
1561 	if (argc < 4) {
1562 		bt_rand(app_key, 16);
1563 	} else {
1564 		len = hex2bin(argv[3], strlen(argv[3]), app_key,
1565 			      sizeof(app_key));
1566 		memset(app_key + len, 0, sizeof(app_key) - len);
1567 	}
1568 
1569 	key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
1570 	if (key == NULL) {
1571 		shell_print(sh, "Could not add AppKey");
1572 		return 0;
1573 	}
1574 
1575 	if (bt_mesh_cdb_app_key_import(key, 0, app_key)) {
1576 		shell_error(sh, "Unable to import app key 0x%03x", app_idx);
1577 		return 0;
1578 	}
1579 
1580 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
1581 		bt_mesh_cdb_app_key_store(key);
1582 	}
1583 
1584 	shell_print(sh, "Added AppKey 0x%03x", app_idx);
1585 
1586 	return 0;
1587 }
1588 
cmd_cdb_app_key_del(const struct shell * sh,size_t argc,char * argv[])1589 static int cmd_cdb_app_key_del(const struct shell *sh, size_t argc,
1590 			      char *argv[])
1591 {
1592 	struct bt_mesh_cdb_app_key *key;
1593 	uint16_t app_idx;
1594 	int err = 0;
1595 
1596 	app_idx = shell_strtoul(argv[1], 0, &err);
1597 	if (err) {
1598 		shell_warn(sh, "Unable to parse input string argument");
1599 		return err;
1600 	}
1601 
1602 	key = bt_mesh_cdb_app_key_get(app_idx);
1603 	if (key == NULL) {
1604 		shell_print(sh, "No AppKey 0x%03x", app_idx);
1605 		return 0;
1606 	}
1607 
1608 	bt_mesh_cdb_app_key_del(key, true);
1609 
1610 	shell_print(sh, "Deleted AppKey 0x%03x", app_idx);
1611 
1612 	return 0;
1613 }
1614 #endif /* CONFIG_BT_MESH_SHELL_CDB */
1615 
cmd_dst(const struct shell * sh,size_t argc,char * argv[])1616 static int cmd_dst(const struct shell *sh, size_t argc, char *argv[])
1617 {
1618 	int err = 0;
1619 
1620 	if (argc < 2) {
1621 		shell_print(sh, "Destination address: 0x%04x%s", bt_mesh_shell_target_ctx.dst,
1622 			    bt_mesh_shell_target_ctx.dst == bt_mesh_primary_addr()
1623 				    ? " (local)"
1624 				    : "");
1625 		return 0;
1626 	}
1627 
1628 	if (!strcmp(argv[1], "local")) {
1629 		bt_mesh_shell_target_ctx.dst = bt_mesh_primary_addr();
1630 	} else {
1631 		bt_mesh_shell_target_ctx.dst = shell_strtoul(argv[1], 0, &err);
1632 		if (err) {
1633 			shell_warn(sh, "Unable to parse input string argument");
1634 			return err;
1635 		}
1636 	}
1637 
1638 	shell_print(sh, "Destination address set to 0x%04x%s", bt_mesh_shell_target_ctx.dst,
1639 		    bt_mesh_shell_target_ctx.dst == bt_mesh_primary_addr() ? " (local)"
1640 										   : "");
1641 	return 0;
1642 }
1643 
cmd_netidx(const struct shell * sh,size_t argc,char * argv[])1644 static int cmd_netidx(const struct shell *sh, size_t argc, char *argv[])
1645 {
1646 	int err = 0;
1647 
1648 	if (argc < 2) {
1649 		shell_print(sh, "NetIdx: 0x%04x", bt_mesh_shell_target_ctx.net_idx);
1650 		return 0;
1651 	}
1652 
1653 	bt_mesh_shell_target_ctx.net_idx = shell_strtoul(argv[1], 0, &err);
1654 	if (err) {
1655 		shell_warn(sh, "Unable to parse input string argument");
1656 		return err;
1657 	}
1658 
1659 	shell_print(sh, "NetIdx set to 0x%04x", bt_mesh_shell_target_ctx.net_idx);
1660 	return 0;
1661 }
1662 
cmd_appidx(const struct shell * sh,size_t argc,char * argv[])1663 static int cmd_appidx(const struct shell *sh, size_t argc, char *argv[])
1664 {
1665 	int err = 0;
1666 
1667 	if (argc < 2) {
1668 		shell_print(sh, "AppIdx: 0x%04x", bt_mesh_shell_target_ctx.app_idx);
1669 		return 0;
1670 	}
1671 
1672 	bt_mesh_shell_target_ctx.app_idx = shell_strtoul(argv[1], 0, &err);
1673 	if (err) {
1674 		shell_warn(sh, "Unable to parse input string argument");
1675 		return err;
1676 	}
1677 
1678 	shell_print(sh, "AppIdx set to 0x%04x", bt_mesh_shell_target_ctx.app_idx);
1679 	return 0;
1680 }
1681 
1682 #if defined(CONFIG_BT_MESH_STATISTIC)
cmd_stat_get(const struct shell * sh,size_t argc,char * argv[])1683 static int cmd_stat_get(const struct shell *sh, size_t argc, char *argv[])
1684 {
1685 	struct bt_mesh_statistic st;
1686 
1687 	bt_mesh_stat_get(&st);
1688 
1689 	shell_print(sh, "Received frames over:");
1690 	shell_print(sh, "adv:       %d", st.rx_adv);
1691 	shell_print(sh, "loopback:  %d", st.rx_loopback);
1692 	shell_print(sh, "proxy:     %d", st.rx_proxy);
1693 	shell_print(sh, "unknown:   %d", st.rx_uknown);
1694 
1695 	shell_print(sh, "Transmitted frames: <planned> - <succeeded>");
1696 	shell_print(sh, "relay adv:   %d - %d", st.tx_adv_relay_planned, st.tx_adv_relay_succeeded);
1697 	shell_print(sh, "local adv:   %d - %d", st.tx_local_planned, st.tx_local_succeeded);
1698 	shell_print(sh, "friend:      %d - %d", st.tx_friend_planned, st.tx_friend_succeeded);
1699 
1700 	return 0;
1701 }
1702 
cmd_stat_clear(const struct shell * sh,size_t argc,char * argv[])1703 static int cmd_stat_clear(const struct shell *sh, size_t argc, char *argv[])
1704 {
1705 	bt_mesh_stat_reset();
1706 
1707 	return 0;
1708 }
1709 #endif
1710 
1711 #if defined(CONFIG_BT_MESH_SHELL_CDB)
1712 SHELL_STATIC_SUBCMD_SET_CREATE(
1713 	cdb_cmds,
1714 	/* Mesh Configuration Database Operations */
1715 	SHELL_CMD_ARG(create, NULL, "[NetKey(1-16 hex)]", cmd_cdb_create, 1, 1),
1716 	SHELL_CMD_ARG(clear, NULL, NULL, cmd_cdb_clear, 1, 0),
1717 	SHELL_CMD_ARG(show, NULL, NULL, cmd_cdb_show, 1, 0),
1718 	SHELL_CMD_ARG(node-add, NULL,
1719 		      "<UUID(1-16 hex)> <Addr> <ElemCnt> <NetKeyIdx> [DevKey(1-16 hex)]",
1720 		      cmd_cdb_node_add, 5, 1),
1721 	SHELL_CMD_ARG(node-del, NULL, "<Addr>", cmd_cdb_node_del, 2, 0),
1722 	SHELL_CMD_ARG(subnet-add, NULL, "<NetKeyIdx> [<NetKey(1-16 hex)>]", cmd_cdb_subnet_add, 2,
1723 		      1),
1724 	SHELL_CMD_ARG(subnet-del, NULL, "<NetKeyIdx>", cmd_cdb_subnet_del, 2, 0),
1725 	SHELL_CMD_ARG(app-key-add, NULL, "<NetKeyIdx> <AppKeyIdx> [<AppKey(1-16 hex)>]",
1726 		      cmd_cdb_app_key_add, 3, 1),
1727 	SHELL_CMD_ARG(app-key-del, NULL, "<AppKeyIdx>", cmd_cdb_app_key_del, 2, 0),
1728 	SHELL_SUBCMD_SET_END);
1729 #endif
1730 
1731 #if defined(CONFIG_BT_MESH_SHELL_PROV)
1732 #if defined(CONFIG_BT_MESH_PROVISIONER)
1733 SHELL_STATIC_SUBCMD_SET_CREATE(auth_cmds,
1734 	SHELL_CMD_ARG(input, NULL, "<Action> <Size>",
1735 		      cmd_auth_method_set_input, 3, 0),
1736 	SHELL_CMD_ARG(output, NULL, "<Action> <Size>",
1737 		      cmd_auth_method_set_output, 3, 0),
1738 	SHELL_CMD_ARG(static, NULL, "<Val(1-16 hex)>", cmd_auth_method_set_static, 2,
1739 		      0),
1740 	SHELL_CMD_ARG(none, NULL, NULL, cmd_auth_method_set_none, 1, 0),
1741 	SHELL_SUBCMD_SET_END);
1742 #endif
1743 
1744 SHELL_STATIC_SUBCMD_SET_CREATE(
1745 	prov_cmds, SHELL_CMD_ARG(input-num, NULL, "<Number>", cmd_input_num, 2, 0),
1746 	SHELL_CMD_ARG(input-str, NULL, "<String>", cmd_input_str, 2, 0),
1747 	SHELL_CMD_ARG(local, NULL, "<NetKeyIdx> <Addr> [IVI]", cmd_provision_local, 3, 1),
1748 #if defined(CONFIG_BT_MESH_SHELL_PROV_CTX_INSTANCE)
1749 	SHELL_CMD_ARG(static-oob, NULL, "[Val]", cmd_static_oob, 2, 1),
1750 	SHELL_CMD_ARG(uuid, NULL, "[UUID(1-16 hex)]", cmd_uuid, 1, 1),
1751 	SHELL_CMD_ARG(beacon-listen, NULL, "<Val(off, on)>", cmd_beacon_listen, 2, 0),
1752 #endif
1753 
1754 	SHELL_CMD_ARG(comp-change, NULL, NULL, cmd_comp_change, 1, 0),
1755 
1756 /* Provisioning operations */
1757 #if defined(CONFIG_BT_MESH_PROVISIONEE)
1758 #if defined(CONFIG_BT_MESH_PB_GATT)
1759 	SHELL_CMD_ARG(pb-gatt, NULL, "<Val(off, on)>", cmd_pb_gatt, 2, 0),
1760 #endif
1761 #if defined(CONFIG_BT_MESH_PB_ADV)
1762 	SHELL_CMD_ARG(pb-adv, NULL, "<Val(off, on)>", cmd_pb_adv, 2, 0),
1763 #endif
1764 #endif /* CONFIG_BT_MESH_PROVISIONEE */
1765 
1766 #if defined(CONFIG_BT_MESH_PROVISIONER)
1767 	SHELL_CMD(auth-method, &auth_cmds, "Authentication methods", bt_mesh_shell_mdl_cmds_help),
1768 	SHELL_CMD_ARG(remote-pub-key, NULL, "<PubKey>", cmd_remote_pub_key_set, 2, 0),
1769 	SHELL_CMD_ARG(remote-adv, NULL,
1770 		      "<UUID(1-16 hex)> <NetKeyIdx> <Addr> "
1771 		      "<AttDur(s)>",
1772 		      cmd_provision_adv, 5, 0),
1773 #endif
1774 
1775 #if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
1776 	SHELL_CMD_ARG(remote-gatt, NULL,
1777 		      "<UUID(1-16 hex)> <NetKeyIdx> <Addr> "
1778 		      "<AttDur(s)>",
1779 		      cmd_provision_gatt, 5, 0),
1780 #endif
1781 	SHELL_SUBCMD_SET_END);
1782 #endif /* CONFIG_BT_MESH_SHELL_PROV */
1783 
1784 #if defined(CONFIG_BT_MESH_SHELL_TEST)
1785 #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE)
1786 SHELL_STATIC_SUBCMD_SET_CREATE(health_srv_cmds,
1787 	/* Health Server Model Operations */
1788 	SHELL_CMD_ARG(add-fault, NULL, "<FaultID>", cmd_add_fault, 2, 0),
1789 	SHELL_CMD_ARG(del-fault, NULL, "[FaultID]", cmd_del_fault, 1, 1),
1790 	SHELL_SUBCMD_SET_END);
1791 #endif
1792 
1793 SHELL_STATIC_SUBCMD_SET_CREATE(test_cmds,
1794 	/* Commands which access internal APIs, for testing only */
1795 	SHELL_CMD_ARG(net-send, NULL, "<HexString>", cmd_net_send,
1796 		      2, 0),
1797 #if defined(CONFIG_BT_MESH_IV_UPDATE_TEST)
1798 	SHELL_CMD_ARG(iv-update, NULL, NULL, cmd_iv_update, 1, 0),
1799 	SHELL_CMD_ARG(iv-update-test, NULL, "<Val(off, on)>", cmd_iv_update_test, 2, 0),
1800 #endif
1801 	SHELL_CMD_ARG(rpl-clear, NULL, NULL, cmd_rpl_clear, 1, 0),
1802 #if defined(CONFIG_BT_MESH_SHELL_HEALTH_SRV_INSTANCE)
1803 	SHELL_CMD(health-srv, &health_srv_cmds, "Health Server test", bt_mesh_shell_mdl_cmds_help),
1804 #endif
1805 	SHELL_SUBCMD_SET_END);
1806 #endif /* CONFIG_BT_MESH_SHELL_TEST */
1807 
1808 #if defined(CONFIG_BT_MESH_SHELL_GATT_PROXY)
1809 SHELL_STATIC_SUBCMD_SET_CREATE(proxy_cmds,
1810 #if defined(CONFIG_BT_MESH_GATT_PROXY)
1811 	SHELL_CMD_ARG(identity-enable, NULL, NULL, cmd_ident, 1, 0),
1812 #endif
1813 
1814 #if defined(CONFIG_BT_MESH_PROXY_CLIENT)
1815 	SHELL_CMD_ARG(connect, NULL, "<NetKeyIdx>", cmd_proxy_connect, 2, 0),
1816 	SHELL_CMD_ARG(disconnect, NULL, "<NetKeyIdx>", cmd_proxy_disconnect, 2, 0),
1817 #endif
1818 
1819 #if defined(CONFIG_BT_MESH_PROXY_SOLICITATION)
1820 	SHELL_CMD_ARG(solicit, NULL, "<NetKeyIdx>",
1821 		      cmd_proxy_solicit, 2, 0),
1822 #endif
1823 	SHELL_SUBCMD_SET_END);
1824 #endif /* CONFIG_BT_MESH_SHELL_GATT_PROXY */
1825 
1826 #if defined(CONFIG_BT_MESH_SHELL_LOW_POWER)
1827 SHELL_STATIC_SUBCMD_SET_CREATE(low_pwr_cmds,
1828 	SHELL_CMD_ARG(set, NULL, "<Val(off, on)>", cmd_lpn, 2, 0),
1829 	SHELL_CMD_ARG(poll, NULL, NULL, cmd_poll, 1, 0),
1830 	SHELL_SUBCMD_SET_END);
1831 #endif
1832 
1833 SHELL_STATIC_SUBCMD_SET_CREATE(target_cmds,
1834 	SHELL_CMD_ARG(dst, NULL, "[DstAddr]", cmd_dst, 1, 1),
1835 	SHELL_CMD_ARG(net, NULL, "[NetKeyIdx]", cmd_netidx, 1, 1),
1836 	SHELL_CMD_ARG(app, NULL, "[AppKeyIdx]", cmd_appidx, 1, 1),
1837 	SHELL_SUBCMD_SET_END);
1838 
1839 #if defined(CONFIG_BT_MESH_STATISTIC)
1840 SHELL_STATIC_SUBCMD_SET_CREATE(stat_cmds,
1841 	SHELL_CMD_ARG(get, NULL, NULL, cmd_stat_get, 1, 0),
1842 	SHELL_CMD_ARG(clear, NULL, NULL, cmd_stat_clear, 1, 0),
1843 	SHELL_SUBCMD_SET_END);
1844 #endif
1845 
1846 /* Placeholder for model shell modules that is configured in the application */
1847 SHELL_SUBCMD_SET_CREATE(model_cmds, (mesh, models));
1848 
1849 /* List of Mesh subcommands.
1850  *
1851  * Each command is documented in doc/reference/bluetooth/mesh/shell.rst.
1852  *
1853  * Please keep the documentation up to date by adding any new commands to the
1854  * list.
1855  */
1856 SHELL_STATIC_SUBCMD_SET_CREATE(mesh_cmds,
1857 	SHELL_CMD_ARG(init, NULL, NULL, cmd_init, 1, 0),
1858 	SHELL_CMD_ARG(reset-local, NULL, NULL, cmd_reset, 1, 0),
1859 
1860 	SHELL_CMD(models, &model_cmds, "Model commands", bt_mesh_shell_mdl_cmds_help),
1861 
1862 #if defined(CONFIG_BT_MESH_SHELL_LOW_POWER)
1863 	SHELL_CMD(lpn, &low_pwr_cmds, "Low Power commands", bt_mesh_shell_mdl_cmds_help),
1864 #endif
1865 
1866 #if defined(CONFIG_BT_MESH_SHELL_CDB)
1867 	SHELL_CMD(cdb, &cdb_cmds, "Configuration Database", bt_mesh_shell_mdl_cmds_help),
1868 #endif
1869 
1870 #if defined(CONFIG_BT_MESH_SHELL_GATT_PROXY)
1871 	SHELL_CMD(proxy, &proxy_cmds, "Proxy commands", bt_mesh_shell_mdl_cmds_help),
1872 #endif
1873 
1874 #if defined(CONFIG_BT_MESH_SHELL_PROV)
1875 	SHELL_CMD(prov, &prov_cmds, "Provisioning commands", bt_mesh_shell_mdl_cmds_help),
1876 #endif
1877 
1878 #if defined(CONFIG_BT_MESH_SHELL_TEST)
1879 	SHELL_CMD(test, &test_cmds, "Test commands", bt_mesh_shell_mdl_cmds_help),
1880 #endif
1881 	SHELL_CMD(target, &target_cmds, "Target commands", bt_mesh_shell_mdl_cmds_help),
1882 
1883 #if defined(CONFIG_BT_MESH_STATISTIC)
1884 	SHELL_CMD(stat, &stat_cmds, "Statistic commands", bt_mesh_shell_mdl_cmds_help),
1885 #endif
1886 
1887 	SHELL_SUBCMD_SET_END
1888 );
1889 
1890 SHELL_CMD_ARG_REGISTER(mesh, &mesh_cmds, "Bluetooth Mesh shell commands",
1891 			bt_mesh_shell_mdl_cmds_help, 1, 1);
1892