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