xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/mesh/src/shell.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /** @file
2  *  @brief Bluetooth Mesh shell
3  *
4  */
5 
6 /*
7  * Copyright (c) 2017 Intel Corporation
8  *
9  * SPDX-License-Identifier: Apache-2.0
10  */
11 
12 #include "syscfg/syscfg.h"
13 
14 #if MYNEWT_VAL(BLE_MESH_SHELL)
15 
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include "shell/shell.h"
20 #include "console/console.h"
21 #include "mesh/mesh.h"
22 #include "mesh/main.h"
23 #include "mesh/glue.h"
24 #include "mesh/testing.h"
25 
26 /* Private includes for raw Network & Transport layer access */
27 #include "net.h"
28 #include "access.h"
29 #include "mesh_priv.h"
30 #include "lpn.h"
31 #include "transport.h"
32 #include "foundation.h"
33 #include "testing.h"
34 #include "settings.h"
35 
36 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
37 #include "mesh/model_srv.h"
38 #include "mesh/model_cli.h"
39 #include "light_model.h"
40 #endif
41 
42 /* This should be higher priority (lower value) than main task priority */
43 #define BLE_MESH_SHELL_TASK_PRIO 126
44 #define BLE_MESH_SHELL_STACK_SIZE 768
45 
46 OS_TASK_STACK_DEFINE(g_blemesh_shell_stack, BLE_MESH_SHELL_STACK_SIZE);
47 
48 struct os_task mesh_shell_task;
49 static struct os_eventq mesh_shell_queue;
50 
51 #define CID_NVAL   0xffff
52 #define CID_VENDOR  0x05C3
53 
54 /* Vendor Model data */
55 #define VND_MODEL_ID_1 0x1234
56 
57 /* Default net, app & dev key values, unless otherwise specified */
58 static const u8_t default_key[16] = {
59 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
60 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
61 };
62 
63 static struct {
64 	u16_t local;
65 	u16_t dst;
66 	u16_t net_idx;
67 	u16_t app_idx;
68 } net = {
69 	.local = BT_MESH_ADDR_UNASSIGNED,
70 	.dst = BT_MESH_ADDR_UNASSIGNED,
71 };
72 
73 static struct bt_mesh_cfg_srv cfg_srv = {
74 	.relay = BT_MESH_RELAY_DISABLED,
75 	.beacon = BT_MESH_BEACON_ENABLED,
76 #if MYNEWT_VAL(BLE_MESH_FRIEND)
77 	.frnd = BT_MESH_FRIEND_DISABLED,
78 #else
79 	.frnd = BT_MESH_FRIEND_NOT_SUPPORTED,
80 #endif
81 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
82 	.gatt_proxy = BT_MESH_GATT_PROXY_DISABLED,
83 #else
84 	.gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED,
85 #endif
86 
87 	.default_ttl = 7,
88 
89 	/* 3 transmissions with 20ms interval */
90 	.net_transmit = BT_MESH_TRANSMIT(2, 20),
91 	.relay_retransmit = BT_MESH_TRANSMIT(2, 20),
92 };
93 
94 #define CUR_FAULTS_MAX 4
95 
96 static u8_t cur_faults[CUR_FAULTS_MAX];
97 static u8_t reg_faults[CUR_FAULTS_MAX * 2];
98 
get_faults(u8_t * faults,u8_t faults_size,u8_t * dst,u8_t * count)99 static void get_faults(u8_t *faults, u8_t faults_size, u8_t *dst, u8_t *count)
100 {
101 	u8_t i, limit = *count;
102 
103 	for (i = 0, *count = 0; i < faults_size && *count < limit; i++) {
104 		if (faults[i]) {
105 			*dst++ = faults[i];
106 			(*count)++;
107 		}
108 	}
109 }
110 
fault_get_cur(struct bt_mesh_model * model,u8_t * test_id,u16_t * company_id,u8_t * faults,u8_t * fault_count)111 static int fault_get_cur(struct bt_mesh_model *model, u8_t *test_id,
112 			 u16_t *company_id, u8_t *faults, u8_t *fault_count)
113 {
114 	printk("Sending current faults\n");
115 
116 	*test_id = 0x00;
117 	*company_id = CID_VENDOR;
118 
119 	get_faults(cur_faults, sizeof(cur_faults), faults, fault_count);
120 
121 	return 0;
122 }
123 
fault_get_reg(struct bt_mesh_model * model,u16_t cid,u8_t * test_id,u8_t * faults,u8_t * fault_count)124 static int fault_get_reg(struct bt_mesh_model *model, u16_t cid,
125 			 u8_t *test_id, u8_t *faults, u8_t *fault_count)
126 {
127 	if (cid != CID_VENDOR) {
128 		printk("Faults requested for unknown Company ID 0x%04x\n", cid);
129 		return -EINVAL;
130 	}
131 
132 	printk("Sending registered faults\n");
133 
134 	*test_id = 0x00;
135 
136 	get_faults(reg_faults, sizeof(reg_faults), faults, fault_count);
137 
138 	return 0;
139 }
140 
fault_clear(struct bt_mesh_model * model,uint16_t cid)141 static int fault_clear(struct bt_mesh_model *model, uint16_t cid)
142 {
143 	if (cid != CID_VENDOR) {
144 		return -EINVAL;
145 	}
146 
147 	memset(reg_faults, 0, sizeof(reg_faults));
148 
149 	return 0;
150 }
151 
fault_test(struct bt_mesh_model * model,uint8_t test_id,uint16_t cid)152 static int fault_test(struct bt_mesh_model *model, uint8_t test_id,
153 		      uint16_t cid)
154 {
155 	if (cid != CID_VENDOR) {
156 		return -EINVAL;
157 	}
158 
159 	if (test_id != 0x00) {
160 		return -EINVAL;
161 	}
162 
163 	return 0;
164 }
165 
166 static const struct bt_mesh_health_srv_cb health_srv_cb = {
167 	.fault_get_cur = fault_get_cur,
168 	.fault_get_reg = fault_get_reg,
169 	.fault_clear = fault_clear,
170 	.fault_test = fault_test,
171 };
172 
173 static struct bt_mesh_health_srv health_srv = {
174 	.cb = &health_srv_cb,
175 };
176 
177 static struct bt_mesh_model_pub health_pub;
178 
179 static void
health_pub_init(void)180 health_pub_init(void)
181 {
182 	health_pub.msg  = BT_MESH_HEALTH_FAULT_MSG(CUR_FAULTS_MAX);
183 }
184 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
185 
186 static struct bt_mesh_cfg_cli cfg_cli = {
187 };
188 
189 #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
190 
191 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
show_faults(u8_t test_id,u16_t cid,u8_t * faults,size_t fault_count)192 void show_faults(u8_t test_id, u16_t cid, u8_t *faults, size_t fault_count)
193 {
194 	size_t i;
195 
196 	if (!fault_count) {
197 		printk("Health Test ID 0x%02x Company ID 0x%04x: no faults\n",
198 		       test_id, cid);
199 		return;
200 	}
201 
202 	printk("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:\n",
203 	       test_id, cid, fault_count);
204 
205 	for (i = 0; i < fault_count; i++) {
206 		printk("\t0x%02x\n", faults[i]);
207 	}
208 }
209 
health_current_status(struct bt_mesh_health_cli * cli,u16_t addr,u8_t test_id,u16_t cid,u8_t * faults,size_t fault_count)210 static void health_current_status(struct bt_mesh_health_cli *cli, u16_t addr,
211 				  u8_t test_id, u16_t cid, u8_t *faults,
212 				  size_t fault_count)
213 {
214 	printk("Health Current Status from 0x%04x\n", addr);
215 	show_faults(test_id, cid, faults, fault_count);
216 }
217 
218 static struct bt_mesh_health_cli health_cli = {
219 	.current_status = health_current_status,
220 };
221 
222 #endif /* MYNEWT_VAL(BLE_MESH_HEALTH_CLI) */
223 
224 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
225 static struct bt_mesh_model_pub gen_onoff_pub;
226 static struct bt_mesh_model_pub gen_level_pub;
227 static struct bt_mesh_model_pub light_lightness_pub;
228 static struct bt_mesh_gen_onoff_srv_cb gen_onoff_srv_cb = {
229 	.get = light_model_gen_onoff_get,
230 	.set = light_model_gen_onoff_set,
231 };
232 static struct bt_mesh_gen_level_srv_cb gen_level_srv_cb = {
233 	.get = light_model_gen_level_get,
234 	.set = light_model_gen_level_set,
235 };
236 static struct bt_mesh_light_lightness_srv_cb light_lightness_srv_cb = {
237 	.get = light_model_light_lightness_get,
238 	.set = light_model_light_lightness_set,
239 };
240 
bt_mesh_set_gen_onoff_srv_cb(struct bt_mesh_gen_onoff_srv_cb * gen_onoff_cb)241 void bt_mesh_set_gen_onoff_srv_cb(struct bt_mesh_gen_onoff_srv_cb *gen_onoff_cb)
242 {
243 	gen_onoff_srv_cb = *gen_onoff_cb;
244 }
245 
bt_mesh_set_gen_level_srv_cb(struct bt_mesh_gen_level_srv_cb * gen_level_cb)246 void bt_mesh_set_gen_level_srv_cb(struct bt_mesh_gen_level_srv_cb *gen_level_cb)
247 {
248 	gen_level_srv_cb = *gen_level_cb;
249 }
250 
bt_mesh_set_light_lightness_srv_cb(struct bt_mesh_light_lightness_srv_cb * light_lightness_cb)251 void bt_mesh_set_light_lightness_srv_cb(struct bt_mesh_light_lightness_srv_cb *light_lightness_cb)
252 {
253 	light_lightness_srv_cb = *light_lightness_cb;
254 }
255 
256 #endif
257 
258 static struct bt_mesh_model root_models[] = {
259 	BT_MESH_MODEL_CFG_SRV(&cfg_srv),
260 	BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
261 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
262 	BT_MESH_MODEL_CFG_CLI(&cfg_cli),
263 #endif
264 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
265 	BT_MESH_MODEL_HEALTH_CLI(&health_cli),
266 #endif
267 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
268 	BT_MESH_MODEL_GEN_ONOFF_SRV(&gen_onoff_srv_cb, &gen_onoff_pub),
269 	BT_MESH_MODEL_GEN_ONOFF_CLI(),
270 	BT_MESH_MODEL_GEN_LEVEL_SRV(&gen_level_srv_cb, &gen_level_pub),
271 	BT_MESH_MODEL_GEN_LEVEL_CLI(),
272 	BT_MESH_MODEL_LIGHT_LIGHTNESS_SRV(&light_lightness_srv_cb, &light_lightness_pub),
273 #endif
274 };
275 
276 static struct bt_mesh_model vnd_models[] = {
277 	BT_MESH_MODEL_VND(CID_VENDOR, VND_MODEL_ID_1,
278 			  BT_MESH_MODEL_NO_OPS, NULL, NULL),
279 };
280 
281 static struct bt_mesh_elem elements[] = {
282 	BT_MESH_ELEM(0, root_models, vnd_models),
283 };
284 
285 static const struct bt_mesh_comp comp = {
286 	.cid = CID_VENDOR,
287 	.elem = elements,
288 	.elem_count = ARRAY_SIZE(elements),
289 };
290 
hex2val(char c)291 static u8_t hex2val(char c)
292 {
293 	if (c >= '0' && c <= '9') {
294 		return c - '0';
295 	} else if (c >= 'a' && c <= 'f') {
296 		return c - 'a' + 10;
297 	} else if (c >= 'A' && c <= 'F') {
298 		return c - 'A' + 10;
299 	} else {
300 		return 0;
301 	}
302 }
303 
hex2bin(const char * hex,u8_t * bin,size_t bin_len)304 static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
305 {
306 	size_t len = 0;
307 
308 	while (*hex && len < bin_len) {
309 		bin[len] = hex2val(*hex++) << 4;
310 
311 		if (!*hex) {
312 			len++;
313 			break;
314 		}
315 
316 		bin[len++] |= hex2val(*hex++);
317 	}
318 
319 	return len;
320 }
321 
prov_complete(u16_t net_idx,u16_t addr)322 static void prov_complete(u16_t net_idx, u16_t addr)
323 {
324 	printk("Local node provisioned, net_idx 0x%04x address 0x%04x\n",
325 	       net_idx, addr);
326 	net.net_idx = net_idx,
327 	net.local = addr;
328 	net.dst = addr;
329 }
330 
prov_reset(void)331 static void prov_reset(void)
332 {
333 	printk("The local node has been reset and needs reprovisioning\n");
334 }
335 
output_number(bt_mesh_output_action_t action,uint32_t number)336 static int output_number(bt_mesh_output_action_t action, uint32_t number)
337 {
338 	printk("OOB Number: %lu\n", number);
339 	return 0;
340 }
341 
output_string(const char * str)342 static int output_string(const char *str)
343 {
344 	printk("OOB String: %s\n", str);
345 	return 0;
346 }
347 
348 static bt_mesh_input_action_t input_act;
349 static u8_t input_size;
350 
cmd_input_num(int argc,char * argv[])351 static int cmd_input_num(int argc, char *argv[])
352 {
353 	int err;
354 
355 	if (argc < 2) {
356 		return -EINVAL;
357 	}
358 
359 	if (input_act != BT_MESH_ENTER_NUMBER) {
360 		printk("A number hasn't been requested!\n");
361 		return 0;
362 	}
363 
364 	if (strlen(argv[1]) < input_size) {
365 		printk("Too short input (%u digits required)\n",
366 		       input_size);
367 		return 0;
368 	}
369 
370 	err = bt_mesh_input_number(strtoul(argv[1], NULL, 10));
371 	if (err) {
372 		printk("Numeric input failed (err %d)\n", err);
373 		return 0;
374 	}
375 
376 	input_act = BT_MESH_NO_INPUT;
377 	return 0;
378 }
379 
380 struct shell_cmd_help cmd_input_num_help = {
381 	NULL, "<number>", NULL
382 };
383 
cmd_input_str(int argc,char * argv[])384 static int cmd_input_str(int argc, char *argv[])
385 {
386 	int err;
387 
388 	if (argc < 2) {
389 		return -EINVAL;
390 	}
391 
392 	if (input_act != BT_MESH_ENTER_STRING) {
393 		printk("A string hasn't been requested!\n");
394 		return 0;
395 	}
396 
397 	if (strlen(argv[1]) < input_size) {
398 		printk("Too short input (%u characters required)\n",
399 		       input_size);
400 		return 0;
401 	}
402 
403 	err = bt_mesh_input_string(argv[1]);
404 	if (err) {
405 		printk("String input failed (err %d)\n", err);
406 		return 0;
407 	}
408 
409 	input_act = BT_MESH_NO_INPUT;
410 	return 0;
411 }
412 
413 struct shell_cmd_help cmd_input_str_help = {
414 	NULL, "<string>", NULL
415 };
416 
input(bt_mesh_input_action_t act,u8_t size)417 static int input(bt_mesh_input_action_t act, u8_t size)
418 {
419 	switch (act) {
420 	case BT_MESH_ENTER_NUMBER:
421 		printk("Enter a number (max %u digits) with: input-num <num>\n",
422 		       size);
423 		break;
424 	case BT_MESH_ENTER_STRING:
425 		printk("Enter a string (max %u chars) with: input-str <str>\n",
426 		       size);
427 		break;
428 	default:
429 		printk("Unknown input action %u (size %u) requested!\n",
430 		       act, size);
431 		return -EINVAL;
432 	}
433 
434 	input_act = act;
435 	input_size = size;
436 	return 0;
437 }
438 
bearer2str(bt_mesh_prov_bearer_t bearer)439 static const char *bearer2str(bt_mesh_prov_bearer_t bearer)
440 {
441 	switch (bearer) {
442 	case BT_MESH_PROV_ADV:
443 		return "PB-ADV";
444 	case BT_MESH_PROV_GATT:
445 		return "PB-GATT";
446 	default:
447 		return "unknown";
448 	}
449 }
450 
link_open(bt_mesh_prov_bearer_t bearer)451 static void link_open(bt_mesh_prov_bearer_t bearer)
452 {
453 	printk("Provisioning link opened on %s\n", bearer2str(bearer));
454 }
455 
link_close(bt_mesh_prov_bearer_t bearer)456 static void link_close(bt_mesh_prov_bearer_t bearer)
457 {
458 	printk("Provisioning link closed on %s\n", bearer2str(bearer));
459 }
460 
461 static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID);
462 
463 static u8_t static_val[16];
464 
465 static struct bt_mesh_prov prov = {
466 	.uuid = dev_uuid,
467 	.link_open = link_open,
468 	.link_close = link_close,
469 	.complete = prov_complete,
470 	.reset = prov_reset,
471 	.static_val = NULL,
472 	.static_val_len = 0,
473 	.output_size = MYNEWT_VAL(BLE_MESH_OOB_OUTPUT_SIZE),
474 	.output_actions = MYNEWT_VAL(BLE_MESH_OOB_OUTPUT_ACTIONS),
475 	.output_number = output_number,
476 	.output_string = output_string,
477 	.input_size = MYNEWT_VAL(BLE_MESH_OOB_INPUT_SIZE),
478 	.input_actions = MYNEWT_VAL(BLE_MESH_OOB_INPUT_ACTIONS),
479 	.input = input,
480 };
481 
cmd_static_oob(int argc,char * argv[])482 static int cmd_static_oob(int argc, char *argv[])
483 {
484 	if (argc < 2) {
485 		prov.static_val = NULL;
486 		prov.static_val_len = 0;
487 	} else {
488 		prov.static_val_len = hex2bin(argv[1], static_val, 16);
489 		if (prov.static_val_len) {
490 			prov.static_val = static_val;
491 		} else {
492 			prov.static_val = NULL;
493 		}
494 	}
495 
496 	if (prov.static_val) {
497 		printk("Static OOB value set (length %u)\n",
498 		       prov.static_val_len);
499 	} else {
500 		printk("Static OOB value cleared\n");
501 	}
502 
503 	return 0;
504 }
505 
506 struct shell_cmd_help cmd_static_oob_help = {
507 	NULL, "[val: 1-16 hex values]", NULL
508 };
509 
cmd_uuid(int argc,char * argv[])510 static int cmd_uuid(int argc, char *argv[])
511 {
512 	u8_t uuid[16];
513 	size_t len;
514 
515 	if (argc < 2) {
516 		return -EINVAL;
517 	}
518 
519 	len = hex2bin(argv[1], uuid, sizeof(uuid));
520 	if (len < 1) {
521 		return -EINVAL;
522 	}
523 
524 	memcpy(dev_uuid, uuid, len);
525 	memset(dev_uuid + len, 0, sizeof(dev_uuid) - len);
526 
527 	printk("Device UUID set\n");
528 
529 	return 0;
530 }
531 
532 struct shell_cmd_help cmd_uuid_help = {
533 	NULL, "<UUID: 1-16 hex values>", NULL
534 };
535 
cmd_reset(int argc,char * argv[])536 static int cmd_reset(int argc, char *argv[])
537 {
538 	bt_mesh_reset();
539 	printk("Local node reset complete\n");
540 	return 0;
541 }
542 
str2u8(const char * str)543 static u8_t str2u8(const char *str)
544 {
545 	if (isdigit(str[0])) {
546 		return strtoul(str, NULL, 0);
547 	}
548 
549 	return (!strcmp(str, "on") || !strcmp(str, "enable"));
550 }
551 
str2bool(const char * str)552 static bool str2bool(const char *str)
553 {
554 	return str2u8(str);
555 }
556 
557 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
cmd_lpn(int argc,char * argv[])558 static int cmd_lpn(int argc, char *argv[])
559 {
560 	static bool enabled;
561 	int err;
562 
563 	if (argc < 2) {
564 		printk("%s\n", enabled ? "enabled" : "disabled");
565 		return 0;
566 	}
567 
568 	if (str2bool(argv[1])) {
569 		if (enabled) {
570 			printk("LPN already enabled\n");
571 			return 0;
572 		}
573 
574 		err = bt_mesh_lpn_set(true);
575 		if (err) {
576 			printk("Enabling LPN failed (err %d)\n", err);
577 		} else {
578 			enabled = true;
579 		}
580 	} else {
581 		if (!enabled) {
582 			printk("LPN already disabled\n");
583 			return 0;
584 		}
585 
586 		err = bt_mesh_lpn_set(false);
587 		if (err) {
588 			printk("Enabling LPN failed (err %d)\n", err);
589 		} else {
590 			enabled = false;
591 		}
592 	}
593 
594 	return 0;
595 }
596 
cmd_poll(int argc,char * argv[])597 static int cmd_poll(int argc, char *argv[])
598 {
599 	int err;
600 
601 	err = bt_mesh_lpn_poll();
602 	if (err) {
603 		printk("Friend Poll failed (err %d)\n", err);
604 	}
605 
606 	return 0;
607 }
608 
lpn_cb(u16_t friend_addr,bool established)609 static void lpn_cb(u16_t friend_addr, bool established)
610 {
611 	if (established) {
612 		printk("Friendship (as LPN) established to Friend 0x%04x\n",
613 		       friend_addr);
614 	} else {
615 		printk("Friendship (as LPN) lost with Friend 0x%04x\n",
616 		       friend_addr);
617 	}
618 }
619 
620 struct shell_cmd_help cmd_lpn_help = {
621 	NULL, "<value: off, on>", NULL
622 };
623 
624 #endif /* MESH_LOW_POWER */
625 
check_pub_addr_unassigned(void)626 static int check_pub_addr_unassigned(void)
627 {
628 #ifdef ARCH_sim
629 	return 0;
630 #else
631 	uint8_t zero_addr[BLE_DEV_ADDR_LEN] = { 0 };
632 
633 	return memcmp(MYNEWT_VAL(BLE_PUBLIC_DEV_ADDR),
634 		      zero_addr, BLE_DEV_ADDR_LEN) == 0;
635 #endif
636 }
637 
cmd_mesh_init(int argc,char * argv[])638 int cmd_mesh_init(int argc, char *argv[])
639 {
640 	int err;
641 	ble_addr_t addr;
642 
643 	if (check_pub_addr_unassigned()) {
644 		/* Use NRPA */
645 		err = ble_hs_id_gen_rnd(1, &addr);
646 		assert(err == 0);
647 		err = ble_hs_id_set_rnd(addr.val);
648 		assert(err == 0);
649 
650 		err = bt_mesh_init(addr.type, &prov, &comp);
651 	}
652 	else {
653 		err = bt_mesh_init(0, &prov, &comp);
654 	}
655 
656 	if (err) {
657 		printk("Mesh initialization failed (err %d)\n", err);
658 	}
659 
660 	printk("Mesh initialized\n");
661 
662 	if (IS_ENABLED(CONFIG_SETTINGS)) {
663 		settings_load();
664 	}
665 
666 	if (bt_mesh_is_provisioned()) {
667 		printk("Mesh network restored from flash\n");
668 	} else {
669 		printk("Use \"pb-adv on\" or \"pb-gatt on\" to enable"
670 		       " advertising\n");
671 	}
672 
673 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
674 	bt_mesh_lpn_set_cb(lpn_cb);
675 #endif
676 
677 	return 0;
678 }
679 
680 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
cmd_ident(int argc,char * argv[])681 static int cmd_ident(int argc, char *argv[])
682 {
683 	int err;
684 
685 	err = bt_mesh_proxy_identity_enable();
686 	if (err) {
687 		printk("Failed advertise using Node Identity (err %d)\n", err);
688 	}
689 
690 	return 0;
691 }
692 #endif /* MESH_GATT_PROXY */
693 
cmd_dst(int argc,char * argv[])694 static int cmd_dst(int argc, char *argv[])
695 {
696 	if (argc < 2) {
697 		printk("Destination address: 0x%04x%s\n", net.dst,
698 		       net.dst == net.local ? " (local)" : "");
699 		return 0;
700 	}
701 
702 	if (!strcmp(argv[1], "local")) {
703 		net.dst = net.local;
704 	} else {
705 		net.dst = strtoul(argv[1], NULL, 0);
706 	}
707 
708 	printk("Destination address set to 0x%04x%s\n", net.dst,
709 	       net.dst == net.local ? " (local)" : "");
710 	return 0;
711 }
712 
713 struct shell_cmd_help cmd_dst_help = {
714 	NULL, "[destination address]", NULL
715 };
716 
cmd_netidx(int argc,char * argv[])717 static int cmd_netidx(int argc, char *argv[])
718 {
719 	if (argc < 2) {
720 		printk("NetIdx: 0x%04x\n", net.net_idx);
721 		return 0;
722 	}
723 
724 	net.net_idx = strtoul(argv[1], NULL, 0);
725 	printk("NetIdx set to 0x%04x\n", net.net_idx);
726 	return 0;
727 }
728 
729 struct shell_cmd_help cmd_netidx_help = {
730 	NULL, "[NetIdx]", NULL
731 };
732 
cmd_appidx(int argc,char * argv[])733 static int cmd_appidx(int argc, char *argv[])
734 {
735 	if (argc < 2) {
736 		printk("AppIdx: 0x%04x\n", net.app_idx);
737 		return 0;
738 	}
739 
740 	net.app_idx = strtoul(argv[1], NULL, 0);
741 	printk("AppIdx set to 0x%04x\n", net.app_idx);
742 	return 0;
743 }
744 
745 struct shell_cmd_help cmd_appidx_help = {
746 	NULL, "[AppIdx]", NULL
747 };
748 
cmd_net_send(int argc,char * argv[])749 static int cmd_net_send(int argc, char *argv[])
750 {
751 	struct os_mbuf *msg = NET_BUF_SIMPLE(32);
752 	struct bt_mesh_msg_ctx ctx = {
753 		.send_ttl = BT_MESH_TTL_DEFAULT,
754 		.net_idx = net.net_idx,
755 		.addr = net.dst,
756 		.app_idx = net.app_idx,
757 
758 	};
759 	struct bt_mesh_net_tx tx = {
760 		.ctx = &ctx,
761 		.src = net.local,
762 		.xmit = bt_mesh_net_transmit_get(),
763 		.sub = bt_mesh_subnet_get(net.net_idx),
764 	};
765 	size_t len;
766 	int err = 0;
767 
768 	if (argc < 2) {
769 		err = -EINVAL;
770 		goto done;
771 	}
772 
773 	if (!tx.sub) {
774 		printk("No matching subnet for NetKey Index 0x%04x\n",
775 		       net.net_idx);
776 		goto done;
777 	}
778 
779 	net_buf_simple_init(msg, 0);
780 	len = hex2bin(argv[1], msg->om_data, net_buf_simple_tailroom(msg) - 4);
781 	net_buf_simple_add(msg, len);
782 
783 	err = bt_mesh_trans_send(&tx, msg, NULL, NULL);
784 	if (err) {
785 		printk("Failed to send (err %d)\n", err);
786 	}
787 
788 done:
789 	os_mbuf_free_chain(msg);
790 	return err;
791 }
792 
793 struct shell_cmd_help cmd_net_send_help = {
794 	NULL, "<hex string>", NULL
795 };
796 
cmd_iv_update(int argc,char * argv[])797 static int cmd_iv_update(int argc, char *argv[])
798 {
799 	if (bt_mesh_iv_update()) {
800 		printk("Transitioned to IV Update In Progress state\n");
801 	} else {
802 		printk("Transitioned to IV Update Normal state\n");
803 	}
804 
805 	printk("IV Index is 0x%08lx\n", bt_mesh.iv_index);
806 
807 	return 0;
808 }
809 
cmd_rpl_clear(int argc,char * argv[])810 static int cmd_rpl_clear(int argc, char *argv[])
811 {
812 	bt_mesh_rpl_clear();
813 	return 0;
814 }
815 
816 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
cmd_lpn_subscribe(int argc,char * argv[])817 static int cmd_lpn_subscribe(int argc, char *argv[])
818 {
819 	u16_t address;
820 
821 	if (argc < 2) {
822 		return -EINVAL;
823 	}
824 
825 	address = strtoul(argv[1], NULL, 0);
826 
827 	printk("address 0x%04x", address);
828 
829 	bt_mesh_lpn_group_add(address);
830 
831 	return 0;
832 }
833 
834 struct shell_cmd_help cmd_lpn_subscribe_help = {
835 	NULL, "<addr>", NULL
836 };
837 
cmd_lpn_unsubscribe(int argc,char * argv[])838 static int cmd_lpn_unsubscribe(int argc, char *argv[])
839 {
840 	u16_t address;
841 
842 	if (argc < 2) {
843 		return -EINVAL;
844 	}
845 
846 	address = strtoul(argv[1], NULL, 0);
847 
848 	printk("address 0x%04x", address);
849 
850 	bt_mesh_lpn_group_del(&address, 1);
851 
852 	return 0;
853 }
854 
855 struct shell_cmd_help cmd_lpn_unsubscribe_help = {
856 	NULL, "<addr>", NULL
857 };
858 #endif
859 
cmd_iv_update_test(int argc,char * argv[])860 static int cmd_iv_update_test(int argc, char *argv[])
861 {
862 	bool enable;
863 
864 	if (argc < 2) {
865 		return -EINVAL;
866 	}
867 
868 	enable = str2bool(argv[1]);
869 	if (enable) {
870 		printk("Enabling IV Update test mode\n");
871 	} else {
872 		printk("Disabling IV Update test mode\n");
873 	}
874 
875 	bt_mesh_iv_update_test(enable);
876 
877 	return 0;
878 }
879 
880 struct shell_cmd_help cmd_iv_update_test_help = {
881 	NULL, "<value: off, on>", NULL
882 };
883 
884 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
885 
cmd_timeout(int argc,char * argv[])886 int cmd_timeout(int argc, char *argv[])
887 {
888 	s32_t timeout;
889 
890 	if (argc < 2) {
891 		timeout = bt_mesh_cfg_cli_timeout_get();
892 		if (timeout == K_FOREVER) {
893 			printk("Message timeout: forever\n");
894 		} else {
895 			printk("Message timeout: %lu seconds\n",
896 			       timeout / 1000);
897 		}
898 
899 		return 0;
900 	}
901 
902 	timeout = strtol(argv[1], NULL, 0);
903 	if (timeout < 0 || timeout > (INT32_MAX / 1000)) {
904 		timeout = K_FOREVER;
905 	} else {
906 		timeout = timeout * 1000;
907 	}
908 
909 	bt_mesh_cfg_cli_timeout_set(timeout);
910 	if (timeout == K_FOREVER) {
911 		printk("Message timeout: forever\n");
912 	} else {
913 		printk("Message timeout: %lu seconds\n",
914 		       timeout / 1000);
915 	}
916 
917 	return 0;
918 }
919 
920 struct shell_cmd_help cmd_timeout_help = {
921 	NULL, "[timeout in seconds]", NULL
922 };
923 
924 
cmd_get_comp(int argc,char * argv[])925 static int cmd_get_comp(int argc, char *argv[])
926 {
927 	struct os_mbuf *comp = NET_BUF_SIMPLE(32);
928 	u8_t status, page = 0x00;
929 	int err = 0;
930 
931 	if (argc > 1) {
932 		page = strtol(argv[1], NULL, 0);
933 	}
934 
935 	net_buf_simple_init(comp, 0);
936 	err = bt_mesh_cfg_comp_data_get(net.net_idx, net.dst, page,
937 					&status, comp);
938 	if (err) {
939 		printk("Getting composition failed (err %d)\n", err);
940 		goto done;
941 	}
942 
943 	if (status != 0x00) {
944 		printk("Got non-success status 0x%02x\n", status);
945 		goto done;
946 	}
947 
948 	printk("Got Composition Data for 0x%04x:\n", net.dst);
949 	printk("\tCID      0x%04x\n", net_buf_simple_pull_le16(comp));
950 	printk("\tPID      0x%04x\n", net_buf_simple_pull_le16(comp));
951 	printk("\tVID      0x%04x\n", net_buf_simple_pull_le16(comp));
952 	printk("\tCRPL     0x%04x\n", net_buf_simple_pull_le16(comp));
953 	printk("\tFeatures 0x%04x\n", net_buf_simple_pull_le16(comp));
954 
955 	while (comp->om_len > 4) {
956 		u8_t sig, vnd;
957 		u16_t loc;
958 		int i;
959 
960 		loc = net_buf_simple_pull_le16(comp);
961 		sig = net_buf_simple_pull_u8(comp);
962 		vnd = net_buf_simple_pull_u8(comp);
963 
964 		printk("\n\tElement @ 0x%04x:\n", loc);
965 
966 		if (comp->om_len < ((sig * 2) + (vnd * 4))) {
967 			printk("\t\t...truncated data!\n");
968 			break;
969 		}
970 
971 		if (sig) {
972 			printk("\t\tSIG Models:\n");
973 		} else {
974 			printk("\t\tNo SIG Models\n");
975 		}
976 
977 		for (i = 0; i < sig; i++) {
978 			u16_t mod_id = net_buf_simple_pull_le16(comp);
979 
980 			printk("\t\t\t0x%04x\n", mod_id);
981 		}
982 
983 		if (vnd) {
984 			printk("\t\tVendor Models:\n");
985 		} else {
986 			printk("\t\tNo Vendor Models\n");
987 		}
988 
989 		for (i = 0; i < vnd; i++) {
990 			u16_t cid = net_buf_simple_pull_le16(comp);
991 			u16_t mod_id = net_buf_simple_pull_le16(comp);
992 
993 			printk("\t\t\tCompany 0x%04x: 0x%04x\n", cid, mod_id);
994 		}
995 	}
996 
997 done:
998 	os_mbuf_free_chain(comp);
999 	return err;
1000 }
1001 
1002 struct shell_cmd_help cmd_get_comp_help = {
1003 	NULL, "[page]", NULL
1004 };
1005 
cmd_beacon(int argc,char * argv[])1006 static int cmd_beacon(int argc, char *argv[])
1007 {
1008 	u8_t status;
1009 	int err;
1010 
1011 	if (argc < 2) {
1012 		err = bt_mesh_cfg_beacon_get(net.net_idx, net.dst, &status);
1013 	} else {
1014 		u8_t val = str2u8(argv[1]);
1015 
1016 		err = bt_mesh_cfg_beacon_set(net.net_idx, net.dst, val,
1017 					     &status);
1018 	}
1019 
1020 	if (err) {
1021 		printk("Unable to send Beacon Get/Set message (err %d)\n", err);
1022 		return 0;
1023 	}
1024 
1025 	printk("Beacon state is 0x%02x\n", status);
1026 
1027 	return 0;
1028 }
1029 
1030 struct shell_cmd_help cmd_beacon_help = {
1031 	NULL, "[val: off, on]", NULL
1032 };
1033 
cmd_ttl(int argc,char * argv[])1034 static int cmd_ttl(int argc, char *argv[])
1035 {
1036 	u8_t ttl;
1037 	int err;
1038 
1039 	if (argc < 2) {
1040 		err = bt_mesh_cfg_ttl_get(net.net_idx, net.dst, &ttl);
1041 	} else {
1042 		u8_t val = strtoul(argv[1], NULL, 0);
1043 
1044 		err = bt_mesh_cfg_ttl_set(net.net_idx, net.dst, val, &ttl);
1045 	}
1046 
1047 	if (err) {
1048 		printk("Unable to send Default TTL Get/Set (err %d)\n", err);
1049 		return 0;
1050 	}
1051 
1052 	printk("Default TTL is 0x%02x\n", ttl);
1053 
1054 	return 0;
1055 }
1056 
1057 struct shell_cmd_help cmd_ttl_help = {
1058 	NULL, "[ttl: 0x00, 0x02-0x7f]", NULL
1059 };
1060 
cmd_friend(int argc,char * argv[])1061 static int cmd_friend(int argc, char *argv[])
1062 {
1063 	u8_t frnd;
1064 	int err;
1065 
1066 	if (argc < 2) {
1067 		err = bt_mesh_cfg_friend_get(net.net_idx, net.dst, &frnd);
1068 	} else {
1069 		u8_t val = str2u8(argv[1]);
1070 
1071 		err = bt_mesh_cfg_friend_set(net.net_idx, net.dst, val, &frnd);
1072 	}
1073 
1074 	if (err) {
1075 		printk("Unable to send Friend Get/Set (err %d)\n", err);
1076 		return 0;
1077 	}
1078 
1079 	printk("Friend is set to 0x%02x\n", frnd);
1080 
1081 	return 0;
1082 }
1083 
1084 struct shell_cmd_help cmd_friend_help = {
1085 	NULL, "[val: off, on]", NULL
1086 };
1087 
cmd_gatt_proxy(int argc,char * argv[])1088 static int cmd_gatt_proxy(int argc, char *argv[])
1089 {
1090 	u8_t proxy;
1091 	int err;
1092 
1093 	if (argc < 2) {
1094 		err = bt_mesh_cfg_gatt_proxy_get(net.net_idx, net.dst, &proxy);
1095 	} else {
1096 		u8_t val = str2u8(argv[1]);
1097 
1098 		err = bt_mesh_cfg_gatt_proxy_set(net.net_idx, net.dst, val,
1099 						 &proxy);
1100 	}
1101 
1102 	if (err) {
1103 		printk("Unable to send GATT Proxy Get/Set (err %d)\n", err);
1104 		return 0;
1105 	}
1106 
1107 	printk("GATT Proxy is set to 0x%02x\n", proxy);
1108 
1109 	return 0;
1110 }
1111 
1112 struct shell_cmd_help cmd_gatt_proxy_help = {
1113 	NULL, "[val: off, on]", NULL
1114 };
1115 
cmd_relay(int argc,char * argv[])1116 static int cmd_relay(int argc, char *argv[])
1117 {
1118 	u8_t relay, transmit;
1119 	int err;
1120 
1121 	if (argc < 2) {
1122 		err = bt_mesh_cfg_relay_get(net.net_idx, net.dst, &relay,
1123 					    &transmit);
1124 	} else {
1125 		u8_t val = str2u8(argv[1]);
1126 		u8_t count, interval, new_transmit;
1127 
1128 		if (val) {
1129 			if (argc > 2) {
1130 				count = strtoul(argv[2], NULL, 0);
1131 			} else {
1132 				count = 2;
1133 			}
1134 
1135 			if (argc > 3) {
1136 				interval = strtoul(argv[3], NULL, 0);
1137 			} else {
1138 				interval = 20;
1139 			}
1140 
1141 			new_transmit = BT_MESH_TRANSMIT(count, interval);
1142 		} else {
1143 			new_transmit = 0;
1144 		}
1145 
1146 		err = bt_mesh_cfg_relay_set(net.net_idx, net.dst, val,
1147 					    new_transmit, &relay, &transmit);
1148 	}
1149 
1150 	if (err) {
1151 		printk("Unable to send Relay Get/Set (err %d)\n", err);
1152 		return 0;
1153 	}
1154 
1155 	printk("Relay is 0x%02x, Transmit 0x%02x (count %u interval %ums)\n",
1156 	       relay, transmit, BT_MESH_TRANSMIT_COUNT(transmit),
1157 	       BT_MESH_TRANSMIT_INT(transmit));
1158 
1159 	return 0;
1160 }
1161 
1162 struct shell_cmd_help cmd_relay_help = {
1163 	NULL, "[val: off, on] [count: 0-7] [interval: 0-32]", NULL
1164 };
1165 
cmd_net_key_add(int argc,char * argv[])1166 static int cmd_net_key_add(int argc, char *argv[])
1167 {
1168 	u8_t key_val[16];
1169 	u16_t key_net_idx;
1170 	u8_t status;
1171 	int err;
1172 
1173 	if (argc < 2) {
1174 		return -EINVAL;
1175 	}
1176 
1177 	key_net_idx = strtoul(argv[1], NULL, 0);
1178 
1179 	if (argc > 2) {
1180 		size_t len;
1181 
1182 		len = hex2bin(argv[3], key_val, sizeof(key_val));
1183 		memset(key_val, 0, sizeof(key_val) - len);
1184 	} else {
1185 		memcpy(key_val, default_key, sizeof(key_val));
1186 	}
1187 
1188 	err = bt_mesh_cfg_net_key_add(net.net_idx, net.dst, key_net_idx,
1189 				      key_val, &status);
1190 	if (err) {
1191 		printk("Unable to send NetKey Add (err %d)\n", err);
1192 		return 0;
1193 	}
1194 
1195 	if (status) {
1196 		printk("NetKeyAdd failed with status 0x%02x\n", status);
1197 	} else {
1198 		printk("NetKey added with NetKey Index 0x%03x\n", key_net_idx);
1199 	}
1200 
1201 	return 0;
1202 }
1203 
1204 struct shell_cmd_help cmd_net_key_add_help = {
1205 	NULL, "<NetKeyIndex> [val]", NULL
1206 };
1207 
cmd_app_key_add(int argc,char * argv[])1208 static int cmd_app_key_add(int argc, char *argv[])
1209 {
1210 	u8_t key_val[16];
1211 	u16_t key_net_idx, key_app_idx;
1212 	u8_t status;
1213 	int err;
1214 
1215 	if (argc < 3) {
1216 		return -EINVAL;
1217 	}
1218 
1219 	key_net_idx = strtoul(argv[1], NULL, 0);
1220 	key_app_idx = strtoul(argv[2], NULL, 0);
1221 
1222 	if (argc > 3) {
1223 		size_t len;
1224 
1225 		len = hex2bin(argv[3], key_val, sizeof(key_val));
1226 		memset(key_val, 0, sizeof(key_val) - len);
1227 	} else {
1228 		memcpy(key_val, default_key, sizeof(key_val));
1229 	}
1230 
1231 	err = bt_mesh_cfg_app_key_add(net.net_idx, net.dst, key_net_idx,
1232 				      key_app_idx, key_val, &status);
1233 	if (err) {
1234 		printk("Unable to send App Key Add (err %d)\n", err);
1235 		return 0;
1236 	}
1237 
1238 	if (status) {
1239 		printk("AppKeyAdd failed with status 0x%02x\n", status);
1240 	} else {
1241 		printk("AppKey added, NetKeyIndex 0x%04x AppKeyIndex 0x%04x\n",
1242 		       key_net_idx, key_app_idx);
1243 	}
1244 
1245 	return 0;
1246 }
1247 
1248 struct shell_cmd_help cmd_app_key_add_help = {
1249 	NULL, "<NetKeyIndex> <AppKeyIndex> [val]", NULL
1250 };
1251 
cmd_mod_app_bind(int argc,char * argv[])1252 static int cmd_mod_app_bind(int argc, char *argv[])
1253 {
1254 	u16_t elem_addr, mod_app_idx, mod_id, cid;
1255 	u8_t status;
1256 	int err;
1257 
1258 	if (argc < 4) {
1259 		return -EINVAL;
1260 	}
1261 
1262 	elem_addr = strtoul(argv[1], NULL, 0);
1263 	mod_app_idx = strtoul(argv[2], NULL, 0);
1264 	mod_id = strtoul(argv[3], NULL, 0);
1265 
1266 	if (argc > 4) {
1267 		cid = strtoul(argv[4], NULL, 0);
1268 		err = bt_mesh_cfg_mod_app_bind_vnd(net.net_idx, net.dst,
1269 						   elem_addr, mod_app_idx,
1270 						   mod_id, cid, &status);
1271 	} else {
1272 		err = bt_mesh_cfg_mod_app_bind(net.net_idx, net.dst, elem_addr,
1273 					       mod_app_idx, mod_id, &status);
1274 	}
1275 
1276 	if (err) {
1277 		printk("Unable to send Model App Bind (err %d)\n", err);
1278 		return 0;
1279 	}
1280 
1281 	if (status) {
1282 		printk("Model App Bind failed with status 0x%02x\n", status);
1283 	} else {
1284 		printk("AppKey successfully bound\n");
1285 	}
1286 
1287 	return 0;
1288 }
1289 
1290 struct shell_cmd_help cmd_mod_app_bind_help = {
1291 	NULL, "<addr> <AppIndex> <Model ID> [Company ID]", NULL
1292 };
1293 
cmd_mod_sub_add(int argc,char * argv[])1294 static int cmd_mod_sub_add(int argc, char *argv[])
1295 {
1296 	u16_t elem_addr, sub_addr, mod_id, cid;
1297 	u8_t status;
1298 	int err;
1299 
1300 	if (argc < 4) {
1301 		return -EINVAL;
1302 	}
1303 
1304 	elem_addr = strtoul(argv[1], NULL, 0);
1305 	sub_addr = strtoul(argv[2], NULL, 0);
1306 	mod_id = strtoul(argv[3], NULL, 0);
1307 
1308 	if (argc > 4) {
1309 		cid = strtoul(argv[4], NULL, 0);
1310 		err = bt_mesh_cfg_mod_sub_add_vnd(net.net_idx, net.dst,
1311 						  elem_addr, sub_addr, mod_id,
1312 						  cid, &status);
1313 	} else {
1314 		err = bt_mesh_cfg_mod_sub_add(net.net_idx, net.dst, elem_addr,
1315 					      sub_addr, mod_id, &status);
1316 	}
1317 
1318 	if (err) {
1319 		printk("Unable to send Model Subscription Add (err %d)\n", err);
1320 		return 0;
1321 	}
1322 
1323 	if (status) {
1324 		printk("Model Subscription Add failed with status 0x%02x\n",
1325 		       status);
1326 	} else {
1327 		printk("Model subscription was successful\n");
1328 	}
1329 
1330 	return 0;
1331 }
1332 
1333 struct shell_cmd_help cmd_mod_sub_add_help = {
1334 	NULL, "<elem addr> <sub addr> <Model ID> [Company ID]", NULL
1335 };
1336 
cmd_mod_sub_del(int argc,char * argv[])1337 static int cmd_mod_sub_del(int argc, char *argv[])
1338 {
1339 	u16_t elem_addr, sub_addr, mod_id, cid;
1340 	u8_t status;
1341 	int err;
1342 
1343 	if (argc < 4) {
1344 		return -EINVAL;
1345 	}
1346 
1347 	elem_addr = strtoul(argv[1], NULL, 0);
1348 	sub_addr = strtoul(argv[2], NULL, 0);
1349 	mod_id = strtoul(argv[3], NULL, 0);
1350 
1351 	if (argc > 4) {
1352 		cid = strtoul(argv[4], NULL, 0);
1353 		err = bt_mesh_cfg_mod_sub_del_vnd(net.net_idx, net.dst,
1354 						  elem_addr, sub_addr, mod_id,
1355 						  cid, &status);
1356 	} else {
1357 		err = bt_mesh_cfg_mod_sub_del(net.net_idx, net.dst, elem_addr,
1358 					      sub_addr, mod_id, &status);
1359 	}
1360 
1361 	if (err) {
1362 		printk("Unable to send Model Subscription Delete (err %d)\n",
1363 		       err);
1364 		return 0;
1365 	}
1366 
1367 	if (status) {
1368 		printk("Model Subscription Delete failed with status 0x%02x\n",
1369 		       status);
1370 	} else {
1371 		printk("Model subscription deltion was successful\n");
1372 	}
1373 
1374 	return 0;
1375 }
1376 
1377 struct shell_cmd_help cmd_mod_sub_del_help = {
1378 	NULL, "<elem addr> <sub addr> <Model ID> [Company ID]", NULL
1379 };
1380 
cmd_mod_sub_add_va(int argc,char * argv[])1381 static int cmd_mod_sub_add_va(int argc, char *argv[])
1382 {
1383 	u16_t elem_addr, sub_addr, mod_id, cid;
1384 	u8_t label[16];
1385 	u8_t status;
1386 	size_t len;
1387 	int err;
1388 
1389 	if (argc < 4) {
1390 		return -EINVAL;
1391 	}
1392 
1393 	elem_addr = strtoul(argv[1], NULL, 0);
1394 
1395 	len = hex2bin(argv[2], label, sizeof(label));
1396 	memset(label + len, 0, sizeof(label) - len);
1397 
1398 	mod_id = strtoul(argv[3], NULL, 0);
1399 
1400 	if (argc > 4) {
1401 		cid = strtoul(argv[4], NULL, 0);
1402 		err = bt_mesh_cfg_mod_sub_va_add_vnd(net.net_idx, net.dst,
1403 						     elem_addr, label, mod_id,
1404 						     cid, &sub_addr, &status);
1405 	} else {
1406 		err = bt_mesh_cfg_mod_sub_va_add(net.net_idx, net.dst,
1407 						 elem_addr, label, mod_id,
1408 						 &sub_addr, &status);
1409 	}
1410 
1411 	if (err) {
1412 		printk("Unable to send Mod Sub VA Add (err %d)\n", err);
1413 		return 0;
1414 	}
1415 
1416 	if (status) {
1417 		printk("Mod Sub VA Add failed with status 0x%02x\n",
1418 		       status);
1419 	} else {
1420 		printk("0x%04x subscribed to Label UUID %s (va 0x%04x)\n",
1421 		       elem_addr, argv[2], sub_addr);
1422 	}
1423 
1424 	return 0;
1425 }
1426 
1427 struct shell_cmd_help cmd_mod_sub_add_va_help = {
1428 	NULL, "<elem addr> <Label UUID> <Model ID> [Company ID]", NULL
1429 };
1430 
cmd_mod_sub_del_va(int argc,char * argv[])1431 static int cmd_mod_sub_del_va(int argc, char *argv[])
1432 {
1433 	u16_t elem_addr, sub_addr, mod_id, cid;
1434 	u8_t label[16];
1435 	u8_t status;
1436 	size_t len;
1437 	int err;
1438 
1439 	if (argc < 4) {
1440 		return -EINVAL;
1441 	}
1442 
1443 	elem_addr = strtoul(argv[1], NULL, 0);
1444 
1445 	len = hex2bin(argv[2], label, sizeof(label));
1446 	memset(label + len, 0, sizeof(label) - len);
1447 
1448 	mod_id = strtoul(argv[3], NULL, 0);
1449 
1450 	if (argc > 4) {
1451 		cid = strtoul(argv[4], NULL, 0);
1452 		err = bt_mesh_cfg_mod_sub_va_del_vnd(net.net_idx, net.dst,
1453 						     elem_addr, label, mod_id,
1454 						     cid, &sub_addr, &status);
1455 	} else {
1456 		err = bt_mesh_cfg_mod_sub_va_del(net.net_idx, net.dst,
1457 						 elem_addr, label, mod_id,
1458 						 &sub_addr, &status);
1459 	}
1460 
1461 	if (err) {
1462 		printk("Unable to send Model Subscription Delete (err %d)\n",
1463 		       err);
1464 		return 0;
1465 	}
1466 
1467 	if (status) {
1468 		printk("Model Subscription Delete failed with status 0x%02x\n",
1469 		       status);
1470 	} else {
1471 		printk("0x%04x unsubscribed from Label UUID %s (va 0x%04x)\n",
1472 		       elem_addr, argv[2], sub_addr);
1473 	}
1474 
1475 	return 0;
1476 }
1477 
1478 struct shell_cmd_help cmd_mod_sub_del_va_help = {
1479 	NULL, "<elem addr> <Label UUID> <Model ID> [Company ID]", NULL
1480 };
1481 
mod_pub_get(u16_t addr,u16_t mod_id,u16_t cid)1482 static int mod_pub_get(u16_t addr, u16_t mod_id, u16_t cid)
1483 {
1484 	struct bt_mesh_cfg_mod_pub pub;
1485 	u8_t status;
1486 	int err;
1487 
1488 	if (cid == CID_NVAL) {
1489 		err = bt_mesh_cfg_mod_pub_get(net.net_idx, net.dst, addr,
1490 					      mod_id, &pub, &status);
1491 	} else {
1492 		err = bt_mesh_cfg_mod_pub_get_vnd(net.net_idx, net.dst, addr,
1493 						  mod_id, cid, &pub, &status);
1494 	}
1495 
1496 	if (err) {
1497 		printk("Model Publication Get failed (err %d)\n", err);
1498 		return 0;
1499 	}
1500 
1501 	if (status) {
1502 		printk("Model Publication Get failed (status 0x%02x)\n",
1503 		       status);
1504 		return 0;
1505 	}
1506 
1507 	printk("Model Publication for Element 0x%04x, Model 0x%04x:\n"
1508 	       "\tPublish Address:                0x%04x\n"
1509 	       "\tAppKeyIndex:                    0x%04x\n"
1510 	       "\tCredential Flag:                %u\n"
1511 	       "\tPublishTTL:                     %u\n"
1512 	       "\tPublishPeriod:                  0x%02x\n"
1513 	       "\tPublishRetransmitCount:         %u\n"
1514 	       "\tPublishRetransmitInterval:      %ums\n",
1515 	       addr, mod_id, pub.addr, pub.app_idx, pub.cred_flag, pub.ttl,
1516 	       pub.period, BT_MESH_PUB_TRANSMIT_COUNT(pub.transmit),
1517 	       BT_MESH_PUB_TRANSMIT_INT(pub.transmit));
1518 
1519 	return 0;
1520 }
1521 
mod_pub_set(u16_t addr,u16_t mod_id,u16_t cid,char * argv[])1522 static int mod_pub_set(u16_t addr, u16_t mod_id, u16_t cid, char *argv[])
1523 {
1524 	struct bt_mesh_cfg_mod_pub pub;
1525 	u8_t status, count;
1526 	u16_t interval;
1527 	int err;
1528 
1529 	pub.addr = strtoul(argv[0], NULL, 0);
1530 	pub.app_idx = strtoul(argv[1], NULL, 0);
1531 	pub.cred_flag = str2bool(argv[2]);
1532 	pub.ttl = strtoul(argv[3], NULL, 0);
1533 	pub.period = strtoul(argv[4], NULL, 0);
1534 
1535 	count = strtoul(argv[5], NULL, 0);
1536 	if (count > 7) {
1537 		printk("Invalid retransmit count\n");
1538 		return -EINVAL;
1539 	}
1540 
1541 	interval = strtoul(argv[6], NULL, 0);
1542 	if (interval > (31 * 50) || (interval % 50)) {
1543 		printk("Invalid retransmit interval %u\n", interval);
1544 		return -EINVAL;
1545 	}
1546 
1547 	pub.transmit = BT_MESH_PUB_TRANSMIT(count, interval);
1548 
1549 	if (cid == CID_NVAL) {
1550 		err = bt_mesh_cfg_mod_pub_set(net.net_idx, net.dst, addr,
1551 					      mod_id, &pub, &status);
1552 	} else {
1553 		err = bt_mesh_cfg_mod_pub_set_vnd(net.net_idx, net.dst, addr,
1554 						  mod_id, cid, &pub, &status);
1555 	}
1556 
1557 	if (err) {
1558 		printk("Model Publication Set failed (err %d)\n", err);
1559 		return 0;
1560 	}
1561 
1562 	if (status) {
1563 		printk("Model Publication Set failed (status 0x%02x)\n",
1564 		       status);
1565 	} else {
1566 		printk("Model Publication successfully set\n");
1567 	}
1568 
1569 	return 0;
1570 }
1571 
cmd_mod_pub(int argc,char * argv[])1572 static int cmd_mod_pub(int argc, char *argv[])
1573 {
1574 	u16_t addr, mod_id, cid;
1575 
1576 	if (argc < 3) {
1577 		return -EINVAL;
1578 	}
1579 
1580 	addr = strtoul(argv[1], NULL, 0);
1581 	mod_id = strtoul(argv[2], NULL, 0);
1582 
1583 	argc -= 3;
1584 	argv += 3;
1585 
1586 	if (argc == 1 || argc == 8) {
1587 		cid = strtoul(argv[0], NULL, 0);
1588 		argc--;
1589 		argv++;
1590 	} else {
1591 		cid = CID_NVAL;
1592 	}
1593 
1594 	if (argc > 0) {
1595 		if (argc < 7) {
1596 			return -EINVAL;
1597 		}
1598 
1599 		return mod_pub_set(addr, mod_id, cid, argv);
1600 	} else {
1601 		return mod_pub_get(addr, mod_id, cid);
1602 	}
1603 }
1604 
1605 struct shell_cmd_help cmd_mod_pub_help = {
1606 	NULL, "<addr> <mod id> [cid] [<PubAddr> "
1607 	"<AppKeyIndex> <cred> <ttl> <period> <count> <interval>]" , NULL
1608 };
1609 
hb_sub_print(struct bt_mesh_cfg_hb_sub * sub)1610 static void hb_sub_print(struct bt_mesh_cfg_hb_sub *sub)
1611 {
1612 	printk("Heartbeat Subscription:\n"
1613 	       "\tSource:      0x%04x\n"
1614 	       "\tDestination: 0x%04x\n"
1615 	       "\tPeriodLog:   0x%02x\n"
1616 	       "\tCountLog:    0x%02x\n"
1617 	       "\tMinHops:     %u\n"
1618 	       "\tMaxHops:     %u\n",
1619 	       sub->src, sub->dst, sub->period, sub->count,
1620 	       sub->min, sub->max);
1621 }
1622 
hb_sub_get(int argc,char * argv[])1623 static int hb_sub_get(int argc, char *argv[])
1624 {
1625 	struct bt_mesh_cfg_hb_sub sub;
1626 	u8_t status;
1627 	int err;
1628 
1629 	err = bt_mesh_cfg_hb_sub_get(net.net_idx, net.dst, &sub, &status);
1630 	if (err) {
1631 		printk("Heartbeat Subscription Get failed (err %d)\n", err);
1632 		return 0;
1633 	}
1634 
1635 	if (status) {
1636 		printk("Heartbeat Subscription Get failed (status 0x%02x)\n",
1637 		       status);
1638 	} else {
1639 		hb_sub_print(&sub);
1640 	}
1641 
1642 	return 0;
1643 }
1644 
hb_sub_set(int argc,char * argv[])1645 static int hb_sub_set(int argc, char *argv[])
1646 {
1647 	struct bt_mesh_cfg_hb_sub sub;
1648 	u8_t status;
1649 	int err;
1650 
1651 	sub.src = strtoul(argv[1], NULL, 0);
1652 	sub.dst = strtoul(argv[2], NULL, 0);
1653 	sub.period = strtoul(argv[3], NULL, 0);
1654 
1655 	err = bt_mesh_cfg_hb_sub_set(net.net_idx, net.dst, &sub, &status);
1656 	if (err) {
1657 		printk("Heartbeat Subscription Set failed (err %d)\n", err);
1658 		return 0;
1659 	}
1660 
1661 	if (status) {
1662 		printk("Heartbeat Subscription Set failed (status 0x%02x)\n",
1663 		       status);
1664 	} else {
1665 		hb_sub_print(&sub);
1666 	}
1667 
1668 	return 0;
1669 }
1670 
cmd_hb_sub(int argc,char * argv[])1671 static int cmd_hb_sub(int argc, char *argv[])
1672 {
1673 	if (argc > 1) {
1674 		if (argc < 4) {
1675 			return -EINVAL;
1676 		}
1677 
1678 		return hb_sub_set(argc, argv);
1679 	} else {
1680 		return hb_sub_get(argc, argv);
1681 	}
1682 }
1683 
1684 struct shell_cmd_help cmd_hb_sub_help = {
1685 	NULL, "<src> <dst> <period>", NULL
1686 };
1687 
hb_pub_get(int argc,char * argv[])1688 static int hb_pub_get(int argc, char *argv[])
1689 {
1690 	struct bt_mesh_cfg_hb_pub pub;
1691 	u8_t status;
1692 	int err;
1693 
1694 	err = bt_mesh_cfg_hb_pub_get(net.net_idx, net.dst, &pub, &status);
1695 	if (err) {
1696 		printk("Heartbeat Publication Get failed (err %d)\n", err);
1697 		return 0;
1698 	}
1699 
1700 	if (status) {
1701 		printk("Heartbeat Publication Get failed (status 0x%02x)\n",
1702 		       status);
1703 		return 0;
1704 	}
1705 
1706 	printk("Heartbeat publication:\n");
1707 	printk("\tdst 0x%04x count 0x%02x period 0x%02x\n",
1708 	       pub.dst, pub.count, pub.period);
1709 	printk("\tttl 0x%02x feat 0x%04x net_idx 0x%04x\n",
1710 	       pub.ttl, pub.feat, pub.net_idx);
1711 
1712 	return 0;
1713 }
1714 
hb_pub_set(int argc,char * argv[])1715 static int hb_pub_set(int argc, char *argv[])
1716 {
1717 	struct bt_mesh_cfg_hb_pub pub;
1718 	u8_t status;
1719 	int err;
1720 
1721 	pub.dst = strtoul(argv[1], NULL, 0);
1722 	pub.count = strtoul(argv[2], NULL, 0);
1723 	pub.period = strtoul(argv[3], NULL, 0);
1724 	pub.ttl = strtoul(argv[4], NULL, 0);
1725 	pub.feat = strtoul(argv[5], NULL, 0);
1726 	pub.net_idx = strtoul(argv[5], NULL, 0);
1727 
1728 	err = bt_mesh_cfg_hb_pub_set(net.net_idx, net.dst, &pub, &status);
1729 	if (err) {
1730 		printk("Heartbeat Publication Set failed (err %d)\n", err);
1731 		return 0;
1732 	}
1733 
1734 	if (status) {
1735 		printk("Heartbeat Publication Set failed (status 0x%02x)\n",
1736 		       status);
1737 	} else {
1738 		printk("Heartbeat publication successfully set\n");
1739 	}
1740 
1741 	return 0;
1742 }
1743 
cmd_hb_pub(int argc,char * argv[])1744 static int cmd_hb_pub(int argc, char *argv[])
1745 {
1746 	if (argc > 1) {
1747 		if (argc < 7) {
1748 			return -EINVAL;
1749 		}
1750 
1751 		return hb_pub_set(argc, argv);
1752 	} else {
1753 		return hb_pub_get(argc, argv);
1754 	}
1755 }
1756 
1757 struct shell_cmd_help cmd_hb_pub_help = {
1758 	NULL, "<dst> <count> <period> <ttl> <features> <NetKeyIndex>" , NULL
1759 };
1760 
1761 #endif /* MYNEWT_VAL(BLE_MESH_CFG_CLI) */
1762 
1763 #if MYNEWT_VAL(BLE_MESH_PROV)
cmd_pb(bt_mesh_prov_bearer_t bearer,int argc,char * argv[])1764 static int cmd_pb(bt_mesh_prov_bearer_t bearer, int argc, char *argv[])
1765 {
1766 	int err;
1767 
1768 	if (argc < 2) {
1769 		return -EINVAL;
1770 	}
1771 
1772 	if (str2bool(argv[1])) {
1773 		err = bt_mesh_prov_enable(bearer);
1774 		if (err) {
1775 			printk("Failed to enable %s (err %d)\n",
1776 			       bearer2str(bearer), err);
1777 		} else {
1778 			printk("%s enabled\n", bearer2str(bearer));
1779 		}
1780 	} else {
1781 		err = bt_mesh_prov_disable(bearer);
1782 		if (err) {
1783 			printk("Failed to disable %s (err %d)\n",
1784 			       bearer2str(bearer), err);
1785 		} else {
1786 			printk("%s disabled\n", bearer2str(bearer));
1787 		}
1788 	}
1789 
1790 	return 0;
1791 
1792 }
1793 
1794 struct shell_cmd_help cmd_pb_help = {
1795 	NULL, "<val: off, on>", NULL
1796 };
1797 
1798 #endif
1799 
1800 #if MYNEWT_VAL(BLE_MESH_PB_ADV)
cmd_pb_adv(int argc,char * argv[])1801 static int cmd_pb_adv(int argc, char *argv[])
1802 {
1803 	return cmd_pb(BT_MESH_PROV_ADV, argc, argv);
1804 }
1805 #endif /* CONFIG_BT_MESH_PB_ADV */
1806 
1807 #if MYNEWT_VAL(BLE_MESH_PB_GATT)
cmd_pb_gatt(int argc,char * argv[])1808 static int cmd_pb_gatt(int argc, char *argv[])
1809 {
1810 	return cmd_pb(BT_MESH_PROV_GATT, argc, argv);
1811 }
1812 #endif /* CONFIG_BT_MESH_PB_GATT */
1813 
cmd_provision(int argc,char * argv[])1814 static int cmd_provision(int argc, char *argv[])
1815 {
1816 	u16_t net_idx, addr;
1817 	u32_t iv_index;
1818 	int err;
1819 
1820 	if (argc < 3) {
1821 		return -EINVAL;
1822 	}
1823 
1824 	net_idx = strtoul(argv[1], NULL, 0);
1825 	addr = strtoul(argv[2], NULL, 0);
1826 
1827 	if (argc > 3) {
1828 		iv_index = strtoul(argv[3], NULL, 0);
1829 	} else {
1830 		iv_index = 0;
1831 	}
1832 
1833 	err = bt_mesh_provision(default_key, net_idx, 0, iv_index, addr,
1834 				default_key);
1835 	if (err) {
1836 		printk("Provisioning failed (err %d)\n", err);
1837 	}
1838 
1839 	return 0;
1840 }
1841 
1842 struct shell_cmd_help cmd_provision_help = {
1843 	NULL, "<NetKeyIndex> <addr> [IVIndex]" , NULL
1844 };
1845 
1846 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
1847 
cmd_fault_get(int argc,char * argv[])1848 static int cmd_fault_get(int argc, char *argv[])
1849 {
1850 	u8_t faults[32];
1851 	size_t fault_count;
1852 	u8_t test_id;
1853 	u16_t cid;
1854 	int err;
1855 
1856 	if (argc < 2) {
1857 		return -EINVAL;
1858 	}
1859 
1860 	cid = strtoul(argv[1], NULL, 0);
1861 	fault_count = sizeof(faults);
1862 
1863 	err = bt_mesh_health_fault_get(net.net_idx, net.dst, net.app_idx, cid,
1864 				       &test_id, faults, &fault_count);
1865 	if (err) {
1866 		printk("Failed to send Health Fault Get (err %d)\n", err);
1867 	} else {
1868 		show_faults(test_id, cid, faults, fault_count);
1869 	}
1870 
1871 	return 0;
1872 }
1873 
1874 struct shell_cmd_help cmd_fault_get_help = {
1875 	NULL, "<Company ID>", NULL
1876 };
1877 
cmd_fault_clear(int argc,char * argv[])1878 static int cmd_fault_clear(int argc, char *argv[])
1879 {
1880 	u8_t faults[32];
1881 	size_t fault_count;
1882 	u8_t test_id;
1883 	u16_t cid;
1884 	int err;
1885 
1886 	if (argc < 2) {
1887 		return -EINVAL;
1888 	}
1889 
1890 	cid = strtoul(argv[1], NULL, 0);
1891 	fault_count = sizeof(faults);
1892 
1893 	err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
1894 					 cid, &test_id, faults, &fault_count);
1895 	if (err) {
1896 		printk("Failed to send Health Fault Clear (err %d)\n", err);
1897 	} else {
1898 		show_faults(test_id, cid, faults, fault_count);
1899 	}
1900 
1901 	return 0;
1902 }
1903 
1904 struct shell_cmd_help cmd_fault_clear_help = {
1905 	NULL, "<Company ID>", NULL
1906 };
1907 
cmd_fault_clear_unack(int argc,char * argv[])1908 static int cmd_fault_clear_unack(int argc, char *argv[])
1909 {
1910 	u16_t cid;
1911 	int err;
1912 
1913 	if (argc < 2) {
1914 		return -EINVAL;
1915 	}
1916 
1917 	cid = strtoul(argv[1], NULL, 0);
1918 
1919 	err = bt_mesh_health_fault_clear(net.net_idx, net.dst, net.app_idx,
1920 					 cid, NULL, NULL, NULL);
1921 	if (err) {
1922 		printk("Health Fault Clear Unacknowledged failed (err %d)\n",
1923 		       err);
1924 	}
1925 
1926 	return 0;
1927 }
1928 
1929 struct shell_cmd_help cmd_fault_clear_unack_help = {
1930 	NULL, "<Company ID>", NULL
1931 };
1932 
cmd_fault_test(int argc,char * argv[])1933 static int cmd_fault_test(int argc, char *argv[])
1934 {
1935 	u8_t faults[32];
1936 	size_t fault_count;
1937 	u8_t test_id;
1938 	u16_t cid;
1939 	int err;
1940 
1941 	if (argc < 3) {
1942 		return -EINVAL;
1943 	}
1944 
1945 	cid = strtoul(argv[1], NULL, 0);
1946 	test_id = strtoul(argv[2], NULL, 0);
1947 	fault_count = sizeof(faults);
1948 
1949 	err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
1950 					cid, test_id, faults, &fault_count);
1951 	if (err) {
1952 		printk("Failed to send Health Fault Test (err %d)\n", err);
1953 	} else {
1954 		show_faults(test_id, cid, faults, fault_count);
1955 	}
1956 
1957 	return 0;
1958 }
1959 
1960 struct shell_cmd_help cmd_fault_test_help = {
1961 	NULL, "<Company ID> <Test ID>", NULL
1962 };
1963 
cmd_fault_test_unack(int argc,char * argv[])1964 static int cmd_fault_test_unack(int argc, char *argv[])
1965 {
1966 	u16_t cid;
1967 	u8_t test_id;
1968 	int err;
1969 
1970 	if (argc < 3) {
1971 		return -EINVAL;
1972 	}
1973 
1974 	cid = strtoul(argv[1], NULL, 0);
1975 	test_id = strtoul(argv[2], NULL, 0);
1976 
1977 	err = bt_mesh_health_fault_test(net.net_idx, net.dst, net.app_idx,
1978 					cid, test_id, NULL, NULL);
1979 	if (err) {
1980 		printk("Health Fault Test Unacknowledged failed (err %d)\n",
1981 		       err);
1982 	}
1983 
1984 	return 0;
1985 }
1986 
1987 struct shell_cmd_help cmd_fault_test_unack_help = {
1988 	NULL, "<Company ID> <Test ID>", NULL
1989 };
1990 
cmd_period_get(int argc,char * argv[])1991 static int cmd_period_get(int argc, char *argv[])
1992 {
1993 	u8_t divisor;
1994 	int err;
1995 
1996 	err = bt_mesh_health_period_get(net.net_idx, net.dst, net.app_idx,
1997 					&divisor);
1998 	if (err) {
1999 		printk("Failed to send Health Period Get (err %d)\n", err);
2000 	} else {
2001 		printk("Health FastPeriodDivisor: %u\n", divisor);
2002 	}
2003 
2004 	return 0;
2005 }
2006 
cmd_period_set(int argc,char * argv[])2007 static int cmd_period_set(int argc, char *argv[])
2008 {
2009 	u8_t divisor, updated_divisor;
2010 	int err;
2011 
2012 	if (argc < 2) {
2013 		return -EINVAL;
2014 	}
2015 
2016 	divisor = strtoul(argv[1], NULL, 0);
2017 
2018 	err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
2019 					divisor, &updated_divisor);
2020 	if (err) {
2021 		printk("Failed to send Health Period Set (err %d)\n", err);
2022 	} else {
2023 		printk("Health FastPeriodDivisor: %u\n", updated_divisor);
2024 	}
2025 
2026 	return 0;
2027 }
2028 
2029 struct shell_cmd_help cmd_period_set_help = {
2030 	NULL, "<divisor>", NULL
2031 };
2032 
cmd_period_set_unack(int argc,char * argv[])2033 static int cmd_period_set_unack(int argc, char *argv[])
2034 {
2035 	u8_t divisor;
2036 	int err;
2037 
2038 	if (argc < 2) {
2039 		return -EINVAL;
2040 	}
2041 
2042 	divisor = strtoul(argv[1], NULL, 0);
2043 
2044 	err = bt_mesh_health_period_set(net.net_idx, net.dst, net.app_idx,
2045 					divisor, NULL);
2046 	if (err) {
2047 		printk("Failed to send Health Period Set (err %d)\n", err);
2048 	}
2049 
2050 	return 0;
2051 }
2052 
2053 struct shell_cmd_help cmd_period_set_unack_help = {
2054 	NULL, "<divisor>", NULL
2055 };
2056 
cmd_attention_get(int argc,char * argv[])2057 static int cmd_attention_get(int argc, char *argv[])
2058 {
2059 	u8_t attention;
2060 	int err;
2061 
2062 	err = bt_mesh_health_attention_get(net.net_idx, net.dst, net.app_idx,
2063 					   &attention);
2064 	if (err) {
2065 		printk("Failed to send Health Attention Get (err %d)\n", err);
2066 	} else {
2067 		printk("Health Attention Timer: %u\n", attention);
2068 	}
2069 
2070 	return 0;
2071 }
2072 
cmd_attention_set(int argc,char * argv[])2073 static int cmd_attention_set(int argc, char *argv[])
2074 {
2075 	u8_t attention, updated_attention;
2076 	int err;
2077 
2078 	if (argc < 2) {
2079 		return -EINVAL;
2080 	}
2081 
2082 	attention = strtoul(argv[1], NULL, 0);
2083 
2084 	err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
2085 					   attention, &updated_attention);
2086 	if (err) {
2087 		printk("Failed to send Health Attention Set (err %d)\n", err);
2088 	} else {
2089 		printk("Health Attention Timer: %u\n", updated_attention);
2090 	}
2091 
2092 	return 0;
2093 }
2094 
2095 struct shell_cmd_help cmd_attention_set_help = {
2096 	NULL, "<timer>", NULL
2097 };
2098 
cmd_attention_set_unack(int argc,char * argv[])2099 static int cmd_attention_set_unack(int argc, char *argv[])
2100 {
2101 	u8_t attention;
2102 	int err;
2103 
2104 	if (argc < 2) {
2105 		return -EINVAL;
2106 	}
2107 
2108 	attention = strtoul(argv[1], NULL, 0);
2109 
2110 	err = bt_mesh_health_attention_set(net.net_idx, net.dst, net.app_idx,
2111 					   attention, NULL);
2112 	if (err) {
2113 		printk("Failed to send Health Attention Set (err %d)\n", err);
2114 	}
2115 
2116 	return 0;
2117 }
2118 
2119 struct shell_cmd_help cmd_attention_set_unack_help = {
2120 	NULL, "<timer>", NULL
2121 };
2122 
2123 #endif /* MYNEWT_VAL(BLE_MESH_HEALTH_CLI) */
2124 
cmd_add_fault(int argc,char * argv[])2125 static int cmd_add_fault(int argc, char *argv[])
2126 {
2127 	u8_t fault_id;
2128 	u8_t i;
2129 
2130 	if (argc < 2) {
2131 		return -EINVAL;
2132 	}
2133 
2134 	fault_id = strtoul(argv[1], NULL, 0);
2135 	if (!fault_id) {
2136 		printk("The Fault ID must be non-zero!\n");
2137 		return -EINVAL;
2138 	}
2139 
2140 	for (i = 0; i < sizeof(cur_faults); i++) {
2141 		if (!cur_faults[i]) {
2142 			cur_faults[i] = fault_id;
2143 			break;
2144 		}
2145 	}
2146 
2147 	if (i == sizeof(cur_faults)) {
2148 		printk("Fault array is full. Use \"del-fault\" to clear it\n");
2149 		return 0;
2150 	}
2151 
2152 	for (i = 0; i < sizeof(reg_faults); i++) {
2153 		if (!reg_faults[i]) {
2154 			reg_faults[i] = fault_id;
2155 			break;
2156 		}
2157 	}
2158 
2159 	if (i == sizeof(reg_faults)) {
2160 		printk("No space to store more registered faults\n");
2161 	}
2162 
2163 	bt_mesh_fault_update(&elements[0]);
2164 
2165 	return 0;
2166 }
2167 
2168 struct shell_cmd_help cmd_add_fault_help = {
2169 	NULL, "<Fault ID>", NULL
2170 };
2171 
cmd_del_fault(int argc,char * argv[])2172 static int cmd_del_fault(int argc, char *argv[])
2173 {
2174 	u8_t fault_id;
2175 	u8_t i;
2176 
2177 	if (argc < 2) {
2178 		memset(cur_faults, 0, sizeof(cur_faults));
2179 		printk("All current faults cleared\n");
2180 		bt_mesh_fault_update(&elements[0]);
2181 		return 0;
2182 	}
2183 
2184 	fault_id = strtoul(argv[1], NULL, 0);
2185 	if (!fault_id) {
2186 		printk("The Fault ID must be non-zero!\n");
2187 		return -EINVAL;
2188 	}
2189 
2190 	for (i = 0; i < sizeof(cur_faults); i++) {
2191 		if (cur_faults[i] == fault_id) {
2192 			cur_faults[i] = 0;
2193 			printk("Fault cleared\n");
2194 		}
2195 	}
2196 
2197 	bt_mesh_fault_update(&elements[0]);
2198 
2199 	return 0;
2200 }
2201 
2202 struct shell_cmd_help cmd_del_fault_help = {
2203 	NULL, "[Fault ID]", NULL
2204 };
2205 
2206 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
cmd_gen_onoff_get(int argc,char * argv[])2207 static int cmd_gen_onoff_get(int argc, char *argv[])
2208 {
2209 	u8_t state;
2210 	int err;
2211 
2212 	err = bt_mesh_gen_onoff_get(net.net_idx, net.dst, net.app_idx,
2213 				    &state);
2214 	if (err) {
2215 		printk("Failed to send Generic OnOff Get (err %d)\n", err);
2216 	} else {
2217 		printk("Gen OnOff State %d\n", state);
2218 	}
2219 
2220 	return 0;
2221 }
2222 
cmd_gen_onoff_set(int argc,char * argv[])2223 static int cmd_gen_onoff_set(int argc, char *argv[])
2224 {
2225 	u8_t state;
2226 	u8_t val;
2227 	int err;
2228 
2229 	if (argc < 2) {
2230 		return -EINVAL;
2231 	}
2232 
2233 	val = strtoul(argv[1], NULL, 0);
2234 
2235 	err = bt_mesh_gen_onoff_set(net.net_idx, net.dst, net.app_idx,
2236 				    val, &state);
2237 	if (err) {
2238 		printk("Failed to send Generic OnOff Get (err %d)\n", err);
2239 	} else {
2240 		printk("Gen OnOff State %d\n", state);
2241 	}
2242 
2243 	return 0;
2244 }
2245 
2246 struct shell_cmd_help cmd_gen_onoff_set_help = {
2247 	NULL, "<0|1>", NULL
2248 };
2249 
cmd_gen_onoff_set_unack(int argc,char * argv[])2250 static int cmd_gen_onoff_set_unack(int argc, char *argv[])
2251 {
2252 	u8_t val;
2253 	int err;
2254 
2255 	if (argc < 2) {
2256 		return -EINVAL;
2257 	}
2258 
2259 	val = strtoul(argv[1], NULL, 0);
2260 
2261 	err = bt_mesh_gen_onoff_set(net.net_idx, net.dst, net.app_idx,
2262 				    val, NULL);
2263 	if (err) {
2264 		printk("Failed to send Generic OnOff Get (err %d)\n", err);
2265 	}
2266 
2267 	return 0;
2268 }
2269 
2270 struct shell_cmd_help cmd_gen_onoff_set_unack_help = {
2271 	NULL, "<0|1>", NULL
2272 };
2273 
cmd_gen_level_get(int argc,char * argv[])2274 static int cmd_gen_level_get(int argc, char *argv[])
2275 {
2276 	s16_t state;
2277 	int err;
2278 
2279 	err = bt_mesh_gen_level_get(net.net_idx, net.dst, net.app_idx,
2280 				    &state);
2281 	if (err) {
2282 		printk("Failed to send Generic Level Get (err %d)\n", err);
2283 	} else {
2284 		printk("Gen Level State %d\n", state);
2285 	}
2286 
2287 	return 0;
2288 }
2289 
cmd_gen_level_set(int argc,char * argv[])2290 static int cmd_gen_level_set(int argc, char *argv[])
2291 {
2292 	s16_t state;
2293 	s16_t val;
2294 	int err;
2295 
2296 	if (argc < 2) {
2297 		return -EINVAL;
2298 	}
2299 
2300 	val = (s16_t)strtoul(argv[1], NULL, 0);
2301 
2302 	err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
2303 				    val, &state);
2304 	if (err) {
2305 		printk("Failed to send Generic Level Get (err %d)\n", err);
2306 	} else {
2307 		printk("Gen Level State %d\n", state);
2308 	}
2309 
2310 	return 0;
2311 }
2312 
2313 struct shell_cmd_help cmd_gen_level_set_help = {
2314 	NULL, "<level>", NULL
2315 };
2316 
cmd_gen_level_set_unack(int argc,char * argv[])2317 static int cmd_gen_level_set_unack(int argc, char *argv[])
2318 {
2319 	s16_t val;
2320 	int err;
2321 
2322 	if (argc < 2) {
2323 		return -EINVAL;
2324 	}
2325 
2326 	val = (s16_t)strtoul(argv[1], NULL, 0);
2327 
2328 	err = bt_mesh_gen_level_set(net.net_idx, net.dst, net.app_idx,
2329 				    val, NULL);
2330 	if (err) {
2331 		printk("Failed to send Generic Level Get (err %d)\n", err);
2332 	}
2333 
2334 	return 0;
2335 }
2336 
2337 struct shell_cmd_help cmd_gen_level_set_unack_help = {
2338 	NULL, "<level>", NULL
2339 };
2340 
2341 #endif /* MYNEWT_VAL(BLE_MESH_SHELL_MODELS) */
2342 
cmd_print_credentials(int argc,char * argv[])2343 static int cmd_print_credentials(int argc, char *argv[])
2344 {
2345 	bt_test_print_credentials();
2346 	return 0;
2347 }
2348 
print_comp_elem(struct bt_mesh_elem * elem,bool primary)2349 static void print_comp_elem(struct bt_mesh_elem *elem,
2350 			    bool primary)
2351 {
2352 	struct bt_mesh_model *mod;
2353 	int i;
2354 
2355 	printk("Loc: %u\n", elem->loc);
2356 	printk("Model count: %u\n", elem->model_count);
2357 	printk("Vnd model count: %u\n", elem->vnd_model_count);
2358 
2359 	for (i = 0; i < elem->model_count; i++) {
2360 		mod = &elem->models[i];
2361 		printk("  Model: %u\n", i);
2362 		printk("    ID: 0x%04x\n", mod->id);
2363 		printk("    Opcode: 0x%08lx\n", mod->op->opcode);
2364 	}
2365 
2366 	for (i = 0; i < elem->vnd_model_count; i++) {
2367 		mod = &elem->vnd_models[i];
2368 		printk("  Vendor model: %u\n", i);
2369 		printk("    Company: 0x%04x\n", mod->vnd.company);
2370 		printk("    ID: 0x%04x\n", mod->vnd.id);
2371 		printk("    Opcode: 0x%08lx\n", mod->op->opcode);
2372 	}
2373 }
2374 
cmd_print_composition_data(int argc,char * argv[])2375 static int cmd_print_composition_data(int argc, char *argv[])
2376 {
2377 	const struct bt_mesh_comp *comp;
2378 	int i;
2379 
2380 	comp = bt_mesh_comp_get();
2381 
2382 	printk("CID: %u\n", comp->cid);
2383 	printk("PID: %u\n", comp->pid);
2384 	printk("VID: %u\n", comp->vid);
2385 
2386 	for (i = 0; i < comp->elem_count; i++) {
2387 		print_comp_elem(&comp->elem[i], i == 0);
2388 	}
2389 
2390 	return 0;
2391 }
2392 
2393 static const struct shell_cmd mesh_commands[] = {
2394 	{ "init", cmd_mesh_init, NULL },
2395 #if MYNEWT_VAL(BLE_MESH_PB_ADV)
2396 	{ "pb-adv", cmd_pb_adv, &cmd_pb_help },
2397 #endif
2398 #if MYNEWT_VAL(BLE_MESH_PB_GATT)
2399 	{ "pb-gatt", cmd_pb_gatt, &cmd_pb_help },
2400 #endif
2401 	{ "reset", cmd_reset, NULL },
2402 	{ "uuid", cmd_uuid, &cmd_uuid_help },
2403 	{ "input-num", cmd_input_num, &cmd_input_num_help },
2404 	{ "input-str", cmd_input_str, &cmd_input_str_help },
2405 	{ "static-oob", cmd_static_oob, &cmd_static_oob_help },
2406 	{ "provision", cmd_provision, &cmd_provision_help },
2407 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
2408 	{ "lpn", cmd_lpn, &cmd_lpn_help },
2409 	{ "poll", cmd_poll, NULL },
2410 #endif
2411 #if MYNEWT_VAL(BLE_MESH_GATT_PROXY)
2412 	{ "ident", cmd_ident, NULL },
2413 #endif
2414 	{ "dst", cmd_dst, &cmd_dst_help },
2415 	{ "netidx", cmd_netidx, &cmd_netidx_help },
2416 	{ "appidx", cmd_appidx, &cmd_appidx_help },
2417 
2418 	/* Commands which access internal APIs, for testing only */
2419 	{ "net-send", cmd_net_send, &cmd_net_send_help },
2420 	{ "iv-update", cmd_iv_update, NULL },
2421 	{ "iv-update-test", cmd_iv_update_test, &cmd_iv_update_test_help },
2422 	{ "rpl-clear", cmd_rpl_clear, NULL },
2423 #if MYNEWT_VAL(BLE_MESH_LOW_POWER)
2424 	{ "lpn-subscribe", cmd_lpn_subscribe, &cmd_lpn_subscribe_help },
2425 	{ "lpn-unsubscribe", cmd_lpn_unsubscribe, &cmd_lpn_unsubscribe_help },
2426 #endif
2427 	{ "print-credentials", cmd_print_credentials, NULL },
2428 	{ "print-composition-data", cmd_print_composition_data, NULL },
2429 
2430 
2431 #if MYNEWT_VAL(BLE_MESH_CFG_CLI)
2432 	/* Configuration Client Model operations */
2433 	{ "timeout", cmd_timeout, &cmd_timeout_help },
2434 	{ "get-comp", cmd_get_comp, &cmd_get_comp_help },
2435 	{ "beacon", cmd_beacon, &cmd_beacon_help },
2436 	{ "ttl", cmd_ttl, &cmd_ttl_help},
2437 	{ "friend", cmd_friend, &cmd_friend_help },
2438 	{ "gatt-proxy", cmd_gatt_proxy, &cmd_gatt_proxy_help },
2439 	{ "relay", cmd_relay, &cmd_relay_help },
2440 	{ "net-key-add", cmd_net_key_add, &cmd_net_key_add_help },
2441 	{ "app-key-add", cmd_app_key_add, &cmd_app_key_add_help },
2442 	{ "mod-app-bind", cmd_mod_app_bind, &cmd_mod_app_bind_help },
2443 	{ "mod-pub", cmd_mod_pub, &cmd_mod_pub_help },
2444 	{ "mod-sub-add", cmd_mod_sub_add, &cmd_mod_sub_add_help },
2445 	{ "mod-sub-del", cmd_mod_sub_del, &cmd_mod_sub_del_help },
2446 	{ "mod-sub-add-va", cmd_mod_sub_add_va, &cmd_mod_sub_add_va_help },
2447 	{ "mod-sub-del-va", cmd_mod_sub_del_va, &cmd_mod_sub_del_va_help },
2448 	{ "hb-sub", cmd_hb_sub, &cmd_hb_sub_help },
2449 	{ "hb-pub", cmd_hb_pub, &cmd_hb_pub_help },
2450 #endif
2451 
2452 #if MYNEWT_VAL(BLE_MESH_HEALTH_CLI)
2453 	/* Health Client Model Operations */
2454 	{ "fault-get", cmd_fault_get, &cmd_fault_get_help },
2455 	{ "fault-clear", cmd_fault_clear, &cmd_fault_clear_help },
2456 	{ "fault-clear-unack", cmd_fault_clear_unack, &cmd_fault_clear_unack_help },
2457 	{ "fault-test", cmd_fault_test, &cmd_fault_test_help },
2458 	{ "fault-test-unack", cmd_fault_test_unack, &cmd_fault_test_unack_help },
2459 	{ "period-get", cmd_period_get, NULL },
2460 	{ "period-set", cmd_period_set, &cmd_period_set_help },
2461 	{ "period-set-unack", cmd_period_set_unack, &cmd_period_set_unack_help },
2462 	{ "attention-get", cmd_attention_get, NULL },
2463 	{ "attention-set", cmd_attention_set, &cmd_attention_set_help },
2464 	{ "attention-set-unack", cmd_attention_set_unack, &cmd_attention_set_unack_help },
2465 #endif
2466 
2467 	/* Health Server Model Operations */
2468 	{ "add-fault", cmd_add_fault, &cmd_add_fault_help },
2469 	{ "del-fault", cmd_del_fault, &cmd_del_fault_help },
2470 
2471 #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS)
2472 	/* Generic Client Model Operations */
2473 	{ "gen-onoff-get", cmd_gen_onoff_get, NULL },
2474 	{ "gen-onoff-set", cmd_gen_onoff_set, &cmd_gen_onoff_set_help },
2475 	{ "gen-onoff-set-unack", cmd_gen_onoff_set_unack, &cmd_gen_onoff_set_unack_help },
2476 	{ "gen-level-get", cmd_gen_level_get, NULL },
2477 	{ "gen-level-set", cmd_gen_level_set, &cmd_gen_level_set_help },
2478 	{ "gen-level-set-unack", cmd_gen_level_set_unack, &cmd_gen_level_set_unack_help },
2479 #endif
2480 
2481 	{ NULL, NULL, NULL}
2482 };
2483 
mesh_shell_thread(void * args)2484 static void mesh_shell_thread(void *args)
2485 {
2486 	while (1) {
2487 		os_eventq_run(&mesh_shell_queue);
2488 	}
2489 }
2490 
bt_mesh_shell_task_init(void)2491 static void bt_mesh_shell_task_init(void)
2492 {
2493 	os_eventq_init(&mesh_shell_queue);
2494 
2495 	os_task_init(&mesh_shell_task, "mesh_sh", mesh_shell_thread, NULL,
2496 		     BLE_MESH_SHELL_TASK_PRIO, OS_WAIT_FOREVER, g_blemesh_shell_stack,
2497 		     BLE_MESH_SHELL_STACK_SIZE);
2498 }
2499 #endif
2500 
ble_mesh_shell_init(void)2501 void ble_mesh_shell_init(void)
2502 {
2503 #if (MYNEWT_VAL(BLE_MESH_SHELL))
2504 
2505 	/* Initialize health pub message */
2506 	health_pub_init();
2507 
2508 	/* Shell and other mesh clients should use separate task to
2509 	   avoid deadlocks with mesh message processing queue */
2510 	bt_mesh_shell_task_init();
2511 	shell_evq_set(&mesh_shell_queue);
2512 	shell_register("mesh", mesh_commands);
2513 
2514 #endif
2515 }
2516