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