Fix the svace issues
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-mesh-dbus-handler.c
1 /*
2  * Bluetooth HAL
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
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
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <dlog.h>
30 #include <vconf.h>
31 #include <ell/ell.h>
32
33 #include "bt-hal-mesh-dbus-handler.h"
34 #include "bt-hal-dbus-common-utils.h"
35 #include "bt-hal-internal.h"
36
37 #include <hardware/bt_mesh.h>
38
39 #define BT_HAL_UUID_LEN 16
40 #define BT_HAL_BLUEZ_MESH_NAME "org.bluez.mesh"
41
42 #define BT_HAL_MESH_NETWORK_INTERFACE "org.bluez.mesh.Network1"
43 #define BT_HAL_MESH_NODE_INTERFACE "org.bluez.mesh.Node1"
44 #define BT_HAL_MESH_MANAGEMENT_INTERFACE "org.bluez.mesh.Management1"
45 #define BT_HAL_MESH_ELEMENT_INTERFACE "org.bluez.mesh.Element1"
46 #define BT_HAL_MESH_APPLICATION_INTERFACE "org.bluez.mesh.Application1"
47 #define BT_HAL_MESH_PROVISION_AGENT_INTERFACE "org.bluez.mesh.ProvisionAgent1"
48 #define BT_HAL_MESH_PROVISIONER_INTERFACE "org.bluez.mesh.Provisioner1"
49 #define BT_HAL_MESH_ERROR_INTERFACE "org.bluez.mesh.Error"
50
51 #define BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE 2048
52
53 static const char *dbus_err_args = "org.freedesktop.DBus.Error.InvalidArgs";
54 static const char *dbus_err_fail = "org.freedesktop.DBus.Error.Failed";
55
56 static struct l_dbus *dbus = NULL;
57 static struct l_dbus_client *client = NULL;
58
59 static struct l_dbus_proxy *net_proxy = NULL;
60 static struct l_dbus_message *agent_msg;
61
62 static handle_stack_msg mesh_event_cb = NULL;
63
64
65 struct subnet_key_request {
66         uint16_t idx;
67         const char *str;
68 };
69
70 struct app_key_request {
71         uint16_t net_idx;
72         uint16_t app_idx;
73         const char *str;
74 };
75
76 struct configuration_request {
77         const char *ele_path;
78         bool rmt;
79         bool is_dev_key;
80         uint16_t dst;
81         uint16_t idx;
82         uint8_t *data;
83         uint16_t len;
84 };
85
86 struct key_config_request {
87         const char *ele_path;
88         uint16_t dst;
89         uint16_t key_req_idx;
90         uint16_t idx;
91         bool update_req;
92 };
93
94 struct mesh_provision_auth_action {
95         const char *action;
96         bt_hal_mesh_auth_variant_e auth_type;
97 };
98
99 static struct mesh_provision_auth_action auth_table[] = {
100         { "blink", BT_HAL_MESH_AUTH_REQ_BLINK_COUNT_INPUT},
101         { "beep", BT_HAL_MESH_AUTH_REQ_BEEP_COUNT_INPUT},
102         { "vibrate", BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT},
103         { "in-numeric", BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT},
104         { "in-alpha", BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT},
105         { "twist", BT_HAL_MESH_AUTH_TWIST_COUNT_DISPLAY},
106         { "push", BT_HAL_MESH_AUTH_PUSH_COUNT_DISPLAY},
107         { "out-numeric", BT_HAL_MESH_AUTH_NUMERIC_DISPLAY},
108         { "out-alpha", BT_HAL_MESH_AUTH_ALPHANUMERIC_DISPLAY},
109         { "static-oob", BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT},
110         { "unknown", BT_HAL_MESH_UNKNOWN_AUTH_METHOD},
111 };
112
113
114 static uint8_t __bt_mesh_util_get_prov_error_code(char *prov_err_str)
115 {
116         uint8_t ret = 0;
117
118         if (!g_strcmp0(prov_err_str, "success"))
119                 ret = BT_HAL_MESH_PROV_ERR_SUCCESS;
120         else if (!g_strcmp0(prov_err_str, "bad-pduread"))
121                 ret = BT_HAL_MESH_PROV_ERR_INVALID_PDU;
122         else if (!g_strcmp0(prov_err_str, "confirmation-failed"))
123                 ret = BT_HAL_MESH_PROV_ERR_CONFIRM_FAILED;
124         else if (!g_strcmp0(prov_err_str, "out-of-resources"))
125                 ret = BT_HAL_MESH_PROV_ERR_INSUF_RESOURCE;
126         else if (!g_strcmp0(prov_err_str, "decryption-error"))
127                 ret = BT_HAL_MESH_PROV_ERR_DECRYPT_FAILED;
128         else if (!g_strcmp0(prov_err_str, "cannot-assign-addresses"))
129                 ret = BT_HAL_MESH_PROV_ERR_CANT_ASSIGN_ADDR;
130         else if (!g_strcmp0(prov_err_str, "timeout"))
131                 ret = BT_HAL_MESH_PROV_ERR_TIMEOUT;
132         else if (!g_strcmp0(prov_err_str, "unexpected-error"))
133                 ret = BT_HAL_MESH_PROV_ERR_UNEXPECTED_ERR;
134
135         return ret;
136 }
137
138 static bt_hal_mesh_auth_variant_e  __mesh_get_authentication_type(char *str)
139 {
140         int len = strlen(str);
141         int sz = L_ARRAY_SIZE(auth_table);
142         int i;
143
144         for (i = 0; i < sz; ++i)
145                 if (len == strlen(auth_table[i].action) &&
146                                 !strcmp(str, auth_table[i].action))
147                         break;
148         if (i < sz) {
149                 return auth_table[i].auth_type;
150         } else {
151                 ERR("Mesh : Not A Proper Authentication Type!");
152                 return BT_HAL_MESH_UNKNOWN_AUTH_METHOD;
153         }
154 }
155
156 enum mesh_dbus_interface_e {
157         MESH_APP_IFACE,
158         MESH_PROV_IFACE,
159         MESH_AGENT_IFACE,
160         MESH_ELEMENT_IFACE,
161 };
162
163 typedef enum mesh_dbus_interface_e mesh_dbus_interface_e;
164
165 struct meshcfg_model {
166         uint16_t elem_index;
167         uint32_t model;
168 };
169
170 typedef struct meshcfg_model meshcfg_model;
171
172 struct meshcfg_el {
173         char *path;
174         uint16_t index;
175         GSList *models;
176 };
177
178 typedef struct meshcfg_el meshcfg_el;
179
180 struct meshcfg_app {
181         /* Remember Proxies & dbus paths */
182         char *path;
183         char *agent_path;
184         struct l_dbus_proxy *proxy;
185         struct l_dbus_proxy *mgmt_proxy;
186
187         /* Local node Info */
188         GSList *elements;
189         uint16_t cid;
190         uint16_t pid;
191         uint16_t vid;
192         uint16_t crpl;
193         uint8_t uuid[16];
194         union {
195                 uint64_t u64;
196                 uint8_t u8[8];
197         } token;
198         bool is_prov;
199         /* Caps */
200         bool static_oob;
201         bool public_oob;
202         uint16_t out_oob;
203         uint16_t in_oob;
204         struct l_dbus_message *msg;
205         guint scan_timer_id;
206 };
207
208 typedef struct meshcfg_app meshcfg_app;
209
210 /* Will contain critical data related to local Mesh Network */
211 static GSList *mesh_apps = NULL;
212
213
214 struct meshcfg_node {
215         const char *path;
216         struct l_dbus_proxy *proxy;
217         struct l_dbus_proxy *mgmt_proxy;
218         union {
219                 uint64_t u64;
220                 uint8_t u8[8];
221         } token;
222 };
223
224 typedef struct meshcfg_node meshcfg_node;
225
226 static void __mesh_append_byte_array(struct l_dbus_message_builder *builder,
227                 unsigned char *data, unsigned int len)
228 {
229         unsigned int i;
230
231         l_dbus_message_builder_enter_array(builder, "y");
232
233         for (i = 0; i < len; i++)
234                 l_dbus_message_builder_append_basic(builder, 'y', &(data[i]));
235
236         l_dbus_message_builder_leave_array(builder);
237 }
238
239 static gint __mesh_compare_network_uuid(gconstpointer data, gconstpointer user_data)
240 {
241         const meshcfg_app *app = (meshcfg_app*) data;
242         uint8_t uuid[16];
243         memcpy(uuid, (uint8_t*) user_data, 16);
244
245         return memcmp(uuid, app->uuid, sizeof(bt_uuid_t));
246 }
247
248 static unsigned char* __mesh_get_net_uuid_from_dbus_proxy_path(
249                 const char *dbus_path)
250 {
251         char uuid[33];
252         size_t sz;
253
254         memcpy(uuid, (void*)&dbus_path[20], sizeof(uuid));
255         uuid[32] = '\0';
256         INFO("Mesh: Net UUID string [%s]", uuid);
257         return l_util_from_hexstring(uuid, &sz);
258 }
259
260 static unsigned char* __mesh_get_net_uuid_from_path(
261                 const char *dbus_path, bool is_prov,
262                         mesh_dbus_interface_e iface)
263 {
264         char uuid[33];
265         size_t sz;
266
267         switch(iface) {
268         case MESH_APP_IFACE:
269         case MESH_PROV_IFACE:  {
270                 memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
271                 uuid[32] = '\0';
272                 return l_util_from_hexstring(uuid, &sz);
273         }
274         case MESH_AGENT_IFACE: {
275                 memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[23], 32);
276                 uuid[32] = '\0';
277                 return l_util_from_hexstring(uuid, &sz);
278         }
279         case MESH_ELEMENT_IFACE: {
280                 memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
281                 uuid[32] = '\0';
282                 return l_util_from_hexstring(uuid, &sz);
283         }
284         default:
285                 return NULL;
286         }
287 }
288
289 static void __mesh_hal_free_elements(gpointer data)
290 {
291         meshcfg_el *element = (meshcfg_el*) data;
292         if (!element)
293                 return;
294         g_free(element->path);
295         if (element->models)
296                 g_slist_free_full(element->models, g_free);
297
298         element->models = NULL;
299         g_free(element);
300 }
301
302 static bool __bt_mesh_proxy_check(meshcfg_app *app)
303 {
304         /* Check meshd stack Vis up or not */
305         if (!dbus) {
306                 ERR("Mesh: DBUS is not UP!, possibly stack not Up!");
307                 return false;
308         }
309         /* Check Network Proxy is added or not */
310         if (!net_proxy) {
311                 ERR("Mesh: Network proxy is not attached yet!");
312                 return false;
313         }
314
315         if (app) {
316                 /* Check App management proxyis added or not */
317                 if (!app->mgmt_proxy) {
318                         ERR("Mesh: Network proxy is not attached yet!");
319                         return false;
320                 }
321                 /* Check App  Node Proxy is added or not */
322                 if (!app->proxy) {
323                         ERR("Mesh: Node proxy is not attached yet!");
324                         return false;
325                 }
326         }
327         return true;
328 }
329
330 static void __bt_hal_mesh_destroy_app_object(gpointer data)
331 {
332
333         meshcfg_app *app = (meshcfg_app*) data;
334         if (!app)
335                 return;
336
337         mesh_apps = g_slist_remove(mesh_apps, app);
338
339         if (app->path) {
340                 INFO("Mesh: App path [%s] ", app->path);
341                 g_free(app->path);
342         }
343         if (app->agent_path) {
344                 INFO("Mesh: Agent Path [%s]", app->agent_path);
345                 g_free(app->agent_path);
346         }
347
348         if (app->elements) {
349                 INFO("Mesh: Total elements present in app [%d]",
350                                 g_slist_length(app->elements));
351                 g_slist_free_full(app->elements, __mesh_hal_free_elements);
352         }
353         g_free(app);
354 }
355
356 static void __mesh_client_connected(struct l_dbus *dbus_obj, void *user_data)
357 {
358         ERR("MESH: D-Bus client connected\n");
359         dbus = dbus_obj;
360         if (dbus)
361                 INFO("Mesh: MeshD connected: dbus [%p]", dbus);
362 }
363
364 static void __mesh_client_disconnected(struct l_dbus *dbus_obj, void *user_data)
365 {
366         ERR("MESH: D-Bus client disconnected, possibly meshd exited \n");
367         /* TODO: Send event to app about meshd termination  & then remove all mesh apps */
368         INFO("Mesh: Total number of networks present [%d]",
369                         g_slist_length(mesh_apps));
370
371         if (mesh_apps) {
372                 g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
373                 mesh_apps = NULL;
374         }
375         /* Set DBUS to NULL */
376         if (dbus)
377                 INFO("Mesh: dbus [%p]", dbus);
378         if (net_proxy)
379                 INFO("Mesh: net proxy [%p]", net_proxy);
380
381         dbus = NULL;
382         net_proxy = NULL;
383         INFO("Mesh: All apps cleaned up after meshd exited");
384 }
385
386 static gint __compare_proxy_path(gconstpointer data, gconstpointer user_data)
387 {
388         int ret = 0;
389         char *app_uuid_path;
390         const meshcfg_app *app = (meshcfg_app*) data;
391         char *path = (char *) user_data;
392         INFO("Mesh: proxy path compare: path [%s]", path);
393         INFO("Mesh: App Path  path [%s]", app->path);
394         if (!path)
395                 return -1;
396
397         app_uuid_path = l_util_hexstring(app->uuid, 16);
398         INFO("Mesh:App UUID string [%s]", app_uuid_path);
399         char **strings =  g_strsplit(path, "node", 2);
400
401         INFO("Mesh:String 0 [%s]", strings[0]);
402         INFO("Mesh:String 1 [%s]", strings[1]);
403         ret = g_strcmp0(strings[1], app_uuid_path);
404         g_free(strings[0]);
405         g_free(strings[1]);
406         l_free(app_uuid_path);
407         return ret;
408 }
409
410 static gint __compare_element_index(gconstpointer data, gconstpointer user_data)
411 {
412         const meshcfg_el *elem = data;
413         uint16_t elem_index = GPOINTER_TO_UINT(user_data);
414         if (!elem)
415                 return 1;
416
417         return (elem->index == elem_index ? 0: -1);
418 }
419
420 static void __mesh_proxy_added(struct l_dbus_proxy *proxy, void *user_data)
421 {
422         const char *interface = l_dbus_proxy_get_interface(proxy);
423         const char *path = l_dbus_proxy_get_path(proxy);
424
425         INFO("MESH: Proxy added: %s (%s)\n", interface, path);
426
427         if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
428                 INFO("Mesh: Network Proxy added");
429                 /* Save Global proxy */
430                 net_proxy = proxy;
431                 if (net_proxy)
432                         INFO("Mesh: Net Proxy [%p]", net_proxy);
433                 return;
434         }
435
436         if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
437                 GSList *l;
438                 meshcfg_app *app;
439                 INFO("Mesh: Mgmt Proxy added");
440                 INFO("Mesh: Number of mesh app present in list [%d]",
441                         g_slist_length(mesh_apps));
442                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
443                 if (l) {
444                         app = l->data;
445                         app->mgmt_proxy = proxy;
446                 } else {
447                         ERR("Mesh: app not found for Mgmt proxy");
448                 }
449                 return;
450         }
451
452         if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
453                 INFO("Mesh: Node Proxy added");
454                 GSList *l;
455                 meshcfg_app *app;
456                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
457                 if (l) {
458                         app = l->data;
459                         app->proxy = proxy;
460                 } else {
461                         ERR("Mesh: app not found for Node proxy");
462                 }
463                 return;
464         }
465 }
466
467 static void __mesh_proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
468 {
469         const char *interface = l_dbus_proxy_get_interface(proxy);
470         const char *path = l_dbus_proxy_get_path(proxy);
471
472         INFO("Proxy removed: %s (%s)\n", interface, path);
473
474         if (!strcmp(interface, BT_HAL_MESH_NETWORK_INTERFACE)) {
475                 INFO("Mesh: Network Interface removed,, possibly meshd terminated.\n");
476                 /*TODO: Send event to app about stop of Mesh service  & then remove all apps */
477                 if (mesh_apps) {
478                         g_slist_free_full(mesh_apps, __bt_hal_mesh_destroy_app_object);
479                         mesh_apps = NULL;
480                         return;
481                 }
482         } else if (!strcmp(interface, BT_HAL_MESH_NODE_INTERFACE)) {
483                 INFO("Mesh: Node Interface removed,, possibly node has left network.\n");
484                 GSList *l;
485                 meshcfg_app *app;
486                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
487                 if (l) {
488                         app = l->data;
489                         /*TODO: Send event to app about removal of a mesh local node */
490                         __bt_hal_mesh_destroy_app_object(app);
491                 } else {
492                         ERR("Mesh: app not found for Mgmt proxy");
493                 }
494                 return;
495         } else if (!strcmp(interface, BT_HAL_MESH_MANAGEMENT_INTERFACE)) {
496                 INFO("Mesh: Managament Interface removed,, possibly node has left network.\n");
497                 GSList *l;
498                 meshcfg_app *app;
499                 l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
500                 if (l) {
501                         app = l->data;
502                         /*TODO: Send event to app about removal of
503                         a mesh local node: first send event, then destroy mesh object */
504                         __bt_hal_mesh_destroy_app_object(app);
505                 } else {
506                         ERR("Mesh: app not found for Mgmt proxy");
507                 }
508                 return;
509         }
510 }
511
512 static void __mesh_dbus_client_ready(struct l_dbus_client *client_obj,
513                 void *user_data)
514 {
515         INFO("Mesh: D-Bus client ready: bluetooth-meshd connected \n");
516         client = client_obj;
517 }
518
519 static void __mesh_ready_callback(void *user_data)
520 {
521         INFO("Mesh: Connected to D-Bus\n");
522         if (!l_dbus_object_manager_enable(dbus, "/"))
523                 ERR("Mesh: Failed to register the ObjectManager\n");
524 }
525
526 bool _bt_hal_mesh_stack_init(void)
527 {
528         INFO("Mesh: Connect with meshd");
529         /* Connect with meshd */
530         dbus = l_dbus_new_default(L_DBUS_SYSTEM_BUS);
531         if (!dbus)
532                 return false;
533
534         INFO("Mesh: Got dbus [%p]", dbus);
535
536         if (!l_dbus_set_ready_handler(dbus, __mesh_ready_callback, NULL, NULL))
537                 return false;
538
539         client = l_dbus_client_new(dbus,
540                         BT_HAL_BLUEZ_MESH_NAME, "/org/bluez/mesh");
541         if (!client)
542                 return false;
543
544         if (!l_dbus_client_set_connect_handler(client,
545                                 __mesh_client_connected, NULL, NULL))
546                 return false;
547
548         if (!l_dbus_client_set_disconnect_handler(client,
549                                 __mesh_client_disconnected, NULL,
550                                 NULL))
551                 return false;
552         if (!l_dbus_client_set_proxy_handlers(client,
553                                 __mesh_proxy_added, __mesh_proxy_removed,
554                                 NULL, NULL, NULL))
555                 return false;
556         if (!l_dbus_client_set_ready_handler(client,
557                                 __mesh_dbus_client_ready, NULL, NULL))
558                 return false;
559
560         INFO("Mesh: Stack Init watchers registered with  meshd");
561         return true;
562 }
563
564 /* To send stack event to hal-mesh handler */
565 void _bt_hal_mesh_register_dbus_handler_cb(handle_stack_msg cb)
566 {
567         mesh_event_cb = cb;
568 }
569
570 /* To send stack event to hal-mesh handler */
571 void _bt_hal_mesh_unregister_dbus_handler_cb()
572 {
573         mesh_event_cb = NULL;
574 }
575
576 static bool __mesh_get_companyid(struct l_dbus *dbus,
577                 struct l_dbus_message *message,
578                         struct l_dbus_message_builder *builder,
579                                 void *user_data)
580 {
581         meshcfg_app *app = (meshcfg_app*) user_data;
582         if (!app)
583                 return false;
584
585         l_dbus_message_builder_append_basic(builder, 'q', &app->cid);
586
587         return true;
588 }
589
590 static bool __mesh_get_productid(struct l_dbus *dbus,
591                 struct l_dbus_message *message,
592                         struct l_dbus_message_builder *builder,
593                                 void *user_data)
594 {
595         meshcfg_app *app = (meshcfg_app*) user_data;
596         if (!app)
597                 return false;
598         l_dbus_message_builder_append_basic(builder, 'q', &app->pid);
599
600         return true;
601 }
602
603 static bool __mesh_get_versionid(struct l_dbus *dbus,
604                 struct l_dbus_message *message,
605                         struct l_dbus_message_builder *builder,
606                                 void *user_data)
607 {
608         meshcfg_app *app = (meshcfg_app*) user_data;
609         if (!app)
610                 return false;
611         l_dbus_message_builder_append_basic(builder, 'q', &app->vid);
612
613         return true;
614 }
615
616 static bool __mesh_get_crpl(struct l_dbus *dbus,
617                 struct l_dbus_message *message,
618                         struct l_dbus_message_builder *builder,
619                                 void *user_data)
620 {
621         meshcfg_app *app = (meshcfg_app*) user_data;
622         if (!app)
623                 return false;
624         l_dbus_message_builder_append_basic(builder, 'q', &app->crpl);
625
626         return true;
627 }
628
629 static void __send_network_attach_event(void *param, uint8_t status)
630 {
631         struct hal_ev_mesh_network_attached ev;
632         meshcfg_app *app = (meshcfg_app*)param;
633
634         memset(&ev, 0, sizeof(ev));
635         memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
636         memcpy(ev.token, app->token.u8, 8);
637
638         ev.status = status;
639         if (mesh_event_cb)
640                 mesh_event_cb(HAL_EV_MESH_NETWORK_ATTACHED,
641                         (void*)&ev, sizeof(ev));
642 }
643
644 static void __bt_hal_mesh_attach_node_reply(struct l_dbus_proxy *proxy,
645                 struct l_dbus_message *msg, void *user_data)
646 {
647         struct l_dbus_message_iter iter_cfg;
648         char *path;
649         meshcfg_app *app = (meshcfg_app*) user_data;
650         INFO("Mesh: Attach Node Reply: App path [%s] Agent Path [%s]",
651                 app->path, app->agent_path);
652
653         if (l_dbus_message_is_error(msg)) {
654                 const char *name;
655                 l_dbus_message_get_error(msg, &name, NULL);
656                 ERR("Mesh: Failed to attach node: %s", name);
657                 goto failed;
658
659         }
660
661         if (!l_dbus_message_get_arguments(msg, "oa(ya(qa{sv}))",
662                                 &path, &iter_cfg))
663                 goto failed;
664
665         INFO("Mesh: Attached with path %s\n", app->path);
666         __send_network_attach_event(app, BT_STATUS_SUCCESS);
667         return;
668 failed:
669         __send_network_attach_event(app, BT_STATUS_FAIL);
670         /* Destroy mesh app object */
671         __bt_hal_mesh_destroy_app_object(app);
672 }
673
674 static void __bt_hal_mesh_attach_node_setup(struct l_dbus_message *msg,
675                 void *user_data)
676 {
677         meshcfg_app *app = (meshcfg_app*) user_data;
678
679         l_dbus_message_set_arguments(msg, "ot", app->path,
680                         l_get_be64(app->token.u8));
681 }
682
683
684 static void __bt_hal_mesh_attach_node(void *user_data)
685 {
686         if (!l_dbus_proxy_method_call(net_proxy, "Attach",
687                                 __bt_hal_mesh_attach_node_setup,
688                                 __bt_hal_mesh_attach_node_reply,
689                                 user_data,
690                                 NULL)) {
691                 ERR("Mesh: Node attach failed!!");
692                 /* Node could not be attached */
693                 __send_network_attach_event(user_data, BT_STATUS_FAIL);
694                 /* Destroy mesh app object */
695                 __bt_hal_mesh_destroy_app_object((meshcfg_app*)user_data);
696         }
697 }
698
699 static struct l_dbus_message *__mesh_node_join_complete(struct l_dbus *dbus,
700                 struct l_dbus_message *message,
701                         void *user_data)
702 {
703         char *str;
704         uint64_t tmp;
705
706         meshcfg_app *app = (meshcfg_app*) user_data;
707         INFO("Mesh: Join Complete");
708
709         /* Return error */
710         if (!l_dbus_message_get_arguments(message, "t", &tmp)) {
711
712                 /* Send Network creation fail event */
713                 __send_network_attach_event(app, BT_STATUS_FAIL);
714
715                 /* Destroy mesh app object */
716                 __bt_hal_mesh_destroy_app_object(app);
717
718                 return l_dbus_message_new_error(message, dbus_err_args, NULL);
719         }
720
721         /* Save token */
722         app->token.u64 = l_get_be64(&tmp);
723         str = l_util_hexstring(&app->token.u8[0], 8);
724         INFO("Mesh: Created new node with token %s\n", str);
725         l_free(str);
726
727         /* Authenticate the node */
728         l_idle_oneshot(__bt_hal_mesh_attach_node, app, NULL);
729         return l_dbus_message_new_method_return(message);
730 }
731
732 static void __bt_hal_mesh_foreach_model_getter(gpointer data,
733                 gpointer user_data)
734 {
735         struct l_dbus_message_builder *builder = (struct l_dbus_message_builder *) user_data;
736         meshcfg_model *model_info = (meshcfg_model*) data;
737
738         l_dbus_message_builder_append_basic(builder, 'q', &model_info->model);
739 }
740
741 static bool __mesh_model_getter(struct l_dbus *dbus,
742                 struct l_dbus_message *message,
743                         struct l_dbus_message_builder *builder,
744                                 void *user_data)
745 {
746         meshcfg_el *element = (meshcfg_el*) user_data;
747
748         l_dbus_message_builder_enter_array(builder, "q");
749         g_slist_foreach(element->models,
750                 __bt_hal_mesh_foreach_model_getter, builder);
751
752         l_dbus_message_builder_leave_array(builder);
753
754         return true;
755 }
756
757 /*TODO: Vendor Model handling is currently not Handled */
758 static bool __mesh_vendor_model_getter(struct l_dbus *dbus,
759                 struct l_dbus_message *message,
760                         struct l_dbus_message_builder *builder,
761                                 void *user_data)
762 {
763         l_dbus_message_builder_enter_array(builder, "(qq)");
764         l_dbus_message_builder_leave_array(builder);
765
766         return true;
767 }
768
769 static bool __mesh_element_index_getter(struct l_dbus *dbus,
770                 struct l_dbus_message *message,
771                         struct l_dbus_message_builder *builder,
772                                 void *user_data)
773 {
774         meshcfg_el *element = (meshcfg_el*) user_data;
775         l_dbus_message_builder_append_basic(builder, 'y', &element->index);
776
777         return true;
778 }
779
780
781 static struct l_dbus_message *__mesh_device_message_received(struct l_dbus *dbus,
782                 struct l_dbus_message *msg, void *user_data)
783 {
784         struct l_dbus_message_iter iter;
785         uint16_t src, idx;
786         uint8_t *data;
787         uint32_t n;
788         bool rmt;
789         const char *dbus_path;
790         uint16_t size;
791         uint8_t *net_uuid;
792         dbus_path =  l_dbus_message_get_path(msg);
793         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,  MESH_ELEMENT_IFACE);
794         uint8_t buf[BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE];
795         struct hal_ev_mesh_devkey_message_event *ev = (void *)buf;
796
797         INFO("Mesh: app path [%s]", dbus_path);
798
799         memset(buf, 0, sizeof(buf));
800         size = (uint16_t) sizeof(*ev);
801         memcpy(ev->net_uuid, net_uuid, 16);
802         g_free(net_uuid);
803
804         if (!l_dbus_message_get_arguments(msg, "qbqay", &src, &rmt, &idx,
805                                 &iter)) {
806                 ERR("Mesh: Cannot parse received message");
807                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
808         }
809
810         if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
811                 ERR("Mesh: Cannot parse received message: data");
812                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
813         }
814
815         INFO("Mesh: Received dev key message (len %u):", n);
816         ev->source_addr = src;
817         ev->is_remote_devkey = rmt;
818         ev->netkey_idx = idx;
819         ev->data_len = n;
820         memcpy(ev->data, data, n);
821         size += n;
822
823         INFO("Mesh: Src [0x%2.2x]", src);
824         INFO("Mesh: Is Remote [%s]", rmt ? "YES" : "NO");
825         INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
826         /* Send DevKeyMessage Received event */
827         if (mesh_event_cb) {
828                 mesh_event_cb(HAL_EV_MESH_DEVKEY_MESSAGE_EVENT, (void*)buf, size);
829         }
830         return l_dbus_message_new_method_return(msg);
831 }
832
833 static void __bt_hal_mesh_setup_ele_iface(struct l_dbus_interface *iface)
834 {
835         INFO("Mesh: Setup element interface properties & methods");
836         /* Properties */
837         l_dbus_interface_property(iface, "Index", 0, "y", __mesh_element_index_getter,
838                         NULL);
839         l_dbus_interface_property(iface, "VendorModels", 0, "a(qq)",
840                         __mesh_vendor_model_getter, NULL);
841         l_dbus_interface_property(iface, "Models", 0, "aq", __mesh_model_getter, NULL);
842
843         /* Methods */
844         l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
845                         __mesh_device_message_received, "", "qbqay", "source",
846                         "remote", "net_index", "data");
847         /* TODO: Other methods */
848 }
849
850 static struct l_dbus_message *__mesh_scan_result_received(struct l_dbus *dbus,
851                 struct l_dbus_message *msg,
852                         void *user_data)
853 {
854         struct l_dbus_message_iter iter, opts;
855         meshcfg_app *app = (meshcfg_app*) user_data;
856         int16_t rssi;
857         uint32_t n;
858         uint8_t *prov_data;
859         char *str;
860         const char *sig = "naya{sv}";
861
862         /* Find network uuid from dbus path */
863         struct hal_ev_mesh_scan_result ev;
864
865         if (!app->scan_timer_id) {
866                 /* Scan is not running */
867                 INFO("Got scan result, but scan is already stopped");
868                 return l_dbus_message_new_method_return(msg);
869         }
870         memset(&ev, 0, sizeof(ev));
871         memcpy(ev.net_uuid, app->uuid, 16);
872
873         if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
874                 ERR("Mesh: Cannot parse scan results");
875                 ev.status = BT_STATUS_FAIL;
876                 if (mesh_event_cb) {
877                         mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
878                 }
879                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
880         }
881
882         if (!l_dbus_message_iter_get_fixed_array(&iter, &prov_data, &n) ||
883                         n < 16) {
884                 ERR("Mesh: Cannot parse scan result: data");
885                 ev.status = BT_STATUS_FAIL;
886                 if (mesh_event_cb) {
887                         mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
888                 }
889                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
890         }
891
892         INFO("Mesh: Scan result:\n");
893         INFO("Mesh: Scan rssi = [%d]\n", rssi);
894         str = l_util_hexstring_upper(prov_data, 16);
895         INFO("Mesh: Scan UUID = [%s]\n",  str);
896         l_free(str);
897
898         if (n >= 18) {
899                 str = l_util_hexstring_upper(prov_data + 16, 2);
900                 INFO("Mesh: Scan OOB = [%s]\n", str);
901                 l_free(str);
902         }
903
904         if (n >= 22) {
905                 str = l_util_hexstring_upper(prov_data + 18, 4);
906                 INFO("Mesh: Scan URI hash = [%s]\n", str);
907                 l_free(str);
908         }
909
910         /* 16 octet Dev UUID */
911         memcpy(ev.dev_uuid, prov_data, 16);
912
913         /* 2 octet Dev OOB Info */
914         memcpy(ev.oob_info, prov_data + 16, 2);
915
916         /* 4 octet URI Hash */
917         memcpy(ev.uri_hash, prov_data + 18, 4);
918
919         ev.rssi = rssi;
920
921         ev.status = BT_STATUS_SUCCESS;
922         if (mesh_event_cb)
923                 mesh_event_cb(HAL_EV_MESH_SCAN_RESULT,
924                         (void*)&ev, sizeof(ev));
925
926         return l_dbus_message_new_method_return(msg);
927 }
928
929 static struct l_dbus_message *__mesh_request_provisioner_call(
930                 struct l_dbus *dbus,
931                         struct l_dbus_message *msg,
932                                 void *user_data)
933 {
934         uint8_t cnt;
935         struct hal_ev_mesh_provision_finished ev;
936         struct hal_ev_mesh_provision_data_request req;
937         char *uuid_string;
938         meshcfg_app *app = user_data;
939
940         INFO("Mesh: provisioning data requested app path [%s]",
941                 app->path);
942         uuid_string = l_util_hexstring(app->uuid, 16);
943         INFO("Mesh: Network UUID [%s]", uuid_string);
944
945         memset(&ev, 0, sizeof(ev));
946         memset(&req, 0, sizeof(req));
947         memcpy(ev.net_uuid, app->uuid, 16);
948         memcpy(req.net_uuid, app->uuid, 16);
949         l_free(uuid_string);
950
951         if (!l_dbus_message_get_arguments(msg, "y", &cnt)) {
952                 ERR("Mesh: Cannot parse request for prov data");
953                 /* Send Event */
954                 ev.status = BT_STATUS_FAIL;
955                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
956                 if (mesh_event_cb)
957                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
958                                 (void*)&ev, sizeof(ev));
959                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
960         }
961
962         app->msg = msg;
963         req.count = cnt;
964         if (mesh_event_cb)
965                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_DATA_REQUEST,
966                         (void*)&req, sizeof(req));
967
968         l_dbus_message_ref(msg);
969         return NULL;
970 }
971
972 static struct l_dbus_message *__mesh_node_add_completed(
973                 struct l_dbus *dbus,
974                         struct l_dbus_message *msg,
975                                 void *user_data)
976 {
977         struct l_dbus_message_iter iter;
978         int16_t unicast;
979         uint8_t cnt;
980         uint32_t n;
981         uint8_t *uuid;
982         struct hal_ev_mesh_provision_finished ev;
983         const char *dbus_path;
984         uint8_t *net_uuid;
985         dbus_path =  l_dbus_message_get_path(msg);
986         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
987                         true,  MESH_PROV_IFACE);
988
989         INFO("Mesh: app path [%s]", dbus_path);
990
991         memset(&ev, 0, sizeof(ev));
992         memcpy(ev.net_uuid, net_uuid, 16);
993
994         g_free(net_uuid);
995
996         if (!l_dbus_message_get_arguments(msg, "ayqy", &iter, &unicast, &cnt)) {
997                 ERR("Mesh: Cannot parse add node complete message");
998                 /* Send Event */
999                 ev.status = BT_STATUS_FAIL;
1000                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1001                 if (mesh_event_cb)
1002                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1003                                 (void*)&ev, sizeof(ev));
1004                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1005         }
1006
1007         if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
1008                         n != 16) {
1009                 ERR("Mesh: Cannot parse add node complete message: uuid");
1010                 /* Send Event */
1011                 ev.status = BT_STATUS_FAIL;
1012                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1013                 if (mesh_event_cb)
1014                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1015                                 (void*)&ev, sizeof(ev));
1016                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1017         }
1018
1019         /* Send Event */
1020         ev.status = BT_STATUS_SUCCESS;
1021         ev.reason = BT_HAL_MESH_PROV_ERR_SUCCESS;
1022         memcpy(ev.dev_uuid, uuid, 16);
1023         ev.unicast = unicast;
1024         ev.count = cnt;
1025
1026         if (mesh_event_cb)
1027                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1028                         (void*)&ev, sizeof(ev));
1029
1030         return l_dbus_message_new_method_return(msg);
1031 }
1032
1033 static struct l_dbus_message *__mesh_node_add_failed(
1034                 struct l_dbus *dbus,
1035                         struct l_dbus_message *msg,
1036                                 void *user_data)
1037 {
1038         struct l_dbus_message_iter iter;
1039         uint32_t n;
1040         uint8_t *uuid;
1041         char *str, *reason;
1042         struct hal_ev_mesh_provision_finished ev;
1043         const char *dbus_path;
1044
1045         uint8_t *net_uuid;
1046         dbus_path =  l_dbus_message_get_path(msg);
1047         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1048                         true,  MESH_PROV_IFACE);
1049
1050         memset(&ev, 0, sizeof(ev));
1051         memcpy(ev.net_uuid, net_uuid, 16);
1052
1053         g_free(net_uuid);
1054         if (!l_dbus_message_get_arguments(msg, "ays", &iter, &reason)) {
1055                 ERR("Mesh: Cannot parse add node failed message");
1056                 /* Send Event */
1057                 ev.status = BT_STATUS_FAIL;
1058                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1059                 if (mesh_event_cb)
1060                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1061                                 (void*)&ev, sizeof(ev));
1062                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1063         }
1064
1065         if (!l_dbus_message_iter_get_fixed_array(&iter, &uuid, &n) ||
1066                         n != 16) {
1067                 ERR("Mesh:Cannot parse add node failed message: uuid");
1068                 ev.status = BT_STATUS_FAIL;
1069                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1070                 if (mesh_event_cb)
1071                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1072                                 (void*)&ev, sizeof(ev));
1073                 return l_dbus_message_new_error(msg, dbus_err_args, NULL);
1074         }
1075
1076         INFO("Mesh: Provisioning failed:\n");
1077         str = l_util_hexstring_upper(uuid, 16);
1078         INFO("Mesh: UUID = [%s] Reason [%s]", str, reason);
1079         l_free(str);
1080
1081         ev.status = BT_STATUS_FAIL;
1082         ev.reason = __bt_mesh_util_get_prov_error_code(str);
1083         memcpy(ev.dev_uuid, uuid, 16);
1084
1085         if (mesh_event_cb)
1086                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1087                         (void*)&ev, sizeof(ev));
1088
1089         return l_dbus_message_new_method_return(msg);
1090 }
1091
1092 static void __bt_hal_mesh_setup_prov_iface(struct l_dbus_interface *interface)
1093 {
1094         INFO("Mesh: Setup provisioner interface properties & methods");
1095         l_dbus_interface_method(interface, "ScanResult", 0,
1096                         __mesh_scan_result_received, "",
1097                         "naya{sv}", "rssi", "data", "options");
1098
1099         l_dbus_interface_method(interface, "RequestProvData", 0,
1100                         __mesh_request_provisioner_call,
1101                         "qq", "y", "net_index", "unicast", "count");
1102
1103         l_dbus_interface_method(interface, "AddNodeComplete", 0,
1104                         __mesh_node_add_completed, "", "ayqy",
1105                         "uuid", "unicast", "count");
1106
1107         l_dbus_interface_method(interface, "AddNodeFailed", 0,
1108                         __mesh_node_add_failed,
1109                         "", "ays", "uuid", "reason");
1110 }
1111
1112 static void __bt_hal_mesh_setup_app_iface(struct l_dbus_interface *iface)
1113 {
1114         INFO("Mesh: Setup application interface properties & methods");
1115
1116         l_dbus_interface_property(iface, "CompanyID", 0, "q",
1117                         __mesh_get_companyid,
1118                         NULL);
1119         l_dbus_interface_property(iface, "VersionID", 0, "q",
1120                         __mesh_get_versionid,
1121                         NULL);
1122         l_dbus_interface_property(iface, "ProductID", 0, "q",
1123                         __mesh_get_productid,
1124                         NULL);
1125         l_dbus_interface_property(iface, "CRPL", 0, "q",
1126                         __mesh_get_crpl, NULL);
1127         l_dbus_interface_method(iface, "JoinComplete", 0,
1128                         __mesh_node_join_complete,
1129                         "", "t", "token");
1130
1131         /* TODO: Methods */
1132 }
1133
1134 static void __mesh_fill_in_capabilities(meshcfg_app *app,
1135                  struct l_dbus_message_builder *builder)
1136 {
1137         if (app->in_oob & 0x08)
1138                 l_dbus_message_builder_append_basic(builder, 's', "in-alpha");
1139         if (app->in_oob & 0x04)
1140                 l_dbus_message_builder_append_basic(builder, 's', "in-numeric");
1141         if (app->in_oob & 0x02)
1142                 l_dbus_message_builder_append_basic(builder, 's', "twist");
1143         if (app->in_oob & 0x01)
1144                 l_dbus_message_builder_append_basic(builder, 's', "push");
1145 }
1146
1147 static void __mesh_fill_out_capabilities(meshcfg_app *app,
1148                  struct l_dbus_message_builder *builder)
1149 {
1150         if (app->out_oob & 0x10)
1151                 l_dbus_message_builder_append_basic(builder, 's', "out-alpha");
1152         if (app->out_oob & 0x08)
1153                 l_dbus_message_builder_append_basic(builder, 's', "out-numeric");
1154         if (app->out_oob & 0x04)
1155                 l_dbus_message_builder_append_basic(builder, 's', "vibrate");
1156         if (app->out_oob & 0x02)
1157                 l_dbus_message_builder_append_basic(builder, 's', "beep");
1158         if (app->out_oob & 0x01)
1159                 l_dbus_message_builder_append_basic(builder, 's', "blink");
1160 }
1161
1162 static bool __mesh_agent_capability_getter(
1163                 struct l_dbus *dbus,struct l_dbus_message *message,
1164                         struct l_dbus_message_builder *builder,
1165                                 void *user_data)
1166 {
1167         meshcfg_app *app;
1168         app = user_data;
1169         INFO("Mesh: app path [%s]", app->path);
1170         INFO("Mesh: Agent path [%s]", app->agent_path);
1171
1172         if (!l_dbus_message_builder_enter_array(builder, "s")) {
1173                 return false;
1174         }
1175
1176         __mesh_fill_out_capabilities(app, builder);
1177         __mesh_fill_in_capabilities(app, builder);
1178
1179         if (app->static_oob)
1180                 l_dbus_message_builder_append_basic(builder,
1181                         's', "static-oob");
1182
1183
1184         l_dbus_message_builder_leave_array(builder);
1185         INFO("Mesh: __agent_capability_getter: Success");
1186         return true;
1187 }
1188
1189 static struct l_dbus_message *__mesh_agent_display_string_request(
1190                 struct l_dbus *dbus,
1191                         struct l_dbus_message *msg,
1192                                 void *user_data)
1193 {
1194         struct hal_ev_mesh_authentication_request ev;
1195         char *str;
1196         uint8_t *net_uuid;
1197         const char *dbus_path;
1198         meshcfg_app *app;
1199         app = user_data;
1200         INFO("Mesh: app path [%s]", app->path);
1201         INFO("Mesh: Agent path [%s]", app->agent_path);
1202
1203         dbus_path =  l_dbus_message_get_path(msg);
1204         net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
1205                         true,  MESH_AGENT_IFACE);
1206
1207         INFO("Mesh: app path [%s]", dbus_path);
1208
1209         memset(&ev, 0, sizeof(ev));
1210         memcpy(ev.net_uuid, net_uuid, 16);
1211
1212
1213         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1214                 ERR("Mesh: Cannot parse \"DisplayString\" arguments");
1215                 struct hal_ev_mesh_provision_finished ev;
1216                 memset(&ev, 0, sizeof(ev));
1217                 memcpy(ev.net_uuid, net_uuid, 16);
1218                 ev.status = BT_STATUS_FAIL;
1219                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1220                 if (mesh_event_cb)
1221                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1222                                 (void*)&ev, sizeof(ev));
1223
1224                 g_free(net_uuid);
1225
1226                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1227         }
1228
1229         INFO("Mesh:[OUT] AlphaNumeric Authentication: Value [%s]", str);
1230         ev.auth_type = __mesh_get_authentication_type(str);
1231         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1232                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1233         g_strlcpy(ev.auth_value, str, sizeof(ev.auth_value));
1234
1235         if (mesh_event_cb)
1236                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1237                         (void*)&ev, sizeof(ev));
1238
1239         g_free(net_uuid);
1240         return l_dbus_message_new_method_return(msg);
1241 }
1242
1243 static struct l_dbus_message *__mesh_agent_display_numeric_request(
1244                 struct l_dbus *dbus,
1245                         struct l_dbus_message *msg,
1246                                 void *user_data)
1247 {
1248         uint32_t n;
1249         struct hal_ev_mesh_authentication_request ev;
1250         char *str;
1251         char *auth_value;
1252         uint8_t *net_uuid;
1253         const char *dbus_path;
1254         meshcfg_app *app;
1255         app = user_data;
1256         INFO("Mesh: app path [%s]", app->path);
1257         INFO("Mesh: Agent path [%s]", app->agent_path);
1258
1259         dbus_path =  l_dbus_message_get_path(msg);
1260         net_uuid = __mesh_get_net_uuid_from_path(app->agent_path,
1261                                 true,  MESH_AGENT_IFACE);
1262
1263         INFO("Mesh: app path [%s]", dbus_path);
1264
1265         memset(&ev, 0, sizeof(ev));
1266         memcpy(ev.net_uuid, net_uuid, 16);
1267
1268
1269         if (!l_dbus_message_get_arguments(msg, "su", &str, &n)) {
1270                 ERR("Mesh: Cannot parse \"DisplayNumeric\" arguments");
1271                 struct hal_ev_mesh_provision_finished ev;
1272                 memset(&ev, 0, sizeof(ev));
1273                 memcpy(ev.net_uuid, net_uuid, 16);
1274                 ev.status = BT_STATUS_FAIL;
1275                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1276                 if (mesh_event_cb) {
1277                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1278                                 (void*)&ev, sizeof(ev));
1279                 }
1280                 g_free(net_uuid);
1281                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1282         }
1283
1284         INFO("Mesh:[OUT] Numeric Authentication type [%s] value [%u]", str, n);
1285         auth_value = l_strdup_printf("%u",n);
1286         ev.auth_type = __mesh_get_authentication_type(str);
1287         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1288                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1289         g_strlcpy(ev.auth_value, auth_value, sizeof(ev.auth_value));
1290
1291         if (mesh_event_cb)
1292                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1293                         (void*)&ev, sizeof(ev));
1294
1295         g_free(net_uuid);
1296
1297         return l_dbus_message_new_method_return(msg);
1298 }
1299
1300 static struct l_dbus_message *__mesh_agent_prompt_numeric_request(
1301                 struct l_dbus *dbus,
1302                         struct l_dbus_message *msg,
1303                                 void *user_data)
1304 {
1305         struct hal_ev_mesh_authentication_request ev;
1306         char *str;
1307         uint8_t *net_uuid;
1308         const char *dbus_path;
1309         GSList *l;
1310         meshcfg_app *app;
1311
1312         dbus_path =  l_dbus_message_get_path(msg);
1313         net_uuid = __mesh_get_net_uuid_from_path(dbus_path,
1314                         true,  MESH_AGENT_IFACE);
1315
1316         INFO("Mesh: app path [%s]", dbus_path);
1317
1318         l = g_slist_find_custom(mesh_apps, net_uuid,
1319                         __mesh_compare_network_uuid);
1320         app = l->data;
1321
1322         memset(&ev, 0, sizeof(ev));
1323         memcpy(ev.net_uuid, net_uuid, 16);
1324
1325         g_free(net_uuid);
1326         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1327                 ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
1328
1329                 struct hal_ev_mesh_provision_finished ev;
1330                 memset(&ev, 0, sizeof(ev));
1331                 memcpy(ev.net_uuid, app->uuid, 16);
1332                 ev.status = BT_STATUS_FAIL;
1333                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1334                 if (mesh_event_cb) {
1335                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1336                                 (void*)&ev, sizeof(ev));
1337                 }
1338                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1339         }
1340
1341         INFO("Mesh:[IN] Numeric Authentication type [%s]", str);
1342
1343         ev.auth_type = __mesh_get_authentication_type(str);
1344         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1345                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1346         agent_msg = msg;
1347         l_dbus_message_ref(msg);
1348         if (mesh_event_cb)
1349                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1350                         (void*)&ev, sizeof(ev));
1351
1352         return NULL;
1353 }
1354
1355 static struct l_dbus_message *__mesh_agent_prompt_static_request(
1356                 struct l_dbus *dbus,
1357                         struct l_dbus_message *msg,
1358                                 void *user_data)
1359 {
1360         struct hal_ev_mesh_authentication_request ev;
1361         char *str;
1362         uint8_t *net_uuid;
1363         const char *dbus_path;
1364         GSList *l;
1365         meshcfg_app *app;
1366
1367         dbus_path =  l_dbus_message_get_path(msg);
1368         net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,
1369                         MESH_AGENT_IFACE);
1370
1371         INFO("Mesh: app path [%s]", dbus_path);
1372
1373         l = g_slist_find_custom(mesh_apps, net_uuid,
1374                         __mesh_compare_network_uuid);
1375         app = l->data;
1376
1377         memset(&ev, 0, sizeof(ev));
1378         memcpy(ev.net_uuid, net_uuid, 16);
1379
1380         g_free(net_uuid);
1381         if (!l_dbus_message_get_arguments(msg, "s", &str)) {
1382                 ERR("Mesh: Cannot parse \"PromptNumeric\" arguments");
1383
1384                 struct hal_ev_mesh_provision_finished ev;
1385                 memset(&ev, 0, sizeof(ev));
1386                 memcpy(ev.net_uuid, app->uuid, 16);
1387                 ev.status = BT_STATUS_FAIL;
1388                 ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
1389                 if (mesh_event_cb)
1390                         mesh_event_cb(HAL_EV_MESH_PROVISIONING_FINISHED,
1391                                         (void*)&ev, sizeof(ev));
1392                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1393         }
1394
1395         INFO("Mesh: [IN] AlphaNumeric Authentication type [%s]", str);
1396
1397         ev.auth_type = __mesh_get_authentication_type(str);
1398         if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
1399                 return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
1400         agent_msg = msg;
1401         l_dbus_message_ref(msg);
1402         if (mesh_event_cb)
1403                 mesh_event_cb(HAL_EV_MESH_AUTHENTICATION_REQUEST,
1404                                 (void*)&ev, sizeof(ev));
1405
1406         return NULL;
1407 }
1408
1409 static void __bt_hal_mesh_setup_agent_iface(struct l_dbus_interface *interface)
1410 {
1411         INFO("Mesh: Setup Agent interface properties & methods");
1412         l_dbus_interface_property(interface, "Capabilities", 0, "as",
1413                         __mesh_agent_capability_getter,
1414                         NULL);
1415         /* TODO: Other properties */
1416         l_dbus_interface_method(interface, "DisplayString", 0,
1417                         __mesh_agent_display_string_request,
1418                         "", "s", "value");
1419         l_dbus_interface_method(interface, "DisplayNumeric", 0,
1420                         __mesh_agent_display_numeric_request,
1421                         "", "su", "type", "number");
1422         l_dbus_interface_method(interface, "PromptNumeric", 0,
1423                         __mesh_agent_prompt_numeric_request,
1424                         "u", "s", "number", "type");
1425         l_dbus_interface_method(interface, "PromptStatic", 0,
1426                         __mesh_agent_prompt_static_request,
1427                         "ay", "s", "data", "type");
1428 }
1429
1430 static void __bt_hal_mesh_register_element_obj(gpointer data, gpointer user_data)
1431 {
1432         meshcfg_el *elem = (meshcfg_el*) data;
1433         INFO("Mesh: Register Element: Index [%d] elem path [%s]",
1434                 elem->index, elem->path);
1435         if (!l_dbus_register_object(dbus, elem->path, NULL, NULL,
1436                                 BT_HAL_MESH_ELEMENT_INTERFACE, elem, NULL)) {
1437                 ERR("Mesh: Failed to register object %s", elem->path);
1438         }
1439 }
1440
1441 bool __bt_hal_mesh_register_agent(meshcfg_app *ptr)
1442 {
1443         if (!ptr)
1444                 return false;
1445
1446         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISION_AGENT_INTERFACE,
1447                                 __bt_hal_mesh_setup_agent_iface, NULL, false)) {
1448                 ERR("Mesh: Unable to register agent interface");
1449                 //return false;
1450         }
1451
1452         INFO("Mesh: Register Agent path [%s]",  ptr->agent_path);
1453         if (!l_dbus_register_object(dbus, ptr->agent_path, NULL, NULL,
1454                                 BT_HAL_MESH_PROVISION_AGENT_INTERFACE, ptr, NULL)) {
1455                 ERR("Mesh: Failed to register object %s", ptr->agent_path);
1456                 return false;
1457         }
1458
1459         if (!l_dbus_object_add_interface(dbus, ptr->agent_path,
1460                                 L_DBUS_INTERFACE_PROPERTIES, NULL)) {
1461                 ERR("Mesh: Failed to add interface %s",
1462                                 L_DBUS_INTERFACE_PROPERTIES);
1463                 return false;
1464         }
1465
1466         return true;
1467 }
1468
1469 bool __bt_hal_mesh_register_application(meshcfg_app *ptr)
1470 {
1471
1472         if (!ptr)
1473                 return false;
1474         if (!dbus)
1475                 return false;
1476
1477         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_APPLICATION_INTERFACE,
1478                                 __bt_hal_mesh_setup_app_iface, NULL, false)) {
1479                 ERR("Mesh: Failed to register interface %s",
1480                                 BT_HAL_MESH_APPLICATION_INTERFACE);
1481                 //return false;
1482         }
1483
1484         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_PROVISIONER_INTERFACE,
1485                                 __bt_hal_mesh_setup_prov_iface, NULL, false)) {
1486                 ERR("Mesh: Failed to register interface %s",
1487                                 BT_HAL_MESH_PROVISIONER_INTERFACE);
1488                 //return false;
1489         }
1490
1491         if (!l_dbus_register_object(dbus, ptr->path, NULL, NULL,
1492                                 BT_HAL_MESH_APPLICATION_INTERFACE, ptr,
1493                                 BT_HAL_MESH_PROVISIONER_INTERFACE, ptr,
1494                                 NULL)) {
1495                 ERR("Mesh: Failed to register object %s", ptr->path);
1496                 return false;
1497         }
1498
1499         if (!__bt_hal_mesh_register_agent(ptr))
1500                 return false;
1501
1502         if (!l_dbus_register_interface(dbus, BT_HAL_MESH_ELEMENT_INTERFACE,
1503                                 __bt_hal_mesh_setup_ele_iface, NULL, false)) {
1504                 ERR("Mesh: Failed to register interface %s",
1505                                 BT_HAL_MESH_ELEMENT_INTERFACE);
1506                 //return false;
1507         }
1508
1509         INFO("Mesh: Number of elements to be registsred [%d]",
1510                         g_slist_length(ptr->elements));
1511
1512         g_slist_foreach(ptr->elements, __bt_hal_mesh_register_element_obj, ptr);
1513
1514         INFO("Mesh: Add Object manager Interface: app path [%s]", ptr->path);
1515         if (!l_dbus_object_add_interface(dbus, ptr->path,
1516                                 L_DBUS_INTERFACE_OBJECT_MANAGER, NULL)) {
1517                 ERR("Mesh: Failed to add interface %s",
1518                                 L_DBUS_INTERFACE_OBJECT_MANAGER);
1519                 return false;
1520         }
1521         INFO("Mesh: Application Register completed");
1522
1523         return true;
1524 }
1525
1526 static void __bt_mesh_hal_create_element_object(gpointer data, gpointer user_data)
1527 {
1528         GSList *l;
1529         meshcfg_el *elem;
1530         meshcfg_model *model_info = (meshcfg_model*) data;
1531         meshcfg_app *app = (meshcfg_app*) user_data;
1532
1533         l = g_slist_find_custom(app->elements,
1534                 GUINT_TO_POINTER(model_info->elem_index), __compare_element_index);
1535         if (l) {
1536                 elem = l->data;
1537         } else {
1538                 elem = g_malloc0(sizeof(meshcfg_el));
1539                 elem->index = model_info->elem_index;
1540                 elem->path = g_strdup_printf("%s/elem%u",app->path, elem->index);
1541                 app->elements = g_slist_append(app->elements, elem);
1542                 INFO("Mesh: Created element index [%d] path [%s]",
1543                         elem->index, elem->path);
1544         }
1545         INFO("Mesh: This is model [0x%4.4x] for Element [0x%2.2x]",
1546                 model_info->model, elem->index);
1547         /* Add Model in the element */
1548         elem->models = g_slist_append(elem->models, model_info);
1549         INFO("Mesh: Model added in element: total Model count in elem [%d] is [%d]",
1550                         elem->index, g_slist_length(elem->models));
1551 }
1552
1553 meshcfg_app *__bt_hal_mesh_create_app(bt_hal_mesh_node_t *node,
1554                 GSList *models, bool is_prov)
1555 {
1556         uint8_t uuid[16];
1557         meshcfg_app *app = NULL;
1558         char *uuid_str = NULL;
1559
1560         uuid_str = l_util_hexstring(node->uuid.uu, sizeof(uuid));
1561
1562         app = g_malloc0(sizeof(meshcfg_app));
1563         memcpy(app->uuid, node->uuid.uu, sizeof(uuid));
1564
1565         app->cid = node->vendor_info.companyid;
1566         app->pid = node->vendor_info.vendorid;
1567         app->vid =  node->vendor_info.versionid;
1568         app->crpl = node->vendor_info.crpl;
1569
1570         if (is_prov) {
1571                 app->path = g_strdup_printf("/tizen/mesh/cfg/%s", uuid_str);
1572                 app->agent_path = g_strdup_printf("%s/agent", app->path);
1573
1574         } else {
1575                 app->path = g_strdup_printf("/tizen/mesh/node/%s", uuid_str);
1576                 app->agent_path = g_strdup_printf("%s/agent", app->path);
1577         }
1578         g_slist_foreach(models, __bt_mesh_hal_create_element_object, app);
1579
1580         g_free(uuid_str);
1581         app->is_prov = is_prov;
1582         INFO("Mesh: app created");
1583         return app;
1584 }
1585
1586 static void __bt_hal_mesh_create_net_reply(
1587                 struct l_dbus_proxy *proxy,
1588                         struct l_dbus_message *msg, void *user_data)
1589 {
1590         meshcfg_app *app;
1591         app = (meshcfg_app*) user_data;
1592
1593         INFO("Mesh: Create Network Reply from Meshd: app path [%s]", app->path);
1594         if (l_dbus_message_is_error(msg)) {
1595                 const char *name;
1596
1597                 l_dbus_message_get_error(msg, &name, NULL);
1598                 ERR("Mesh: Failed to create network: %s", name);
1599
1600                 /* Send Network creation fail event */
1601                 __send_network_attach_event(app, BT_STATUS_FAIL);
1602
1603                 /* Destroy mesh app object */
1604                 __bt_hal_mesh_destroy_app_object(app);
1605                 return;
1606         }
1607 }
1608
1609 static void __bt_hal_mesh_create_net_setup(struct l_dbus_message *msg,
1610                 void *user_data)
1611 {
1612         meshcfg_app *app;
1613         struct l_dbus_message_builder *builder;
1614         app = (meshcfg_app*) user_data;
1615
1616         builder = l_dbus_message_builder_new(msg);
1617
1618         INFO("Mesh: Create Network Setup app path [%s]", app->path);
1619         l_dbus_message_builder_append_basic(builder, 'o', app->path);
1620         __mesh_append_byte_array(builder, app->uuid, 16);
1621         l_dbus_message_builder_finalize(builder);
1622         l_dbus_message_builder_destroy(builder);
1623 }
1624
1625 static void __mesh_trigger_scan_finished_event(meshcfg_app *app)
1626 {
1627         struct hal_ev_mesh_scan_state_changed ev;
1628
1629         memset(&ev, 0, sizeof(ev));
1630         memcpy(ev.net_uuid, app->uuid, 16);
1631
1632         ev.status = BT_STATUS_SUCCESS;
1633
1634         ev.state = HAL_MESH_SCAN_STATE_STOPPED;
1635         if (mesh_event_cb)
1636                 mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
1637                         (void*)&ev, sizeof(ev));
1638 }
1639
1640 static gboolean __bt_mesh_scan_timer_cb(gpointer user_data)
1641 {
1642         meshcfg_app *app = (meshcfg_app*) user_data;
1643         __mesh_trigger_scan_finished_event(app);
1644         return false;
1645 }
1646
1647 void __bt_mesh_enable_scanning_timer(uint8_t *net_uuid, uint16_t secs)
1648 {
1649         GSList *l;
1650         meshcfg_app *app;
1651         l = g_slist_find_custom(mesh_apps, net_uuid,
1652                         __mesh_compare_network_uuid);
1653         app = l->data;
1654
1655         if (app->scan_timer_id > 0) {
1656                 g_source_remove(app->scan_timer_id);
1657                 app->scan_timer_id = 0;
1658         }
1659
1660         app->scan_timer_id = g_timeout_add_seconds(secs,
1661                         __bt_mesh_scan_timer_cb, app);
1662
1663         return;
1664 }
1665
1666 static void __mesh_scan_reply(struct l_dbus_proxy *proxy,
1667                 struct l_dbus_message *msg, void *user_data)
1668 {
1669         struct hal_ev_mesh_scan_state_changed ev;
1670         const char *dbus_path;
1671         uint8_t *net_uuid;
1672         dbus_path =  l_dbus_proxy_get_path(proxy);
1673         INFO("Mesh: DBUS path [%s]", dbus_path);
1674         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1675
1676         uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
1677         INFO("Mesh: Scan duration [%u]", secs);
1678
1679         memset(&ev, 0, sizeof(ev));
1680         memcpy(ev.net_uuid, net_uuid, 16);
1681
1682         if (l_dbus_message_is_error(msg)) {
1683                 const char *name;
1684                 l_dbus_message_get_error(msg, &name, NULL);
1685                 ERR("Mesh: Failed to start unprovisioned scan: [%s]", name);
1686                 ev.status = BT_STATUS_FAIL;
1687         } else {
1688                 INFO("Mesh: Unprovisioned scan started\n");
1689                 ev.status = BT_STATUS_SUCCESS;
1690                 __bt_mesh_enable_scanning_timer(net_uuid, secs);
1691         }
1692
1693         ev.state = HAL_MESH_SCAN_STATE_STARTED;
1694         if (mesh_event_cb)
1695                 mesh_event_cb(HAL_EV_MESH_SCAN_STATE_CHANGED,
1696                         (void*)&ev, sizeof(ev));
1697         l_free(net_uuid);
1698 }
1699
1700 static void append_dict_entry_basic(struct l_dbus_message_builder *builder,
1701                 const char *key, const char *signature,
1702                 const void *data)
1703 {
1704         if (!builder)
1705                 return;
1706
1707         l_dbus_message_builder_enter_dict(builder, "sv");
1708         l_dbus_message_builder_append_basic(builder, 's', key);
1709         l_dbus_message_builder_enter_variant(builder, signature);
1710         l_dbus_message_builder_append_basic(builder, signature[0], data);
1711         l_dbus_message_builder_leave_variant(builder);
1712         l_dbus_message_builder_leave_dict(builder);
1713 }
1714
1715 static void __mesh_scan_setup(struct l_dbus_message *msg, void *user_data)
1716 {
1717         struct l_dbus_message_builder *builder;
1718         uint16_t secs = (uint16_t) L_PTR_TO_UINT(user_data);
1719         INFO("Mesh: Scan duration [%u]", secs);
1720
1721         builder = l_dbus_message_builder_new(msg);
1722         l_dbus_message_builder_enter_array(builder, "{sv}");
1723         append_dict_entry_basic(builder, "Seconds", "q", &secs);
1724         l_dbus_message_builder_leave_array(builder);
1725         l_dbus_message_builder_finalize(builder);
1726         l_dbus_message_builder_destroy(builder);
1727 }
1728
1729
1730 bt_status_t _bt_hal_mesh_network_set_caps(
1731                 bt_uuid_t *net_uuid, bt_hal_mesh_prov_caps_t *caps)
1732 {
1733         GSList *l;
1734         meshcfg_app *app;
1735         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
1736         if (l) {
1737                 app = l->data;
1738                 /* Fill OOB data */
1739                 app->public_oob = caps->public_oob;
1740                 app->static_oob = caps->static_oob;
1741                 app->out_oob = caps->out_oob;
1742                 app->in_oob = caps->in_oob;
1743         } else {
1744                 ERR("Mesh: app not found!!");
1745                 return BT_STATUS_PARM_INVALID;
1746
1747         }
1748         return BT_STATUS_SUCCESS;
1749 }
1750
1751 static void __bt_hal_mesh_add_node_reply(
1752                 struct l_dbus_proxy *proxy,
1753                         struct l_dbus_message *msg,
1754                                 void *user_data)
1755 {
1756         struct hal_ev_mesh_provision_status ev;
1757         const char *dbus_path;
1758         uint8_t *net_uuid;
1759         dbus_path =  l_dbus_proxy_get_path(proxy);
1760         INFO("Mesh: DBUS path [%s]", dbus_path);
1761         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1762
1763         bt_uuid_t *dev_uuid = (bt_uuid_t*) user_data;
1764
1765         INFO("Mesh: app path [%s]", dbus_path);
1766
1767         memset(&ev, 0, sizeof(ev));
1768         memcpy(ev.net_uuid, net_uuid, 16);
1769         memcpy(ev.dev_uuid, dev_uuid->uu, 16);
1770
1771         /* Free User data */
1772         g_free((void*)dev_uuid);
1773         l_free(net_uuid);
1774
1775         if (l_dbus_message_is_error(msg)) {
1776                 const char *name;
1777
1778                 l_dbus_message_get_error(msg, &name, NULL);
1779                 ERR("Mesh: Failed to start provisioning: %s", name);
1780                 ev.status = BT_STATUS_FAIL;
1781         } else {
1782                 INFO("Mesh: Provisioning started\n");
1783                 ev.status = BT_STATUS_SUCCESS;
1784         }
1785         if (mesh_event_cb)
1786                 mesh_event_cb(HAL_EV_MESH_PROVISIONING_STATUS,
1787                         (void*)&ev, sizeof(ev));
1788         INFO("Mesh: Provisioning status sent");
1789 }
1790
1791 static void __bt_hal_mesh_add_node_setup(struct l_dbus_message *msg,
1792                 void *user_data)
1793 {
1794         char *uuid;
1795         bt_uuid_t *dev = user_data;
1796         struct l_dbus_message_builder *builder;
1797         uuid =  l_util_hexstring(dev->uu, 16);
1798         INFO("Mesh: Add Node Setup UUID [%s]", uuid);
1799
1800         builder = l_dbus_message_builder_new(msg);
1801         __mesh_append_byte_array(builder, dev->uu, 16);
1802         l_dbus_message_builder_enter_array(builder, "{sv}");
1803         l_dbus_message_builder_leave_array(builder);
1804         l_dbus_message_builder_finalize(builder);
1805         l_dbus_message_builder_destroy(builder);
1806 }
1807
1808 bt_status_t _bt_hal_mesh_provision_device(
1809                 bt_uuid_t *net_uuid, bt_uuid_t *dev_uuid)
1810 {
1811         GSList *l;
1812         meshcfg_app *app;
1813         bt_uuid_t *dev;
1814         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
1815         if (l) {
1816                 app = l->data;
1817                 dev = g_memdup((gpointer)dev_uuid, 16);
1818                 INFO("Mesh: Schedule Add Node request to meshd");
1819                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "AddNode",
1820                                         __bt_hal_mesh_add_node_setup,
1821                                         __bt_hal_mesh_add_node_reply,
1822                                         (void*)dev, NULL))
1823                         return BT_STATUS_FAIL;
1824         } else {
1825                 ERR("Mesh: app not found!!");
1826                 return BT_STATUS_PARM_INVALID;
1827
1828         }
1829         return BT_STATUS_SUCCESS;
1830 }
1831
1832 static void __bt_hal_mesh_subnet_key_setup(
1833                 struct l_dbus_message *msg, void *user_data)
1834 {
1835         struct subnet_key_request *req = user_data;
1836         uint16_t idx = (uint16_t) req->idx;
1837
1838         l_dbus_message_set_arguments(msg, "q", idx);
1839 }
1840
1841 static void __bt_hal_mesh_subnet_key_reply(struct l_dbus_proxy *proxy,
1842                 struct l_dbus_message *msg, void *user_data)
1843 {
1844         struct hal_ev_mesh_netkey_execute_event ev;
1845         const char *dbus_path;
1846         uint8_t *net_uuid;
1847         struct subnet_key_request *req = user_data;
1848         const char *method = req->str;
1849
1850         dbus_path =  l_dbus_proxy_get_path(proxy);
1851         INFO("Mesh: DBUS path [%s]", dbus_path);
1852         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1853
1854         memset(&ev, 0, sizeof(ev));
1855         memcpy(ev.net_uuid, net_uuid, 16);
1856         ev.key_idx = req->idx;
1857
1858         g_free(net_uuid);
1859
1860         if (l_dbus_message_is_error(msg)) {
1861                 const char *name;
1862
1863                 l_dbus_message_get_error(msg, &name, NULL);
1864                 ERR("Mesh: Subnet [%s] failed: error: [%s]", method, name);
1865                 ev.status = BT_STATUS_FAIL;
1866         }
1867
1868         ev.status = BT_STATUS_SUCCESS;
1869
1870         if (!strcmp("CreateSubnet", method)) {
1871                 INFO("Mesh: Reply for CreateSubnet");
1872                 ev.key_event = HAL_MESH_KEY_ADD;
1873         } else if (!strcmp("DeleteSubnet", method)) {
1874                 INFO("Mesh: Reply for DeleteSubnet");
1875                 ev.key_event = HAL_MESH_KEY_DELETE;
1876         } else if (!strcmp("UpdateSubnet", method)) {
1877                 INFO("Mesh: Reply for UpdateSubnet");
1878                 ev.key_event = HAL_MESH_KEY_UPDATE;
1879         }
1880
1881         if (mesh_event_cb)
1882                 mesh_event_cb(HAL_EV_MESH_NETKEY_EXECUTE_EVENT,
1883                         (void*)&ev, sizeof(ev));
1884 }
1885
1886 static bool  __mesh_subnet_netkey_command_execute(meshcfg_app *app,
1887                         uint16_t index, const char *key_execute_method)
1888 {
1889         struct subnet_key_request *req;
1890
1891         req = l_new(struct subnet_key_request, 1);
1892         req->str = key_execute_method;
1893         req->idx = index;
1894
1895         if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
1896                                 __bt_hal_mesh_subnet_key_setup,
1897                                 __bt_hal_mesh_subnet_key_reply,
1898                                 req, l_free))
1899                 return false;
1900
1901         return true;
1902 }
1903
1904 static void __bt_hal_mesh_app_key_setup(struct l_dbus_message *msg,
1905         void *user_data)
1906 {
1907         struct app_key_request *req = user_data;
1908         uint16_t net_idx = (uint16_t) req->net_idx;
1909         uint16_t app_idx = (uint16_t) req->app_idx;
1910
1911         if (g_strcmp0(req->str,"CreateAppKey") == 0)
1912                 l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
1913         else
1914                 l_dbus_message_set_arguments(msg, "q", app_idx);
1915 }
1916
1917 static void __bt_hal_mesh_app_key_reply(struct l_dbus_proxy *proxy,
1918                 struct l_dbus_message *msg, void *user_data)
1919 {
1920         struct hal_ev_mesh_appkey_execute_event ev;
1921         const char *dbus_path;
1922         uint8_t *net_uuid;
1923         struct app_key_request *req = user_data;
1924         const char *method = req->str;
1925
1926         dbus_path =  l_dbus_proxy_get_path(proxy);
1927         INFO("Mesh: DBUS path [%s]", dbus_path);
1928         net_uuid = __mesh_get_net_uuid_from_dbus_proxy_path(dbus_path);
1929
1930         memset(&ev, 0, sizeof(ev));
1931         memcpy(ev.net_uuid, net_uuid, 16);
1932         ev.net_idx = req->net_idx;
1933         ev.app_idx = req->app_idx;
1934
1935         g_free(net_uuid);
1936
1937         if (l_dbus_message_is_error(msg)) {
1938                 const char *name;
1939
1940                 l_dbus_message_get_error(msg, &name, NULL);
1941                 ERR("Mesh: AppKey execute [%s] failed: error: [%s]", method, name);
1942                 ev.status = BT_STATUS_FAIL;
1943         } else
1944                 ev.status = BT_STATUS_SUCCESS;
1945
1946         if (!strcmp("CreateAppKey", method)) {
1947                 INFO("Mesh: AppKey Create Reply");
1948                 ev.key_event = HAL_MESH_KEY_ADD;
1949         } else if (!strcmp("DeleteAppKey", method)) {
1950                 INFO("Mesh: AppKey Delete Reply");
1951                 ev.key_event = HAL_MESH_KEY_DELETE;
1952         } else if (!strcmp("UpdateAppKey", method)) {
1953                 INFO("Mesh: AppKey Update Reply");
1954                 ev.key_event = HAL_MESH_KEY_UPDATE;
1955         }
1956
1957         if (mesh_event_cb)
1958                 mesh_event_cb(HAL_EV_MESH_APPKEY_EXECUTE_EVENT, (void*)&ev, sizeof(ev));
1959 }
1960
1961 static bool  __mesh_subnet_appkey_command_execute(meshcfg_app *app,
1962                         uint16_t net_idx, uint16_t app_idx,
1963                                 const char *key_execute_method)
1964 {
1965         struct app_key_request *req;
1966
1967         req = l_new(struct app_key_request, 1);
1968         req->str = key_execute_method;
1969         req->net_idx = net_idx;
1970         req->app_idx = app_idx;
1971
1972         if (!l_dbus_proxy_method_call(app->mgmt_proxy, key_execute_method,
1973                                 __bt_hal_mesh_app_key_setup,
1974                                 __bt_hal_mesh_app_key_reply,
1975                                 req, l_free))
1976                 return false;
1977
1978         return true;
1979 }
1980
1981 bt_status_t _bt_hal_mesh_network_subnet_execute(bt_uuid_t *net_uuid,
1982                         bt_mesh_key_op_e op, uint16_t netkey_idx)
1983 {
1984         GSList *l;
1985         meshcfg_app *app;
1986         bool status = true;
1987         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
1988         if (l) {
1989                 app = l->data;
1990
1991                 if (op == BT_MESH_KEY_CREATE)
1992                         status = __mesh_subnet_netkey_command_execute(app,
1993                                         netkey_idx, "CreateSubnet");
1994                 else if (op == BT_MESH_KEY_DELETE)
1995                         status = __mesh_subnet_netkey_command_execute(app,
1996                                         netkey_idx, "DeleteSubnet");
1997                 else if (op == BT_MESH_KEY_UPDATE)
1998                         status = __mesh_subnet_netkey_command_execute(app,
1999                                         netkey_idx, "UpdateSubnet");
2000                 if (!status)
2001                         return BT_STATUS_FAIL;
2002
2003         } else {
2004                 ERR("Mesh: app not found!!");
2005                 return BT_STATUS_PARM_INVALID;
2006
2007         }
2008         return BT_STATUS_SUCCESS;
2009 }
2010
2011 bt_status_t _bt_hal_mesh_network_appkey_execute(bt_uuid_t *net_uuid,
2012                         bt_mesh_key_op_e op, uint16_t netkey_idx, uint16_t appkey_idx)
2013 {
2014         GSList *l;
2015         meshcfg_app *app;
2016         bool status = true;
2017         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2018         if (l) {
2019                 app = l->data;
2020
2021                 if (op == BT_MESH_KEY_CREATE)
2022                         status = __mesh_subnet_appkey_command_execute(app,
2023                                 netkey_idx, appkey_idx, "CreateAppKey");
2024                 else if (op == BT_MESH_KEY_DELETE)
2025                         status = __mesh_subnet_appkey_command_execute(app,
2026                                 netkey_idx, appkey_idx, "DeleteAppKey");
2027                 else if (op == BT_MESH_KEY_UPDATE) {
2028                         INFO("Mesh: Update ApKey command NK Idx [0x%2.2x] AK Idx [0x%2.2x]",
2029                                         netkey_idx, appkey_idx);
2030                         status = __mesh_subnet_appkey_command_execute(app,
2031                                 netkey_idx, appkey_idx, "UpdateAppKey");
2032                 }
2033                 if (!status)
2034                         return BT_STATUS_FAIL;
2035
2036         } else {
2037                 ERR("Mesh: app not found!!");
2038                 return BT_STATUS_PARM_INVALID;
2039
2040         }
2041         return BT_STATUS_SUCCESS;
2042 }
2043
2044 bt_status_t _bt_hal_mesh_send_provision_data(
2045                 bt_uuid_t *net_uuid, uint16_t netkey_idx, uint16_t unicast)
2046 {
2047         GSList *l;
2048         meshcfg_app *app;
2049         struct l_dbus_message *msg;
2050         struct l_dbus_message *reply;
2051
2052         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2053         if (l) {
2054                 app = l->data;
2055                 msg = app->msg;
2056
2057                 reply = l_dbus_message_new_method_return(msg);
2058                 l_dbus_message_set_arguments(reply, "qq", netkey_idx,  unicast);
2059                 l_dbus_send(dbus, reply);
2060         } else {
2061                 ERR("Mesh: app not found!!");
2062                 return BT_STATUS_PARM_INVALID;
2063         }
2064         return BT_STATUS_SUCCESS;
2065 }
2066
2067 bt_status_t _bt_hal_mesh_network_scan_cancel(bt_uuid_t *net_uuid)
2068 {
2069         GSList *l;
2070         meshcfg_app *app;
2071         l = g_slist_find_custom(mesh_apps,
2072                 net_uuid->uu, __mesh_compare_network_uuid);
2073         if (l) {
2074                 app = l->data;
2075                 if (!__bt_mesh_proxy_check(app)) {
2076                         ERR("Mesh: Proxy check failed!!");
2077                         return BT_STATUS_FAIL;
2078                 }
2079                 if (!l_dbus_proxy_method_call(app->mgmt_proxy,
2080                                 "UnprovisionedScanCancel",
2081                                         NULL, NULL, NULL, NULL))
2082                         return BT_STATUS_FAIL;
2083         } else {
2084                 ERR("Mesh: app not found!!");
2085                 return BT_STATUS_PARM_INVALID;
2086         }
2087
2088         /* Stop Scan timer */
2089         if (app->scan_timer_id > 0) {
2090                 g_source_remove(app->scan_timer_id);
2091                 app->scan_timer_id = 0;
2092         }
2093
2094         /* Trigger Scan finished event */
2095         __mesh_trigger_scan_finished_event(app);
2096
2097         return BT_STATUS_SUCCESS;
2098 }
2099
2100 bt_status_t _bt_hal_mesh_auth_reply(bt_hal_mesh_auth_variant_e auth_type,
2101                         const char *auth_value)
2102 {
2103         uint32_t val_u32;
2104         struct l_dbus_message *reply = NULL;
2105         struct l_dbus_message_builder *builder;
2106         uint8_t *alpha;
2107         bt_status_t ret = BT_STATUS_SUCCESS;
2108         size_t sz = 0;
2109
2110         /* Proxy Check */
2111         if (!__bt_mesh_proxy_check(0)) {
2112                 ERR("Mesh: Proxy check failed!!");
2113                 return BT_STATUS_FAIL;
2114         }
2115         INFO("Mesh: Authentication Reply: auth type [%d]", auth_type);
2116         INFO("Mesh: Authentication Reply: auth value [%s]", auth_value);
2117         /* For Numeric Type Inputs: Numeric, Blink, Beep & Vibrate */
2118         if (auth_type >= BT_HAL_MESH_AUTH_REQ_NUMERIC_INPUT &&
2119                         auth_type <= BT_HAL_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT) {
2120                 INFO("Mesh: Authentication reply: Numeric Type");
2121                 val_u32 = atoi(auth_value);
2122                 reply = l_dbus_message_new_method_return(agent_msg);
2123                 l_dbus_message_set_arguments(reply, "u", val_u32);
2124                 if (!reply)
2125                         reply = l_dbus_message_new_error(agent_msg, dbus_err_fail, NULL);
2126                 l_dbus_send(dbus, reply);
2127                 ret = BT_STATUS_SUCCESS;
2128         /* For Alpha-Numeric */
2129         } else if (auth_type == BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT ||
2130                         auth_type == BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT ||
2131                         auth_type == BT_HAL_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT ) {
2132                 INFO("Mesh: Authentication reply: Alpha-Numeric Type");
2133                 alpha = l_util_from_hexstring(auth_value, &sz);
2134                 reply = l_dbus_message_new_method_return(agent_msg);
2135                 builder = l_dbus_message_builder_new(reply);
2136                 __mesh_append_byte_array(builder, alpha, 16);
2137                 l_dbus_message_builder_finalize(builder);
2138                 l_dbus_message_builder_destroy(builder);
2139                 l_free(alpha);
2140                 if (!reply)
2141                         reply = l_dbus_message_new_error(agent_msg, dbus_err_fail, NULL);
2142                 l_dbus_send(dbus, reply);
2143                 ret = BT_STATUS_SUCCESS;
2144         }
2145         return ret;
2146 }
2147
2148 bt_status_t _bt_hal_mesh_network_scan(bt_uuid_t *net_uuid,
2149                 bt_hal_mesh_scan_param_t *param)
2150 {
2151         GSList *l;
2152         meshcfg_app *app;
2153         l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
2154         if (l) {
2155                 app = l->data;
2156                 if (!__bt_mesh_proxy_check(app)) {
2157                         ERR("Mesh: Proxy check failed!!");
2158                         return BT_STATUS_FAIL;
2159                 }
2160                 if (!l_dbus_proxy_method_call(app->mgmt_proxy, "UnprovisionedScan",
2161                                         __mesh_scan_setup, __mesh_scan_reply,
2162                                         L_UINT_TO_PTR(param->scan_time), NULL))
2163                         return BT_STATUS_FAIL;
2164         } else {
2165                 ERR("Mesh: app not found!!");
2166                 return BT_STATUS_PARM_INVALID;
2167         }
2168         return BT_STATUS_SUCCESS;
2169 }
2170
2171 bt_status_t _bt_hal_mesh_create_network(
2172                 bt_hal_mesh_node_t *node, GSList *models, bool is_prov)
2173 {
2174         meshcfg_app *app;
2175
2176         INFO("Mesh: Create Network Request");
2177
2178         if (!__bt_mesh_proxy_check(0)) {
2179                 ERR("Mesh: Proxy check failed!!");
2180                 return BT_STATUS_FAIL;
2181         }
2182
2183         INFO("Mesh: Node Element count [%d]", node->num_elements);
2184         INFO("Mesh: Node Primary Unicast[0x%2.2x]", node->primary_unicast);
2185         INFO("Mesh: Node Vendor Info: CID[0x%2.2x]", node->vendor_info.companyid);
2186         INFO("Mesh: Node Vendor Info: VID[0x%2.2x]", node->vendor_info.vendorid);
2187         INFO("Mesh: Node Vendor Info: VSID[0x%2.2x]", node->vendor_info.versionid);
2188         INFO("Mesh: Node Vendor Info: CRPL[0x%2.2x]", node->vendor_info.crpl);
2189         INFO("Mesh: Node Total Number of Models in the node[%d]", g_slist_length(models));
2190         /* Create DBUS APP */
2191         app = __bt_hal_mesh_create_app(node, models, is_prov);
2192         if (!app)
2193                 return BT_STATUS_FAIL;
2194
2195         /* Register DBUS APP */
2196         if (!__bt_hal_mesh_register_application(app)) {
2197                 goto failed;
2198         }
2199
2200         if (app->token.u64 == 0) {
2201                 INFO("Mesh: Create New Network");
2202                 /* Create CFG Network */
2203                 if (!l_dbus_proxy_method_call(net_proxy, "CreateNetwork",
2204                                         __bt_hal_mesh_create_net_setup,
2205                                         __bt_hal_mesh_create_net_reply, app,
2206                                         NULL)) {
2207                         ERR("Mesh: Network Create failed!!");
2208                         goto failed;
2209                 }
2210         } else {
2211                 INFO("Mesh: Attach Node to Network");
2212                 /* Attach to Network */
2213                 if (!l_dbus_proxy_method_call(net_proxy, "Attach",
2214                                         __bt_hal_mesh_attach_node_setup,
2215                                         __bt_hal_mesh_attach_node_reply,
2216                                         app,
2217                                 NULL)) {
2218                         ERR("Mesh: Node attach failed!!");
2219                         goto failed;
2220                 }
2221         }
2222
2223         INFO("Mesh: Node registration request scheudled");
2224         mesh_apps = g_slist_append(mesh_apps, app);
2225         INFO("Mesh: Total number of apps in list  [%d]",
2226                 g_slist_length(mesh_apps));
2227         return BT_STATUS_SUCCESS;
2228 failed:
2229         ERR("Mesh: network can not be created!!");
2230         __bt_hal_mesh_destroy_app_object(app);
2231         return BT_STATUS_FAIL;
2232 }
2233
2234 static void __bt_hal_mesh_config_send(
2235                 struct l_dbus_message *msg, void *user_data)
2236 {
2237         struct configuration_request *req = user_data;
2238         struct l_dbus_message_builder *builder;
2239
2240         builder = l_dbus_message_builder_new(msg);
2241
2242         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2243         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2244         if (req->is_dev_key)
2245                 l_dbus_message_builder_append_basic(builder, 'b', &req->rmt);
2246
2247         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2248         __mesh_append_byte_array(builder, req->data, req->len);
2249         l_dbus_message_builder_finalize(builder);
2250         l_dbus_message_builder_destroy(builder);
2251 }
2252
2253 static void __bt_hal_mesh_key_config_send(
2254                 struct l_dbus_message *msg, void *user_data)
2255 {
2256         struct key_config_request *req = user_data;
2257         struct l_dbus_message_builder *builder;
2258
2259         builder = l_dbus_message_builder_new(msg);
2260
2261         l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
2262         l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
2263         l_dbus_message_builder_append_basic(builder, 'q', &req->key_req_idx);
2264         l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
2265         l_dbus_message_builder_append_basic(builder, 'b', &req->update_req);
2266         l_dbus_message_builder_finalize(builder);
2267         l_dbus_message_builder_destroy(builder);
2268 }
2269
2270 bt_status_t _bt_hal_mesh_send_key_config_message(
2271                 bt_uuid_t *network, uint16_t dest,
2272                         bool is_netkey, bool is_update,
2273                                 uint16_t key_idx, uint16_t netkey_idx)
2274 {
2275         GSList *l;
2276         GSList *l1;
2277         struct key_config_request *req;
2278         meshcfg_app *app;
2279         meshcfg_el *elem;
2280         const char *key_method = (!is_netkey) ? "AddAppKey" : "AddNetKey";
2281         /* Source is Config Client Local Node */
2282         int src_elem_idx = 0;
2283         l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
2284         if (l) {
2285                 app = l->data;
2286                 if (!__bt_mesh_proxy_check(app)) {
2287                         ERR("Mesh: Proxy check failed!!");
2288                         return BT_STATUS_FAIL;
2289                 }
2290                 l1 = g_slist_find_custom(app->elements,
2291                         GUINT_TO_POINTER(src_elem_idx), __compare_element_index);
2292                 if (!l1)
2293                         return BT_STATUS_FAIL;
2294                 elem = l1->data;
2295
2296                 req = l_new(struct key_config_request, 1);
2297                 req->ele_path = elem->path;
2298                 req->dst = dest;
2299                 req->key_req_idx = key_idx;
2300                 req->idx = netkey_idx; /* Encryption Key index */
2301                 req->update_req = is_update;
2302
2303                 if (!l_dbus_proxy_method_call(app->proxy, key_method,
2304                                         __bt_hal_mesh_key_config_send, NULL,
2305                                         (void*)req, l_free))
2306                         return BT_STATUS_FAIL;
2307         } else {
2308                 ERR("Mesh: app not found!!");
2309                 return BT_STATUS_PARM_INVALID;
2310
2311         }
2312         return BT_STATUS_SUCCESS;
2313 }
2314
2315 bt_status_t _bt_hal_mesh_send_configuration_message(
2316         bt_uuid_t *network, uint16_t dest,
2317                 bool is_dev_key, uint16_t netkey_idx,
2318                         uint8_t *buf, int len)
2319 {
2320         GSList *l;
2321         GSList *l1;
2322         struct configuration_request *req;
2323         meshcfg_app *app;
2324         meshcfg_el *elem;
2325         int src_elem_idx = 0;
2326         l = g_slist_find_custom(mesh_apps, network->uu,
2327                         __mesh_compare_network_uuid);
2328         if (l) {
2329                 app = l->data;
2330                 if (!__bt_mesh_proxy_check(app)) {
2331                         ERR("Mesh: Proxy check failed!!");
2332                         return BT_STATUS_FAIL;
2333                 }
2334                 l1 = g_slist_find_custom(app->elements,
2335                                 GUINT_TO_POINTER(src_elem_idx),
2336                                 __compare_element_index);
2337                 if (!l1)
2338                         return BT_STATUS_FAIL;
2339                 elem = l1->data;
2340
2341                 req = l_new(struct configuration_request, 1);
2342                 req->ele_path = elem->path;
2343                 req->dst = dest;
2344                 req->idx = netkey_idx;
2345                 req->data = buf;
2346                 req->len = len;
2347                 req->rmt = true;
2348                 req->is_dev_key = is_dev_key;
2349
2350                 if (!l_dbus_proxy_method_call(app->proxy, "DevKeySend",
2351                                         __bt_hal_mesh_config_send, NULL,
2352                                         (void*)req, l_free))
2353                         return BT_STATUS_FAIL;
2354         } else {
2355                 ERR("Mesh: app not found!!");
2356                 return BT_STATUS_PARM_INVALID;
2357
2358         }
2359         return BT_STATUS_SUCCESS;
2360 }