4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6 * @author: Anupam Roy <anupam.r@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 #include "bt-service-common.h"
24 #include "bt-service-core-adapter.h"
25 #include "bt-service-event-receiver.h"
26 #include "bt-request-handler.h"
27 #include "bluetooth-api.h"
29 #include "bluetooth-api.h"
30 #include "bluetooth-mesh-api.h"
31 #include "bt-internal-types.h"
32 #include "bt-service-util.h"
33 #include "bt-service-common.h"
34 #include "bt-service-event.h"
36 #include "bt-service-mesh-cdb.h"
37 #include "bt-service-mesh-keys.h"
38 #include "bt-service-mesh-util.h"
42 #include "bt-internal-types.h"
44 struct _bt_mesh_node_t {
46 struct l_queue *net_keys;
47 struct l_queue *app_keys;
53 struct mesh_network_t {
55 struct l_queue *nodes;
58 static struct l_queue *networks;
60 struct mesh_key_index {
65 static bool __mesh_match_bound_key(const void *a, const void *b)
67 uint16_t app_idx = L_PTR_TO_UINT(a);
68 const struct mesh_key_index *data = b;
70 uint16_t net_idx = L_PTR_TO_UINT(b);
72 return (net_idx == _bt_mesh_keys_get_bound_key(
73 (uint8_t*)data->uuid, app_idx));
76 static bool __mesh_match_node_dev_uuid(const void *a, const void *b)
78 const struct _bt_mesh_node_t *node = a;
79 uint8_t* dev_uuid = (uint8_t*)b;
81 if (memcmp(node->uuid, dev_uuid, 16) == 0) {
82 BT_INFO("Mesh: Found Node with given Dev UUID");
89 static bool __mesh_net_uuid_match(const void *a, const void *b)
91 const struct mesh_network_t *net = a;
92 uint8_t* uuid = (uint8_t*)b;
94 if (memcmp(net->net_uuid, uuid, 16) == 0) {
95 BT_INFO("Mesh: Found network with given Net UUID");
102 static bool __mesh_remove_node_entry(void *a, void *b)
105 struct _bt_mesh_node_t *rmt = (struct _bt_mesh_node_t*) a;
107 num_ele = rmt->num_ele;
109 for (i = 0; i < num_ele; ++i)
110 l_queue_destroy(rmt->els[i], NULL);
114 l_queue_destroy(rmt->net_keys, l_free);
115 l_queue_destroy(rmt->app_keys, l_free);
121 static bool __mesh_key_present(struct l_queue *keys, uint16_t app_idx)
123 const struct l_queue_entry *l;
125 for (l = l_queue_get_entries(keys); l; l = l->next) {
126 uint16_t idx = L_PTR_TO_UINT(l->data);
135 static int __mesh_compare_mod_id(const void *a, const void *b,
138 uint32_t id1 = L_PTR_TO_UINT(a);
139 uint32_t id2 = L_PTR_TO_UINT(b);
141 if (id1 >= MESH_VENDOR_ID_MASK)
142 id1 &= ~MESH_VENDOR_ID_MASK;
144 if (id2 >= MESH_VENDOR_ID_MASK)
145 id2 &= ~MESH_VENDOR_ID_MASK;
156 static int __mesh_compare_unicast(const void *a, const void *b,
159 const struct _bt_mesh_node_t *a_rmt = a;
160 const struct _bt_mesh_node_t *b_rmt = b;
162 if (a_rmt->unicast < b_rmt->unicast)
165 if (a_rmt->unicast > b_rmt->unicast)
171 static bool __mesh_match_node_addr(const void *a, const void *b)
173 const struct _bt_mesh_node_t *rmt = a;
174 uint16_t addr = L_PTR_TO_UINT(b);
176 if (addr >= rmt->unicast &&
177 addr <= (rmt->unicast + rmt->num_ele - 1))
183 void _bt_mesh_node_load_net(uint8_t net_uuid[])
185 struct mesh_network_t *network;
186 BT_INFO("Mesh:Nodes: Create new network");
188 if (l_queue_find(networks, __mesh_net_uuid_match, net_uuid))
192 networks = l_queue_new();
194 network = l_new(struct mesh_network_t, 1);
195 memcpy(network->net_uuid, net_uuid, 16);
196 network->nodes = l_queue_new();
197 l_queue_push_tail(networks, network);
200 void _bt_mesh_node_unload_net(uint8_t net_uuid[])
202 struct mesh_network_t *network;
204 BT_INFO("Mesh:Nodes: Unload network with all nodes");
206 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
207 if (!network || !network->nodes)
210 /* Only remove the ndoe from the Local Network object:
211 DONT touch configuration file */
212 numnodes = l_queue_foreach_remove(network->nodes,
213 __mesh_remove_node_entry, NULL);
214 BT_INFO("Mesh:Nodes: Unloadeded [%d] Nodes from the network", numnodes);
215 l_queue_remove(networks, network);
218 BT_INFO("Mesh: After unloading, number of networks [%d]",
219 l_queue_length(networks));
222 bool _bt_mesh_node_get_unicast_from_dev_uuid(uint8_t net_uuid[],
223 const uint8_t dev_uuid[], uint16_t *unicast)
225 struct _bt_mesh_node_t *rmt;
226 struct mesh_network_t *network;
228 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
232 rmt = l_queue_find(network->nodes,
233 __mesh_match_node_dev_uuid, dev_uuid);
237 *unicast = rmt->unicast;
241 bool _bt_mesh_node_get_element_count(uint8_t net_uuid[],
242 uint16_t unicast, uint8_t *count)
244 struct _bt_mesh_node_t *rmt;
245 struct mesh_network_t *network;
247 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
251 rmt = l_queue_find(network->nodes, __mesh_match_node_addr,
252 L_UINT_TO_PTR(unicast));
256 *count = rmt->num_ele;
261 uint8_t _bt_mesh_node_del_node(_bt_mesh_cdb_t *cfg,
264 struct _bt_mesh_node_t *rmt;
266 struct mesh_network_t *network;
271 BT_INFO("Mesh: Uload Node Entry [0x%2.2x]", unicast);
272 network = l_queue_find(networks, __mesh_net_uuid_match, cfg->uuid);
276 rmt = l_queue_find(network->nodes,
277 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
281 rmt = l_queue_remove_if(network->nodes, __mesh_match_node_addr,
282 L_UINT_TO_PTR(unicast));
286 num_ele = rmt->num_ele;
288 for (i = 0; i < num_ele; ++i)
289 l_queue_destroy(rmt->els[i], NULL);
293 l_queue_destroy(rmt->net_keys, NULL);
294 l_queue_destroy(rmt->app_keys, NULL);
300 bool _bt_mesh_node_add_node(uint8_t net_uuid[],
301 const uint8_t node_uuid[16], uint16_t unicast,
302 uint8_t ele_cnt, uint16_t net_idx)
304 struct _bt_mesh_node_t *rmt;
305 struct mesh_network_t *network;
307 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
311 rmt = l_queue_find(network->nodes,
312 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
316 rmt = l_new(struct _bt_mesh_node_t, 1);
317 memcpy(rmt->uuid, node_uuid, 16);
318 rmt->unicast = unicast;
319 rmt->num_ele = ele_cnt;
320 rmt->net_keys = l_queue_new();
322 l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
324 rmt->els = l_new(struct l_queue *, ele_cnt);
327 network->nodes = l_queue_new();
329 if (l_queue_insert(network->nodes, rmt, __mesh_compare_unicast, NULL))
330 BT_INFO("Mesh: node added to Network");
332 BT_INFO("Mesh: node could not be added to Network");
336 bool _bt_mesh_node_get_models(uint8_t net_uuid[],
337 uint16_t unicast, uint8_t ele_idx,
340 struct _bt_mesh_node_t *rmt;
341 struct mesh_network_t *network;
342 const struct l_queue_entry *entry;
344 BT_INFO("Mesh: Get All Models in an element [0x%4.4x] Index [0x%x]",
347 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
351 rmt = l_queue_find(network->nodes,
352 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
356 if (!rmt->els[ele_idx])
359 entry = l_queue_get_entries(rmt->els[ele_idx]);
361 BT_INFO("Mesh: Total Models in Element [%d]",
362 l_queue_length(rmt->els[ele_idx]));
363 for (; entry; entry = entry->next) {
364 uint32_t model = L_PTR_TO_UINT(entry->data);
365 g_array_append_vals(*out, &model, sizeof(uint32_t));
366 BT_INFO("Mesh: Appended Model ID [0x%4.4x]", model);
371 bool _bt_mesh_node_set_model(uint8_t net_uuid[],
372 uint16_t unicast, uint8_t ele_idx,
373 uint32_t mod_id, bool vendor)
375 struct _bt_mesh_node_t *rmt;
376 struct mesh_network_t *network;
378 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
382 rmt = l_queue_find(network->nodes,
383 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
387 if (ele_idx >= rmt->num_ele)
390 if (!rmt->els[ele_idx])
391 rmt->els[ele_idx] = l_queue_new();
394 mod_id = MESH_VENDOR_ID_MASK | mod_id;
396 BT_INFO("Mesh: Insert Model in Element Index [0x%x]", ele_idx);
397 BT_INFO("Mesh: Insert Model Id [0x%4.4x]", mod_id);
398 l_queue_insert(rmt->els[ele_idx], L_UINT_TO_PTR(mod_id),
399 __mesh_compare_mod_id, NULL);
401 BT_INFO("Mesh: Current model count after update in element is [%d]",
402 l_queue_length(rmt->els[ele_idx]));
407 bool _bt_mesh_node_del_net_key(_bt_mesh_cdb_t *cfg,
408 uint8_t net_uuid[], uint16_t addr,
411 struct _bt_mesh_node_t *rmt;
413 struct mesh_network_t *network;
414 struct mesh_key_index *user_data;
416 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
420 rmt = l_queue_find(network->nodes,
421 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
425 if (!l_queue_remove(rmt->net_keys, L_UINT_TO_PTR(net_idx)))
428 user_data = g_malloc0(sizeof(struct mesh_key_index));
429 memcpy(user_data->uuid, net_uuid, 16);
430 user_data->idx = net_idx;
432 data = l_queue_remove_if(rmt->app_keys,
433 __mesh_match_bound_key, user_data);
435 uint16_t app_idx = (uint16_t) L_PTR_TO_UINT(data);
437 _bt_mesh_conf_node_delete_application_key(cfg, rmt->unicast, app_idx);
438 data = l_queue_remove_if(rmt->app_keys,
439 __mesh_match_bound_key, user_data);
446 bool _bt_mesh_node_get_all_appkeys(uint8_t net_uuid[],
447 uint16_t unicast, uint16_t netkey, GArray **out)
449 struct mesh_network_t *network;
450 const struct l_queue_entry *entry;
451 struct _bt_mesh_node_t *rmt;
453 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
457 rmt = l_queue_find(network->nodes,
458 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
462 entry = l_queue_get_entries(rmt->app_keys);
464 for (; entry; entry = entry->next) {
466 uint16_t app_idx = L_PTR_TO_UINT(entry->data);
467 net_idx = _bt_mesh_keys_get_bound_key(net_uuid, app_idx);
468 if (net_idx == netkey)
469 g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
474 bool _bt_mesh_node_get_all_netkeys(uint8_t net_uuid[],
475 uint16_t unicast, GArray **out)
477 struct mesh_network_t *network;
478 const struct l_queue_entry *entry;
479 struct _bt_mesh_node_t *rmt;
481 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
485 rmt = l_queue_find(network->nodes,
486 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
490 entry = l_queue_get_entries(rmt->net_keys);
492 for (; entry; entry = entry->next) {
494 uint16_t net_idx = L_PTR_TO_UINT(entry->data);
496 g_array_append_vals(*out, &net_idx, sizeof(uint16_t));
501 bool _bt_mesh_node_get_all(uint8_t net_uuid[], GArray **out)
503 struct mesh_network_t *network;
504 const struct l_queue_entry *entry;
505 bluetooth_mesh_node_info_t n;
507 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
511 entry = l_queue_get_entries(network->nodes);
513 for (; entry; entry = entry->next) {
515 memset(&n, 0x00, sizeof(bluetooth_mesh_node_info_t));
516 struct _bt_mesh_node_t *node = entry->data;
518 n.primary_unicast = node->unicast;
519 _bt_mesh_util_convert_hex_to_string(node->uuid, 16,
520 n.dev_uuid, sizeof(n.dev_uuid));
521 BT_INFO("Mesh: Dev UUID [%s]", n.dev_uuid);
523 g_array_append_vals(*out, &n,
524 sizeof(bluetooth_mesh_node_info_t));
529 bool _bt_mesh_node_is_netkey_added_in_network(uint8_t net_uuid[],
532 struct mesh_network_t *network;
533 const struct l_queue_entry *entry;
535 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
539 entry = l_queue_get_entries(network->nodes);
541 for (; entry; entry = entry->next) {
542 struct _bt_mesh_node_t *node = entry->data;
544 if (__mesh_key_present(node->net_keys, net_idx))
550 bool _bt_mesh_node_is_appkey_added_in_network(uint8_t net_uuid[],
553 struct mesh_network_t *network;
554 const struct l_queue_entry *entry;
556 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
560 entry = l_queue_get_entries(network->nodes);
562 for (; entry; entry = entry->next) {
563 struct _bt_mesh_node_t *node = entry->data;
565 if (__mesh_key_present(node->app_keys, app_idx))
571 bool _bt_mesh_node_is_appkey_exists(uint8_t net_uuid[],
572 uint16_t addr, uint16_t app_idx)
574 struct _bt_mesh_node_t *rmt;
575 struct mesh_network_t *network;
577 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
581 rmt = l_queue_find(network->nodes,
582 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
586 if (__mesh_key_present(rmt->app_keys, app_idx))
592 bool _bt_mesh_node_is_netkey_exists(uint8_t net_uuid[],
593 uint16_t addr, uint16_t net_idx)
595 struct _bt_mesh_node_t *rmt;
596 struct mesh_network_t *network;
598 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
602 rmt = l_queue_find(network->nodes,
603 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
607 if (__mesh_key_present(rmt->net_keys, net_idx))
613 bool _bt_mesh_node_add_net_key(uint8_t net_uuid[],
614 uint16_t addr, uint16_t net_idx)
616 struct _bt_mesh_node_t *rmt;
617 struct mesh_network_t *network;
619 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
623 rmt = l_queue_find(network->nodes,
624 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
628 if (__mesh_key_present(rmt->net_keys, net_idx))
631 l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
635 bool _bt_mesh_node_add_app_key(uint8_t net_uuid[],
636 uint16_t addr, uint16_t app_idx)
638 struct _bt_mesh_node_t *rmt;
639 struct mesh_network_t *network;
641 network = l_queue_find(networks,
642 __mesh_net_uuid_match, net_uuid);
646 rmt = l_queue_find(network->nodes,
647 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
652 rmt->app_keys = l_queue_new();
654 if (__mesh_key_present(rmt->app_keys, app_idx))
657 l_queue_push_tail(rmt->app_keys, L_UINT_TO_PTR(app_idx));
658 BT_INFO("Mesh: Total appkeys present in node [%d]",
659 l_queue_length(rmt->app_keys));
663 bool _bt_mesh_node_del_app_key(uint8_t net_uuid[],
664 uint16_t addr, uint16_t app_idx)
666 struct _bt_mesh_node_t *rmt;
667 struct mesh_network_t *network;
669 network = l_queue_find(networks,
670 __mesh_net_uuid_match, net_uuid);
672 BT_INFO("Mesh: Could not find Network");
676 rmt = l_queue_find(network->nodes,
677 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
679 BT_INFO("Mesh: Remote Node not found!");
683 BT_INFO("Mesh: Total appkeys present in node [%d]",
684 l_queue_length(rmt->app_keys));
685 BT_INFO("Mesh: To be deleted AppKey Idx [0x%2.2x]", app_idx);
686 return l_queue_remove(rmt->app_keys, L_UINT_TO_PTR(app_idx));
689 uint16_t _bt_mesh_node_get_subnet_idx(uint8_t net_uuid[],
692 struct _bt_mesh_node_t *rmt;
694 struct mesh_network_t *network;
696 network = l_queue_find(networks,
697 __mesh_net_uuid_match, net_uuid);
699 return MESH_NET_IDX_INVALID;
701 rmt = l_queue_find(network->nodes,
702 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
704 if (!rmt || l_queue_isempty(rmt->net_keys))
705 return MESH_NET_IDX_INVALID;
707 net_idx = L_PTR_TO_UINT(l_queue_peek_head(rmt->net_keys));
709 return (uint16_t) net_idx;
712 uint16_t _bt_mesh_node_get_next_unicast(uint8_t net_uuid[],
713 uint16_t low, uint16_t high, uint8_t ele_cnt)
715 struct _bt_mesh_node_t *rmt;
716 const struct l_queue_entry *l;
718 struct mesh_network_t *network;
720 network = l_queue_find(networks,
721 __mesh_net_uuid_match, net_uuid);
723 BT_ERR("Mesh: Net UUID did not match");
727 /* Note: the address space includes both
728 low and high terminal values */
729 if (ele_cnt > (high - low + 1))
732 if (!network->nodes || l_queue_isempty(network->nodes))
736 l = l_queue_get_entries(network->nodes);
738 /* Cycle through the sorted (by unicast) node list */
739 for (; l; l = l->next) {
742 if (rmt->unicast >= (addr + ele_cnt))
745 if ((rmt->unicast + rmt->num_ele) > addr)
746 addr = rmt->unicast + rmt->num_ele;
749 if ((addr + ele_cnt - 1) <= high)