From 26eaaf1a3367d5af783ceb964dd6e0aa45583ea5 Mon Sep 17 00:00:00 2001 From: Atul Rai Date: Fri, 14 Oct 2016 14:24:02 +0530 Subject: [PATCH] [Adapt:OAL]Implement Health Device Profile in OAL This patch adds OAL implementation for Health Device Profile. Change-Id: I44ea867eb5a0824d5eb01da86ae5218238b30c53 Signed-off-by: Atul Rai --- bt-oal/CMakeLists.txt | 1 + bt-oal/include/oal-event.h | 20 +++ bt-oal/include/oal-hdp.h | 140 ++++++++++++++++++ bt-oal/oal-hdp.c | 355 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 516 insertions(+) create mode 100755 bt-oal/include/oal-hdp.h create mode 100755 bt-oal/oal-hdp.c diff --git a/bt-oal/CMakeLists.txt b/bt-oal/CMakeLists.txt index 49515ed..0d8ff75 100755 --- a/bt-oal/CMakeLists.txt +++ b/bt-oal/CMakeLists.txt @@ -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 diff --git a/bt-oal/include/oal-event.h b/bt-oal/include/oal-event.h index 2d363ce..9c39300 100755 --- a/bt-oal/include/oal-event.h +++ b/bt-oal/include/oal-event.h @@ -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 index 0000000..0ca025b --- /dev/null +++ b/bt-oal/include/oal-hdp.h @@ -0,0 +1,140 @@ +/* + * Open Adaptation Layer (OAL) + * + * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd. + * + * Contact: Atul Kumar Rai + * + * 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 +#include + +#include + +#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 index 0000000..c615429 --- /dev/null +++ b/bt-oal/oal-hdp.c @@ -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 +#include +#include + +#include +#include + +#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; +} -- 2.7.4