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