--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}