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