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