bf441163d5d1c7379967b06673b7a076b00ec54c
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / mesh / bt-service-mesh-main.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
6  * @author: Anupam Roy <anupam.r@samsung.com>
7  *
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
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21 #include <dirent.h>
22 #include <ftw.h>
23 #include <unistd.h>
24 #include <stdio.h>
25
26 #include <glib.h>
27 #include <dlog.h>
28 #include <limits.h>
29 #include <time.h>
30 #include <sys/time.h>
31 #include <ell/ell.h>
32 #include <actd/unit_control.h>
33
34 #include "bluetooth-api.h"
35 #include "bt-internal-types.h"
36 #include "bt-service-common.h"
37 #include "bt-service-event.h"
38 #include "bt-service-event-receiver.h"
39 #include "bt-service-util.h"
40
41 #include "bt-service-mesh-util.h"
42 #include "bt-service-mesh-network.h"
43 #include "bt-service-mesh-nodes.h"
44 #include "bt-service-mesh-config-client.h"
45 #include "bt-service-mesh-model.h"
46 #include "bt-service-mesh-common.h"
47
48 #include <oal-mesh.h>
49
50 #define MESH_SYSTEMD_SERVICE_NAME "bluetooth-mesh.service"
51 #define MESH_LAUNCH_DELAY 500
52
53 static guint launch_timer = 0;
54 static guint mesh_app_ref_count;
55 struct l_timeout *wait_timer;
56
57 static GSList *apps;
58
59 static int __bt_meshd_launch()
60 {
61         int ret = UNIT_CONTROL_OK;
62         BT_INFO("Mesh: Launch Meshd");
63         ret = actd_start_unit(UNIT_CONTROL_BUS_TYPE_SYSTEM,
64                                 MESH_SYSTEMD_SERVICE_NAME, 5000);
65
66         if (ret != UNIT_CONTROL_OK) {
67                 BT_ERR("Failed to call systemact service: %d", ret);
68                 return BLUETOOTH_ERROR_INTERNAL;
69         }
70         BT_INFO("Mesh: Launch Meshd successful");
71
72         return BLUETOOTH_ERROR_NONE;
73 }
74
75 static void __bt_meshd_terminate()
76 {
77         int ret = UNIT_CONTROL_OK;
78         BT_INFO("Mesh: Stop Meshd");
79
80         ret = actd_stop_unit(UNIT_CONTROL_BUS_TYPE_SYSTEM,
81                                 MESH_SYSTEMD_SERVICE_NAME, 5000);
82         if (ret != UNIT_CONTROL_OK) {
83                 BT_ERR("Failed to call systemact service: %d", ret);
84                 return;
85         }
86
87         BT_INFO("Mesh: Meshd stop successful");
88 }
89
90 static void __bt_mesh_terminate()
91 {
92         oal_status_t status = OAL_STATUS_SUCCESS;
93
94         /* Terminate bluetooth-meshd */
95         __bt_meshd_terminate();
96
97         /* Reset states */
98         _bt_mesh_set_scanning_state(false);
99         _bt_mesh_set_provisioning_state(false);
100
101         status = mesh_disable();
102         if (OAL_STATUS_SUCCESS != status) {
103                 BT_ERR("Mesh: Failed to de-initialize Mesh profile, status: %d",
104                                 status);
105                 return;
106         }
107
108         /* Un-Register Mesh event handler */
109         _bt_service_unregister_event_handler_callback(BT_MESH_MODULE);
110 }
111
112 bool _bt_is_mesh_initialized()
113 {
114         return (mesh_app_ref_count ? true : false);
115 }
116
117 /* Event handlers */
118 static void __bt_mesh_handle_pending_request_info(int result,
119                 int service_function, void *param,
120                         unsigned int size)
121 {
122         GSList *l;
123         GArray *out_param;
124         invocation_info_t *req_info = NULL;
125
126         for (l = _bt_get_invocation_list(); l != NULL; ) {
127                 req_info = l->data;
128                 l = g_slist_next(l);
129                 if (req_info == NULL ||
130                         req_info->service_function != service_function)
131                         continue;
132
133                 switch (service_function) {
134                 case BT_MESH_INIT: {
135                         BT_INFO("Mesh: Request: BT_MESH_INIT Sender: [%s] result[%d]",
136                                         req_info->sender, result);
137
138                         if (result == BLUETOOTH_ERROR_NONE) {
139
140                                 /* Save Mesh App Owner */
141                                 char *owner = g_strdup(req_info->sender);
142                                 BT_INFO("Mesh: Insert Sender Mesh App List[%s]",
143                                                 req_info->sender);
144                                 apps = g_slist_append(apps, owner);
145
146                                 /* Increase mesh app ref count */
147                                 mesh_app_ref_count++;
148                                 l_timeout_remove(wait_timer);
149                         } else {
150                                 /* Init failed - Terminate bluetooth-mesh */
151                                 __bt_mesh_terminate();
152                         }
153
154                         out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
155                         _bt_service_method_return(req_info->context,
156                                 out_param, result);
157                         _bt_free_info_from_invocation_list(req_info);
158                         break;
159                 }
160                 case BT_MESH_NETWORK_CREATE: {
161                         char uuid_str[BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1];
162                         bluetooth_mesh_node_t *node;
163                         bluetooth_mesh_network_t *network;
164                         ret_if(param == NULL);
165                         BT_INFO("Mesh: Request: BT_MESH_NETWORK_CREATE Sender: [%s] result[%d]",
166                                         req_info->sender, result);
167
168                         node = (bluetooth_mesh_node_t*) param;
169                         network = (bluetooth_mesh_network_t*)req_info->user_data;
170
171                         _bt_mesh_util_convert_hex_to_string(
172                                 (uint8_t *) node->uuid, 16, uuid_str,
173                                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
174
175                         BT_INFO("Mesh: Network UUID from event [%s] Netw UUID from req [%s]",
176                                         uuid_str, network->uuid);
177
178                         if (!g_strcmp0(network->uuid, uuid_str)) {
179                                 BT_INFO("Mesh: BT_MESH_NETWORK_CREATE Request found uuid [%s]",
180                                         network->uuid);
181                                 if (BLUETOOTH_ERROR_NONE != _bt_mesh_network_create_cdb(
182                                         result, req_info->sender,
183                                         network->app_cred, node->uuid,
184                                                 node->token.u8, network->name.name)) {
185                                         result = BLUETOOTH_ERROR_INTERNAL;
186                                         BT_ERR("!!Mesh: BT_MESH_NETWORK_CREATE Failed!!");
187                                 }
188
189                                 _bt_mesh_util_convert_hex_to_string(
190                                         (uint8_t *) node->token.u8, 8,
191                                                 network->token.token,
192                                                 BLUETOOTH_MESH_NETWORK_TOKEN_STRING_LENGTH + 1);
193
194                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
195                                 g_array_append_vals(out_param, network,
196                                         sizeof(bluetooth_mesh_network_t));
197                                 _bt_service_method_return(req_info->context,
198                                         out_param, result);
199                                 _bt_free_info_from_invocation_list(req_info);
200                                 g_array_free(out_param, TRUE);
201                         }
202                         break;
203                 }
204                 case BT_MESH_NETWORK_DESTROY: {
205                         bluetooth_mesh_network_t *event;
206                         bluetooth_mesh_network_t *network;
207                         ret_if(param == NULL);
208                         BT_INFO("Mesh: Request: BT_MESH_NETWORK_DESTROY Sender: [%s] result[%d]",
209                                         req_info->sender, result);
210
211                         event = (bluetooth_mesh_network_t*) param;
212                         network = (bluetooth_mesh_network_t*)req_info->user_data;
213
214                         BT_INFO("Mesh: Network UUID from event [%s] Net UUID from req [%s]",
215                                         event->uuid, network->uuid);
216
217                         if (!g_strcmp0(network->uuid, event->uuid)) {
218                                 BT_INFO("Mesh: BT_MESH_NETWORK_DESTROY Request found uuid [%s]",
219                                         network->uuid);
220
221                                 result = _bt_mesh_network_remove_net_configuration(network);
222
223                                 BT_INFO("Mesh: Return Invocation for BT_MESH_NETWORK_DESTROY");
224                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
225                                 g_array_append_vals(out_param, network,
226                                         sizeof(bluetooth_mesh_network_t));
227                                 _bt_service_method_return(req_info->context,
228                                         out_param, result);
229                                 _bt_free_info_from_invocation_list(req_info);
230                                 g_array_free(out_param, TRUE);
231                         }
232                         break;
233                 }
234                 case BT_MESH_NETWORK_LOAD: {
235                         char token_str[BLUETOOTH_MESH_NETWORK_TOKEN_STRING_LENGTH + 1];
236                         bluetooth_mesh_node_t *node;
237                         bluetooth_mesh_network_t *network;
238                         ret_if(param == NULL);
239                         BT_INFO("Mesh: Request: BT_MESH_NETWORK_LOAD Sender: [%s]",
240                                 req_info->sender);
241
242                         node = (bluetooth_mesh_node_t*) param;
243                         network = (bluetooth_mesh_network_t*)req_info->user_data;
244
245                         _bt_mesh_util_convert_hex_to_string(
246                                 (uint8_t *) node->token.u8, 8, token_str,
247                                         BLUETOOTH_MESH_NETWORK_TOKEN_STRING_LENGTH + 1);
248                         BT_INFO("Mesh: Received Token [%s]", token_str);
249
250                         if (!g_strcmp0(network->token.token, token_str)) {
251                                 char *network_name = NULL;
252                                 BT_INFO("Mesh: BT_MESH_NETWORK_LOAD Request found Token [%s]",
253                                         token_str);
254
255                                 BT_INFO("Mesh: Load the Network resources");
256                                 /* Send request to mesh-network to load keys and Nodes for the network */
257                                 if (BLUETOOTH_ERROR_NONE == _bt_mesh_network_load_cdb(
258                                                 result, req_info->sender, network->app_cred,
259                                                         node->uuid, node->token.u8, &network_name)) {
260                                         g_strlcpy(network->name.name, network_name,
261                                                 sizeof(network->name.name));
262                                         BT_INFO("Mesh: Got Name of the Network [%s]",
263                                                 network->name.name);
264                                 } else
265                                         BT_ERR("!!Mesh: BT_MESH_NETWORK_LOAD Failed!!");
266
267                                 _bt_mesh_util_convert_hex_to_string((uint8_t *) node->uuid, 16, network->uuid,
268                                                 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
269
270                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
271                                 g_array_append_vals(out_param, network, sizeof(bluetooth_mesh_network_t));
272                                 _bt_service_method_return(req_info->context, out_param, result);
273                                 _bt_free_info_from_invocation_list(req_info);
274                                 g_array_free(out_param, TRUE);
275                         }
276                         break;
277                 }
278                 case BT_MESH_NETWORK_SCAN: {
279                         bluetooth_mesh_network_t *network;
280                         event_mesh_scan_status_t *event;
281                         char net_uuid[BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1];
282
283                         event = (event_mesh_scan_status_t*) param;
284                         network = (bluetooth_mesh_network_t*)req_info->user_data;
285                         _bt_mesh_util_convert_hex_to_string(
286                                 (uint8_t *) event->net_uuid.uuid, 16, net_uuid,
287                                 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
288
289                         BT_DBG("Request Sender: [%s]", req_info->sender);
290                         if (!g_strcmp0(network->uuid, net_uuid)) {
291                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
292                                 g_array_append_vals(out_param,
293                                         network, sizeof(bluetooth_mesh_network_t));
294                                 _bt_service_method_return(req_info->context,
295                                         out_param, result);
296                                 _bt_free_info_from_invocation_list(req_info);
297                                 g_array_free(out_param, TRUE);
298                         }
299                         break;
300                 }
301                 case BT_MESH_NETWORK_PROVISION_DEVICE: {
302                         bluetooth_mesh_provisioning_request_t *req_data;
303                         bluetooth_mesh_provisioning_request_t status_data;
304                         event_mesh_provisioning_status_t *event;
305                         memset(&status_data,
306                                 0x00, sizeof(bluetooth_mesh_provisioning_request_t));
307
308                         event = (event_mesh_provisioning_status_t*) param;
309                         req_data = (bluetooth_mesh_provisioning_request_t*) req_info->user_data;
310
311                         _bt_mesh_util_convert_hex_to_string(
312                                 (uint8_t *) event->net_uuid.uuid, 16, status_data.net_uuid,
313                                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
314
315                         _bt_mesh_util_convert_hex_to_string(
316                                 (uint8_t *) event->dev_uuid.uuid, 16, status_data.dev_uuid,
317                                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
318                         BT_INFO("Mesh: Provision Status: Device UUID [%s]", status_data.dev_uuid);
319                         BT_INFO("Mesh: Provision Status: Net UUID [%s]", status_data.net_uuid);
320                         BT_INFO("Mesh: Provision Status: Result [%d]", event->status);
321                         if (event->status == OAL_STATUS_SUCCESS)
322                                 BT_INFO("Mesh: Provisioning status : SUCCESS");
323                         else
324                                 BT_INFO("Mesh: Provisioning status : FAIL");
325
326                         BT_DBG("Request Sender: [%s]", req_info->sender);
327                         if (!g_strcmp0(req_data->net_uuid, status_data.net_uuid)) {
328                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
329                                 g_array_append_vals(out_param, &status_data,
330                                         sizeof(bluetooth_mesh_provisioning_request_t));
331                                 _bt_service_method_return(req_info->context, out_param, result);
332                                 _bt_free_info_from_invocation_list(req_info);
333                                 g_array_free(out_param, TRUE);
334                         }
335                         break;
336                 }
337                 /* Fall through */
338                 case BT_MESH_NETWORK_DELETE_NETKEY:
339                 case BT_MESH_NETWORK_UPDATE_NETKEY:
340                 case BT_MESH_NETWORK_ADD_NETKEY: {
341                         bluetooth_mesh_network_t *network;
342                         event_mesh_netkey_operation_t *event;
343                         char net_uuid[BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1];
344
345                         event = (event_mesh_netkey_operation_t*) param;
346                         network = (bluetooth_mesh_network_t*)req_info->user_data;
347                         _bt_mesh_util_convert_hex_to_string(
348                                 (uint8_t *) event->net_uuid.uuid, 16, net_uuid,
349                                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
350
351                         BT_DBG("Request Sender: [%s]", req_info->sender);
352                         if (!g_strcmp0(network->uuid, net_uuid)) {
353                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
354                                 g_array_append_vals(out_param, &event->key_idx, sizeof(guint16));
355                                 _bt_service_method_return(req_info->context, out_param, result);
356                                 _bt_free_info_from_invocation_list(req_info);
357                                 g_array_free(out_param, TRUE);
358                         }
359                         break;
360                 }
361                 /* Fall through */
362                 case BT_MESH_NETWORK_DELETE_APPKEY:
363                 case BT_MESH_NETWORK_UPDATE_APPKEY:
364                 case BT_MESH_NETWORK_ADD_APPKEY: {
365                         bluetooth_mesh_network_t *network;
366                         event_mesh_appkey_operation_t *event;
367                         char net_uuid[BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1];
368
369                         event = (event_mesh_appkey_operation_t*) param;
370                         network = (bluetooth_mesh_network_t*)req_info->user_data;
371                         _bt_mesh_util_convert_hex_to_string((uint8_t *) event->net_uuid.uuid, 16, net_uuid,
372                                 BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
373
374                         BT_DBG("Request Sender: [%s]", req_info->sender);
375                         if (!g_strcmp0(network->uuid, net_uuid)) {
376                                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
377                                 g_array_append_vals(out_param, &event->app_idx, sizeof(guint16));
378                                 _bt_service_method_return(req_info->context, out_param, result);
379                                 _bt_free_info_from_invocation_list(req_info);
380                                 g_array_free(out_param, TRUE);
381                         }
382                         break;
383                 }
384                 default:
385                         BT_DBG("Unknown function(%d)", service_function);
386                         break;
387                 }
388         }
389 }
390
391 static void __handle_mesh_network_subnet_operation_event(
392                 event_mesh_netkey_operation_t *event)
393 {
394         int result = BLUETOOTH_ERROR_NONE;
395
396         if (event->status != OAL_STATUS_SUCCESS)
397                 result = BLUETOOTH_ERROR_INTERNAL;
398
399         /* Handle DBUS Context return */
400         if (event->op == OAL_MESH_KEY_ADD) {
401                 if (result == BLUETOOTH_ERROR_NONE)
402                         _bt_mesh_network_handle_netkey_added(event->net_uuid.uuid, event->key_idx);
403
404                 __bt_mesh_handle_pending_request_info(result, BT_MESH_NETWORK_ADD_NETKEY,
405                                 event, sizeof(event_mesh_netkey_operation_t));
406         } else if (event->op == OAL_MESH_KEY_DELETE) {
407                 if (result == BLUETOOTH_ERROR_NONE)
408                         _bt_mesh_network_handle_netkey_deleted(event->net_uuid.uuid, event->key_idx);
409
410                 __bt_mesh_handle_pending_request_info(result, BT_MESH_NETWORK_DELETE_NETKEY,
411                                 event, sizeof(event_mesh_netkey_operation_t));
412         } else if (event->op == OAL_MESH_KEY_UPDATE) {
413                 _bt_mesh_network_handle_netkey_updated(event->net_uuid.uuid, event->key_idx);
414
415                 __bt_mesh_handle_pending_request_info(result, BT_MESH_NETWORK_UPDATE_NETKEY,
416                                 event, sizeof(event_mesh_netkey_operation_t));
417         }
418 }
419
420 static void __handle_mesh_network_appkey_operation_event(
421                         event_mesh_appkey_operation_t *event)
422 {
423         int result = BLUETOOTH_ERROR_NONE;
424
425         if (event->status != OAL_STATUS_SUCCESS)
426                 result = BLUETOOTH_ERROR_INTERNAL;
427         /* Handle DBUS Context return */
428         if (event->op == OAL_MESH_KEY_ADD) {
429                 BT_INFO("Mesh: Appkey Add event");
430                 if (result == BLUETOOTH_ERROR_NONE)
431                         _bt_mesh_network_handle_appkey_added(
432                                         event->net_uuid.uuid, event->net_idx, event->app_idx);
433
434                 __bt_mesh_handle_pending_request_info(result, BT_MESH_NETWORK_ADD_APPKEY,
435                                 event, sizeof(event_mesh_netkey_operation_t));
436         } else if (event->op == OAL_MESH_KEY_DELETE) {
437                 BT_INFO("Mesh: Appkey Delete event");
438                 if (result == BLUETOOTH_ERROR_NONE)
439                         _bt_mesh_network_handle_appkey_deleted(
440                                         event->net_uuid.uuid, event->net_idx, event->app_idx);
441
442                 __bt_mesh_handle_pending_request_info(result, BT_MESH_NETWORK_DELETE_APPKEY,
443                                 event, sizeof(event_mesh_netkey_operation_t));
444         } else if (event->op == OAL_MESH_KEY_UPDATE) {
445                 BT_INFO("Mesh: Appkey Update event");
446                 __bt_mesh_handle_pending_request_info(result, BT_MESH_NETWORK_UPDATE_APPKEY,
447                                 event, sizeof(event_mesh_netkey_operation_t));
448         }
449 }
450
451 static void  __handle_mesh_devkey_message_received_event(
452                 event_mesh_devkey_message_t *event)
453 {
454         _bt_mesh_config_client_devkey_msg_handler(event);
455 }
456
457 static void  __handle_mesh_message_received_event(
458                 event_mesh_message_t *event)
459 {
460         _bt_mesh_msg_handler(event);
461 }
462
463 static void  __handle_mesh_network_proxy_added_event(
464                 event_mesh_network_proxy_added_t *event)
465 {
466         int result = BLUETOOTH_ERROR_NONE;
467
468         if (event->status != OAL_STATUS_SUCCESS)
469                 result = BLUETOOTH_ERROR_INTERNAL;
470
471         /* Handle DBUS Context return */
472         BT_INFO("Mesh: Handle DBUS Context return");
473         __bt_mesh_handle_pending_request_info(result,
474                         BT_MESH_INIT,
475                         NULL, 0);
476 }
477
478 static void __handle_mesh_network_attached_event(
479                 event_mesh_network_attached_t *event)
480 {
481         int result = BLUETOOTH_ERROR_NONE;
482         bluetooth_mesh_node_t node;
483
484         if (event->status != OAL_STATUS_SUCCESS)
485                 result = BLUETOOTH_ERROR_INTERNAL;
486
487         memset(&node, 0x00, sizeof(bluetooth_mesh_node_t));
488
489         memcpy(node.uuid, event->uuid.uuid, 16);
490         memcpy(node.token.u8, event->token, 8);
491
492         __bt_mesh_handle_pending_request_info(result,
493                         BT_MESH_NETWORK_CREATE,
494                         &node, sizeof(bluetooth_mesh_node_t));
495         __bt_mesh_handle_pending_request_info(result,
496                         BT_MESH_NETWORK_LOAD,
497                         &node, sizeof(bluetooth_mesh_node_t));
498 }
499
500 static void __handle_mesh_network_destroyed_event(
501                 event_mesh_network_destroyed_t *event)
502 {
503         int result = BLUETOOTH_ERROR_NONE;
504         bluetooth_mesh_network_t network;
505
506         if (event->status != OAL_STATUS_SUCCESS) {
507                 BT_INFO("Mesh: Network Destroyed Event: result is Failed!");
508                 result = BLUETOOTH_ERROR_INTERNAL;
509         } else {
510                 BT_INFO("Mesh: Network Destroyed Event: result is Success!");
511         }
512
513         memset(&network, 0x00, sizeof(bluetooth_mesh_network_t));
514         _bt_mesh_util_convert_hex_to_string(
515                         (uint8_t *) event->uuid.uuid, 16, network.uuid,
516                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
517         _bt_mesh_util_convert_hex_to_string(
518                         (uint8_t *) event->token, 8, network.token.token,
519                         BLUETOOTH_MESH_NETWORK_TOKEN_STRING_LENGTH + 1);
520
521         __bt_mesh_handle_pending_request_info(result,
522                         BT_MESH_NETWORK_DESTROY,
523                         &network, sizeof(bluetooth_mesh_network_t));
524 }
525
526 static void __handle_mesh_network_scan_started_event(
527         event_mesh_scan_status_t *event)
528 {
529         GVariant *out_var = NULL, *param = NULL;
530         GArray *info = NULL;
531         bluetooth_mesh_network_t network;
532
533         int result = BLUETOOTH_ERROR_NONE;
534         if (event->status != OAL_STATUS_SUCCESS) {
535                 result = BLUETOOTH_ERROR_INTERNAL;
536                 _bt_mesh_set_scanning_state(false);
537         } else
538                 _bt_mesh_set_scanning_state(true);
539
540         /* Handle DBUS Context return */
541         __bt_mesh_handle_pending_request_info(result,
542                         BT_MESH_NETWORK_SCAN,
543                         event, sizeof(event_mesh_scan_status_t));
544
545         /* Handle Scan started event */
546         if (result == BLUETOOTH_ERROR_NONE) {
547                 memset(&network, 0x00, sizeof(bluetooth_mesh_network_t));
548                 _bt_mesh_util_convert_hex_to_string(
549                         (uint8_t *) event->net_uuid.uuid, 16, network.uuid,
550                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
551
552                 info = g_array_new(FALSE, FALSE, sizeof(gchar));
553                 g_array_append_vals(info, &network,
554                         sizeof(bluetooth_mesh_network_t));
555
556                 out_var = g_variant_new_from_data((const GVariantType *)"ay",
557                         info->data, info->len,
558                         TRUE, NULL, NULL);
559
560                 param = g_variant_new("(iv)", result, out_var);
561                 _bt_send_event(BT_MESH_EVENT,
562                         BLUETOOTH_EVENT_MESH_SCAN_STARTED,
563                         param);
564         }
565 }
566
567 static void __handle_mesh_network_scan_finished_event(
568         event_mesh_scan_status_t *event)
569 {
570         GVariant *out_var = NULL, *param = NULL;
571         GArray *info = NULL;
572         bluetooth_mesh_network_t network;
573         int result = BLUETOOTH_ERROR_NONE;
574         if (event->status != OAL_STATUS_SUCCESS) {
575                 BT_INFO("Mesh: Scan Finished: status:: FAILED!");
576                 result = BLUETOOTH_ERROR_INTERNAL;
577         } else
578                 BT_INFO("Mesh: Scan Finished: status:: SUCCESS!");
579
580         /* Handle Scan finsihed event */
581         if (result == BLUETOOTH_ERROR_NONE) {
582                 memset(&network, 0x00, sizeof(bluetooth_mesh_network_t));
583                 _bt_mesh_util_convert_hex_to_string(
584                         (uint8_t *) event->net_uuid.uuid, 16, network.uuid,
585                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
586
587                 info = g_array_new(FALSE, FALSE, sizeof(gchar));
588                 g_array_append_vals(info, &network,
589                         sizeof(bluetooth_mesh_network_t));
590
591                 out_var = g_variant_new_from_data((const GVariantType *)"ay",
592                         info->data, info->len,
593                         TRUE, NULL, NULL);
594
595                 param = g_variant_new("(iv)", result, out_var);
596                 _bt_send_event(BT_MESH_EVENT,
597                         BLUETOOTH_EVENT_MESH_SCAN_FINISHED,
598                         param);
599                 _bt_mesh_set_scanning_state(false);
600         }
601 }
602
603 static void __handle_mesh_network_provisioning_started_event(
604                 event_mesh_provisioning_status_t *status)
605 {
606         int result = BLUETOOTH_ERROR_NONE;
607         BT_INFO("Mesh: Provisioning started");
608
609         __bt_mesh_handle_pending_request_info(result,
610                         BT_MESH_NETWORK_PROVISION_DEVICE,
611                         status, sizeof(event_mesh_provisioning_status_t));
612
613         _bt_mesh_set_provisioning_state(true);
614 }
615
616 static void __handle_mesh_network_provisioning_failed_event(
617                 event_mesh_provisioning_status_t *status)
618 {
619         int result = BLUETOOTH_ERROR_INTERNAL;
620         BT_INFO("Mesh: Provisioning failed!!");
621         __bt_mesh_handle_pending_request_info(result,
622                         BT_MESH_NETWORK_PROVISION_DEVICE,
623                         status, sizeof(event_mesh_provisioning_status_t));
624
625         _bt_mesh_set_provisioning_state(false);
626 }
627
628 static void __handle_mesh_network_provisioning_finished_event(
629                 event_mesh_provisioning_finished_t *event)
630 {
631         GVariant *out_var = NULL, *param = NULL;
632         GArray *info = NULL;
633         bluetooth_mesh_provisioning_result_t prov_result;
634         BT_INFO("Mesh: Provisioning Finished!");
635
636         memset(&prov_result, 0x00,
637                         sizeof(bluetooth_mesh_provisioning_result_t));
638
639         if (event->status != OAL_STATUS_SUCCESS)
640                 prov_result.result = BLUETOOTH_ERROR_INTERNAL;
641         else
642                 prov_result.result = BLUETOOTH_ERROR_NONE;
643
644         prov_result.reason = event->reason;
645         prov_result.unicast = event->unicast;
646         prov_result.count = event->count;
647
648         _bt_mesh_util_convert_hex_to_string(
649                         (uint8_t *) event->net_uuid.uuid, 16, prov_result.net_uuid,
650                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
651
652         _bt_mesh_util_convert_hex_to_string(
653                         (uint8_t *) event->dev_uuid.uuid, 16, prov_result.dev_uuid,
654                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
655
656         info = g_array_new(FALSE, FALSE, sizeof(gchar));
657         g_array_append_vals(info, &prov_result,
658                         sizeof(bluetooth_mesh_provisioning_result_t));
659
660         out_var = g_variant_new_from_data((const GVariantType *)"ay",
661                         info->data, info->len,
662                         TRUE, NULL, NULL);
663
664         param = g_variant_new("(iv)", prov_result.result, out_var);
665         _bt_send_event(BT_MESH_EVENT,
666                         BLUETOOTH_EVENT_MESH_PROVISIONING_FINISHED,
667                         param);
668
669         /* Add Remote Node entry in Local CDB */
670         if (event->status == OAL_STATUS_SUCCESS) {
671                 BT_INFO("Mesh: Provisioning done, add node to Network");
672                 BT_INFO("Mesh: Node UUID [%s]", prov_result.dev_uuid);
673                 BT_INFO("Mesh: Node Unicast[0x%2.2x] Element Count [%d]",
674                         event->unicast, event->count);
675
676                 _bt_mesh_network_add_remote_node(
677                         event->net_uuid.uuid, event->dev_uuid.uuid,
678                                 event->unicast, event->count);
679         }
680         /* Unset provisioning state */
681         _bt_mesh_set_provisioning_state(false);
682 }
683
684 static void __handle_mesh_network_provisioning_data_requested_event(
685         event_mesh_provisioning_data_requested_t *event)
686 {
687         _bt_mesh_network_request_provisioning_data_request(
688                         event->net_uuid.uuid, event->count);
689 }
690
691 static void __handle_mesh_network_authentication_requested_event(
692                 event_mesh_authentication_requested_t *event)
693 {
694         GVariant *out_var = NULL, *param = NULL;
695         GArray *info = NULL;
696         bluetooth_mesh_authentication_request_t auth_req;
697
698         memset(&auth_req, 0x00,
699                         sizeof(bluetooth_mesh_authentication_request_t));
700
701         auth_req.auth_type = event->auth_type;
702         g_strlcpy(auth_req.auth_value, event->auth_value,
703                         sizeof(auth_req.auth_value));
704
705         _bt_mesh_util_convert_hex_to_string(
706                         (uint8_t *) event->net_uuid.uuid, 16, auth_req.net_uuid,
707                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
708
709         BT_INFO("Mesh: Authentication Requested by Device: Network [%s]",
710                 auth_req.net_uuid);
711         info = g_array_new(FALSE, FALSE, sizeof(gchar));
712         g_array_append_vals(info, &auth_req,
713                         sizeof(bluetooth_mesh_authentication_request_t));
714
715         out_var = g_variant_new_from_data((const GVariantType *)"ay",
716                         info->data, info->len,
717                         TRUE, NULL, NULL);
718
719         param = g_variant_new("(iv)", BLUETOOTH_ERROR_NONE, out_var);
720         _bt_send_event(BT_MESH_EVENT,
721                         BLUETOOTH_EVENT_MESH_AUTHENTICATION_REQUEST,
722                         param);
723 }
724
725 static void __handle_mesh_network_scan_result_event(
726                 event_mesh_scan_result_t *event)
727 {
728         GVariant *out_var = NULL, *param = NULL;
729         GArray *info = NULL;
730         bluetooth_mesh_scan_result_t data;
731         int result = BLUETOOTH_ERROR_NONE;
732
733         memset(&data, 0x00, sizeof(bluetooth_mesh_scan_result_t));
734
735         /* Fill Network UUID */
736         _bt_mesh_util_convert_hex_to_string(
737                 (uint8_t *) event->net_uuid.uuid, 16, data.net_uuid,
738                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
739
740         /* Fill Device UUID */
741         _bt_mesh_util_convert_hex_to_string(
742                 (uint8_t *) event->result.dev_uuid.uuid, 16, data.dev_uuid,
743                         BLUETOOTH_MESH_NETWORK_UUID_STRING_LENGTH + 1);
744
745         /* Fill RSSI */
746         data.rssi = event->result.rssi;
747
748         /* Fill OOB Info */
749         memcpy(&data.oob_info, event->result.oob_info, 2);
750
751         /* Fill URI Hash Info */
752         memcpy(&data.uri_hash, event->result.uri_hash, 4);
753
754         if (event->status != OAL_STATUS_SUCCESS)
755                 result = BLUETOOTH_ERROR_INTERNAL;
756
757         /* Fill Data */
758         info = g_array_new(FALSE, FALSE, sizeof(gchar));
759         g_array_append_vals(info, &data,
760                 sizeof(bluetooth_mesh_scan_result_t));
761
762         out_var = g_variant_new_from_data((const GVariantType *)"ay",
763                         info->data, info->len,
764                         TRUE, NULL, NULL);
765
766         param = g_variant_new("(iv)", result, out_var);
767         _bt_send_event(BT_MESH_EVENT,
768                         BLUETOOTH_EVENT_MESH_SCAN_RESULT,
769                         param);
770 }
771
772 static void __handle_mesh_events(int event_type,
773                 gpointer event_data)
774 {
775         BT_INFO("Mesh: Got Mesh event!!! event type [%d]", event_type);
776         if (event_type == OAL_EVENT_MESH_PROVISIONING_STARTED)
777                 BT_INFO("Mesh: Provisioning started event");
778
779         switch (event_type) {
780         case OAL_EVENT_MESH_NETWORK_PROXY_ADDED:
781                 __handle_mesh_network_proxy_added_event(
782                         (event_mesh_network_proxy_added_t*)event_data);
783                 BT_PERMANENT_LOG("Mesh: Network proxy added!!");
784                 break;
785         case OAL_EVENT_MESH_NETWORK_ATTACHED:
786                 __handle_mesh_network_attached_event(
787                         (event_mesh_network_attached_t*)event_data);
788                 BT_PERMANENT_LOG("Mesh: Network attached!!");
789                 break;
790         case OAL_EVENT_MESH_NETWORK_DESTROYED:
791                 __handle_mesh_network_destroyed_event(
792                         (event_mesh_network_destroyed_t*)event_data);
793                 BT_PERMANENT_LOG("Mesh: Network Destroyed!!");
794                 break;
795         case OAL_EVENT_MESH_SCAN_STARTED:
796                 __handle_mesh_network_scan_started_event(
797                         (event_mesh_scan_status_t*)event_data);
798                 BT_PERMANENT_LOG("Mesh: Network Scan Stated!!");
799                 break;
800         case OAL_EVENT_MESH_SCAN_FINISHED:
801                 __handle_mesh_network_scan_finished_event(
802                         (event_mesh_scan_status_t*)event_data);
803                 BT_PERMANENT_LOG("Mesh: Network Scan Finished!!");
804                 break;
805         case OAL_EVENT_MESH_SCAN_RESULT:
806                 __handle_mesh_network_scan_result_event(
807                         (event_mesh_scan_result_t*)event_data);
808                 BT_PERMANENT_LOG("Mesh: Network Scan Result!!");
809                 break;
810         case OAL_EVENT_MESH_PROVISIONING_STARTED:
811                 BT_INFO("Mesh: Network Provisioning Started");
812                 __handle_mesh_network_provisioning_started_event(
813                         (event_mesh_provisioning_status_t*)event_data);
814                 BT_PERMANENT_LOG("Mesh: Network Provisioning Started");
815                 break;
816         case OAL_EVENT_MESH_PROVISIONING_FAILED:
817                 BT_INFO("Mesh: Network Provisioning Failed!!!!");
818                 __handle_mesh_network_provisioning_failed_event(
819                         (event_mesh_provisioning_status_t*)event_data);
820                 BT_PERMANENT_LOG("Mesh: Network Provisioning Failed");
821                 break;
822         case OAL_EVENT_MESH_PROVISIONING_FINISHED:
823                 __handle_mesh_network_provisioning_finished_event(
824                         (event_mesh_provisioning_finished_t*)event_data);
825                 BT_PERMANENT_LOG("Mesh: Network Provisioning Finished");
826                 break;
827         case OAL_EVENT_MESH_PROVISIONING_DATA_REQUESTED:
828                 __handle_mesh_network_provisioning_data_requested_event(
829                         (event_mesh_provisioning_data_requested_t*)event_data);
830                 BT_PERMANENT_LOG("Mesh: Network Provisioning Data Requested");
831                 break;
832         case OAL_EVENT_MESH_AUTHENTICATION_REQUESTED:
833                 __handle_mesh_network_authentication_requested_event(
834                         (event_mesh_authentication_requested_t*)event_data);
835                 BT_PERMANENT_LOG("Mesh: Network Authentication Requested");
836                 break;
837         case OAL_EVENT_MESH_NETKEY_EXECUTE_EVENT:
838                 __handle_mesh_network_subnet_operation_event(
839                         (event_mesh_netkey_operation_t*)event_data);
840                 BT_PERMANENT_LOG("Mesh: Network Subnet operation event");
841                 break;
842         case OAL_EVENT_MESH_APPKEY_EXECUTE_EVENT:
843                  __handle_mesh_network_appkey_operation_event(
844                         (event_mesh_appkey_operation_t*)event_data);
845                 BT_PERMANENT_LOG("Mesh: AppKey operation event");
846                 break;
847         case OAL_EVENT_MESH_DEVKEY_MESSAGE_RECEIVED:
848                 __handle_mesh_devkey_message_received_event(
849                         (event_mesh_devkey_message_t*)event_data);
850                 BT_PERMANENT_LOG("Mesh: DevKey Message Received event");
851                 break;
852         case OAL_EVENT_MESH_MODEL_MESSAGE_RECEIVED:
853                 __handle_mesh_message_received_event(
854                         (event_mesh_message_t*)event_data);
855                 BT_PERMANENT_LOG("Mesh: Model Message Received event");
856                 break;
857         default:
858         break;
859         }
860 }
861
862 static int __bt_mesh_enable()
863 {
864         oal_status_t status = OAL_STATUS_SUCCESS;
865         BT_INFO("Mesh: Set dbus callbacks");
866         status = mesh_enable();
867         if (OAL_STATUS_SUCCESS != status &&
868                         OAL_STATUS_ALREADY_DONE != status) {
869                 BT_ERR("Mesh: Failed to enable mesh interface, status: %d",
870                                 status);
871                 return BLUETOOTH_ERROR_INTERNAL;
872         }
873         BT_INFO("Mesh: Stack Initialization Done successfully: status [%d]",
874                         status);
875
876         /* Register MESH event handler */
877         _bt_service_register_event_handler_callback(BT_MESH_MODULE,
878                         __handle_mesh_events);
879
880         return (status == OAL_STATUS_SUCCESS ? BLUETOOTH_ERROR_NONE : \
881                         BLUETOOTH_ERROR_ALREADY_INITIALIZED);
882 }
883
884 static gboolean __bt_mesh_launch_timer_expired_cb(gpointer data)
885 {
886         BT_INFO("Mesh: Enable Mesh dbus");
887         int ret = BLUETOOTH_ERROR_NONE;
888         ret = __bt_mesh_enable();
889         if (BLUETOOTH_ERROR_NONE != ret &&
890                 BLUETOOTH_ERROR_ALREADY_INITIALIZED != ret)
891                 BT_ERR("Mesh: Mesh enable failed: %d", ret);
892
893         /* Reset launch timer ID */
894         BT_INFO("Mesh: Timer ID after expiry [%u]", launch_timer);
895         launch_timer = 0;
896
897         return FALSE;
898 }
899
900 static void __bt_mesh_init_wait_response_timeout(
901         struct l_timeout *timeout, void *user_data)
902 {
903         int result = BLUETOOTH_ERROR_TIMEOUT;
904
905         /* Handle DBUS Context return */
906         BT_INFO("Mesh: Handle DBUS Context return");
907         __bt_mesh_handle_pending_request_info(result,
908                         BT_MESH_INIT,
909                         NULL, 0);
910         l_timeout_remove(wait_timer);
911 }
912
913 int _bt_mesh_init(const char *sender)
914 {
915         int ret = BLUETOOTH_ERROR_NONE;
916
917         BT_INFO("Mesh: Total apps using Mesh: [%d]",
918                 mesh_app_ref_count);
919
920         BT_INFO("Mesh: Mesh App Sender [%s]", sender);
921
922         BT_INFO("Mesh: Current Timer ID [%u]", launch_timer);
923         if (launch_timer > 0) {
924                 BT_INFO("Mesh: BT_MESH_INIT in progress");
925                 return ret;
926         }
927
928         if (mesh_app_ref_count) {
929                 BT_INFO("Mesh: Mesh Stack already initialized");
930
931                 /* Save Mesh App Owner */
932                 apps = g_slist_append(apps, g_strdup(sender));
933
934                 /* Increase mesh app ref count */
935                 mesh_app_ref_count++;
936                 return BLUETOOTH_ERROR_ALREADY_INITIALIZED;
937         }
938
939         BT_INFO("Mesh: Mesh Stack init not done yet!");
940         /* Launch bluetooth-meshd */
941         ret = __bt_meshd_launch();
942         if (BLUETOOTH_ERROR_NONE != ret) {
943                 BT_ERR("Mesh: Meshd launch failed: %d", ret);
944                 return ret;
945         }
946
947         /* wait for half a second*/
948         launch_timer = g_timeout_add(MESH_LAUNCH_DELAY,
949                                 (GSourceFunc)__bt_mesh_launch_timer_expired_cb,
950                                                                         NULL);
951         BT_INFO("Mesh: Timer ID [%u]", launch_timer);
952
953         /* Add mesh init request timeout */
954         wait_timer = l_timeout_create(MESH_DEFAULT_RESPONSE_TIMEOUT,
955                         __bt_mesh_init_wait_response_timeout, NULL, NULL);
956
957         return ret;
958 }
959
960 static gint __bt_mesh_match_sender(gconstpointer a, gconstpointer b)
961 {
962         char *owner_a = (char*) a;
963         char *owner_b = (char*) b;
964
965         return g_strcmp0(owner_a, owner_b);
966 }
967
968 int _bt_mesh_deinit(const char *sender)
969 {
970         GSList *l = NULL;
971         char *owner = NULL;
972
973         BT_INFO("Mesh: Deinit Request from App [%s]", sender);
974         BT_INFO("Mesh: Total Apps available in list [%d]",
975                         g_slist_length(apps));
976
977         /* Find & remove app entry from list */
978         l = g_slist_find_custom(apps, sender,
979                         (GCompareFunc)__bt_mesh_match_sender);
980         if (!l) {
981                 BT_ERR("Mesh: App is not Mesh App");
982                 return BLUETOOTH_ERROR_INTERNAL;
983         }
984
985         BT_INFO("Mesh: Deinit Mesh: Sender Found: [%s]", sender);
986
987         if (launch_timer > 0) {
988                 g_source_remove(launch_timer);
989                 launch_timer = 0;
990         }
991
992         BT_INFO("Mesh: Current number of applications using mesh [%d]",
993                         mesh_app_ref_count);
994
995         if (mesh_app_ref_count == 1) {
996                 BT_INFO("Mesh: Only one app using Mesh Stack: Unload & reduce ref count");
997
998                 /* Terminate bluetooth-mesh */
999                 __bt_mesh_terminate();
1000         }
1001
1002         /* Decrease mesh app ref count */
1003         mesh_app_ref_count--;
1004
1005         owner = l->data;
1006         apps = g_slist_remove(apps, owner);
1007         g_free(owner);
1008
1009         _bt_mesh_deinitialized();
1010
1011         return BLUETOOTH_ERROR_NONE;
1012 }
1013
1014 void _bt_mesh_handle_app_termination(const char *sender)
1015 {
1016         BT_INFO("Mesh: Handle App termination: dbus app name[%s]",
1017                         sender);
1018
1019         _bt_mesh_deinit(sender);
1020 }