1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2017 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <sys/printk.h>
10 
11 #include <settings/settings.h>
12 
13 #include <bluetooth/bluetooth.h>
14 #include <bluetooth/mesh.h>
15 
16 #include "board.h"
17 
18 #define MOD_LF 0x0000
19 
20 #define GROUP_ADDR 0xc000
21 #define PUBLISHER_ADDR  0x000f
22 
23 #define OP_VENDOR_BUTTON BT_MESH_MODEL_OP_3(0x00, BT_COMP_ID_LF)
24 
25 static const uint8_t net_key[16] = {
26 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
27 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
28 };
29 static const uint8_t dev_key[16] = {
30 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
31 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
32 };
33 static const uint8_t app_key[16] = {
34 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
35 	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
36 };
37 static const uint16_t net_idx;
38 static const uint16_t app_idx;
39 static const uint32_t iv_index;
40 static uint8_t flags;
41 static uint16_t addr = NODE_ADDR;
42 
heartbeat(const struct bt_mesh_hb_sub * sub,uint8_t hops,uint16_t feat)43 static void heartbeat(const struct bt_mesh_hb_sub *sub, uint8_t hops,
44 		      uint16_t feat)
45 {
46 	board_heartbeat(hops, feat);
47 	board_play("100H");
48 }
49 
50 static struct bt_mesh_cfg_cli cfg_cli = {
51 };
52 
attention_on(struct bt_mesh_model * model)53 static void attention_on(struct bt_mesh_model *model)
54 {
55 	printk("attention_on()\n");
56 	board_attention(true);
57 	board_play("100H100C100H100C100H100C");
58 }
59 
attention_off(struct bt_mesh_model * model)60 static void attention_off(struct bt_mesh_model *model)
61 {
62 	printk("attention_off()\n");
63 	board_attention(false);
64 }
65 
66 static const struct bt_mesh_health_srv_cb health_srv_cb = {
67 	.attn_on = attention_on,
68 	.attn_off = attention_off,
69 };
70 
71 static struct bt_mesh_health_srv health_srv = {
72 	.cb = &health_srv_cb,
73 };
74 
75 BT_MESH_HEALTH_PUB_DEFINE(health_pub, 0);
76 
77 static struct bt_mesh_model root_models[] = {
78 	BT_MESH_MODEL_CFG_SRV,
79 	BT_MESH_MODEL_CFG_CLI(&cfg_cli),
80 	BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
81 };
82 
vnd_button_pressed(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)83 static int vnd_button_pressed(struct bt_mesh_model *model,
84 			       struct bt_mesh_msg_ctx *ctx,
85 			       struct net_buf_simple *buf)
86 {
87 	printk("src 0x%04x\n", ctx->addr);
88 
89 	if (ctx->addr == bt_mesh_model_elem(model)->addr) {
90 		return 0;
91 	}
92 
93 	board_other_dev_pressed(ctx->addr);
94 	board_play("100G200 100G");
95 
96 	return 0;
97 }
98 
99 static const struct bt_mesh_model_op vnd_ops[] = {
100 	{ OP_VENDOR_BUTTON, BT_MESH_LEN_EXACT(0), vnd_button_pressed },
101 	BT_MESH_MODEL_OP_END,
102 };
103 
104 static struct bt_mesh_model vnd_models[] = {
105 	BT_MESH_MODEL_VND(BT_COMP_ID_LF, MOD_LF, vnd_ops, NULL, NULL),
106 };
107 
108 static struct bt_mesh_elem elements[] = {
109 	BT_MESH_ELEM(0, root_models, vnd_models),
110 };
111 
112 static const struct bt_mesh_comp comp = {
113 	.cid = BT_COMP_ID_LF,
114 	.elem = elements,
115 	.elem_count = ARRAY_SIZE(elements),
116 };
117 
configure(void)118 static void configure(void)
119 {
120 	printk("Configuring...\n");
121 
122 	/* Add Application Key */
123 	bt_mesh_cfg_app_key_add(net_idx, addr, net_idx, app_idx, app_key, NULL);
124 
125 	/* Bind to vendor model */
126 	bt_mesh_cfg_mod_app_bind_vnd(net_idx, addr, addr, app_idx,
127 				     MOD_LF, BT_COMP_ID_LF, NULL);
128 
129 	/* Bind to Health model */
130 	bt_mesh_cfg_mod_app_bind(net_idx, addr, addr, app_idx,
131 				 BT_MESH_MODEL_ID_HEALTH_SRV, NULL);
132 
133 	/* Add model subscription */
134 	bt_mesh_cfg_mod_sub_add_vnd(net_idx, addr, addr, GROUP_ADDR,
135 				    MOD_LF, BT_COMP_ID_LF, NULL);
136 
137 #if NODE_ADDR == PUBLISHER_ADDR
138 	{
139 		struct bt_mesh_cfg_hb_pub pub = {
140 			.dst = GROUP_ADDR,
141 			.count = 0xff,
142 			.period = 0x05,
143 			.ttl = 0x07,
144 			.feat = 0,
145 			.net_idx = net_idx,
146 		};
147 
148 		bt_mesh_cfg_hb_pub_set(net_idx, addr, &pub, NULL);
149 		printk("Publishing heartbeat messages\n");
150 	}
151 #endif
152 	printk("Configuration complete\n");
153 
154 	board_play("100C100D100E100F100G100A100H");
155 }
156 
157 static const uint8_t dev_uuid[16] = { 0xdd, 0xdd };
158 
159 static const struct bt_mesh_prov prov = {
160 	.uuid = dev_uuid,
161 };
162 
163 BT_MESH_HB_CB_DEFINE(hb_cb) = {
164 	.recv = heartbeat,
165 };
166 
bt_ready(int err)167 static void bt_ready(int err)
168 {
169 	if (err) {
170 		printk("Bluetooth init failed (err %d)\n", err);
171 		return;
172 	}
173 
174 	printk("Bluetooth initialized\n");
175 
176 	err = bt_mesh_init(&prov, &comp);
177 	if (err) {
178 		printk("Initializing mesh failed (err %d)\n", err);
179 		return;
180 	}
181 
182 	printk("Mesh initialized\n");
183 
184 	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
185 		printk("Loading stored settings\n");
186 		settings_load();
187 	}
188 
189 	err = bt_mesh_provision(net_key, net_idx, flags, iv_index, addr,
190 				dev_key);
191 	if (err == -EALREADY) {
192 		printk("Using stored settings\n");
193 	} else if (err) {
194 		printk("Provisioning failed (err %d)\n", err);
195 		return;
196 	} else {
197 		printk("Provisioning completed\n");
198 		configure();
199 	}
200 
201 #if NODE_ADDR != PUBLISHER_ADDR
202 	/* Heartbeat subcscription is a temporary state (due to there
203 	 * not being an "indefinite" value for the period, so it never
204 	 * gets stored persistently. Therefore, we always have to configure
205 	 * it explicitly.
206 	 */
207 	{
208 		struct bt_mesh_cfg_hb_sub sub = {
209 			.src = PUBLISHER_ADDR,
210 			.dst = GROUP_ADDR,
211 			.period = 0x10,
212 		};
213 
214 		bt_mesh_cfg_hb_sub_set(net_idx, addr, &sub, NULL);
215 		printk("Subscribing to heartbeat messages\n");
216 	}
217 #endif
218 }
219 
220 static uint16_t target = GROUP_ADDR;
221 
board_button_1_pressed(void)222 void board_button_1_pressed(void)
223 {
224 	NET_BUF_SIMPLE_DEFINE(msg, 3 + 4);
225 	struct bt_mesh_msg_ctx ctx = {
226 		.app_idx = app_idx,
227 		.addr = target,
228 		.send_ttl = BT_MESH_TTL_DEFAULT,
229 	};
230 
231 	/* Bind to Health model */
232 	bt_mesh_model_msg_init(&msg, OP_VENDOR_BUTTON);
233 
234 	if (bt_mesh_model_send(&vnd_models[0], &ctx, &msg, NULL, NULL)) {
235 		printk("Unable to send Vendor Button message\n");
236 	}
237 
238 	printk("Button message sent with OpCode 0x%08x\n", OP_VENDOR_BUTTON);
239 }
240 
board_set_target(void)241 uint16_t board_set_target(void)
242 {
243 	switch (target) {
244 	case GROUP_ADDR:
245 		target = 1U;
246 		break;
247 	case 9:
248 		target = GROUP_ADDR;
249 		break;
250 	default:
251 		target++;
252 		break;
253 	}
254 
255 	return target;
256 }
257 
258 static K_SEM_DEFINE(tune_sem, 0, 1);
259 static const char *tune_str;
260 
board_play(const char * str)261 void board_play(const char *str)
262 {
263 	tune_str = str;
264 	k_sem_give(&tune_sem);
265 }
266 
main(void)267 void main(void)
268 {
269 	int err;
270 
271 	printk("Initializing...\n");
272 
273 	err = board_init(&addr);
274 	if (err) {
275 		printk("Board initialization failed\n");
276 		return;
277 	}
278 
279 	printk("Unicast address: 0x%04x\n", addr);
280 
281 	/* Initialize the Bluetooth Subsystem */
282 	err = bt_enable(bt_ready);
283 	if (err) {
284 		printk("Bluetooth init failed (err %d)\n", err);
285 		return;
286 	}
287 
288 	while (1) {
289 		k_sem_take(&tune_sem, K_FOREVER);
290 		board_play_tune(tune_str);
291 	}
292 
293 }
294