Fix the svace issue (DEREF_OF_NULL)
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-mesh-dbus-handler.c
index 99163ad..0b9f872 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <hardware/bt_mesh.h>
 
+#define BT_HAL_MESH_DBUS_NAME "org.projectx.bt.mesh"
+
 #define BT_HAL_UUID_LEN 16
 #define BT_HAL_BLUEZ_MESH_NAME "org.bluez.mesh"
 
@@ -49,6 +51,7 @@
 #define BT_HAL_MESH_ERROR_INTERFACE "org.bluez.mesh.Error"
 
 #define BT_HAL_MESH_MAX_DEVKEY_BUF_SIZE 2048
+#define BT_HAL_MESH_MAX_MSG_BUF_SIZE 2048
 
 static const char *dbus_err_args = "org.freedesktop.DBus.Error.InvalidArgs";
 static const char *dbus_err_fail = "org.freedesktop.DBus.Error.Failed";
@@ -96,6 +99,11 @@ struct mesh_provision_auth_action {
        bt_hal_mesh_auth_variant_e auth_type;
 };
 
+struct mesh_remote_node_info {
+       uint16_t unicast;
+       uint8_t num_elements;
+};
+
 static struct mesh_provision_auth_action auth_table[] = {
        { "blink", BT_HAL_MESH_AUTH_REQ_BLINK_COUNT_INPUT},
        { "beep", BT_HAL_MESH_AUTH_REQ_BEEP_COUNT_INPUT},
@@ -264,7 +272,7 @@ static unsigned char* __mesh_get_net_uuid_from_path(
        char uuid[33];
        size_t sz;
 
-       switch(iface) {
+       switch (iface) {
        case MESH_APP_IFACE:
        case MESH_PROV_IFACE:  {
                memcpy(uuid, is_prov ? (void*) &dbus_path[16] : (void*) &dbus_path[17], 32);
@@ -414,7 +422,22 @@ static gint __compare_element_index(gconstpointer data, gconstpointer user_data)
        if (!elem)
                return 1;
 
-       return (elem->index == elem_index ? 0: -1);
+       return (elem->index == elem_index ? 0 : -1);
+}
+
+static void __send_network_destroy_event(void *param, uint8_t status)
+{
+       struct hal_ev_mesh_network_destroyed ev;
+       meshcfg_app *app = (meshcfg_app*)param;
+
+       memset(&ev, 0, sizeof(ev));
+       memcpy(ev.uuid, app->uuid, sizeof(app->uuid));
+       memcpy(ev.token, app->token.u8, 8);
+
+       ev.status = status;
+       if (mesh_event_cb)
+               mesh_event_cb(HAL_EV_MESH_NETWORK_DESTROYED,
+                       (void*)&ev, sizeof(ev));
 }
 
 static void __mesh_proxy_added(struct l_dbus_proxy *proxy, void *user_data)
@@ -486,7 +509,8 @@ static void __mesh_proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
                l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
                if (l) {
                        app = l->data;
-                       /*TODO: Send event to app about removal of a mesh local node */
+                       /* Send event to app about removal of a mesh local node */
+                       __send_network_destroy_event(app, BT_STATUS_SUCCESS);
                        __bt_hal_mesh_destroy_app_object(app);
                } else {
                        ERR("Mesh: app not found for Mgmt proxy");
@@ -499,8 +523,8 @@ static void __mesh_proxy_removed(struct l_dbus_proxy *proxy, void *user_data)
                l = g_slist_find_custom(mesh_apps, path, __compare_proxy_path);
                if (l) {
                        app = l->data;
-                       /*TODO: Send event to app about removal of
-                       a mesh local node: first send event, then destroy mesh object */
+                       /* Send event to app about removal of a mesh local node */
+                       __send_network_destroy_event(app, BT_STATUS_SUCCESS);
                        __bt_hal_mesh_destroy_app_object(app);
                } else {
                        ERR("Mesh: app not found for Mgmt proxy");
@@ -516,11 +540,23 @@ static void __mesh_dbus_client_ready(struct l_dbus_client *client_obj,
        client = client_obj;
 }
 
+static void __mesh_acquire_name_callback(struct l_dbus *dbus_obj, bool success,
+                                       bool queued, void *user_data)
+{
+       if (success == false)
+               ERR("Mesh: Fail to acquire dbus name\n");
+
+       if (!l_dbus_object_manager_enable(dbus_obj, "/"))
+               ERR("Mesh: Failed to register the ObjectManager\n");
+}
+
 static void __mesh_ready_callback(void *user_data)
 {
        INFO("Mesh: Connected to D-Bus\n");
-       if (!l_dbus_object_manager_enable(dbus, "/"))
-               ERR("Mesh: Failed to register the ObjectManager\n");
+
+       if (!l_dbus_name_acquire(dbus, BT_HAL_MESH_DBUS_NAME, false, false, false,
+                               __mesh_acquire_name_callback, NULL))
+               ERR("Mesh: Failed to own well-known name\n");
 }
 
 bool _bt_hal_mesh_stack_init(void)
@@ -561,6 +597,21 @@ bool _bt_hal_mesh_stack_init(void)
        return true;
 }
 
+void _bt_hal_mesh_stack_deinit(void)
+{
+       INFO("Mesh: Stack Deinit");
+
+       if (client) {
+               l_dbus_client_destroy(client);
+               client = NULL;
+       }
+
+       if (dbus) {
+               l_dbus_destroy(dbus);
+               dbus = NULL;
+       }
+}
+
 /* To send stack event to hal-mesh handler */
 void _bt_hal_mesh_register_dbus_handler_cb(handle_stack_msg cb)
 {
@@ -824,8 +875,59 @@ static struct l_dbus_message *__mesh_device_message_received(struct l_dbus *dbus
        INFO("Mesh: Is Remote [%s]", rmt ? "YES" : "NO");
        INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
        /* Send DevKeyMessage Received event */
-       if (mesh_event_cb) {
+       if (mesh_event_cb)
                mesh_event_cb(HAL_EV_MESH_DEVKEY_MESSAGE_EVENT, (void*)buf, size);
+       return l_dbus_message_new_method_return(msg);
+}
+
+static struct l_dbus_message *__mesh_message_received(struct l_dbus *dbus,
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct l_dbus_message_iter iter;
+       uint16_t src, idx, dst;
+       uint8_t *data;
+       uint32_t n;
+       const char *dbus_path;
+       uint16_t size;
+       uint8_t *net_uuid;
+       dbus_path =  l_dbus_message_get_path(msg);
+       net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,  MESH_ELEMENT_IFACE);
+       uint8_t buf[BT_HAL_MESH_MAX_MSG_BUF_SIZE];
+       struct hal_ev_mesh_message_event *ev = (void *)buf;
+
+       INFO("Mesh: app path [%s]", dbus_path);
+
+       memset(buf, 0, sizeof(buf));
+       size = (uint16_t) sizeof(*ev);
+       memcpy(ev->net_uuid, net_uuid, 16);
+       g_free(net_uuid);
+
+       if (!l_dbus_message_get_arguments(msg, "qqvay", &src, &idx, &dst,
+                               &iter)) {
+               ERR("Mesh: Cannot parse received message");
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       if (!l_dbus_message_iter_get_fixed_array(&iter, &data, &n)) {
+               ERR("Mesh: Cannot parse received message: data");
+               return l_dbus_message_new_error(msg, dbus_err_args, NULL);
+       }
+
+       INFO("Mesh: Received mesh message (len %u):", n);
+       ev->source_addr = src;
+       ev->dest_addr = dst;
+       ev->key_idx = idx;
+       ev->data_len = n;
+       memcpy(ev->data, data, n);
+       size += n;
+
+       INFO("Mesh: Src [0x%2.2x]", src);
+       INFO("Mesh: Dst [0x%2.2x]", dst);
+       INFO("Mesh: NetKey Idx [0x%2.2x]", idx);
+       /* Send Message Received event */
+       if (mesh_event_cb) {
+               INFO("Mesh: Send message event");
+               mesh_event_cb(HAL_EV_MESH_MESSAGE_EVENT, (void*)buf, size);
        }
        return l_dbus_message_new_method_return(msg);
 }
@@ -844,6 +946,9 @@ static void __bt_hal_mesh_setup_ele_iface(struct l_dbus_interface *iface)
        l_dbus_interface_method(iface, "DevKeyMessageReceived", 0,
                        __mesh_device_message_received, "", "qbqay", "source",
                        "remote", "net_index", "data");
+       l_dbus_interface_method(iface, "MessageReceived", 0,
+                       __mesh_message_received, "", "qqvay", "source",
+                       "key_index", "destination", "data");
        /* TODO: Other methods */
 }
 
@@ -873,9 +978,8 @@ static struct l_dbus_message *__mesh_scan_result_received(struct l_dbus *dbus,
        if (!l_dbus_message_get_arguments(msg, sig, &rssi, &iter, &opts)) {
                ERR("Mesh: Cannot parse scan results");
                ev.status = BT_STATUS_FAIL;
-               if (mesh_event_cb) {
+               if (mesh_event_cb)
                        mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
-               }
                return l_dbus_message_new_error(msg, dbus_err_args, NULL);
        }
 
@@ -883,9 +987,8 @@ static struct l_dbus_message *__mesh_scan_result_received(struct l_dbus *dbus,
                        n < 16) {
                ERR("Mesh: Cannot parse scan result: data");
                ev.status = BT_STATUS_FAIL;
-               if (mesh_event_cb) {
+               if (mesh_event_cb)
                        mesh_event_cb(HAL_EV_MESH_SCAN_RESULT, (void*)&ev, sizeof(ev));
-               }
                return l_dbus_message_new_error(msg, dbus_err_args, NULL);
        }
 
@@ -1160,7 +1263,7 @@ static void __mesh_fill_out_capabilities(meshcfg_app *app,
 }
 
 static bool __mesh_agent_capability_getter(
-               struct l_dbus *dbus,struct l_dbus_message *message,
+               struct l_dbus *dbus, struct l_dbus_message *message,
                        struct l_dbus_message_builder *builder,
                                void *user_data)
 {
@@ -1169,9 +1272,8 @@ static bool __mesh_agent_capability_getter(
        INFO("Mesh: app path [%s]", app->path);
        INFO("Mesh: Agent path [%s]", app->agent_path);
 
-       if (!l_dbus_message_builder_enter_array(builder, "s")) {
+       if (!l_dbus_message_builder_enter_array(builder, "s"))
                return false;
-       }
 
        __mesh_fill_out_capabilities(app, builder);
        __mesh_fill_in_capabilities(app, builder);
@@ -1282,7 +1384,7 @@ static struct l_dbus_message *__mesh_agent_display_numeric_request(
        }
 
        INFO("Mesh:[OUT] Numeric Authentication type [%s] value [%u]", str, n);
-       auth_value = l_strdup_printf("%u",n);
+       auth_value = l_strdup_printf("%u", n);
        ev.auth_type = __mesh_get_authentication_type(str);
        if (ev.auth_type == BT_HAL_MESH_UNKNOWN_AUTH_METHOD)
                return l_dbus_message_new_error(msg, dbus_err_fail, NULL);
@@ -1317,6 +1419,10 @@ static struct l_dbus_message *__mesh_agent_prompt_numeric_request(
 
        l = g_slist_find_custom(mesh_apps, net_uuid,
                        __mesh_compare_network_uuid);
+       if (!l) {
+               g_free(net_uuid);
+               return NULL;
+       }
        app = l->data;
 
        memset(&ev, 0, sizeof(ev));
@@ -1362,7 +1468,7 @@ static struct l_dbus_message *__mesh_agent_prompt_static_request(
        uint8_t *net_uuid;
        const char *dbus_path;
        GSList *l;
-       meshcfg_app *app;
+       meshcfg_app *app = NULL;
 
        dbus_path =  l_dbus_message_get_path(msg);
        net_uuid = __mesh_get_net_uuid_from_path(dbus_path, true,
@@ -1372,7 +1478,13 @@ static struct l_dbus_message *__mesh_agent_prompt_static_request(
 
        l = g_slist_find_custom(mesh_apps, net_uuid,
                        __mesh_compare_network_uuid);
-       app = l->data;
+
+       if (l) {
+               app = l->data;
+       } else {
+               ERR("Mesh: app not found");
+       }
+
 
        memset(&ev, 0, sizeof(ev));
        memcpy(ev.net_uuid, net_uuid, 16);
@@ -1383,7 +1495,10 @@ static struct l_dbus_message *__mesh_agent_prompt_static_request(
 
                struct hal_ev_mesh_provision_finished ev;
                memset(&ev, 0, sizeof(ev));
-               memcpy(ev.net_uuid, app->uuid, 16);
+
+               if (app)
+                       memcpy(ev.net_uuid, app->uuid, 16);
+
                ev.status = BT_STATUS_FAIL;
                ev.reason = BT_HAL_MESH_PROV_ERR_INTERNAL;
                if (mesh_event_cb)
@@ -1537,7 +1652,7 @@ static void __bt_mesh_hal_create_element_object(gpointer data, gpointer user_dat
        } else {
                elem = g_malloc0(sizeof(meshcfg_el));
                elem->index = model_info->elem_index;
-               elem->path = g_strdup_printf("%s/elem%u",app->path, elem->index);
+               elem->path = g_strdup_printf("%s/elem%u", app->path, elem->index);
                app->elements = g_slist_append(app->elements, elem);
                INFO("Mesh: Created element index [%d] path [%s]",
                        elem->index, elem->path);
@@ -1583,6 +1698,36 @@ meshcfg_app *__bt_hal_mesh_create_app(bt_hal_mesh_node_t *node,
        return app;
 }
 
+static void __bt_hal_mesh_leave_net_reply(
+               struct l_dbus_proxy *proxy,
+                       struct l_dbus_message *msg, void *user_data)
+{
+       meshcfg_app *app;
+       app = (meshcfg_app*) user_data;
+
+       INFO("Mesh: Leave Network Reply from Meshd: app path [%s]", app->path);
+       if (l_dbus_message_is_error(msg)) {
+               const char *name;
+
+               l_dbus_message_get_error(msg, &name, NULL);
+               ERR("Mesh: Failed to leave network: %s", name);
+
+               /* Send Network Destroy fail event */
+               __send_network_destroy_event(app, BT_STATUS_FAIL);
+       } else {
+               INFO("Mesh: Leave Network: Success, cleanup app after proxy removed");
+       }
+}
+
+static void __bt_hal_mesh_leave_net_setup(struct l_dbus_message *msg,
+               void *user_data)
+{
+       meshcfg_app *app = (meshcfg_app*) user_data;
+
+       l_dbus_message_set_arguments(msg, "t", l_get_be64(app->token.u8));
+       INFO("Mesh: Leave Network Setup app path [%s]", app->path);
+}
+
 static void __bt_hal_mesh_create_net_reply(
                struct l_dbus_proxy *proxy,
                        struct l_dbus_message *msg, void *user_data)
@@ -1650,6 +1795,8 @@ void __bt_mesh_enable_scanning_timer(uint8_t *net_uuid, uint16_t secs)
        meshcfg_app *app;
        l = g_slist_find_custom(mesh_apps, net_uuid,
                        __mesh_compare_network_uuid);
+       if (!l)
+               return;
        app = l->data;
 
        if (app->scan_timer_id > 0) {
@@ -1908,7 +2055,7 @@ static void __bt_hal_mesh_app_key_setup(struct l_dbus_message *msg,
        uint16_t net_idx = (uint16_t) req->net_idx;
        uint16_t app_idx = (uint16_t) req->app_idx;
 
-       if (g_strcmp0(req->str,"CreateAppKey") == 0)
+       if (g_strcmp0(req->str, "CreateAppKey") == 0)
                l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
        else
                l_dbus_message_set_arguments(msg, "q", app_idx);
@@ -2128,7 +2275,7 @@ bt_status_t _bt_hal_mesh_auth_reply(bt_hal_mesh_auth_variant_e auth_type,
        /* For Alpha-Numeric */
        } else if (auth_type == BT_HAL_MESH_AUTH_REQ_ALPHANUMERIC_INPUT ||
                        auth_type == BT_HAL_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT ||
-                       auth_type == BT_HAL_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT ) {
+                       auth_type == BT_HAL_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT) {
                INFO("Mesh: Authentication reply: Alpha-Numeric Type");
                alpha = l_util_from_hexstring(auth_value, &sz);
                reply = l_dbus_message_new_method_return(agent_msg);
@@ -2168,6 +2315,91 @@ bt_status_t _bt_hal_mesh_network_scan(bt_uuid_t *net_uuid,
        return BT_STATUS_SUCCESS;
 }
 
+static void __bt_hal_mesh_delete_node_setup(struct l_dbus_message *msg,
+               void *user_data)
+{
+       struct mesh_remote_node_info *node_info = \
+               (struct mesh_remote_node_info*) user_data;
+
+       l_dbus_message_set_arguments(msg, "qy",
+               node_info->unicast, node_info->num_elements);
+       INFO("Mesh: Delete Remote Node Setup params passed");
+}
+
+static void __bt_hal_mesh_delete_node_reply(
+               struct l_dbus_proxy *proxy,
+                       struct l_dbus_message *msg, void *user_data)
+{
+       INFO("Mesh: Delete Remote Node Reply from DBUS");
+}
+
+bt_status_t _bt_hal_mesh_node_delete(bt_uuid_t *network,
+               uint16_t unicast, uint16_t num_elements)
+{
+       GSList *l;
+       meshcfg_app *app;
+       struct mesh_remote_node_info *node_info;
+       INFO("Mesh: Delete Remote Node");
+       l = g_slist_find_custom(mesh_apps, network->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               if (!__bt_mesh_proxy_check(app)) {
+                       ERR("Mesh: Proxy check failed!!");
+                       return BT_STATUS_FAIL;
+               }
+               INFO("Mesh: Delete Remote Node Unicast [0x%2.2x] Num els [%u]",
+                       unicast, num_elements);
+
+               /* Delete Remote Node Request */
+               node_info = g_malloc0(sizeof(struct mesh_remote_node_info));
+               node_info->unicast = unicast;
+               node_info->num_elements = num_elements;
+
+               if (!l_dbus_proxy_method_call(app->mgmt_proxy, "DeleteRemoteNode",
+                                       __bt_hal_mesh_delete_node_setup,
+                                       __bt_hal_mesh_delete_node_reply, node_info,
+                                       l_free)) {
+                       ERR("Mesh: Delete Remote Node Request failed!!");
+                       g_free(node_info);
+                       return BT_STATUS_FAIL;
+               }
+       } else {
+               ERR("Mesh: App not found!!");
+               return BT_STATUS_PARM_INVALID;
+       }
+       INFO("Mesh: Delete Remote Node Call issued successfully!!");
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_mesh_network_destroy(bt_uuid_t *net_uuid)
+{
+       GSList *l;
+       meshcfg_app *app;
+       INFO("Mesh: Destroy network");
+       l = g_slist_find_custom(mesh_apps, net_uuid->uu, __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               if (!__bt_mesh_proxy_check(app)) {
+                       ERR("Mesh: Proxy check failed!!");
+                       return BT_STATUS_FAIL;
+               }
+               INFO("Mesh: Create New Network");
+               /* Create CFG Network */
+               if (!l_dbus_proxy_method_call(net_proxy, "Leave",
+                                       __bt_hal_mesh_leave_net_setup,
+                                       __bt_hal_mesh_leave_net_reply, app,
+                                       NULL)) {
+                       ERR("Mesh: Network Leave failed!!");
+                       return BT_STATUS_FAIL;
+               }
+       } else {
+               ERR("Mesh: App not found!!");
+               return BT_STATUS_PARM_INVALID;
+       }
+       INFO("Mesh: Network Leave Call issued successfully!!");
+       return BT_STATUS_SUCCESS;
+}
+
 bt_status_t _bt_hal_mesh_create_network(
                bt_hal_mesh_node_t *node, GSList *models, bool is_prov)
 {
@@ -2193,9 +2425,8 @@ bt_status_t _bt_hal_mesh_create_network(
                return BT_STATUS_FAIL;
 
        /* Register DBUS APP */
-       if (!__bt_hal_mesh_register_application(app)) {
+       if (!__bt_hal_mesh_register_application(app))
                goto failed;
-       }
 
        if (app->token.u64 == 0) {
                INFO("Mesh: Create New Network");
@@ -2267,6 +2498,22 @@ static void __bt_hal_mesh_key_config_send(
        l_dbus_message_builder_destroy(builder);
 }
 
+static void __bt_hal_mesh_model_execute_message(
+               struct l_dbus_message *msg, void *user_data)
+{
+       struct configuration_request *req = user_data;
+       struct l_dbus_message_builder *builder;
+
+       builder = l_dbus_message_builder_new(msg);
+
+       l_dbus_message_builder_append_basic(builder, 'o', req->ele_path);
+       l_dbus_message_builder_append_basic(builder, 'q', &req->dst);
+       l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
+       __mesh_append_byte_array(builder, req->data, req->len);
+       l_dbus_message_builder_finalize(builder);
+       l_dbus_message_builder_destroy(builder);
+}
+
 bt_status_t _bt_hal_mesh_send_key_config_message(
                bt_uuid_t *network, uint16_t dest,
                        bool is_netkey, bool is_update,
@@ -2289,6 +2536,8 @@ bt_status_t _bt_hal_mesh_send_key_config_message(
                }
                l1 = g_slist_find_custom(app->elements,
                        GUINT_TO_POINTER(src_elem_idx), __compare_element_index);
+               if (!l1)
+                       return BT_STATUS_FAIL;
                elem = l1->data;
 
                req = l_new(struct key_config_request, 1);
@@ -2356,3 +2605,49 @@ bt_status_t _bt_hal_mesh_send_configuration_message(
        }
        return BT_STATUS_SUCCESS;
 }
+
+bt_status_t _bt_hal_mesh_model_execute_message(
+       bt_uuid_t *network, uint16_t dest,
+       uint16_t appkey_idx, uint8_t *buf, int len)
+{
+       GSList *l;
+       GSList *l1;
+       struct configuration_request *req;
+       meshcfg_app *app;
+       meshcfg_el *elem;
+       int src_elem_idx = 0;
+       l = g_slist_find_custom(mesh_apps, network->uu,
+                       __mesh_compare_network_uuid);
+       if (l) {
+               app = l->data;
+               if (!__bt_mesh_proxy_check(app)) {
+                       ERR("Mesh: Proxy check failed!!");
+                       return BT_STATUS_FAIL;
+               }
+               l1 = g_slist_find_custom(app->elements,
+                               GUINT_TO_POINTER(src_elem_idx),
+                               __compare_element_index);
+               if (!l1)
+                       return BT_STATUS_FAIL;
+               elem = l1->data;
+
+               req = l_new(struct configuration_request, 1);
+               req->ele_path = elem->path;
+               req->dst = dest;
+               req->idx = appkey_idx;
+               req->data = buf;
+               req->len = len;
+               req->rmt = false;
+               req->is_dev_key = false;
+
+               if (!l_dbus_proxy_method_call(app->proxy, "Send",
+                                       __bt_hal_mesh_model_execute_message,
+                                       NULL, (void*)req, l_free))
+                       return BT_STATUS_FAIL;
+       } else {
+               ERR("Mesh: app not found!!");
+               return BT_STATUS_PARM_INVALID;
+
+       }
+       return BT_STATUS_SUCCESS;
+}