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 bool _bt_mesh_node_add_node(uint8_t net_uuid[],
262 const uint8_t node_uuid[16], uint16_t unicast,
263 uint8_t ele_cnt, uint16_t net_idx)
265 struct _bt_mesh_node_t *rmt;
266 struct mesh_network_t *network;
268 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
272 rmt = l_queue_find(network->nodes,
273 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
277 rmt = l_new(struct _bt_mesh_node_t, 1);
278 memcpy(rmt->uuid, node_uuid, 16);
279 rmt->unicast = unicast;
280 rmt->num_ele = ele_cnt;
281 rmt->net_keys = l_queue_new();
283 l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
285 rmt->els = l_new(struct l_queue *, ele_cnt);
288 network->nodes = l_queue_new();
290 if (l_queue_insert(network->nodes, rmt, __mesh_compare_unicast, NULL))
291 BT_INFO("Mesh: node added to Network");
293 BT_INFO("Mesh: node could not be added to Network");
297 bool _bt_mesh_node_get_models(uint8_t net_uuid[],
298 uint16_t unicast, uint8_t ele_idx,
301 struct _bt_mesh_node_t *rmt;
302 struct mesh_network_t *network;
303 const struct l_queue_entry *entry;
305 BT_INFO("Mesh: Get All Models in an element [0x%4.4x] Index [0x%x]",
308 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
312 rmt = l_queue_find(network->nodes,
313 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
317 if (!rmt->els[ele_idx])
320 entry = l_queue_get_entries(rmt->els[ele_idx]);
322 BT_INFO("Mesh: Total Models in Element [%d]",
323 l_queue_length(rmt->els[ele_idx]));
324 for (; entry; entry = entry->next) {
325 uint32_t model = L_PTR_TO_UINT(entry->data);
326 g_array_append_vals(*out, &model, sizeof(uint32_t));
327 BT_INFO("Mesh: Appended Model ID [0x%4.4x]", model);
332 bool _bt_mesh_node_set_model(uint8_t net_uuid[],
333 uint16_t unicast, uint8_t ele_idx,
334 uint32_t mod_id, bool vendor)
336 struct _bt_mesh_node_t *rmt;
337 struct mesh_network_t *network;
339 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
343 rmt = l_queue_find(network->nodes,
344 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
348 if (ele_idx >= rmt->num_ele)
351 if (!rmt->els[ele_idx])
352 rmt->els[ele_idx] = l_queue_new();
355 mod_id = MESH_VENDOR_ID_MASK | mod_id;
357 BT_INFO("Mesh: Insert Model in Element Index [0x%x]", ele_idx);
358 BT_INFO("Mesh: Insert Model Id [0x%4.4x]", mod_id);
359 l_queue_insert(rmt->els[ele_idx], L_UINT_TO_PTR(mod_id),
360 __mesh_compare_mod_id, NULL);
362 BT_INFO("Mesh: Current model count after update in element is [%d]",
363 l_queue_length(rmt->els[ele_idx]));
368 bool _bt_mesh_node_del_net_key(_bt_mesh_cdb_t *cfg,
369 uint8_t net_uuid[], uint16_t addr,
372 struct _bt_mesh_node_t *rmt;
374 struct mesh_network_t *network;
375 struct mesh_key_index *user_data;
377 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
381 rmt = l_queue_find(network->nodes,
382 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
386 if (!l_queue_remove(rmt->net_keys, L_UINT_TO_PTR(net_idx)))
389 user_data = g_malloc0(sizeof(struct mesh_key_index));
390 memcpy(user_data->uuid, net_uuid, 16);
391 user_data->idx = net_idx;
393 data = l_queue_remove_if(rmt->app_keys,
394 __mesh_match_bound_key, user_data);
396 uint16_t app_idx = (uint16_t) L_PTR_TO_UINT(data);
398 _bt_mesh_conf_node_delete_application_key(cfg, rmt->unicast, app_idx);
399 data = l_queue_remove_if(rmt->app_keys,
400 __mesh_match_bound_key, user_data);
407 bool _bt_mesh_node_get_all_appkeys(uint8_t net_uuid[],
408 uint16_t unicast, uint16_t netkey, GArray **out)
410 struct mesh_network_t *network;
411 const struct l_queue_entry *entry;
412 struct _bt_mesh_node_t *rmt;
414 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
418 rmt = l_queue_find(network->nodes,
419 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
423 entry = l_queue_get_entries(rmt->app_keys);
425 for (; entry; entry = entry->next) {
427 uint16_t app_idx = L_PTR_TO_UINT(entry->data);
428 net_idx = _bt_mesh_keys_get_bound_key(net_uuid, app_idx);
429 if (net_idx == netkey)
430 g_array_append_vals(*out, &app_idx, sizeof(uint16_t));
435 bool _bt_mesh_node_get_all_netkeys(uint8_t net_uuid[],
436 uint16_t unicast, GArray **out)
438 struct mesh_network_t *network;
439 const struct l_queue_entry *entry;
440 struct _bt_mesh_node_t *rmt;
442 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
446 rmt = l_queue_find(network->nodes,
447 __mesh_match_node_addr, L_UINT_TO_PTR(unicast));
451 entry = l_queue_get_entries(rmt->net_keys);
453 for (; entry; entry = entry->next) {
455 uint16_t net_idx = L_PTR_TO_UINT(entry->data);
457 g_array_append_vals(*out, &net_idx, sizeof(uint16_t));
462 bool _bt_mesh_node_get_all(uint8_t net_uuid[], GArray **out)
464 struct mesh_network_t *network;
465 const struct l_queue_entry *entry;
466 bluetooth_mesh_node_info_t n;
468 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
472 entry = l_queue_get_entries(network->nodes);
474 for (; entry; entry = entry->next) {
476 memset(&n, 0x00, sizeof(bluetooth_mesh_node_info_t));
477 struct _bt_mesh_node_t *node = entry->data;
479 n.primary_unicast = node->unicast;
480 _bt_mesh_util_convert_hex_to_string(node->uuid, 16,
481 n.dev_uuid, sizeof(n.dev_uuid));
482 BT_INFO("Mesh: Dev UUID [%s]", n.dev_uuid);
484 g_array_append_vals(*out, &n,
485 sizeof(bluetooth_mesh_node_info_t));
490 bool _bt_mesh_node_is_netkey_added_in_network(uint8_t net_uuid[],
493 struct mesh_network_t *network;
494 const struct l_queue_entry *entry;
496 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
500 entry = l_queue_get_entries(network->nodes);
502 for (; entry; entry = entry->next) {
503 struct _bt_mesh_node_t *node = entry->data;
505 if (__mesh_key_present(node->net_keys, net_idx))
511 bool _bt_mesh_node_is_appkey_added_in_network(uint8_t net_uuid[],
514 struct mesh_network_t *network;
515 const struct l_queue_entry *entry;
517 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
521 entry = l_queue_get_entries(network->nodes);
523 for (; entry; entry = entry->next) {
524 struct _bt_mesh_node_t *node = entry->data;
526 if (__mesh_key_present(node->app_keys, app_idx))
532 bool _bt_mesh_node_is_appkey_exists(uint8_t net_uuid[],
533 uint16_t addr, uint16_t app_idx)
535 struct _bt_mesh_node_t *rmt;
536 struct mesh_network_t *network;
538 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
542 rmt = l_queue_find(network->nodes,
543 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
547 if (__mesh_key_present(rmt->app_keys, app_idx))
553 bool _bt_mesh_node_is_netkey_exists(uint8_t net_uuid[],
554 uint16_t addr, uint16_t net_idx)
556 struct _bt_mesh_node_t *rmt;
557 struct mesh_network_t *network;
559 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
563 rmt = l_queue_find(network->nodes,
564 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
568 if (__mesh_key_present(rmt->net_keys, net_idx))
574 bool _bt_mesh_node_add_net_key(uint8_t net_uuid[],
575 uint16_t addr, uint16_t net_idx)
577 struct _bt_mesh_node_t *rmt;
578 struct mesh_network_t *network;
580 network = l_queue_find(networks, __mesh_net_uuid_match, net_uuid);
584 rmt = l_queue_find(network->nodes,
585 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
589 if (__mesh_key_present(rmt->net_keys, net_idx))
592 l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
596 bool _bt_mesh_node_add_app_key(uint8_t net_uuid[],
597 uint16_t addr, uint16_t app_idx)
599 struct _bt_mesh_node_t *rmt;
600 struct mesh_network_t *network;
602 network = l_queue_find(networks,
603 __mesh_net_uuid_match, net_uuid);
607 rmt = l_queue_find(network->nodes,
608 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
613 rmt->app_keys = l_queue_new();
615 if (__mesh_key_present(rmt->app_keys, app_idx))
618 l_queue_push_tail(rmt->app_keys, L_UINT_TO_PTR(app_idx));
619 BT_INFO("Mesh: Total appkeys present in node [%d]",
620 l_queue_length(rmt->app_keys));
624 bool _bt_mesh_node_del_app_key(uint8_t net_uuid[],
625 uint16_t addr, uint16_t app_idx)
627 struct _bt_mesh_node_t *rmt;
628 struct mesh_network_t *network;
630 network = l_queue_find(networks,
631 __mesh_net_uuid_match, net_uuid);
633 BT_INFO("Mesh: Could not find Network");
637 rmt = l_queue_find(network->nodes,
638 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
640 BT_INFO("Mesh: Remote Node not found!");
644 BT_INFO("Mesh: Total appkeys present in node [%d]",
645 l_queue_length(rmt->app_keys));
646 BT_INFO("Mesh: To be deleted AppKey Idx [0x%2.2x]", app_idx);
647 return l_queue_remove(rmt->app_keys, L_UINT_TO_PTR(app_idx));
650 uint16_t _bt_mesh_node_get_subnet_idx(uint8_t net_uuid[],
653 struct _bt_mesh_node_t *rmt;
655 struct mesh_network_t *network;
657 network = l_queue_find(networks,
658 __mesh_net_uuid_match, net_uuid);
660 return MESH_NET_IDX_INVALID;
662 rmt = l_queue_find(network->nodes,
663 __mesh_match_node_addr, L_UINT_TO_PTR(addr));
665 if (!rmt || l_queue_isempty(rmt->net_keys))
666 return MESH_NET_IDX_INVALID;
668 net_idx = L_PTR_TO_UINT(l_queue_peek_head(rmt->net_keys));
670 return (uint16_t) net_idx;
673 uint16_t _bt_mesh_node_get_next_unicast(uint8_t net_uuid[],
674 uint16_t low, uint16_t high, uint8_t ele_cnt)
676 struct _bt_mesh_node_t *rmt;
677 const struct l_queue_entry *l;
679 struct mesh_network_t *network;
681 network = l_queue_find(networks,
682 __mesh_net_uuid_match, net_uuid);
684 BT_ERR("Mesh: Net UUID did not match");
688 /* Note: the address space includes both
689 low and high terminal values */
690 if (ele_cnt > (high - low + 1))
693 if (!network->nodes || l_queue_isempty(network->nodes))
697 l = l_queue_get_entries(network->nodes);
699 /* Cycle through the sorted (by unicast) node list */
700 for (; l; l = l->next) {
703 if (rmt->unicast >= (addr + ele_cnt))
706 if ((rmt->unicast + rmt->num_ele) > addr)
707 addr = rmt->unicast + rmt->num_ele;
710 if ((addr + ele_cnt - 1) <= high)