1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <api/mesh.h>
8
9 #include "provisioner_prov.h"
10 #include "provisioner_main.h"
11 #include "provisioner_proxy.h"
12
13 #include "mesh_provisioner.h"
14
15 #ifdef CONFIG_BT_MESH_PROVISIONER
16
17 typedef struct _mesh_provisoner {
18 provisioner_cb prov_cb;
19
20 uint8_t filter_policy;
21 uint8_t uuid_filter[16];
22 uint8_t uuid_filter_start;
23 uint8_t uuid_filter_length;
24
25 k_timer_t found_dev_timer;
26 uint32_t found_dev_timeout;//
27
28 uint8_t init_flag: 1;
29 uint8_t filter_flag: 1;
30 uint8_t found_dev_succeed: 1;
31 uint8_t prov_dev_succeed: 1;
32 uint8_t prov_show_dev: 1;
33 uint8_t enable: 1;
34 struct bt_mesh_device_delete del_dev;
35 ble_mesh_provisioner_t comp;
36 } mesh_provisoner;
37
38 #define TAG "BT_MESH_PROVISIONER"
39
40 #define COMMON_SUB_ADDR 0xF001
41 #define COMMON_PUB_ADDR 0xF000
42 #define K_FOREVER -1
43 #define UUID_FILTER_MAX_LENGTH 16
44 #define STATIC_OOB_MAX_LENGTH 16
45 #define LOCAL_USER_TERM_CONN 0x16
46 extern struct k_sem prov_input_sem;
47 u8_t prov_input[8];
48 u8_t prov_input_size;
49 static uint8_t g_static_oob_data[STATIC_OOB_MAX_LENGTH + 1];
50 static int provisioner_input_static_oob();
51 static int provisioner_input_num(bt_mesh_output_action_t act, u8_t size);
52 static int provisioner_output_num(bt_mesh_input_action_t act, u8_t size);
53 static void provisioner_link_open(bt_mesh_prov_bearer_t bearer, uint8_t addr_val[6], uint8_t addr_type, uint8_t uuid[16], uint8_t prov_count);
54 static void provisioner_link_close(bt_mesh_prov_bearer_t bearer, u8_t reason, uint8_t addr_val[6], uint8_t addr_type, uint8_t uuid[16], uint8_t prov_count);
55 static void provisioner_complete(int node_idx, const u8_t device_uuid[16],
56 u16_t unicast_addr, u8_t element_num,
57 u16_t netkey_idx, bool gatt_flag);
58
59 static struct bt_mesh_provisioner g_provisioner = {
60 .prov_uuid = 0,
61 .prov_attention = 0,
62 .prov_algorithm = 0,
63 .prov_pub_key_oob = 0,
64 .prov_pub_key_oob_cb = 0,
65 .prov_static_oob_val = g_static_oob_data,
66 .prov_static_oob_len = 0,
67 .prov_input_static_oob = provisioner_input_static_oob,
68 .prov_input_num = provisioner_input_num,
69 .prov_output_num = provisioner_output_num,
70 .flags = 0,
71 .iv_index = 0,
72 .prov_link_open = provisioner_link_open,
73 .prov_link_close = provisioner_link_close,
74 .prov_complete = provisioner_complete,
75 };
76
77 mesh_provisoner g_mesh_prov = {
78 .comp = {.provisioner = &g_provisioner,},
79 };
80
provisioner_unprovisioned_dev_found(const u8_t addr[6],const u8_t addr_type,const u8_t adv_type,const u8_t dev_uuid[16],u16_t oob_info,bt_mesh_prov_bearer_t bearer)81 static void provisioner_unprovisioned_dev_found(const u8_t addr[6], const u8_t addr_type,
82 const u8_t adv_type, const u8_t dev_uuid[16],
83 u16_t oob_info, bt_mesh_prov_bearer_t bearer)
84 {
85 if (!g_mesh_prov.prov_show_dev) {
86 return;
87 }
88
89 if (g_mesh_prov.filter_flag) {
90 if (memcmp(g_mesh_prov.uuid_filter, dev_uuid + g_mesh_prov.uuid_filter_start, g_mesh_prov.uuid_filter_length)) {
91 return;
92 }
93 }
94
95 if (g_mesh_prov.prov_cb) {
96 mesh_node_t node;
97 node.bearer = bearer;
98 node.addr_type = addr_type;
99 memcpy(node.dev_addr, addr, sizeof(node.dev_addr));
100 node.oob_info = oob_info;
101 memcpy(node.uuid, dev_uuid, sizeof(node.uuid));
102 g_mesh_prov.prov_cb(BT_MESH_EVENT_RECV_UNPROV_DEV_ADV, &node);
103 }
104
105 g_mesh_prov.found_dev_succeed = 1;
106 }
107
108
provisioner_input_num(bt_mesh_output_action_t act,u8_t size)109 static int provisioner_input_num(bt_mesh_output_action_t act, u8_t size)
110 {
111 bool input_num_flag = 0;
112
113 if (BT_MESH_DISPLAY_NUMBER == act) {
114 input_num_flag = true;
115
116 if (g_mesh_prov.prov_cb) {
117 g_mesh_prov.prov_cb(BT_MESH_EVENT_OOB_INPUT_NUM, &size);
118 }
119
120 } else if (BT_MESH_DISPLAY_STRING == act) {
121 input_num_flag = false;
122
123 if (g_mesh_prov.prov_cb) {
124 g_mesh_prov.prov_cb(BT_MESH_EVENT_OOB_INPUT_STRING, &size);
125 }
126 }
127
128 k_sem_take(&prov_input_sem, K_FOREVER);
129 LOGI(TAG, "xxxxxxxxxxxx: %s", prov_input);
130 LOGI(TAG, "get input ");
131 LOGI(TAG, "xxxxxxxxxxxx: %u", prov_input_size);
132
133 bt_mesh_prov_input_data(prov_input, prov_input_size, input_num_flag);
134
135 return 0;
136 }
137
138
provisioner_input_static_oob()139 static int provisioner_input_static_oob()
140 {
141
142 if (g_mesh_prov.prov_cb) {
143 g_mesh_prov.prov_cb(BT_MESH_EVENT_OOB_INPUT_STATIC_OOB, NULL);
144 } else {
145 return 0;
146 }
147
148 k_sem_take(&prov_input_sem, K_FOREVER);
149 g_static_oob_data[16] = '\0';
150
151 LOGI(TAG, "xxxxxxxxxxxx: %s", g_static_oob_data);
152 LOGI(TAG, "get input ");
153
154 return 0;
155
156 }
157
158
provisioner_output_num(bt_mesh_input_action_t act,u8_t size)159 static int provisioner_output_num(bt_mesh_input_action_t act, u8_t size)
160 {
161 bt_u32_t div[8] = { 10, 100, 1000, 10000, 100000,
162 1000000, 10000000, 100000000
163 };
164 bt_u32_t num = 0;
165 u8_t temp[8];
166 u8_t i;
167 bool output_num_flag = 0;
168
169 if (BT_MESH_ENTER_NUMBER == act) {
170
171 output_num_flag = true;
172 extern int bt_rand(void *buf, size_t len);
173 bt_rand(&num, size);
174
175 num %= div[size - 1];
176
177 LOGI(TAG, "===================");
178 LOGI(TAG, "input number %06u in the device", num);
179 LOGI(TAG, "===================");
180
181 memset(temp, 0, sizeof(temp));
182
183 for (i = size; i > 0; i--) {
184 temp[i - 1] = num & 0xFF;
185 num >>= 8;
186
187 if (num == 0) {
188 break;
189 }
190 }
191 } else if (BT_MESH_ENTER_STRING == act) {
192 output_num_flag = false;
193
194 extern int bt_rand(void *buf, size_t len);
195 bt_rand(temp, size);
196
197 /* Normalize to '0' .. '9' & 'A' .. 'Z' */
198 for (i = 0; i < size; i++) {
199 temp[i] %= 36;
200
201 if (temp[i] < 10) {
202 temp[i] += '0';
203 } else {
204 temp[i] += 'A' - 10;
205 }
206 }
207
208 temp[size] = '\0';
209
210 LOGI(TAG, "===================");
211 LOGI(TAG, "input string %s in the device", temp);
212 LOGI(TAG, "===================");
213 }
214
215 bt_mesh_prov_output_data(temp, size, output_num_flag);
216
217 return 0;
218
219 }
220
221
provisioner_link_open(bt_mesh_prov_bearer_t bearer,uint8_t addr_val[6],uint8_t addr_type,uint8_t uuid[16],uint8_t prov_count)222 static void provisioner_link_open(bt_mesh_prov_bearer_t bearer, uint8_t addr_val[6], uint8_t addr_type, uint8_t uuid[16], uint8_t prov_count)
223 {
224 LOGD(TAG, "Provisioner link opened on %d\n", bearer);
225
226 if (addr_val && uuid) {
227 memcpy(g_mesh_prov.del_dev.uuid, uuid, sizeof(g_mesh_prov.del_dev.uuid));
228 memcpy(g_mesh_prov.del_dev.addr, addr_val, sizeof(g_mesh_prov.del_dev.addr));
229 g_mesh_prov.del_dev.addr_type = addr_type;
230 }
231 }
232
233
provisioner_link_close(bt_mesh_prov_bearer_t bearer,u8_t reason,uint8_t addr_val[6],uint8_t addr_type,uint8_t uuid[16],uint8_t prov_count)234 static void provisioner_link_close(bt_mesh_prov_bearer_t bearer, u8_t reason, uint8_t addr_val[6], uint8_t addr_type, uint8_t uuid[16], uint8_t prov_count)
235 {
236 LOGD(TAG, "Provisioner link closed on %d reason %d\n", bearer, reason);
237 int ret = 0;
238
239 //ADV
240 if (BT_MESH_PROV_ADV == bearer && reason && g_mesh_prov.prov_cb) {
241 g_mesh_prov.prov_cb(BT_MESH_EVENT_PROV_FAILD, (void *)&reason);
242 } else if (BT_MESH_PROV_GATT == bearer && (reason && LOCAL_USER_TERM_CONN != reason) && g_mesh_prov.prov_cb) {
243 g_mesh_prov.prov_cb(BT_MESH_EVENT_PROV_FAILD, (void *)&reason);
244 }
245
246 if (DEF_MAX_PROV_RETRY < prov_count) {
247 ret = ble_mesh_provisioner_dev_del(g_mesh_prov.del_dev.addr, g_mesh_prov.del_dev.addr_type, g_mesh_prov.del_dev.uuid);
248 if (ret) {
249 LOGE(TAG, "del the faild prov dev faild");
250 } else {
251 LOGD(TAG, "remove the faild prov dev succeed");
252 }
253
254 }
255 }
256
257
provisioner_complete(int node_idx,const u8_t device_uuid[16],u16_t unicast_addr,u8_t element_num,u16_t netkey_idx,bool gatt_flag)258 static void provisioner_complete(int node_idx, const u8_t device_uuid[16],
259 u16_t unicast_addr, u8_t element_num,
260 u16_t netkey_idx, bool gatt_flag)
261 {
262
263 if (g_mesh_prov.prov_cb) {
264 mesh_node_t node = {0};
265 node.prim_unicast = unicast_addr;
266 node.element_num = element_num;
267 node.net_idx = netkey_idx;
268 node.bearer = gatt_flag?BT_MESH_PROV_GATT:BT_MESH_PROV_ADV;
269 memcpy(node.uuid, device_uuid, 16);
270 g_mesh_prov.prov_dev_succeed = 1;
271 g_mesh_prov.prov_cb(BT_MESH_EVENT_PROV_COMP, &node);
272 }
273 }
274
found_dev_time_out(void * timer,void * arg)275 static void found_dev_time_out(void *timer, void *arg)
276 {
277
278 k_timer_stop(&g_mesh_prov.found_dev_timer);
279
280 if (g_mesh_prov.found_dev_succeed) {
281 g_mesh_prov.found_dev_succeed = 0;
282 } else {
283 g_mesh_prov.prov_cb(BT_MESH_EVENT_FOUND_DEV_TIMEOUT, NULL);
284 }
285
286 }
287
ble_mesh_provisioner_init(provisioner_config_t * param)288 int ble_mesh_provisioner_init(provisioner_config_t *param)
289 {
290
291 if (!param || param->unicast_addr_local >= param->unicast_addr_start) {
292 return -1;
293 }
294
295 k_timer_init(&g_mesh_prov.found_dev_timer, found_dev_time_out, NULL);
296
297 g_provisioner.prov_unicast_addr = param->unicast_addr_local;
298 g_provisioner.prov_start_address = param->unicast_addr_start;
299 g_provisioner.prov_attention = param->attention_time;
300 g_mesh_prov.prov_cb = param->cb;
301 g_mesh_prov.comp.provisioner = &g_provisioner;
302 g_mesh_prov.init_flag = 1;
303
304 return 0;
305 }
306
ble_mesh_provisioner_get_provisioner_data()307 const ble_mesh_provisioner_t *ble_mesh_provisioner_get_provisioner_data()
308 {
309 if (!g_mesh_prov.init_flag) {
310 return NULL;
311 }
312
313 return &g_mesh_prov.comp;
314 }
315
ble_mesh_provisioner_enable()316 int ble_mesh_provisioner_enable()
317 {
318
319 int16_t ret;
320
321 if (!g_mesh_prov.init_flag) {
322 return -1;
323 }
324
325 ret = bt_mesh_provisioner_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
326
327 if (ret) {
328 return ret;
329 }
330
331 ret = bt_mesh_prov_adv_pkt_cb_register(provisioner_unprovisioned_dev_found);
332
333 if (ret) {
334 return ret;
335 }
336
337 g_mesh_prov.enable = 1;
338
339 return 0;
340 }
341
342
ble_mesh_provisioner_disable()343 int ble_mesh_provisioner_disable()
344 {
345 int16_t ret;
346
347 if (!g_mesh_prov.init_flag) {
348 return -1;
349 }
350
351 ret = bt_mesh_provisioner_disable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT);
352
353 if (ret) {
354 return ret;
355 }
356
357 if (g_mesh_prov.found_dev_timeout) {
358 k_timer_stop(&g_mesh_prov.found_dev_timer);
359 }
360
361 g_mesh_prov.enable = 0;
362
363 return 0;
364 }
365
366
ble_mesh_provisioner_dev_filter(uint8_t enable,uuid_filter_t * filter)367 int ble_mesh_provisioner_dev_filter(uint8_t enable, uuid_filter_t *filter)
368 {
369 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable) {
370 return -1;
371 }
372
373 if (!enable) {
374 g_mesh_prov.filter_flag = 0;
375 return 0;
376 }
377
378 if (!filter || !filter->uuid || !filter->uuid_length) {
379 return -1;
380 }
381
382 if ((filter->filter_start + filter->uuid_length) > 16) {
383 return -1;
384 }
385
386 memcpy(g_mesh_prov.uuid_filter, filter->uuid, filter->uuid_length);
387 g_mesh_prov.uuid_filter_start = filter->filter_start;
388 g_mesh_prov.uuid_filter_length = filter->uuid_length;
389
390 g_mesh_prov.filter_flag = 1;
391 return 0;
392 }
393
ble_mesh_provisioner_show_dev(uint8_t enable,uint32_t timeout)394 int ble_mesh_provisioner_show_dev(uint8_t enable, uint32_t timeout)
395 {
396 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable) {
397 return -1;
398 }
399
400 if (enable) {
401 g_mesh_prov.prov_show_dev = 1;
402
403 if (timeout) {
404 k_timer_start(&g_mesh_prov.found_dev_timer, timeout * 1000);
405 g_mesh_prov.found_dev_succeed = 0;
406 }
407 } else {
408 k_timer_stop(&g_mesh_prov.found_dev_timer);
409 g_mesh_prov.prov_show_dev = 0;
410 }
411
412 return 0;
413
414 }
415
ble_mesh_provisioner_dev_add(mesh_node_t * node,uint8_t add_appkey)416 int ble_mesh_provisioner_dev_add(mesh_node_t *node, uint8_t add_appkey)
417 {
418 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable) {
419 return -1;
420 }
421
422 int16_t err;
423 struct bt_mesh_unprov_dev_add unprov_dev = {0};
424 if (!node) {
425 return -1;
426 }
427
428
429 unprov_dev.addr_type = node->addr_type;
430 memcpy(unprov_dev.addr, node->dev_addr, 6);
431 memcpy(unprov_dev.uuid, node->uuid, sizeof(unprov_dev.uuid));
432
433 unprov_dev.oob_info = node->oob_info;
434 unprov_dev.bearer = node->bearer;
435 unprov_dev.auto_add_appkey = add_appkey;
436
437 err = bt_mesh_provisioner_add_unprov_dev(&unprov_dev, RM_AFTER_PROV | FLUSHABLE_DEV);
438
439 if (err) {
440 LOGE(TAG, "add unprov device fail err %d\n", err);
441 return err;
442 }
443
444 return 0;
445 }
446
447
448
449
ble_mesh_provisioner_get_add_appkey_flag(u16_t unicast_addr)450 int ble_mesh_provisioner_get_add_appkey_flag(u16_t unicast_addr)
451 {
452 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable) {
453 return -1;
454 }
455 extern uint8_t get_node_auto_add_appkey_flag(u16_t unicast_addr);
456 return get_node_auto_add_appkey_flag(unicast_addr);
457 }
458
459
460
ble_mesh_provisioner_dev_del(uint8_t addr[6],uint8_t addr_type,uint8_t uuid[16])461 int ble_mesh_provisioner_dev_del(uint8_t addr[6], uint8_t addr_type, uint8_t uuid[16])
462 {
463
464 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable || !addr || !uuid) {
465 return -1;
466 }
467
468 int16_t err;
469 struct bt_mesh_device_delete del_dev;
470
471 memcpy(del_dev.addr, addr, sizeof(del_dev.addr));
472 memcpy(del_dev.uuid, uuid, sizeof(del_dev.uuid));
473 del_dev.addr_type = addr_type;
474
475 err = bt_mesh_provisioner_delete_unprov_device(&del_dev);
476
477 if (err) {
478 LOGE(TAG, "del unprov device fail err %d\n", err);
479 return err;
480 }
481
482 return 0;
483 }
484
485
ble_mesh_provisioner_OOB_input_string(const char * str)486 int ble_mesh_provisioner_OOB_input_string(const char *str)
487 {
488 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable || !str) {
489 return -1;
490 }
491
492 uint8_t input_length = strlen(str) < prov_input_size ? strlen(str) : prov_input_size;
493
494 memcpy(prov_input, str, input_length);
495 k_sem_give(&prov_input_sem);
496 return 0;
497 }
498
ble_mesh_provisioner_OOB_input_num(uint32_t num)499 int ble_mesh_provisioner_OOB_input_num(uint32_t num)
500 {
501 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable || !num) {
502 return -1;
503 }
504
505 uint8_t i;
506 memset(prov_input, 0, sizeof(prov_input));
507
508 for (i = prov_input_size; i > 0; i--) {
509 prov_input[i - 1] = num & 0xFF;
510 num >>= 8;
511 }
512
513 k_sem_give(&prov_input_sem);
514
515 return 0;
516 }
517
518
ble_mesh_provisioner_static_OOB_set(const uint8_t * oob,uint16_t oob_size)519 int ble_mesh_provisioner_static_OOB_set(const uint8_t *oob, uint16_t oob_size)
520 {
521 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable || !oob || 16 != oob_size) {
522 return -1;
523 }
524
525 memcpy(g_static_oob_data, oob, oob_size);
526 g_provisioner.prov_static_oob_len = oob_size;
527 k_sem_give(&prov_input_sem);
528
529 return 0;
530
531 }
532
533
ble_mesh_provisioner_get_node_info(u16_t unicast_addr)534 mesh_node_t *ble_mesh_provisioner_get_node_info(u16_t unicast_addr)
535 {
536 if (!g_mesh_prov.init_flag || !g_mesh_prov.enable || !unicast_addr || unicast_addr > 0x8000) {
537 return NULL;
538 }
539
540 static mesh_node_t g_node_info;
541
542 struct bt_mesh_node_t *node;
543
544 memset(&g_node_info, 0, sizeof(mesh_node_t));
545
546 node = bt_mesh_provisioner_get_node_info(unicast_addr);
547
548 if (!node) {
549 return NULL;
550 } else {
551 memcpy(g_node_info.uuid, node->dev_uuid, 16);
552 memcpy(g_node_info.dev_addr, node->addr_val, 6);
553 g_node_info.addr_type = node->addr_type;
554 g_node_info.prim_unicast = node->unicast_addr;
555 g_node_info.oob_info = node->oob_info;
556 g_node_info.element_num = node->element_num;
557 g_node_info.node_name = (uint8_t *)node->node_name;
558 g_node_info.flags = node->flags;
559 g_node_info.iv_index = node->iv_index;
560 g_node_info.net_idx = node->net_idx;
561 }
562
563 return &g_node_info;
564 }
565
566 #endif
567
568