[Adapt:OAL]Implement Health Device Profile in OAL 02/93102/1
authorAtul Rai <a.rai@samsung.com>
Fri, 14 Oct 2016 08:54:02 +0000 (14:24 +0530)
committerAtul Rai <a.rai@samsung.com>
Fri, 14 Oct 2016 08:54:02 +0000 (14:24 +0530)
This patch adds OAL implementation for Health Device Profile.

Change-Id: I44ea867eb5a0824d5eb01da86ae5218238b30c53
Signed-off-by: Atul Rai <a.rai@samsung.com>
bt-oal/CMakeLists.txt
bt-oal/include/oal-event.h
bt-oal/include/oal-hdp.h [new file with mode: 0755]
bt-oal/oal-hdp.c [new file with mode: 0755]

index 49515ed..0d8ff75 100755 (executable)
@@ -18,6 +18,7 @@ oal-hid-host.c
 oal-socket.c
 oal-audio-src.c
 oal-hfp.c
+oal-hdp.c
 common/oal-utils.c
 common/oal-common.c
 common/oal-event-dispatcher.c
index 2d363ce..9c39300 100755 (executable)
@@ -86,6 +86,10 @@ extern "C" {
        EVENT(OAL_EVENT_HFP_AUDIO_CONNECTING)                /* bt_address_t*/ \
        EVENT(OAL_EVENT_HFP_AUDIO_CONNECTED)                /* bt_address_t*/ \
        EVENT(OAL_EVENT_HFP_AUDIO_DISCONNECTING)                /* bt_address_t*/ \
+       EVENT(OAL_EVENT_HDP_APP_REGISTERED)                     /* HDP APP registered */ \
+       EVENT(OAL_EVENT_HDP_APP_UNREGISTERED)                   /* HDP APP un-registered */ \
+       EVENT(OAL_EVENT_HDP_CHANNEL_CONNECTED)                  /* HDP channel connected */ \
+       EVENT(OAL_EVENT_HDP_CHANNEL_DESTROYED)                  /* HDP channel destroyed */ \
        EVENT(OAL_EVENT_END)                                /* End of event*/\
 
 
@@ -182,6 +186,22 @@ typedef struct {
        bt_address_t address;   /**< Address of remote server */
 } event_socket_client_conn_t;
 
+/*********Datastructures for HDP callback******************/
+/* HDP: App registration event data */
+typedef struct {
+       int app_id;
+       oal_status_t status;
+} event_hdp_app_reg_t;
+
+/* HDP: Channel connection event data */
+typedef struct {
+       int fd;
+       int app_id;
+       int channel_id;
+       int ch_type;
+       bt_address_t address;
+} event_hdp_channel_conn_t;
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/bt-oal/include/oal-hdp.h b/bt-oal/include/oal-hdp.h
new file mode 100755 (executable)
index 0000000..0ca025b
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Open Adaptation Layer (OAL)
+ *
+ * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 _OAL_HDP_H_
+#define _OAL_HDP_H_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include <oal-manager.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       OAL_HDP_ROLE_SOURCE,
+       OAL_HDP_ROLE_SINK
+} oal_hdp_role_t;
+
+typedef enum {
+       OAL_CHANNEL_TYPE_RELIABLE,
+       OAL_CHANNEL_TYPE_STREAMING,
+       OAL_CHANNEL_TYPE_ANY
+} oal_channel_type_t;
+
+/**
+ * @brief Initialize Health Device Profile
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre OAL API must be initialized with oal_bt_init().
+ *
+ * @see  hdp_cleanup()
+ */
+oal_status_t hdp_init(void);
+
+
+/**
+ * @brief Cleanup Health Device Profile
+ *
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ *
+ * @pre HDP should be initialized with hdp_init().
+ *
+ * @see  hdp_init()
+ */
+oal_status_t hdp_cleanup(void);
+
+/**
+ * @brief Register HDP application
+ *
+ * @details  Result will be notified through an OAL event
+ *
+ * @param[in] role: HDP application role (SOURCE/SINK)
+ * @param[in] channel_type: HDP application channel type (RELIABLE/STREAMMING/ANY)
+ * @param[in] name: Application name
+ * @param[in] data_type: Data type supported by HDP application
+ * @return Registered application app_id >= 0 on success, otherwise a negative value.
+ * @remark None
+ *
+ * @pre HDP should be initialized with hdp_init().
+ *
+ * @see  OAL_EVENT_HDP_APP_REGISTERED
+ */
+int hdp_register_application(oal_hdp_role_t role,
+       oal_channel_type_t channel_type, const char *name, int data_type);
+
+/**
+ * @brief Un-register HDP application
+ *
+ * @details  Result will be notified through an OAL event
+ *
+ * @param[in] app_id: HDP application id to be unregistered
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ * @remark None
+ *
+ * @pre HDP should be initialized with hdp_init().
+ *
+ * @see  OAL_EVENT_HDP_APP_UNREGISTERED
+ */
+oal_status_t hdp_unregister_application(int app_id);
+
+/**
+ * @brief Connec HDP channel
+ *
+ * @details  Result will be notified through an OAL event
+ *
+ * @pre HDP should be initialized with hdp_init().
+ *
+ * @param[in]   app_id HDP application id for which channel to be connected
+ * @param[in]   addresss Remote HDP device address
+ * @return Connected channel_id on success, otherwise a negative value.
+ * @remark None
+ *
+ * @see  OAL_EVENT_HDP_CHANNEL_CONNECTED
+ */
+int hdp_connect_channel(int app_id, bt_address_t *address);
+
+/**
+ * @brief Disconnect hdp channel
+ *
+ * @details  Result will be notified through an OAL event
+ *
+ * @pre HDP should be initialized with hdp_init().
+ *
+ * @param[in]   channel_id HDP channel id to be disconnected
+ * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value.
+ * @retval #OAL_STATUS_SUCCESS Successful
+ * @remark      None
+ *
+ * @see  OAL_EVENT_HDP_CHANNEL_DESTROYED
+ */
+oal_status_t hdp_disconnect_channel(int channel_id);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _OAL_HDP_H_ */
diff --git a/bt-oal/oal-hdp.c b/bt-oal/oal-hdp.c
new file mode 100755 (executable)
index 0000000..c615429
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Open Adaptation Layer (OAL)
+ *
+ * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlog.h>
+#include <string.h>
+
+#include <bluetooth.h>
+#include <bt_hl.h>
+
+#include "oal-event.h"
+#include "oal-internal.h"
+#include "oal-common.h"
+#include "oal-manager.h"
+#include "oal-utils.h"
+#include "oal-hdp.h"
+
+#define CHECK_OAL_HDP_ENABLED() \
+       do { \
+               if (hdp_api == NULL) { \
+                       BT_ERR("HDP Not Enabled"); \
+                       return -1; \
+               } \
+       } while (0)
+
+typedef struct {
+       int app_id;
+       int role;
+       int data_type;
+       int channel_type;
+} oal_hdp_app_data_t;
+
+static void hdp_app_reg_state_cb(int app_id, bthl_app_reg_state_t state);
+static void hdp_channel_state_cb(int app_id, bt_bdaddr_t *bd_addr,
+               int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd);
+
+static bthl_callbacks_t sBluetoothHdpCallbacks = {
+       sizeof(sBluetoothHdpCallbacks),
+       hdp_app_reg_state_cb,
+       hdp_channel_state_cb,
+};
+
+static const bthl_interface_t *hdp_api;
+static GSList *app_list;
+
+static oal_hdp_app_data_t *__get_hdp_app_data(int app_id)
+{
+       GSList *l;
+
+       for (l = app_list; l != NULL; l = g_slist_next(l)) {
+               oal_hdp_app_data_t *app = l->data;
+
+               if (app && (app->app_id == app_id))
+                       return app;
+       }
+
+       return NULL;
+}
+
+static void __free_hdp_app_data(int app_id)
+{
+       oal_hdp_app_data_t *app = __get_hdp_app_data(app_id);
+
+       if (!app) {
+               BT_ERR("No app found with id: %d", app_id);
+               return;
+       }
+
+       app_list = g_slist_remove(app_list, app);
+       g_free(app);
+}
+
+static void hdp_app_reg_state_cb(int app_id, bthl_app_reg_state_t state)
+{
+       event_hdp_app_reg_t *event_data = g_new0(event_hdp_app_reg_t, 1);
+       oal_event_t event;
+
+       BT_DBG("app_id: %d, state: %d", app_id, state);
+
+       switch (state) {
+       case BTHL_APP_REG_STATE_REG_SUCCESS:
+               event = OAL_EVENT_HDP_APP_REGISTERED;
+               event_data->status = OAL_STATUS_SUCCESS;
+               break;
+       case BTHL_APP_REG_STATE_REG_FAILED:
+               event = OAL_EVENT_HDP_APP_REGISTERED;
+               event_data->status = OAL_STATUS_INTERNAL_ERROR;
+               __free_hdp_app_data(app_id);
+               break;
+       case BTHL_APP_REG_STATE_DEREG_SUCCESS:
+               event = OAL_EVENT_HDP_APP_UNREGISTERED;
+               event_data->status = OAL_STATUS_SUCCESS;
+               __free_hdp_app_data(app_id);
+               break;
+       case BTHL_APP_REG_STATE_DEREG_FAILED:
+               event = OAL_EVENT_HDP_APP_UNREGISTERED;
+               event_data->status = OAL_STATUS_INTERNAL_ERROR;
+               break;
+       default:
+               BT_ERR("Unknown state:%d received", state);
+               return;
+       }
+
+       event_data->app_id = app_id;
+       send_event(event, event_data, sizeof(event_hdp_app_reg_t));
+}
+
+static void hdp_channel_state_cb(int app_id, bt_bdaddr_t *bd_addr,
+               int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd)
+{
+       event_hdp_channel_conn_t *event_data;
+       oal_event_t event;
+       oal_hdp_app_data_t *app;
+
+       BT_DBG("app_id: %d, channel_id:%d, state:%d, fd:%d", app_id, channel_id, state, fd);
+
+       app = __get_hdp_app_data(app_id);
+       if (!app) {
+               BT_ERR("No app found with app_id: %d", app_id);
+               return;
+       }
+
+       switch (state) {
+       case BTHL_CONN_STATE_CONNECTING:
+               BT_DBG("BTHL_CONN_STATE_CONNECTING");
+               return;
+       case BTHL_CONN_STATE_DISCONNECTING:
+               BT_DBG("BTHL_CONN_STATE_DISCONNECTING");
+               return;
+       case BTHL_CONN_STATE_CONNECTED:
+               BT_DBG("BTHL_CONN_STATE_CONNECTED");
+               event = OAL_EVENT_HDP_CHANNEL_CONNECTED;
+               break;
+       case BTHL_CONN_STATE_DISCONNECTED:
+               BT_DBG("BTHL_CONN_STATE_DISCONNECTED");
+               event = OAL_EVENT_HDP_CHANNEL_DESTROYED;
+               break;
+       case BTHL_CONN_STATE_DESTROYED:
+               BT_DBG("BTHL_CONN_STATE_DESTROYED");
+               event = OAL_EVENT_HDP_CHANNEL_DESTROYED;
+               break;
+       default:
+               BT_ERR("Unknown stat: %d", state);
+               return;
+       }
+
+       event_data = g_new0(event_hdp_channel_conn_t, 1);
+       event_data->fd = fd;
+       event_data->app_id = app_id;
+       event_data->channel_id = channel_id;
+       event_data->ch_type = app->channel_type;
+       memcpy(event_data->address.addr, bd_addr->address, BT_ADDRESS_BYTES_NUM);
+
+       send_event_bda_trace(event, event_data,
+               sizeof(event_hdp_channel_conn_t), (bt_address_t*)bd_addr);
+}
+
+oal_status_t hdp_init(void)
+{
+       const bt_interface_t *blued_api;
+       int ret;
+
+       API_TRACE();
+
+       if(hdp_api != NULL){
+               BT_WARN("HID Interface is already initialized...");
+               return OAL_STATUS_ALREADY_DONE;
+       }
+
+       blued_api = adapter_get_stack_interface();
+       if(blued_api == NULL) {
+               BT_ERR("Stack is not initialized");
+               return OAL_STATUS_NOT_READY;
+       }
+
+       hdp_api = (const bthl_interface_t *)blued_api->get_profile_interface(BT_PROFILE_HEALTH_ID);
+       if(hdp_api == NULL) {
+               BT_ERR("HDP interface failed");
+               return OAL_STATUS_INTERNAL_ERROR;
+       }
+
+       if((ret = hdp_api->init(&sBluetoothHdpCallbacks)) != BT_STATUS_SUCCESS) {
+               BT_ERR("HDP Init failed: %s", status2string(ret));
+               hdp_api->cleanup();
+               hdp_api = NULL;
+               return convert_to_oal_status(ret);
+       }
+
+       return OAL_STATUS_SUCCESS;
+}
+
+oal_status_t hdp_cleanup(void)
+{
+       GSList *l = app_list;
+
+       API_TRACE();
+
+       CHECK_OAL_HDP_ENABLED();
+
+       BT_DBG("+");
+
+       hdp_api->cleanup();
+       hdp_api = NULL;
+
+       for (l = app_list; NULL != l;) {
+               oal_hdp_app_data_t *app = l->data;
+               l = l->next;
+               if (app)
+                       __free_hdp_app_data(app->app_id);
+       }
+
+       if (app_list)
+               g_free(app_list);
+
+       BT_DBG("-");
+       return OAL_STATUS_SUCCESS;
+}
+
+int hdp_register_application(oal_hdp_role_t role,
+               oal_channel_type_t channel_type, const char *name, int data_type)
+{
+       int ret;
+       int app_id = -1;
+       bthl_mdep_role_t mdep_role;
+       bthl_channel_type_t ch_type;
+       bthl_reg_param_t *reg_param;
+       oal_hdp_app_data_t *app_data;
+
+       API_TRACE();
+
+       CHECK_OAL_HDP_ENABLED();
+
+       switch (role) {
+       case OAL_HDP_ROLE_SOURCE:
+               mdep_role = BTHL_MDEP_ROLE_SOURCE;
+               break;
+       case OAL_HDP_ROLE_SINK:
+               mdep_role = BTHL_MDEP_ROLE_SINK;
+               break;
+       default:
+               BT_ERR("Unknown role:%d", role);
+               return -1;
+       }
+
+       switch (channel_type) {
+       case OAL_CHANNEL_TYPE_RELIABLE:
+               ch_type = BTHL_CHANNEL_TYPE_RELIABLE;
+               break;
+       case OAL_CHANNEL_TYPE_STREAMING:
+               ch_type = BTHL_CHANNEL_TYPE_STREAMING;
+               break;
+       case OAL_CHANNEL_TYPE_ANY:
+               ch_type = BTHL_CHANNEL_TYPE_ANY;
+               break;
+       default:
+               BT_ERR("Unknown channel_type:%d", channel_type);
+               return -1;
+       }
+
+       reg_param = g_new0(bthl_reg_param_t, 1);
+       reg_param->application_name = name;
+       reg_param->number_of_mdeps = 1;
+       reg_param->mdep_cfg = g_new0(bthl_mdep_cfg_t, 1);
+       reg_param->mdep_cfg->mdep_role = mdep_role;
+       reg_param->mdep_cfg->data_type = data_type;
+       reg_param->mdep_cfg->channel_type = ch_type;
+
+       ret = hdp_api->register_application(reg_param, &app_id);
+       g_free(reg_param->mdep_cfg);
+       g_free(reg_param);
+
+       if(ret != BT_STATUS_SUCCESS || 0 > app_id) {
+               BT_ERR("HDP register_application failed: %s", status2string(ret));
+               return -1;
+       }
+
+       app_data = g_new0(oal_hdp_app_data_t, 1);
+       app_data->app_id = app_id;
+       app_data->role = role;
+       app_data->data_type = data_type;
+       app_data->channel_type = channel_type;
+
+       app_list = g_slist_append(app_list, app_data);
+
+       return app_id;
+}
+
+oal_status_t hdp_unregister_application(int app_id)
+{
+       int ret;
+
+       API_TRACE();
+
+       CHECK_OAL_HDP_ENABLED();
+
+       ret = hdp_api->unregister_application(app_id);
+       if(ret != BT_STATUS_SUCCESS) {
+               BT_ERR("HDP unregister_application failed: %s", status2string(ret));
+               return convert_to_oal_status(ret);
+       }
+
+       return OAL_STATUS_SUCCESS;
+}
+
+int hdp_connect_channel(int app_id, bt_address_t *address)
+{
+       int channel_id = -1;
+       int mdep_index = 0;
+       int ret;
+
+       API_TRACE();
+
+       CHECK_OAL_HDP_ENABLED();
+
+       ret = hdp_api->connect_channel(app_id, (bt_bdaddr_t*)address, mdep_index, &channel_id);
+       if (BT_STATUS_SUCCESS != ret || 0 > channel_id) {
+               BT_ERR("HDP connect_channel failed: %s", status2string(ret));
+               return -1;
+       }
+
+       return channel_id;
+}
+
+oal_status_t hdp_disconnect_channel(int channel_id)
+{
+       int ret;
+
+       API_TRACE();
+
+       CHECK_OAL_HDP_ENABLED();
+
+       ret = hdp_api->destroy_channel(channel_id);
+       if (BT_STATUS_SUCCESS != ret) {
+               BT_ERR("HDP destroy_channel failed: %s", status2string(ret));
+               return convert_to_oal_status(ret);
+       }
+
+       return OAL_STATUS_SUCCESS;
+}