[Adapt: HAL] Implement BlueZ HAL interface for HDP 01/93101/1
authorAtul Rai <a.rai@samsung.com>
Fri, 14 Oct 2016 08:42:54 +0000 (14:12 +0530)
committerAtul Rai <a.rai@samsung.com>
Fri, 14 Oct 2016 08:46:06 +0000 (14:16 +0530)
This patch adds BlueZ HAL interface implementation for
Health device profile.

Change-Id: I3d18a4cdd315317dbba7ea13a3f17d79ee007f84
Signed-off-by: Atul Rai <a.rai@samsung.com>
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/hardware/bt_hl.h [new file with mode: 0644]
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/inc/bt-hal.h
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hdp.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hdp.h [new file with mode: 0644]

index 3b965da..9a478fc 100644 (file)
@@ -18,6 +18,8 @@ SET(SRCS
 ./src/bt-hal-hid-dbus-handler.c
 ./src/bt-hal-socket.c
 ./src/bt-hal-rfcomm-dbus-handler.c
+./src/bt-hal-hdp.c
+./src/bt-hal-hdp-dbus-handler.c
 )
 
 SET(PREFIX ${CMAKE_INSTALL_PREFIX})
diff --git a/bt-oal/bluez_hal/hardware/bt_hl.h b/bt-oal/bluez_hal/hardware/bt_hl.h
new file mode 100644 (file)
index 0000000..35ff1ec
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_INCLUDE_BT_HL_H
+#define ANDROID_INCLUDE_BT_HL_H
+
+__BEGIN_DECLS
+
+/* HL connection states */
+
+typedef enum
+{
+    BTHL_MDEP_ROLE_SOURCE,
+    BTHL_MDEP_ROLE_SINK
+} bthl_mdep_role_t;
+
+typedef enum {
+    BTHL_APP_REG_STATE_REG_SUCCESS,
+    BTHL_APP_REG_STATE_REG_FAILED,
+    BTHL_APP_REG_STATE_DEREG_SUCCESS,
+    BTHL_APP_REG_STATE_DEREG_FAILED
+} bthl_app_reg_state_t;
+
+typedef enum
+{
+    BTHL_CHANNEL_TYPE_RELIABLE,
+    BTHL_CHANNEL_TYPE_STREAMING,
+    BTHL_CHANNEL_TYPE_ANY
+} bthl_channel_type_t;
+
+
+/* HL connection states */
+typedef enum {
+    BTHL_CONN_STATE_CONNECTING,
+    BTHL_CONN_STATE_CONNECTED,
+    BTHL_CONN_STATE_DISCONNECTING,
+    BTHL_CONN_STATE_DISCONNECTED,
+    BTHL_CONN_STATE_DESTROYED
+} bthl_channel_state_t;
+
+typedef struct
+{
+    bthl_mdep_role_t        mdep_role;
+    int                     data_type;
+    bthl_channel_type_t     channel_type;
+    const char                   *mdep_description; /* MDEP description to be used in the SDP (optional); null terminated */
+} bthl_mdep_cfg_t;
+
+typedef struct
+{
+    const char      *application_name;
+    const char      *provider_name;   /* provider name to be used in the SDP (optional); null terminated */
+    const char      *srv_name;        /* service name to be used in the SDP (optional); null terminated*/
+    const char      *srv_desp;        /* service description to be used in the SDP (optional); null terminated */
+    int             number_of_mdeps;
+    bthl_mdep_cfg_t *mdep_cfg;  /* Dynamic array */
+} bthl_reg_param_t;
+
+/** Callback for application registration status.
+ *  state will have one of the values from  bthl_app_reg_state_t
+ */
+typedef void (* bthl_app_reg_state_callback)(int app_id, bthl_app_reg_state_t state);
+
+/** Callback for channel connection state change.
+ *  state will have one of the values from
+ *  bthl_connection_state_t and fd (file descriptor)
+ */
+typedef void (* bthl_channel_state_callback)(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd);
+
+/** BT-HL callback structure. */
+typedef struct {
+    /** set to sizeof(bthl_callbacks_t) */
+    size_t      size;
+    bthl_app_reg_state_callback     app_reg_state_cb;
+    bthl_channel_state_callback     channel_state_cb;
+} bthl_callbacks_t;
+
+
+/** Represents the standard BT-HL interface. */
+typedef struct {
+
+    /** set to sizeof(bthl_interface_t)  */
+    size_t          size;
+
+    /**
+     * Register the Bthl callbacks
+     */
+    bt_status_t (*init)( bthl_callbacks_t* callbacks );
+
+    /** Register HL application */
+    bt_status_t (*register_application) ( bthl_reg_param_t *p_reg_param, int *app_id);
+
+    /** Unregister HL application */
+    bt_status_t (*unregister_application) (int app_id);
+
+    /** connect channel */
+    bt_status_t (*connect_channel)(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int *channel_id);
+
+    /** destroy channel */
+    bt_status_t (*destroy_channel)(int channel_id);
+
+    /** Close the  Bthl callback **/
+    void (*cleanup)(void);
+
+} bthl_interface_t;
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_HL_H */
index 868e02e..29f23b9 100644 (file)
@@ -316,5 +316,22 @@ struct hal_ev_handsfree_audio_state {
         uint8_t state;
         uint8_t bdaddr[6];
 } __attribute__((packed));
+
+#define HAL_EV_HDP_APP_REG_STATE            0x93
+struct hal_ev_hdp_app_reg_state {
+       uint16_t app_id;
+       uint8_t state;
+} __attribute__((packed));
+
+#define HAL_EV_HDP_CONN_STATE            0x94
+struct hal_ev_hdp_conn_state {
+       uint16_t app_id;
+        uint8_t bdaddr[6];
+       uint8_t mdep_index;
+       uint16_t channel_id;
+       uint8_t channel_state;
+       int32_t data_fd;
+} __attribute__((packed));
+
 #endif //_BT_HAL_MSG_H_
 
index 7df0d24..334337e 100644 (file)
@@ -27,6 +27,7 @@
 #include <hardware/bt_av.h>
 #include <hardware/bt_hf.h>
 #include <hardware/bt_sock.h>
+#include <hardware/bt_hl.h>
 
 /*TODO: Profile interfaces headers and exposed methods of Android HAL framework to be included in next patches */
 #endif //_BT_HAL_H
index 1128779..92cf5f4 100644 (file)
@@ -36,6 +36,7 @@
 #include <bt-hal-socket.h>
 #include <bt-hal-av.h>
 #include <bt-hal-hf.h>
+#include <bt-hal-hdp.h>
 
 #define enum_prop_to_hal(prop, hal_prop, type) do { \
        static type e; \
@@ -233,7 +234,7 @@ static const void *get_profile_interface(const char *profile_id)
                return NULL;
 
        if (!strcmp(profile_id, BT_PROFILE_HEALTH_ID))
-               return NULL;
+               return bt_get_hl_interface();
 
        if (!strcmp(profile_id, BT_PROFILE_AV_RC_CTRL_ID))
                return NULL;
diff --git a/bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.c
new file mode 100644 (file)
index 0000000..2539108
--- /dev/null
@@ -0,0 +1,1027 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+#include <gio/gunixfdlist.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "bt-hal-hdp-dbus-handler.h"
+#include "bt-hal-dbus-common-utils.h"
+#include "bt-hal-internal.h"
+#include "bt-hal-msg.h"
+
+#define BT_HAL_HDP_MANAGER_INTERFACE  "org.bluez.HealthManager1"
+#define BT_HAL_HDP_DEVICE_INTERFACE  "org.bluez.HealthDevice1"
+#define BT_HAL_HDP_CHANNEL_INTERFACE  "org.bluez.HealthChannel1"
+#define BT_HAL_HDP_CHANNEL_ID_MAX 255
+
+static GSList *app_list;
+typedef struct {
+       int app_id;
+       char address[BT_HAL_ADDRESS_STRING_SIZE];
+       int channel_id;
+       char *obj_path;
+       int fd;
+}hdp_conn_info_t;
+
+typedef struct {
+       int id;
+       char *path;
+       int channel_type;
+       GSList *conn_list;
+}hdp_app_data_t;
+
+static handle_stack_msg event_cb = NULL;
+static int latest_id = -1;
+static gboolean id_used[BT_HAL_HDP_CHANNEL_ID_MAX];
+
+static void __hdp_send_conn_event(hdp_conn_info_t *conn_info, int state)
+{
+       struct hal_ev_hdp_conn_state ev;
+
+       DBG("+");
+
+       /* Prepare to send HDP app registration state event */
+       memset(&ev, 0, sizeof(ev));
+       ev.app_id = conn_info->app_id;
+       _bt_convert_addr_string_to_type(ev.bdaddr, conn_info->address);
+       ev.mdep_index = 0;
+       ev.channel_id = conn_info->channel_id;
+       ev.data_fd = conn_info->fd;
+       ev.channel_state = state;
+       if (!event_cb)
+               ERR("HDP dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HDP_CONN_STATE, (void *)&ev, sizeof(ev));
+
+       DBG("-");
+}
+
+int __hdp_assign_channel_id(void)
+{
+       int index;
+
+       DBG("latest_id: %d", latest_id);
+
+       index = latest_id + 1;
+       if (index >= BT_HAL_HDP_CHANNEL_ID_MAX)
+               index = 0;
+
+       DBG("index: %d", index);
+
+       while (id_used[index] == TRUE) {
+               if (index == latest_id) {
+                       /* No available ID */
+                       ERR("All request ID is used");
+                       return -1;
+               }
+
+               index++;
+               if (index >= BT_HAL_HDP_CHANNEL_ID_MAX)
+                       index = 0;
+       }
+
+       latest_id = index;
+       id_used[index] = TRUE;
+       DBG("Assigned Id: %d", latest_id);
+
+       return latest_id;
+}
+
+void __hdp_delete_channnel_id(int id)
+{
+       if (id >= BT_HAL_HDP_CHANNEL_ID_MAX || id < 0) {
+               ERR("Invalid id %d", id);
+               return;
+       }
+
+       id_used[id] = FALSE;
+       latest_id = id - 1;
+       DBG("id: %d, latest_id: %d", id, latest_id);
+}
+
+static hdp_app_data_t *__get_hdp_app_by_id(int id)
+{
+       GSList *l;
+
+       for (l = app_list; l != NULL; l = l->next) {
+               hdp_app_data_t *app = l->data;
+               if (app && app->id == id)
+                       return app;
+       }
+
+       return NULL;
+}
+
+static hdp_app_data_t *__get_hdp_app_by_path(char *app_path)
+{
+       GSList *l;
+
+       if (!app_path)
+               return NULL;
+
+       for (l = app_list; l != NULL; l = l->next) {
+               hdp_app_data_t *app = l->data;
+               if (app && 0 == g_strcmp0(app->path, app_path))
+                       return app;
+       }
+
+       return NULL;
+}
+
+static hdp_conn_info_t *__hdp_find_conn_info_by_ch_path(const char *channel_path)
+{
+       GSList *l;
+       GSList *l1;
+
+       if (!channel_path)
+               return NULL;
+
+       for (l = app_list; l != NULL; l = l->next) {
+               hdp_app_data_t *app = l->data;
+               if (!app)
+                       continue;
+
+               for (l1 = app->conn_list; l1 != NULL; l1 = l1->next) {
+                       hdp_conn_info_t *info = l1->data;
+                       if (info && 0 == g_strcmp0(info->obj_path, channel_path))
+                       return info;
+               }
+       }
+
+       return NULL;
+}
+
+static hdp_conn_info_t *__hdp_find_conn_info_by_ch_id(int channel_id)
+{
+       GSList *l;
+       GSList *l1;
+
+       for (l = app_list; l != NULL; l = l->next) {
+               hdp_app_data_t *app = l->data;
+               if (!app)
+                       continue;
+
+               for (l1 = app->conn_list; l1 != NULL; l1 = l1->next) {
+                       hdp_conn_info_t *info = l1->data;
+                       if (info && info->channel_id == channel_id)
+                       return info;
+               }
+       }
+
+       return NULL;
+}
+
+static hdp_conn_info_t *__hdp_app_create_incomming_conn_info(const char *path)
+{
+       hdp_conn_info_t *conn_info = NULL;
+       hdp_app_data_t *app;
+       GDBusConnection *conn;
+       GDBusProxy *proxy;
+       GVariantIter *property_iter;
+       const char *property;
+       GVariant *value = NULL;
+       GVariant *reply;
+       GError *err = NULL;
+       char *device = NULL;
+       char *dev_path;
+       char *app_path = NULL;
+       char *type_qos = NULL;
+       gsize len;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return NULL;
+       }
+
+       /* Retrive device info */
+       proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL,
+                       BT_HAL_BLUEZ_NAME,
+                       path,
+                       BT_HAL_PROPERTIES_INTERFACE,
+                       NULL, &err);
+       if (!proxy) {
+               ERR("Unable to create proxy: %s", err->message);
+               g_clear_error(&err);
+               return NULL;
+       }
+
+       dev_path = g_strdup(BT_HAL_HDP_CHANNEL_INTERFACE);
+       reply = g_dbus_proxy_call_sync(proxy, "GetAll",
+                       g_variant_new("(s)", dev_path),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL, &err);
+       g_free(dev_path);
+       g_object_unref(proxy);
+       if (!reply) {
+               ERR(" HDP:dbus Can't get the reply");
+               if (err) {
+                       ERR("%s", err->message);;
+                       g_clear_error(&err);
+               }
+               return NULL;
+       }
+
+       g_variant_get(reply, "(a{sv})", &property_iter);
+       while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
+               DBG("String received = %s\n", property);
+               if (g_strcmp0("Type", property) == 0)
+                       type_qos = g_variant_dup_string(value, &len);
+               else if (g_strcmp0("Device", property) == 0)
+                       device = g_variant_dup_string(value, &len);
+               else if (g_strcmp0("Application", property) == 0)
+                       app_path = g_variant_dup_string(value, &len);
+       }
+
+       DBG("QOS = %s, Device = %s, Apphandler = %s", type_qos, device, app_path);
+       g_variant_iter_free(property_iter);
+       g_variant_unref(reply);
+       g_free(device);
+
+       if (!type_qos || !app_path) {
+               ERR("Pasing failed");
+               goto free;
+       }
+
+       app = __get_hdp_app_by_path(app_path);
+       if (!app) {
+               ERR("Could not find the app with path: %s", app_path);
+               goto free;
+       }
+
+       conn_info = g_new0(hdp_conn_info_t, 1);
+       conn_info->channel_id = __hdp_assign_channel_id();
+       _bt_convert_device_path_to_address(path, conn_info->address);
+       conn_info->app_id = app->id;
+       conn_info->fd = -1;
+
+       DBG("App Id: %d, remote_address: %s", app->id, conn_info->address);
+       app->conn_list = g_slist_append(app->conn_list, conn_info);
+
+free:
+       g_free(type_qos);
+       g_free(app_path);
+
+       DBG("-");
+       return conn_info;
+}
+
+static void __hdp_free_conn_info(hdp_conn_info_t *conn_info)
+{
+       DBG("+");
+
+       if (!conn_info) {
+               ERR("conn_info is NULL");
+               return;
+       }
+
+       __hdp_delete_channnel_id(conn_info->channel_id);
+       if (0 < conn_info->fd)
+               close(conn_info->fd);
+       g_free(conn_info->obj_path);
+       g_free(conn_info);
+
+       DBG("-");
+}
+
+static void __hdp_free_app_data(hdp_app_data_t *app)
+{
+       DBG("+");
+
+       g_slist_foreach(app->conn_list, (GFunc)__hdp_free_conn_info, NULL);
+       g_free(app->conn_list);
+       g_free(app->path);
+       g_free(app);
+
+       DBG("-");
+}
+
+static int __hdp_acquire_fd(const char *path)
+{
+       GDBusConnection *conn;
+       GDBusProxy *proxy;
+       GVariant *reply;
+       GUnixFDList *out_fd_list = NULL;
+       GError *err = NULL;
+       int index;
+       int fd;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return  -1;
+       }
+
+       proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL,
+                       BT_HAL_BLUEZ_NAME,
+                       path,
+                       BT_HAL_HDP_CHANNEL_INTERFACE,
+                       NULL, &err);
+       if (!proxy) {
+               ERR("Unable to create proxy: %s", err->message);
+               g_clear_error(&err);
+               return -1;
+       }
+
+       reply = g_dbus_proxy_call_with_unix_fd_list_sync(proxy,
+                       "Acquire",
+                       NULL, G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL, &out_fd_list,
+                       NULL, &err);
+       g_object_unref(proxy);
+       if (!reply) {
+               ERR(" HDP:****** dbus Can't create application ****");
+               if (err) {
+                       ERR("%s", err->message);;
+                       g_clear_error(&err);
+               }
+
+               return -1;
+       }
+
+       g_variant_get(reply, "(h)", &index);
+       fd = g_unix_fd_list_get(out_fd_list, index, NULL);
+
+       INFO("File Descriptor = %d, Dev_path = %s \n", fd, path);
+       g_variant_unref(reply);
+       g_object_unref(out_fd_list);
+
+       DBG("-");
+       return fd;
+}
+
+static void __hdp_handle_connect(GVariant *parameters)
+{
+       hdp_conn_info_t *conn_info = NULL;
+       const char *obj_channel_path;
+       int fd;
+
+       DBG("+");
+
+       g_variant_get(parameters, "(&o)", &obj_channel_path);
+       INFO("Channel connected, Path = %s", obj_channel_path);
+
+       conn_info = __hdp_find_conn_info_by_ch_path(obj_channel_path);
+
+       fd = __hdp_acquire_fd(obj_channel_path);
+       if (0 > fd) {
+               ERR("__hdp_acquire_fd failed");
+               goto err;
+       }
+
+       if (!conn_info) {
+               INFO("conn_info not found, incomming connection request");
+               /* Create hdp app connection info */
+               conn_info = __hdp_app_create_incomming_conn_info(obj_channel_path);
+               if (!conn_info) {
+                       ERR("Could not create app conn info");
+                       close(fd);
+                       return;
+               }
+       }
+
+       conn_info->fd = fd;
+       /* Send channel_connect callback with status: success */
+       __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_CONNECTED);
+
+       DBG("-");
+       return;
+err:
+       if (conn_info) {
+               hdp_app_data_t *app = __get_hdp_app_by_id(conn_info->app_id);
+
+               ERR("Outgoing connection failed for app_id:%d, send event", conn_info->app_id);
+               /* Send channel_connect callback with status: disconnected and fd = -1 */
+               __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_DISCONNECTED);
+               app->conn_list = g_slist_remove(app->conn_list, conn_info);
+               __hdp_free_conn_info(conn_info);
+       }
+}
+
+static void __hdp_handle_disconnect(GVariant *parameters,
+               const gchar *object_path)
+{
+       const char *obj_channel_path;
+       hdp_app_data_t *app;
+       hdp_conn_info_t *conn_info;
+
+       DBG("+");
+
+       g_variant_get(parameters, "(&o)", &obj_channel_path);
+       INFO("Channel Deleted, Path = %s, channel_path: %s",
+                       object_path, obj_channel_path);
+
+       conn_info = __hdp_find_conn_info_by_ch_path(obj_channel_path);
+       if (!conn_info) {
+               INFO("No conn_info found for channel path:%s", obj_channel_path);
+               return;
+       }
+
+       /* Send channel_connect callback with status: success */
+       __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_DESTROYED);
+
+       app = __get_hdp_app_by_id(conn_info->app_id);
+       app->conn_list = g_slist_remove(app->conn_list, conn_info);
+       __hdp_free_conn_info(conn_info);
+
+       DBG("-");
+}
+
+static void __hdp_handle_property_changed(GVariant *parameters)
+{
+       char *property = NULL;
+       GVariant *value = NULL;
+       char *obj_main_channel_path = NULL;
+       GVariantIter *property_iter = NULL;
+       gsize len;
+
+       DBG("+");
+
+       g_variant_get(parameters, "(a{sv})", &property_iter);
+       while (g_variant_iter_loop(property_iter, "{sv}", &property, &value)) {
+               if (g_strcmp0("MainChannel", property) == 0) {
+                       INFO("Property MainChannel received");
+                       obj_main_channel_path = g_variant_dup_string(value, &len);
+                       DBG("Main Channel  Path = %s", obj_main_channel_path);
+                       break;
+               }
+       }
+       g_variant_iter_free(property_iter);
+       g_free(property);
+       g_variant_unref(value);
+       g_free(obj_main_channel_path);
+
+       DBG("-");
+}
+
+static void __hdp_event_filter(GDBusConnection *connection,
+               const gchar *sender_name,
+               const gchar *object_path,
+               const gchar *interface_name,
+               const gchar *signal_name,
+               GVariant *parameters,
+               gpointer user_data)
+{
+       DBG("Path = %s", object_path);
+       if (object_path == NULL || g_strcmp0(object_path, "/") == 0)
+               return;
+
+       if (signal_name == NULL)
+               return;
+
+       if (strcasecmp(signal_name, "ChannelConnected") == 0)
+               __hdp_handle_connect(parameters);
+
+       else if (strcasecmp(signal_name, "ChannelDeleted") == 0)
+               __hdp_handle_disconnect(parameters, object_path);
+
+       else if (strcasecmp(signal_name, "PropertyChanged") == 0)
+               __hdp_handle_property_changed(parameters);
+
+       return;
+}
+
+static int __hdp_filter_subscribe_signal(GDBusConnection *conn,
+                               gboolean subscribe)
+{
+       static guint subs_add_filter_id = 0;
+
+       if (conn == NULL)
+               return BT_HAL_ERROR_INVALID_PARAM;
+
+       if (subscribe && subs_add_filter_id) {
+       }
+
+       if (subscribe) {
+               if (subs_add_filter_id == 0) {
+                       subs_add_filter_id = g_dbus_connection_signal_subscribe(
+                                       conn, NULL, BT_HAL_HDP_DEVICE_INTERFACE,
+                                       NULL, NULL, NULL, 0,
+                                       __hdp_event_filter, NULL, NULL);
+               } else {
+                       INFO("Signal already subscribed");
+               }
+       } else {
+               if (subs_add_filter_id > 0) {
+                       g_dbus_connection_signal_unsubscribe(conn,
+                                       subs_add_filter_id);
+                       subs_add_filter_id = 0;
+               }
+       }
+
+       return BT_HAL_ERROR_NONE;
+}
+
+static int __hdp_add_filter(void)
+{
+       static GDBusConnection *hdp_conn;
+
+       DBG("+");
+
+       hdp_conn = _bt_get_system_gconn();
+       if(!hdp_conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_HAL_ERROR_INTERNAL;
+       }
+
+       return __hdp_filter_subscribe_signal(hdp_conn, TRUE);
+
+       DBG("-");
+}
+
+static int __hdp_remove_filter(void)
+{
+       static GDBusConnection *hdp_conn;
+
+       DBG("+");
+
+       hdp_conn = _bt_get_system_gconn();
+       if(!hdp_conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_HAL_ERROR_INTERNAL;
+       }
+
+       return __hdp_filter_subscribe_signal(hdp_conn, FALSE);
+
+       DBG("-");
+}
+
+static void __hdp_send_app_reg_event(int app_id, unsigned int state)
+{
+       struct hal_ev_hdp_app_reg_state ev;
+
+       DBG("+");
+
+       /* Prepare to send HDP app registration state event */
+       memset(&ev, 0, sizeof(ev));
+       ev.app_id = app_id;
+       ev.state = state;
+       if (!event_cb)
+               ERR("HDP dbus handler callback not registered");
+       else
+               event_cb(HAL_EV_HDP_APP_REG_STATE, (void *)&ev, sizeof(ev));
+
+       DBG("-");
+}
+
+static gboolean __hdp_application_created_cb(gpointer data)
+{
+       hdp_app_data_t *app = data;
+
+       DBG("+");
+       if (!app) {
+               ERR("__hdp_application_created_cb called with null app data");
+               return FALSE;
+       }
+
+       app_list = g_slist_append(app_list, app);
+       if (BT_HAL_ERROR_NONE != __hdp_add_filter()) {
+               ERR("Funtion failed");
+               __hdp_send_app_reg_event(app->id, BTHL_APP_REG_STATE_REG_FAILED);
+               return FALSE;
+       }
+
+       __hdp_send_app_reg_event(app->id, BTHL_APP_REG_STATE_REG_SUCCESS);
+
+       DBG("-");
+       return FALSE;
+}
+
+static gboolean  __hdp_application_destroyed_cb(gpointer data)
+{
+       hdp_app_data_t *app = data;
+       int len;
+
+       DBG("+");
+       if (!app) {
+               ERR("__hdp_application_destroyed_cb called with null app data");
+               return FALSE;
+       }
+
+       app_list = g_slist_remove(app_list, app);
+
+       len = g_slist_length(app_list);
+       DBG("List length = %d\n", len);
+       if (0 == len)
+               __hdp_remove_filter();
+
+       __hdp_send_app_reg_event(app->id, BTHL_APP_REG_STATE_DEREG_SUCCESS);
+       __hdp_free_app_data(app);
+
+       DBG("-");
+       return FALSE;
+}
+
+static GDBusProxy *__get_health_device_proxy(char *address)
+{
+       GDBusConnection *conn;
+       GDBusProxy *hdp_proxy;
+       GError *err = NULL;
+       char *adapter_path;
+       char *dev_path;
+
+       DBG("+");
+
+       adapter_path = _bt_get_adapter_path();
+       if (!adapter_path) {
+               ERR("Could not get adapter path");
+               return NULL;
+       }
+
+       dev_path = g_strdup_printf("%s/dev_%s", adapter_path, address);
+       if (!dev_path) {
+               ERR("Failed to create dev_path");
+               return NULL;
+       }
+
+       g_strdelimit(dev_path, ":", '_');
+       DBG("dev_path: %s", dev_path);
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+       if(!conn) {
+               ERR("ERROR: Can't get on system bus [%s]", err->message);
+               g_clear_error(&err);
+               g_free(dev_path);
+               return NULL;
+       }
+
+       hdp_proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL, BT_HAL_BLUEZ_NAME,
+                       dev_path, BT_HAL_HDP_DEVICE_INTERFACE,
+                       NULL, NULL);
+       if (!hdp_proxy)
+               ERR("Failed to get the HDP server proxy");
+       g_object_unref(conn);
+       g_free(dev_path);
+
+       DBG("-");
+       return hdp_proxy;
+}
+
+static void __hdp_connect_request_cb(GDBusProxy *hdp_proxy,
+               GAsyncResult *res, gpointer user_data)
+{
+       GVariant *reply;
+       GError *err = NULL;
+       hdp_conn_info_t *conn_info = user_data;
+       hdp_app_data_t *app;
+       char *obj_path = NULL;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
+       g_object_unref(hdp_proxy);
+       if (!reply) {
+               if (err) {
+                       ERR("HDP connection Dbus Call Error: %s", err->message);
+                       g_clear_error(&err);
+               }
+               /* Send channel_connect callback with status: disconnected and fd = -1 */
+               __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_DISCONNECTED);
+               __hdp_free_conn_info(conn_info);
+               return;
+       }
+
+       g_variant_get(reply, "(&o)", &obj_path);
+       DBG("Obj Path returned = %s\n", obj_path);
+       conn_info->obj_path = g_strdup(obj_path);
+
+       app = __get_hdp_app_by_id(conn_info->app_id);
+       if (!app) {
+               ERR("No app with app_id: %d exists");
+               __hdp_free_conn_info(conn_info);
+               return;
+       }
+
+       app->conn_list = g_slist_append(app->conn_list, conn_info);
+       DBG("-");
+}
+
+static void __hdp_disconnect_request_cb(GDBusProxy *hdp_proxy,
+               GAsyncResult *res, gpointer user_data)
+{
+       hdp_conn_info_t *conn_info = user_data;
+       GVariant *reply;
+       GError *err = NULL;
+
+       DBG("+");
+
+       reply = g_dbus_proxy_call_finish(hdp_proxy, res, &err);
+       g_object_unref(hdp_proxy);
+       if (!reply) {
+               if (err) {
+                       ERR("HDP disconnection Dbus Call Error: %s", err->message);
+                       g_clear_error(&err);
+               }
+
+               /* Send channel_connect callback with status: connected */
+               __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_CONNECTED);
+               return;
+       }
+
+       DBG("-");
+}
+
+bt_status_t _bt_hal_dbus_handler_hdp_register_application(int role,
+               int data_type, int channel_type, const char *description, int *app_id)
+{
+       GDBusConnection *conn;
+       GDBusProxy *proxy = NULL;
+       GVariantBuilder *builder;
+       const char *key_type;
+       const char *svalue;
+       guint16 value;
+       GVariant *reply = NULL;
+       char *app_path;
+       GError *err = NULL;
+       hdp_app_data_t *app;
+
+       DBG("+");
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL,
+                       BT_HAL_BLUEZ_NAME,
+                       "/org/bluez",
+                       BT_HAL_HDP_MANAGER_INTERFACE,
+                       NULL, &err);
+       if (!proxy) {
+               ERR("Unable to create proxy: %s", err->message);
+               g_clear_error(&err);
+               return BT_STATUS_FAIL;
+       }
+
+       builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
+
+       key_type = "DataType";
+       value = (guint16)data_type;
+       g_variant_builder_add(builder, "{sv}", key_type, g_variant_new("q", value));
+
+       key_type = "Role";
+       svalue = (role == BTHL_MDEP_ROLE_SINK) ? "Sink" : "Source";
+       g_variant_builder_add(builder, "{sv}", key_type, g_variant_new("s", svalue));
+
+       key_type = "Description";
+       svalue = (description) ? description : "Health Device";
+       g_variant_builder_add(builder, "{sv}", key_type, g_variant_new("s", svalue));
+
+       if (role == BTHL_MDEP_ROLE_SOURCE) {
+               key_type = "ChannelType";
+               if (channel_type == BTHL_CHANNEL_TYPE_RELIABLE) {
+                       svalue = "reliable";
+                       DBG("%s : %s", key_type, svalue);
+               } else if (channel_type == BTHL_CHANNEL_TYPE_STREAMING) {
+                       svalue = "streaming";
+                       DBG("%s : %s", key_type, svalue);
+               } else {
+                       g_variant_builder_unref(builder);
+                       g_object_unref(proxy);
+                       return BT_STATUS_PARM_INVALID;
+               }
+
+               g_variant_builder_add(builder, "{sv}", key_type, g_variant_new("s", svalue));
+       }
+
+       reply = g_dbus_proxy_call_sync(proxy, "CreateApplication",
+                       g_variant_new("(a{sv})", builder),
+                       G_DBUS_CALL_FLAGS_NONE, -1,
+                       NULL, &err);
+       g_variant_builder_unref(builder);
+       g_object_unref(proxy);
+       if (!reply) {
+               ERR(" HDP:dbus Can't create application");
+               if (err) {
+                       ERR("%s", err->message);
+                       g_clear_error(&err);
+               }
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_get(reply, "(&o)", &app_path);
+       DBG("Created health application: %s", (char *)app_path);
+
+       app = g_new0(hdp_app_data_t, 1);
+       app->path = g_strdup(app_path);
+       sscanf(app_path, "/org/bluez/health_app_%d", &(app->id));
+       app->channel_type = channel_type;
+       g_variant_unref(reply);
+
+       *app_id = app->id;
+       DBG("App Id: %d", *app_id);
+
+       g_idle_add(__hdp_application_created_cb, (gpointer)app);
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_hdp_unregister_application(int app_id)
+{
+       GDBusConnection *conn;
+       GDBusProxy *proxy = NULL;
+       GVariant *reply = NULL;
+       GError *err = NULL;
+       hdp_app_data_t *app;
+
+       DBG("+");
+
+       DBG("app_id: %d", app_id);
+       app = __get_hdp_app_by_id(app_id);
+       if (!app) {
+               ERR("No app with app_id: %d exists");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
+                       NULL,
+                       BT_HAL_BLUEZ_NAME,
+                       "/org/bluez",
+                       BT_HAL_HDP_MANAGER_INTERFACE,
+                       NULL, &err);
+       if (!proxy) {
+               if (err) {
+                       ERR("Unable to create proxy: %s", err->message);
+                       g_clear_error(&err);
+               } else {
+                       ERR("Unable to create proxy");
+               }
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("app->path: %s", app->path);
+       reply = g_dbus_proxy_call_sync(proxy, "DestroyApplication",
+                       g_variant_new("(o)", app->path),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1, NULL, &err);
+       g_object_unref(proxy);
+       if (!reply) {
+               ERR(" HDP:dbus Can't Destroy application");
+               if (err) {
+                       ERR("%s", err->message);
+                       g_clear_error(&err);
+               }
+               return BT_STATUS_FAIL;
+       }
+
+       g_variant_unref(reply);
+       DBG("Destroyed health application: %s", (char *)app->path);
+       g_idle_add(__hdp_application_destroyed_cb, (gpointer)app);
+       DBG("-");
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_hdp_connect_channel(int app_id, bt_bdaddr_t *bd_addr, int *channel_id)
+{
+       GDBusProxy *hdp_proxy;
+       hdp_app_data_t *app;
+       hdp_conn_info_t *conn_info;
+       char *ch_type;
+       char address[BT_HAL_ADDRESS_STRING_SIZE];
+
+       DBG("+");
+
+       if (!bd_addr) {
+               ERR("Address is NULL");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       if (!channel_id) {
+               ERR("channel_id is NULL");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       app = __get_hdp_app_by_id(app_id);
+       if (!app) {
+               ERR("No app with app_id: %d exists", app_id);
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       if (BTHL_CHANNEL_TYPE_RELIABLE == app->channel_type)
+               ch_type = "Reliable";
+       else if (BTHL_CHANNEL_TYPE_STREAMING == app->channel_type)
+               ch_type = "Streaming";
+       else
+               ch_type = "Any";
+
+       DBG("create conection to %s, channel_type: %s", address, ch_type);
+
+       hdp_proxy = __get_health_device_proxy(address);
+       if (!hdp_proxy) {
+               ERR("Failed to get the health device proxy");
+               return BT_STATUS_FAIL;
+       }
+
+       DBG("app path %s", app->path);
+
+       *channel_id = __hdp_assign_channel_id();
+       conn_info = g_new0(hdp_conn_info_t, 1);
+       conn_info->app_id = app->id;
+       g_strlcpy(conn_info->address, address, BT_HAL_ADDRESS_STRING_SIZE);
+       conn_info->channel_id = *channel_id;
+       conn_info->fd = -1;
+
+       g_dbus_proxy_call(hdp_proxy, "CreateChannel",
+                       g_variant_new("(os)", app->path, ch_type),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+                       (GAsyncReadyCallback)__hdp_connect_request_cb,
+                       conn_info);
+
+       /* Send channel_connect callback with status: connecting and fd = -1 */
+       __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_CONNECTING);
+       DBG("-");
+
+       return BT_STATUS_SUCCESS;
+}
+
+bt_status_t _bt_hal_dbus_handler_hdp_destroy_channel(int channel_id)
+{
+       GDBusProxy *hdp_proxy;
+       hdp_conn_info_t *conn_info;
+
+       DBG("+");
+
+       conn_info = __hdp_find_conn_info_by_ch_id(channel_id);
+       if (!conn_info) {
+               ERR("No conn found with channel_id: %d", channel_id);
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       DBG("Destroy channel with channel_id: %d, remote_addr: %s", channel_id, conn_info->address);
+
+       hdp_proxy = __get_health_device_proxy(conn_info->address);
+       if (!hdp_proxy) {
+               ERR("Failed to get the health device proxy");
+               return BT_STATUS_FAIL;
+       }
+
+       g_dbus_proxy_call(hdp_proxy, "DestroyChannel",
+                       g_variant_new("(o)", conn_info->obj_path),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL,
+                       (GAsyncReadyCallback)__hdp_disconnect_request_cb,
+                       conn_info);
+
+       /* Send channel_connect callback with status: connecting and fd = -1 */
+       __hdp_send_conn_event(conn_info, BTHL_CONN_STATE_DISCONNECTING);
+
+       DBG("-");
+       return BT_STATUS_SUCCESS;
+}
+
+/* To send stack event to hal-hidhost handler */
+void _bt_hal_register_hdp_dbus_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+/* To send stack event to hal-hidhost handler */
+void _bt_hal_unregister_hdp_dbus_handler_cb()
+{
+       event_cb = NULL;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-hdp-dbus-handler.h
new file mode 100644 (file)
index 0000000..d3b2666
--- /dev/null
@@ -0,0 +1,49 @@
+/* Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#ifndef _BT_HAL_HDP_DBUS_HANDLER_H_
+#define _BT_HAL_HDP_DBUS_HANDLER_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#include "bt-hal-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_hal_register_hdp_dbus_handler_cb(handle_stack_msg cb);
+void _bt_hal_unregister_hdp_dbus_handler_cb();
+bt_status_t _bt_hal_dbus_handler_hdp_register_application(int role,
+       int data_type, int channel_type, const char *description, int *app_id);
+bt_status_t _bt_hal_dbus_handler_hdp_unregister_application(int app_id);
+bt_status_t _bt_hal_dbus_handler_hdp_connect_channel(int app_id, bt_bdaddr_t *bd_addr, int *channel_id);
+bt_status_t _bt_hal_dbus_handler_hdp_destroy_channel(int channel_id);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_HAL_HDP_DBUS_HANDLER_H_ */
diff --git a/bt-oal/bluez_hal/src/bt-hal-hdp.c b/bt-oal/bluez_hal/src/bt-hal-hdp.c
new file mode 100644 (file)
index 0000000..67ad646
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+
+#include "bt-hal-event-receiver.h"
+#include "bt-hal-hdp-dbus-handler.h"
+
+static const bthl_callbacks_t *bt_hal_hdp_cbacks;
+
+static bool interface_ready(void)
+{
+       return bt_hal_hdp_cbacks != NULL;
+}
+
+static void __bt_hal_handle_app_reg_state(void *buf, uint16_t len)
+{
+       struct hal_ev_hdp_app_reg_state *ev = buf;
+
+       DBG("+");
+
+       if (!ev) {
+               ERR("Event data is NULL, return");
+               return;
+       }
+
+       if (bt_hal_hdp_cbacks->app_reg_state_cb)
+               bt_hal_hdp_cbacks->app_reg_state_cb(ev->app_id, ev->state);
+
+       DBG("-");
+}
+
+static void __bt_hal_handle_hdp_conn_state(void *buf, uint16_t len)
+{
+       struct hal_ev_hdp_conn_state *ev = buf;
+
+       DBG("+");
+
+       if (!ev) {
+               ERR("Event data is NULL, return");
+               return;
+       }
+
+       if (bt_hal_hdp_cbacks->channel_state_cb)
+               bt_hal_hdp_cbacks->channel_state_cb(ev->app_id, (bt_bdaddr_t *)(ev->bdaddr),
+                       ev->mdep_index, ev->channel_id, ev->channel_state, ev->data_fd);
+
+       DBG("-");
+}
+
+static void __bt_hal_handle_hdp_events(int message, void *buf, uint16_t len)
+{
+       DBG("+");
+
+       if (!interface_ready())
+               return;
+
+       switch(message) {
+       case HAL_EV_HDP_APP_REG_STATE:
+               DBG("Event: HAL_EV_HDP_APP_REG_STATE");
+               __bt_hal_handle_app_reg_state(buf, len);
+               break;
+       case HAL_EV_HDP_CONN_STATE:
+               DBG("Event: HAL_EV_HDP_CONN_STATE");
+               __bt_hal_handle_hdp_conn_state(buf, len);
+               break;
+       default:
+               DBG("Event Currently not handled!!");
+               break;
+       }
+
+       DBG("-");
+}
+
+/** Register HL application */
+static bt_status_t hdp_register_application(bthl_reg_param_t *p_reg_param, int *app_id)
+{
+       int ret = BT_STATUS_SUCCESS;
+       int role;
+       int data_type;
+       int channel_type;
+       const char *desc;
+
+       if (!p_reg_param)
+               return BT_STATUS_PARM_INVALID;
+
+       if (!p_reg_param->application_name)
+               return BT_STATUS_PARM_INVALID;
+
+       if (!app_id)
+               return BT_STATUS_PARM_INVALID;
+
+       /* Currently only 1 dep config is supported per app id */
+       if (0 > p_reg_param->number_of_mdeps || 1 < p_reg_param->number_of_mdeps) {
+               ERR("Currently only 1 dep config is supported per app");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       role = p_reg_param->mdep_cfg[0].mdep_role;
+       data_type = p_reg_param->mdep_cfg[0].data_type;
+       channel_type = p_reg_param->mdep_cfg[0].channel_type;
+       desc = p_reg_param->mdep_cfg[0].mdep_description;
+
+       ret = _bt_hal_dbus_handler_hdp_register_application(
+                       role, data_type, channel_type, desc, app_id);
+       if (BT_STATUS_SUCCESS != ret) {
+               ERR("_bt_hal_dbus_handler_hdp_register_application failed");
+               *app_id = -1;
+       } else {
+               DBG("app_id: %d", *app_id);
+       }
+
+       return ret;
+}
+
+/** Unregister HL application */
+static bt_status_t hdp_unregister_application(int app_id)
+{
+       int ret;
+
+       DBG("+");
+
+       ret = _bt_hal_dbus_handler_hdp_unregister_application(app_id);
+       if (BT_STATUS_SUCCESS != ret)
+               ERR("_bt_hal_dbus_handler_hdp_unregister_application failed");
+       DBG("-");
+
+       return ret;
+}
+
+/** connect channel */
+static bt_status_t hdp_connect_channel(int app_id, bt_bdaddr_t *bd_addr, int mdep_cfg_index, int *channel_id)
+{
+       int ret;
+
+       DBG("+");
+
+       *channel_id = -1;
+       ret = _bt_hal_dbus_handler_hdp_connect_channel(app_id, bd_addr, channel_id);
+       if (BT_STATUS_SUCCESS != ret)
+               ERR("_bt_hal_dbus_handler_hdp_unregister_application failed");
+
+       DBG("-");
+       return ret;
+}
+
+/** destroy channel */
+static bt_status_t hdp_destroy_channel(int channel_id)
+{
+       int ret;
+
+       DBG("+");
+
+       ret = _bt_hal_dbus_handler_hdp_destroy_channel(channel_id);
+       if (BT_STATUS_SUCCESS != ret)
+               ERR("_bt_hal_dbus_handler_hdp_unregister_application failed");
+
+       DBG("-");
+       return ret;
+}
+
+static bt_status_t init(bthl_callbacks_t *callbacks)
+{
+       DBG("");
+
+       if (interface_ready())
+               return BT_STATUS_DONE;
+
+       bt_hal_hdp_cbacks = callbacks;
+       DBG("Register HDP events callback function");
+       _bt_hal_register_hdp_dbus_handler_cb(__bt_hal_handle_hdp_events);
+
+       return BT_STATUS_SUCCESS;
+}
+
+static void cleanup(void)
+{
+       DBG("");
+
+       if (!interface_ready())
+               return;
+
+       DBG("Un-register HDP events callback function");
+       _bt_hal_unregister_hdp_dbus_handler_cb();
+
+       bt_hal_hdp_cbacks = NULL;
+}
+
+static bthl_interface_t hl_if = {
+       .size = sizeof(hl_if),
+       .init = init,
+       .register_application = hdp_register_application,
+       .unregister_application = hdp_unregister_application,
+       .connect_channel = hdp_connect_channel,
+       .destroy_channel = hdp_destroy_channel,
+       .cleanup = cleanup
+};
+
+bthl_interface_t *bt_get_hl_interface(void)
+{
+       return &hl_if;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-hdp.h b/bt-oal/bluez_hal/src/bt-hal-hdp.h
new file mode 100644 (file)
index 0000000..10c80d4
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_HAL_HDP_H__
+#define __BT_HAL_HDP_H__
+
+#include <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+bthl_interface_t *bt_get_hl_interface(void);
+
+#endif //__BT_HAL_HDP_H__