#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"
#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";
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},
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);
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)
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");
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");
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)
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)
{
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);
}
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 */
}
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);
}
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);
}
}
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)
{
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);
}
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);
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));
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,
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);
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)
} 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);
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)
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) {
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);
/* 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);
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)
{
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");
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,
}
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);
}
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;
+}