From 492d0bd778071736cdf4caeb4a7ad77aeb1d8786 Mon Sep 17 00:00:00 2001 From: Amit Purwar Date: Wed, 16 Oct 2019 11:39:50 +0530 Subject: [PATCH] Adapt HF Profile Connect & Disconnect to BT HAL framework Change-Id: I1c59ff115e7048b168fe7540514c5a7a3c815fc4 Signed-off-by: Amit Purwar --- bt-oal/CMakeLists.txt | 1 + bt-oal/bluez_hal/CMakeLists.txt | 2 + bt-oal/bluez_hal/inc/bt-hal-msg.h | 12 + bt-oal/bluez_hal/inc/bt-hal.h | 1 + bt-oal/bluez_hal/src/bt-hal-bluetooth.c | 4 + bt-oal/bluez_hal/src/bt-hal-event-receiver.c | 50 ++- bt-oal/bluez_hal/src/bt-hal-event-receiver.h | 1 + .../bluez_hal/src/bt-hal-hf-client-dbus-handler.c | 208 ++++++++++++ .../bluez_hal/src/bt-hal-hf-client-dbus-handler.h | 48 +++ bt-oal/bluez_hal/src/bt-hal-hf-client.c | 230 +++++++++++++ bt-oal/bluez_hal/src/bt-hal-hf-client.h | 32 ++ bt-oal/bluez_hal/src/bt-hal-internal.h | 1 + bt-oal/hardware/bt_hf_client.h | 363 +++++++++++++++++++++ bt-oal/include/oal-event.h | 4 + bt-oal/include/oal-hf-client.h | 92 ++++++ bt-oal/oal-hf-client.c | 212 ++++++++++++ bt-service-adaptation/CMakeLists.txt | 1 + .../services/adapter/bt-service-core-adapter.c | 5 + .../services/audio/bt-service-audio.c | 37 ++- .../services/audio/hf/bt-service-hf-client.c | 183 +++++++++++ .../services/bt-request-handler.c | 40 +++ .../services/bt-service-event-receiver.c | 12 + .../services/include/bt-service-audio-common.h | 7 +- .../services/include/bt-service-hf-client.h | 42 +++ 24 files changed, 1583 insertions(+), 5 deletions(-) create mode 100644 bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.c create mode 100644 bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.h create mode 100644 bt-oal/bluez_hal/src/bt-hal-hf-client.c create mode 100644 bt-oal/bluez_hal/src/bt-hal-hf-client.h create mode 100644 bt-oal/hardware/bt_hf_client.h create mode 100644 bt-oal/include/oal-hf-client.h create mode 100644 bt-oal/oal-hf-client.c create mode 100644 bt-service-adaptation/services/audio/hf/bt-service-hf-client.c create mode 100644 bt-service-adaptation/services/include/bt-service-hf-client.h diff --git a/bt-oal/CMakeLists.txt b/bt-oal/CMakeLists.txt index a864ae8..f8dbf7a 100755 --- a/bt-oal/CMakeLists.txt +++ b/bt-oal/CMakeLists.txt @@ -25,6 +25,7 @@ oal-avrcp-ctrl.c oal-hfp.c oal-hdp.c oal-gatt.c +oal-hf-client.c common/oal-utils.c common/oal-common.c common/oal-event-dispatcher.c diff --git a/bt-oal/bluez_hal/CMakeLists.txt b/bt-oal/bluez_hal/CMakeLists.txt index d099a2a..d0216c9 100644 --- a/bt-oal/bluez_hal/CMakeLists.txt +++ b/bt-oal/bluez_hal/CMakeLists.txt @@ -31,6 +31,8 @@ SET(SRCS ./src/bt-hal-gatt.c ./src/bt-hal-gatt-server.c ./src/bt-hal-gatt-client.c +./src/bt-hal-hf-client.c +./src/bt-hal-hf-client-dbus-handler.c ) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/bt-oal/bluez_hal/inc/bt-hal-msg.h b/bt-oal/bluez_hal/inc/bt-hal-msg.h index d9d249d..7c5b316 100644 --- a/bt-oal/bluez_hal/inc/bt-hal-msg.h +++ b/bt-oal/bluez_hal/inc/bt-hal-msg.h @@ -767,4 +767,16 @@ struct hal_ev_gatt_server_mtu_changed { int32_t mtu; } __attribute__((packed)); +/* HF Client Headers */ +#define HAL_EV_HF_CLIENT_CONN_STATE_DISCONNECTED 0x00 +#define HAL_EV_HF_CLIENT_CONN_STATE_CONNECTING 0x01 +#define HAL_EV_HF_CLIENT_CONN_STATE_CONNECTED 0x02 +#define HAL_EV_HF_CLIENT_CONN_STATE_SLC_CONNECTED 0x03 +#define HAL_EV_HF_CLIENT_CONN_STATE_DISCONNECTING 0x04 + +#define HAL_EV_HF_CLIENT_CONN_STATE 0xCD +struct hal_ev_hf_client_conn_state { + uint8_t state; + uint8_t bdaddr[6]; +} __attribute__((packed)); #endif //_BT_HAL_MSG_H_ diff --git a/bt-oal/bluez_hal/inc/bt-hal.h b/bt-oal/bluez_hal/inc/bt-hal.h index 948729c..38c55f9 100644 --- a/bt-oal/bluez_hal/inc/bt-hal.h +++ b/bt-oal/bluez_hal/inc/bt-hal.h @@ -29,6 +29,7 @@ #include #include #include +#include /*TODO: Profile interfaces headers and exposed methods of Android HAL framework to be included in next patches */ #endif //_BT_HAL_H diff --git a/bt-oal/bluez_hal/src/bt-hal-bluetooth.c b/bt-oal/bluez_hal/src/bt-hal-bluetooth.c index 547a613..2783924 100644 --- a/bt-oal/bluez_hal/src/bt-hal-bluetooth.c +++ b/bt-oal/bluez_hal/src/bt-hal-bluetooth.c @@ -45,6 +45,7 @@ #include #include #endif +#include #define enum_prop_to_hal(prop, hal_prop, type) do { \ static type e; \ @@ -266,6 +267,9 @@ static const void *get_profile_interface(const char *profile_id) if (!strcmp(profile_id, BT_PROFILE_HANDSFREE_ID)) return bt_get_hf_interface(); + if (!strcmp(profile_id, BT_PROFILE_HANDSFREE_CLIENT_ID)) + return bt_get_hf_client_interface(); + if (!strcmp(profile_id, BT_PROFILE_GATT_ID)) return bt_get_gatt_interface(); diff --git a/bt-oal/bluez_hal/src/bt-hal-event-receiver.c b/bt-oal/bluez_hal/src/bt-hal-event-receiver.c index 38c838d..2f78578 100644 --- a/bt-oal/bluez_hal/src/bt-hal-event-receiver.c +++ b/bt-oal/bluez_hal/src/bt-hal-event-receiver.c @@ -55,6 +55,7 @@ static handle_stack_msg hid_event_cb = NULL; static handle_stack_msg av_event_cb = NULL; static handle_stack_msg a2dp_sink_event_cb = NULL; static handle_stack_msg hf_event_cb = NULL; +static handle_stack_msg hf_client_event_cb = NULL; static handle_stack_msg avrcp_ctrl_event_cb = NULL; static handle_stack_msg avrcp_tg_event_cb = NULL; static handle_stack_msg gatt_event_cb = NULL; @@ -112,6 +113,7 @@ static void __bt_hal_send_hf_connection_state_event(gboolean connected, const ch static void __bt_hal_send_device_trusted_profile_changed_event(uint32_t trust_val, const char *address); static void __bt_hal_handle_adv_report(GVariant *msg, const char *path); static void __bt_hal_handle_gatts_mtu_changed_event(char *address, int mtu); +static void __bt_hal_send_hf_client_connection_state_event(gboolean connected, const char *address); static gboolean __bt_hal_discovery_finished_cb(gpointer user_data) @@ -501,8 +503,7 @@ static void __bt_hal_flight_ps_mode_cb(keynode_t *node, void *data) if (flight_mode != TRUE) { ERR("Ignore the event"); return; - } - else { + } else { ERR("Flight Mode == TRUE"); } } else { @@ -2057,7 +2058,7 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me } else if (state == BT_HAL_PROFILE_STATE_CONNECTING) { DBG("A2DP Sink Profile state changed: BT_HAL_PROFILE_STATE_CONNECTING"); } - } else if (strncmp(profile_uuid, HFP_HF_UUID, strlen(HFP_HF_UUID)) == 0) { + } else if (strcmp(profile_uuid, HFP_HF_UUID) == 0) { if (state == BT_HAL_PROFILE_STATE_CONNECTING) DBG("HFP Profile state changed: BT_PROFILE_STATE_CONNECTING"); else if (state == BT_HAL_PROFILE_STATE_CONNECTED) { @@ -2071,6 +2072,20 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me } else { ERR("HFP Profile state: Invalid"); } + } else if (strncmp(profile_uuid, HFP_AG_UUID, strlen(HFP_AG_UUID)) == 0) { + if (state == BT_HAL_PROFILE_STATE_CONNECTING) + DBG("HFP Client Profile state changed: BT_PROFILE_STATE_CONNECTING"); + else if (state == BT_HAL_PROFILE_STATE_CONNECTED) { + DBG("HFP Client Profile state changed: BT_PROFILE_STATE_CONNECTED"); + __bt_hal_send_hf_client_connection_state_event(TRUE, address); + } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTED) { + DBG("HFP Client Profile state changed: BT_PROFILE_STATE_DISCONNECTED"); + __bt_hal_send_hf_client_connection_state_event(FALSE, address); + } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTING) { + DBG("HFP Client Profile state changed: BT_PROFILE_STATE_DISCONNECTING"); + } else { + ERR("HFP Client Profile state: Invalid"); + } } else if ((strncmp(profile_uuid, AVRCP_TARGET_UUID, strlen(AVRCP_TARGET_UUID)) == 0)) { if (state == BT_HAL_PROFILE_STATE_CONNECTED) { DBG("AVRCP Controller Profile state changed: BT_HAL_PROFILE_STATE_CONNECTED"); @@ -2585,6 +2600,29 @@ static void __bt_hal_send_hf_connection_state_event(gboolean connected, hf_event_cb(HAL_EV_HANDSFREE_CONN_STATE, &ev, sizeof(ev)); } +/* HF(Client Role) Profile Events */ +static void __bt_hal_send_hf_client_connection_state_event(gboolean connected, + const char *address) +{ + struct hal_ev_hf_client_conn_state ev; + + if (connected == TRUE) + INFO("HF Client Profile Connected for address [%s]", address); + else + INFO("HF Client Profile DisConnected for address [%s]", address); + + ev.state = (connected == TRUE) ? + HAL_EV_HF_CLIENT_CONN_STATE_CONNECTED : + HAL_EV_HF_CLIENT_CONN_STATE_DISCONNECTED; + + _bt_hal_convert_addr_string_to_type(ev.bdaddr, address); + + if (!hf_client_event_cb) + ERR("HF Client event handler not registered"); + else + hf_client_event_cb(HAL_EV_HF_CLIENT_CONN_STATE, &ev, sizeof(ev)); +} + void _bt_hal_register_event_handler_cb(bt_hal_module_e module, handle_stack_msg cb) { switch (module) { @@ -2600,6 +2638,9 @@ void _bt_hal_register_event_handler_cb(bt_hal_module_e module, handle_stack_msg case HAL_HF_AG: hf_event_cb = cb; break; + case HAL_HF_CLIENT: + hf_client_event_cb = cb; + break; case HAL_AVRCP_TG: avrcp_tg_event_cb = cb; break; @@ -2629,6 +2670,9 @@ void _bt_hal_unregister_event_handler_cb(bt_hal_module_e module) case HAL_HF_AG: hf_event_cb = NULL; break; + case HAL_HF_CLIENT: + hf_client_event_cb = NULL; + break; case HAL_AVRCP_TG: avrcp_tg_event_cb = NULL; break; diff --git a/bt-oal/bluez_hal/src/bt-hal-event-receiver.h b/bt-oal/bluez_hal/src/bt-hal-event-receiver.h index 29ce3b3..2996266 100644 --- a/bt-oal/bluez_hal/src/bt-hal-event-receiver.h +++ b/bt-oal/bluez_hal/src/bt-hal-event-receiver.h @@ -45,6 +45,7 @@ typedef enum { HAL_A2DP_SRC, HAL_A2DP_SNK, HAL_HF_AG, + HAL_HF_CLIENT, HAL_AVRCP_TG, HAL_AVRCP_CTRL, HAL_GATT, diff --git a/bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.c new file mode 100644 index 0000000..84d954b --- /dev/null +++ b/bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.c @@ -0,0 +1,208 @@ +/* + * BLUETOOTH HAL + * + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 +#include +#include + +#include "bt-hal-hf-dbus-handler.h" +#include "bt-hal-dbus-common-utils.h" +#include "bt-hal-internal.h" + +static handle_stack_msg event_cb = NULL; + +/* To send stack event to hal-hf handler */ +void _bt_hal_register_hf_client_dbus_handler_cb(handle_stack_msg cb) +{ + event_cb = cb; +} + +/* To send stack event to hal-hf handler */ +void _bt_hal_unregister_hf_client_dbus_handler_cb() +{ + event_cb = NULL; +} + +static void __bt_hf_client_connect_cb(GDBusProxy *proxy, GAsyncResult *res, + gpointer user_data) +{ + GError *g_error = NULL; + struct hal_ev_hf_client_conn_state ev; + GVariant *reply = NULL; + char *address = user_data; + int result = BT_STATUS_SUCCESS; + + DBG("+"); + + reply = g_dbus_proxy_call_finish(proxy, res, &g_error); + g_object_unref(proxy); + if (reply == NULL) { + ERR("HF Client Connect Dbus Call Error"); + if (g_error) { + ERR("Error: %s", g_error->message); + g_clear_error(&g_error); + } + result = BT_STATUS_FAIL; + } + g_variant_unref(reply); + + DBG("Address: %s", address); + /* + * If result is success, HF client connected event will be triggered + * automatically from stack, so return from here. + */ + if (result == BT_STATUS_SUCCESS) { + /* Prepare to send HF client connecting event */ + memset(&ev, 0, sizeof(ev)); + _bt_hal_convert_addr_string_to_type(ev.bdaddr, address); + ev.state = HAL_EV_HF_CLIENT_CONN_STATE_CONNECTING; + if (!event_cb) + ERR("HF client dbus handler callback not registered"); + else + event_cb(HAL_EV_HF_CLIENT_CONN_STATE, (void *)&ev, sizeof(ev)); + + } else { + /* Prepare to send HF client connection state event */ + ERR("HF client Connection has failed!!"); + memset(&ev, 0, sizeof(ev)); + _bt_hal_convert_addr_string_to_type(ev.bdaddr, address); + ev.state = HAL_EV_HF_CLIENT_CONN_STATE_DISCONNECTED; + if (!event_cb) + ERR("HF client DBUS handler callback not registered"); + else + event_cb(HAL_EV_HF_CLIENT_CONN_STATE, (void *)&ev, sizeof(ev)); + } + g_free(address); +} + +bt_status_t _bt_hal_dbus_handler_hf_client_connect(bt_bdaddr_t *bd_addr) +{ + char *address; + int ret; + + if (!bd_addr) { + ERR("bd_addr is NULL, return"); + return BT_STATUS_PARM_INVALID; + } + + address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char)); + if (!address) { + ERR("Memory allocation failed"); + return BT_STATUS_NOMEM; + } + _bt_hal_convert_addr_type_to_string(address, bd_addr->address); + + DBG("Connect profile :HFP_AG_UUID"); + ret = _bt_hal_connect_profile(address, HFP_AG_UUID, + __bt_hf_client_connect_cb, address); + + if (ret != BT_HAL_ERROR_NONE) { + ERR("_bt_hal_connect_profile(HF) Error"); + g_free(address); + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} + +static void __bt_hf_client_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res, + gpointer user_data) +{ + GError *g_error = NULL; + struct hal_ev_hf_client_conn_state ev; + GVariant *reply = NULL; + char *address = user_data; + int result = BT_STATUS_SUCCESS; + + DBG("+"); + + reply = g_dbus_proxy_call_finish(proxy, res, &g_error); + g_object_unref(proxy); + if (reply == NULL) { + ERR("HF Client Disconnect Dbus Call Error"); + if (g_error) { + ERR("Error: %s\n", g_error->message); + g_clear_error(&g_error); + } + result = BT_STATUS_FAIL; + } + g_variant_unref(reply); + + if (result == BT_STATUS_SUCCESS) { + DBG("HF Client Disconnect successful for Device: %s", address); + /* Prepare to send HF Client Disconnecting event */ + memset(&ev, 0, sizeof(ev)); + _bt_hal_convert_addr_string_to_type(ev.bdaddr, address); + ev.state = HAL_EV_HF_CLIENT_CONN_STATE_DISCONNECTING; + if (!event_cb) + ERR("HF Client dbus handler callback not registered"); + else + event_cb(HAL_EV_HF_CLIENT_CONN_STATE, (void *)&ev, sizeof(ev)); + + } else { + /* Prepare to send HF Client Disconnection state event */ + ERR("HF Client Disconnect failed for Device: %s", address); + memset(&ev, 0, sizeof(ev)); + _bt_hal_convert_addr_string_to_type(ev.bdaddr, address); + ev.state = HAL_EV_HF_CLIENT_CONN_STATE_DISCONNECTED; + if (!event_cb) + ERR("HF Client DBUS handler callback not registered"); + else + event_cb(HAL_EV_HF_CLIENT_CONN_STATE, (void *)&ev, sizeof(ev)); + } + g_free(address); + DBG("-"); +} + +bt_status_t _bt_hal_dbus_handler_hf_client_disconnect(bt_bdaddr_t *bd_addr) +{ + char *address; + int ret; + + if (!bd_addr) { + ERR("bd_addr is NULL, return"); + return BT_STATUS_PARM_INVALID; + } + + address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char)); + if (!address) { + ERR("Memory allocation failed"); + return BT_STATUS_NOMEM; + } + _bt_hal_convert_addr_type_to_string(address, bd_addr->address); + + DBG("Disconnect profile :HFP_AG_UUID"); + + ret = _bt_hal_disconnect_profile(address, HFP_AG_UUID, + __bt_hf_client_disconnect_cb, address); + + if (ret != BT_HAL_ERROR_NONE) { + ERR("_bt_hal_connect_profile Error"); + g_free(address); + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} diff --git a/bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.h new file mode 100644 index 0000000..7c7d11a --- /dev/null +++ b/bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.h @@ -0,0 +1,48 @@ +/* + * BLUETOOTH HAL + * + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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_HF_CLIENT_DBUS_HANDLER_H_ +#define _BT_HAL_HF_CLIENT_DBUS_HANDLER_H_ + +#include +#include + +#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_hf_client_dbus_handler_cb(handle_stack_msg cb); + +void _bt_hal_unregister_hf_client_dbus_handler_cb(); + +bt_status_t _bt_hal_dbus_handler_hf_client_connect(bt_bdaddr_t *bd_addr); + +bt_status_t _bt_hal_dbus_handler_hf_client_disconnect(bt_bdaddr_t *bd_addr); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _BT_HAL_HF_CLIENT_DBUS_HANDLER_H_*/ diff --git a/bt-oal/bluez_hal/src/bt-hal-hf-client.c b/bt-oal/bluez_hal/src/bt-hal-hf-client.c new file mode 100644 index 0000000..8467d2a --- /dev/null +++ b/bt-oal/bluez_hal/src/bt-hal-hf-client.c @@ -0,0 +1,230 @@ +/* + * BLUETOOTH HAL + * + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 "bt-hal.h" +#include "bt-hal-log.h" +#include "bt-hal-msg.h" +#include "bt-hal-utils.h" + +#include "bt-hal-hf-client-dbus-handler.h" +#include "bt-hal-event-receiver.h" +#include "bt-hal-hf-client.h" + +static bthf_client_callbacks_t *bt_hal_hf_client_cbacks; + +static bool interface_ready(void) +{ + return bt_hal_hf_client_cbacks != NULL; +} + +static bt_status_t bt_hal_hf_client_connect(bt_bdaddr_t *bd_addr) +{ + DBG(""); + return _bt_hal_dbus_handler_hf_client_connect(bd_addr); +} + +static bt_status_t bt_hal_hf_client_disconnect(bt_bdaddr_t *bd_addr) +{ + DBG(""); + return _bt_hal_dbus_handler_hf_client_disconnect(bd_addr); +} + +static bt_status_t bt_hal_hf_client_connect_audio(bt_bdaddr_t *bd_addr) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_disconnect_audio(bt_bdaddr_t *bd_addr) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_start_voice_recognition(void) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_stop_voice_recognition(void) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_volume_control(bthf_client_volume_type_t type, int volume) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_dial(const char *number) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_dial_memory(int location) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_handle_call_action(bthf_client_call_action_t action, int idx) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_query_current_calls(void) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_query_current_operator_name(void) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_retrieve_subscriber_info(void) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_send_dtmf(char code) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_request_last_voice_tag_number(void) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_send_at_cmd(int cmd, int val1, int val2, const char *arg) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static bt_status_t bt_hal_hf_client_send_voice_data(unsigned char *p_buf, unsigned char len) +{ + DBG(""); + return BT_STATUS_UNSUPPORTED; +} + +static void __bt_hal_handle_hf_client_conn_state(void *buf, uint16_t len) +{ + struct hal_ev_hf_client_conn_state *ev = buf; + unsigned int peer_feat = 0; + unsigned int chld_feat = 0; + + if (bt_hal_hf_client_cbacks->connection_state_cb) + bt_hal_hf_client_cbacks->connection_state_cb(ev->state, + peer_feat, chld_feat, (bt_bdaddr_t *) ev->bdaddr); +} + +static void __bt_hal_handle_hf_client_events(int message, void *buf, uint16_t len) +{ + DBG("+"); + if (!interface_ready()) + return; + switch (message) { + case HAL_EV_HF_CLIENT_CONN_STATE: + DBG("Event: HAL_EV_HF_CLIENT_CONN_STATE"); + __bt_hal_handle_hf_client_conn_state(buf, len); + break; + default: + DBG("Event Currently not handled!!"); + break; + } + DBG("-"); +} + +static bt_status_t bt_hal_hf_init(bthf_client_callbacks_t* callbacks) +{ + DBG(""); + + if (interface_ready()) + return BT_STATUS_DONE; + + bt_hal_hf_client_cbacks = callbacks; + DBG("Register HF Client Role callback function"); + _bt_hal_register_hf_client_dbus_handler_cb(__bt_hal_handle_hf_client_events); + _bt_hal_register_event_handler_cb(HAL_HF_CLIENT, __bt_hal_handle_hf_client_events); + return BT_STATUS_SUCCESS; +} + +static void bt_hal_hf_cleanup(void) +{ + if (!interface_ready()) + return; + + _bt_hal_unregister_event_handler_cb(HAL_HF_AG); + bt_hal_hf_client_cbacks = NULL; +} + +static bthf_client_interface_t bthf_client_if = { + .size = sizeof(bthf_client_if), + .init = bt_hal_hf_init, + .connect = bt_hal_hf_client_connect, + .disconnect = bt_hal_hf_client_disconnect, + .connect_audio = bt_hal_hf_client_connect_audio, + .disconnect_audio = bt_hal_hf_client_disconnect_audio, + .start_voice_recognition = bt_hal_hf_client_start_voice_recognition, + .stop_voice_recognition = bt_hal_hf_client_stop_voice_recognition, + .volume_control = bt_hal_hf_client_volume_control, + .dial = bt_hal_hf_client_dial, + .dial_memory = bt_hal_hf_client_dial_memory, + .handle_call_action = bt_hal_hf_client_handle_call_action, + .query_current_calls = bt_hal_hf_client_query_current_calls, + .query_current_operator_name = bt_hal_hf_client_query_current_operator_name, + .retrieve_subscriber_info = bt_hal_hf_client_retrieve_subscriber_info, + .send_dtmf = bt_hal_hf_client_send_dtmf, + .request_last_voice_tag_number = bt_hal_hf_client_request_last_voice_tag_number, + .cleanup = bt_hal_hf_cleanup, + .send_at_cmd = bt_hal_hf_client_send_at_cmd, + .send_voice_data = bt_hal_hf_client_send_voice_data, +}; + +/******************************************************************************* +** +** Function bt_get_hf_client_interface +** +** Description Get the hf client callback interface +** +** Returns bthf_client_interface_t +** +*******************************************************************************/ +bthf_client_interface_t *bt_get_hf_client_interface() +{ + return &bthf_client_if; +} diff --git a/bt-oal/bluez_hal/src/bt-hal-hf-client.h b/bt-oal/bluez_hal/src/bt-hal-hf-client.h new file mode 100644 index 0000000..e8d5b28 --- /dev/null +++ b/bt-oal/bluez_hal/src/bt-hal-hf-client.h @@ -0,0 +1,32 @@ +/* + * BLUETOOTH HAL + * + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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_HF_CLIENT_H__ +#define __BT_HAL_HF_CLIENT_H__ + +#include +#include +#include +#include +#include + +bthf_client_interface_t *bt_get_hf_client_interface(void); + +#endif //__BT_HAL_HF_CLIENT_H__ + diff --git a/bt-oal/bluez_hal/src/bt-hal-internal.h b/bt-oal/bluez_hal/src/bt-hal-internal.h index 80c6fc9..5746e60 100644 --- a/bt-oal/bluez_hal/src/bt-hal-internal.h +++ b/bt-oal/bluez_hal/src/bt-hal-internal.h @@ -70,6 +70,7 @@ typedef enum { #define AVRCP_CTRL_UUID "0000110e-0000-1000-8000-00805f9b34fb" #define AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb" #define HFP_HF_UUID "0000111e-0000-1000-8000-00805f9b34fb" +#define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb" /* TODO More declarations to be added in subsequent patches */ #ifdef __cplusplus diff --git a/bt-oal/hardware/bt_hf_client.h b/bt-oal/hardware/bt_hf_client.h new file mode 100644 index 0000000..fdce093 --- /dev/null +++ b/bt-oal/hardware/bt_hf_client.h @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution + * 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_HF_CLIENT_H +#define ANDROID_INCLUDE_BT_HF_CLIENT_H + +__BEGIN_DECLS + +typedef enum { + BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED = 0, + BTHF_CLIENT_CONNECTION_STATE_CONNECTING, + BTHF_CLIENT_CONNECTION_STATE_CONNECTED, + BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED, + BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING +} bthf_client_connection_state_t; + +typedef enum { + BTHF_CLIENT_AUDIO_STATE_DISCONNECTED = 0, + BTHF_CLIENT_AUDIO_STATE_CONNECTING, + BTHF_CLIENT_AUDIO_STATE_CONNECTED, + BTHF_CLIENT_AUDIO_STATE_CONNECTED_MSBC, +} bthf_client_audio_state_t; + +typedef enum { + BTHF_CLIENT_VR_STATE_STOPPED = 0, + BTHF_CLIENT_VR_STATE_STARTED +} bthf_client_vr_state_t; + +typedef enum { + BTHF_CLIENT_VOLUME_TYPE_SPK = 0, + BTHF_CLIENT_VOLUME_TYPE_MIC +} bthf_client_volume_type_t; + +typedef enum { + BTHF_CLIENT_NETWORK_STATE_NOT_AVAILABLE = 0, + BTHF_CLIENT_NETWORK_STATE_AVAILABLE +} bthf_client_network_state_t; + +typedef enum { + BTHF_CLIENT_SERVICE_TYPE_HOME = 0, + BTHF_CLIENT_SERVICE_TYPE_ROAMING +} bthf_client_service_type_t; + +typedef enum { + BTHF_CLIENT_CALL_STATE_ACTIVE = 0, + BTHF_CLIENT_CALL_STATE_HELD, + BTHF_CLIENT_CALL_STATE_DIALING, + BTHF_CLIENT_CALL_STATE_ALERTING, + BTHF_CLIENT_CALL_STATE_INCOMING, + BTHF_CLIENT_CALL_STATE_WAITING, + BTHF_CLIENT_CALL_STATE_HELD_BY_RESP_HOLD, +} bthf_client_call_state_t; + +typedef enum { + BTHF_CLIENT_CALL_NO_CALLS_IN_PROGRESS = 0, + BTHF_CLIENT_CALL_CALLS_IN_PROGRESS +} bthf_client_call_t; + +typedef enum { + BTHF_CLIENT_CALLSETUP_NONE = 0, + BTHF_CLIENT_CALLSETUP_INCOMING, + BTHF_CLIENT_CALLSETUP_OUTGOING, + BTHF_CLIENT_CALLSETUP_ALERTING + +} bthf_client_callsetup_t; + +typedef enum { + BTHF_CLIENT_CALLHELD_NONE = 0, + BTHF_CLIENT_CALLHELD_HOLD_AND_ACTIVE, + BTHF_CLIENT_CALLHELD_HOLD, +} bthf_client_callheld_t; + +typedef enum { + BTHF_CLIENT_RESP_AND_HOLD_HELD = 0, + BTRH_CLIENT_RESP_AND_HOLD_ACCEPT, + BTRH_CLIENT_RESP_AND_HOLD_REJECT, +} bthf_client_resp_and_hold_t; + +typedef enum { + BTHF_CLIENT_CALL_DIRECTION_OUTGOING = 0, + BTHF_CLIENT_CALL_DIRECTION_INCOMING +} bthf_client_call_direction_t; + +typedef enum { + BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE = 0, + BTHF_CLIENT_CALL_MPTY_TYPE_MULTI +} bthf_client_call_mpty_type_t; + +typedef enum { + BTHF_CLIENT_CMD_COMPLETE_OK = 0, + BTHF_CLIENT_CMD_COMPLETE_ERROR, + BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_CARRIER, + BTHF_CLIENT_CMD_COMPLETE_ERROR_BUSY, + BTHF_CLIENT_CMD_COMPLETE_ERROR_NO_ANSWER, + BTHF_CLIENT_CMD_COMPLETE_ERROR_DELAYED, + BTHF_CLIENT_CMD_COMPLETE_ERROR_BLACKLISTED, + BTHF_CLIENT_CMD_COMPLETE_ERROR_CME +} bthf_client_cmd_complete_t; + +typedef enum { + BTHF_CLIENT_CALL_ACTION_CHLD_0 = 0, + BTHF_CLIENT_CALL_ACTION_CHLD_1, + BTHF_CLIENT_CALL_ACTION_CHLD_2, + BTHF_CLIENT_CALL_ACTION_CHLD_3, + BTHF_CLIENT_CALL_ACTION_CHLD_4, + BTHF_CLIENT_CALL_ACTION_CHLD_1x, + BTHF_CLIENT_CALL_ACTION_CHLD_2x, + BTHF_CLIENT_CALL_ACTION_ATA, + BTHF_CLIENT_CALL_ACTION_CHUP, + BTHF_CLIENT_CALL_ACTION_BTRH_0, + BTHF_CLIENT_CALL_ACTION_BTRH_1, + BTHF_CLIENT_CALL_ACTION_BTRH_2, +} bthf_client_call_action_t; + +typedef enum { + BTHF_CLIENT_SERVICE_UNKNOWN = 0, + BTHF_CLIENT_SERVICE_VOICE, + BTHF_CLIENT_SERVICE_FAX +} bthf_client_subscriber_service_type_t; + +typedef enum { + BTHF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED = 0, + BTHF_CLIENT_IN_BAND_RINGTONE_PROVIDED, +} bthf_client_in_band_ring_state_t; + +/* Peer features masks */ +#define BTHF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */ +#define BTHF_CLIENT_PEER_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */ +#define BTHF_CLIENT_PEER_FEAT_VREC 0x00000004 /* Voice recognition */ +#define BTHF_CLIENT_PEER_FEAT_INBAND 0x00000008 /* In-band ring tone */ +#define BTHF_CLIENT_PEER_FEAT_VTAG 0x00000010 /* Attach a phone number to a voice tag */ +#define BTHF_CLIENT_PEER_FEAT_REJECT 0x00000020 /* Ability to reject incoming call */ +#define BTHF_CLIENT_PEER_FEAT_ECS 0x00000040 /* Enhanced Call Status */ +#define BTHF_CLIENT_PEER_FEAT_ECC 0x00000080 /* Enhanced Call Control */ +#define BTHF_CLIENT_PEER_FEAT_EXTERR 0x00000100 /* Extended error codes */ +#define BTHF_CLIENT_PEER_FEAT_CODEC 0x00000200 /* Codec Negotiation */ + +/* Peer call handling features masks */ +#define BTHF_CLIENT_CHLD_FEAT_REL 0x00000001 /* 0 Release waiting call or held calls */ +#define BTHF_CLIENT_CHLD_FEAT_REL_ACC 0x00000002 /* 1 Release active calls and accept other (waiting or held) cal */ +#define BTHF_CLIENT_CHLD_FEAT_REL_X 0x00000004 /* 1x Release specified active call only */ +#define BTHF_CLIENT_CHLD_FEAT_HOLD_ACC 0x00000008 /* 2 Active calls on hold and accept other (waiting or held) call */ +#define BTHF_CLIENT_CHLD_FEAT_PRIV_X 0x00000010 /* 2x Request private mode with specified call (put the rest on hold) */ +#define BTHF_CLIENT_CHLD_FEAT_MERGE 0x00000020 /* 3 Add held call to multiparty */ +#define BTHF_CLIENT_CHLD_FEAT_MERGE_DETACH 0x00000040 /* 4 Connect two calls and leave (disconnect from) multiparty */ + +/** Callback for connection state change. + * state will have one of the values from BtHfConnectionState + * peer/chld_features are valid only for BTHF_CLIENT_CONNECTION_STATE_SLC_CONNECTED state + */ +typedef void (*bthf_client_connection_state_callback)(bthf_client_connection_state_t state, unsigned int peer_feat, unsigned int chld_feat, bt_bdaddr_t *bd_addr); + +/** Callback for audio connection state change. + * state will have one of the values from BtHfAudioState + */ +typedef void (*bthf_client_audio_state_callback)(bthf_client_audio_state_t state, bt_bdaddr_t *bd_addr); + +/** Callback for VR connection state change. + * state will have one of the values from BtHfVRState + */ +typedef void (*bthf_client_vr_cmd_callback)(bthf_client_vr_state_t state); + +/** Callback for network state change + */ +typedef void (*bthf_client_network_state_callback) (bthf_client_network_state_t state); + +/** Callback for network roaming status change + */ +typedef void (*bthf_client_network_roaming_callback) (bthf_client_service_type_t type); + +/** Callback for signal strength indication + */ +typedef void (*bthf_client_network_signal_callback) (int signal_strength); + +/** Callback for battery level indication + */ +typedef void (*bthf_client_battery_level_callback) (int battery_level); + +/** Callback for current operator name + */ +typedef void (*bthf_client_current_operator_callback) (const char *name); + +/** Callback for call indicator + */ +typedef void (*bthf_client_call_callback) (bthf_client_call_t call); + +/** Callback for callsetup indicator + */ +typedef void (*bthf_client_callsetup_callback) (bthf_client_callsetup_t callsetup); + +/** Callback for callheld indicator + */ +typedef void (*bthf_client_callheld_callback) (bthf_client_callheld_t callheld); + +/** Callback for response and hold + */ +typedef void (*bthf_client_resp_and_hold_callback) (bthf_client_resp_and_hold_t resp_and_hold); + +/** Callback for Calling Line Identification notification + * Will be called only when there is an incoming call and number is provided. + */ +typedef void (*bthf_client_clip_callback) (const char *number); + +/** + * Callback for Call Waiting notification + */ +typedef void (*bthf_client_call_waiting_callback) (const char *number); + +/** + * Callback for listing current calls. Can be called multiple time. + * If number is unknown NULL is passed. + */ +typedef void (*bthf_client_current_calls) (int index, bthf_client_call_direction_t dir, + bthf_client_call_state_t state, + bthf_client_call_mpty_type_t mpty, + const char *number); + +/** Callback for audio volume change + */ +typedef void (*bthf_client_volume_change_callback) (bthf_client_volume_type_t type, int volume); + +/** Callback for command complete event + * cme is valid only for BTHF_CLIENT_CMD_COMPLETE_ERROR_CME type + */ +typedef void (*bthf_client_cmd_complete_callback) (bthf_client_cmd_complete_t type, int cme); + +/** Callback for subscriber information + */ +typedef void (*bthf_client_subscriber_info_callback) (const char *name, bthf_client_subscriber_service_type_t type); + +/** Callback for in-band ring tone settings + */ +typedef void (*bthf_client_in_band_ring_tone_callback) (bthf_client_in_band_ring_state_t state); + +/** + * Callback for requested number from AG + */ +typedef void (*bthf_client_last_voice_tag_number_callback) (const char *number); + +/** + * Callback for sending ring indication to app + */ +typedef void (*bthf_client_ring_indication_callback) (void); + +/** + * Callback for sending voice data to app + */ +typedef void (*bthf_client_get_voice_data_callback) (uint8_t *p_buf, uint8_t len); + +/** BT-HF callback structure. */ +typedef struct { + /** set to sizeof(BtHfClientCallbacks) */ + size_t size; + bthf_client_connection_state_callback connection_state_cb; + bthf_client_audio_state_callback audio_state_cb; + bthf_client_vr_cmd_callback vr_cmd_cb; + bthf_client_network_state_callback network_state_cb; + bthf_client_network_roaming_callback network_roaming_cb; + bthf_client_network_signal_callback network_signal_cb; + bthf_client_battery_level_callback battery_level_cb; + bthf_client_current_operator_callback current_operator_cb; + bthf_client_call_callback call_cb; + bthf_client_callsetup_callback callsetup_cb; + bthf_client_callheld_callback callheld_cb; + bthf_client_resp_and_hold_callback resp_and_hold_cb; + bthf_client_clip_callback clip_cb; + bthf_client_call_waiting_callback call_waiting_cb; + bthf_client_current_calls current_calls_cb; + bthf_client_volume_change_callback volume_change_cb; + bthf_client_cmd_complete_callback cmd_complete_cb; + bthf_client_subscriber_info_callback subscriber_info_cb; + bthf_client_in_band_ring_tone_callback in_band_ring_tone_cb; + bthf_client_last_voice_tag_number_callback last_voice_tag_number_callback; + bthf_client_ring_indication_callback ring_indication_cb; + bthf_client_get_voice_data_callback get_voice_data_cb; +} bthf_client_callbacks_t; + +/** Represents the standard BT-HF interface. */ +typedef struct { + + /** set to sizeof(BtHfClientInterface) */ + size_t size; + /** + * Register the BtHf callbacks + */ + bt_status_t (*init)(bthf_client_callbacks_t* callbacks); + + /** connect to audio gateway */ + bt_status_t (*connect)(bt_bdaddr_t *bd_addr); + + /** disconnect from audio gateway */ + bt_status_t (*disconnect)(bt_bdaddr_t *bd_addr); + + /** create an audio connection */ + bt_status_t (*connect_audio)(bt_bdaddr_t *bd_addr); + + /** close the audio connection */ + bt_status_t (*disconnect_audio)(bt_bdaddr_t *bd_addr); + + /** start voice recognition */ + bt_status_t (*start_voice_recognition)(void); + + /** stop voice recognition */ + bt_status_t (*stop_voice_recognition)(void); + + /** volume control */ + bt_status_t (*volume_control) (bthf_client_volume_type_t type, int volume); + + /** place a call with number a number + * if number is NULL last called number is called (aka re-dial)*/ + bt_status_t (*dial) (const char *number); + + /** place a call with number specified by location (speed dial) */ + bt_status_t (*dial_memory) (int location); + + /** perform specified call related action + * idx is limited only for enhanced call control related action + */ + bt_status_t (*handle_call_action) (bthf_client_call_action_t action, int idx); + + /** query list of current calls */ + bt_status_t (*query_current_calls) (void); + + /** query name of current selected operator */ + bt_status_t (*query_current_operator_name) (void); + + /** Retrieve subscriber information */ + bt_status_t (*retrieve_subscriber_info) (void); + + /** Send DTMF code*/ + bt_status_t (*send_dtmf) (char code); + + /** Request a phone number from AG corresponding to last voice tag recorded */ + bt_status_t (*request_last_voice_tag_number) (void); + + /** Closes the interface. */ + void (*cleanup)(void); + + /** Send AT Command. */ + bt_status_t (*send_at_cmd) (int cmd, int val1, int val2, const char *arg); + + /** send sco packet over HCI */ + bt_status_t (*send_voice_data)(unsigned char *p_buf, unsigned char len); +} bthf_client_interface_t; + +__END_DECLS + +#endif /* ANDROID_INCLUDE_BT_HF_CLIENT_H */ diff --git a/bt-oal/include/oal-event.h b/bt-oal/include/oal-event.h index 96d6f38..b095a8c 100644 --- a/bt-oal/include/oal-event.h +++ b/bt-oal/include/oal-event.h @@ -98,6 +98,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_HF_CLIENT_DISCONNECTED) /* bt_address_t*/ \ + EVENT(OAL_EVENT_HF_CLIENT_CONNECTING) /* bt_address_t*/ \ + EVENT(OAL_EVENT_HF_CLIENT_CONNECTED) /* bt_address_t*/ \ + EVENT(OAL_EVENT_HF_CLIENT_DISCONNECTING) /* bt_address_t*/ \ EVENT(OAL_EVENT_AVRCP_CONNECTED) /* AVRCP Target connected */ \ EVENT(OAL_EVENT_AVRCP_DISCONNECTED) /* AVRCP Target disconnected */ \ EVENT(OAL_EVENT_AVRCP_REMOTE_FEATURES) /* AVRCP FATURE INFO*/ \ diff --git a/bt-oal/include/oal-hf-client.h b/bt-oal/include/oal-hf-client.h new file mode 100644 index 0000000..33edbc9 --- /dev/null +++ b/bt-oal/include/oal-hf-client.h @@ -0,0 +1,92 @@ +/* + * Open Adaptation Layer (OAL) + * + * Copyright (c) 2019 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. + * + */ + + +#ifndef _OAL_HF_CLIENT_H_ +#define _OAL_HF_CLIENT_H_ + +#include +#include +#include +#include "oal-event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enable Audio HFP Client profile or HF Role of HFP profile + * + * @remarks BT audio gateway devices will be able to connect. + * + * @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 hfp_client_disable() + */ +oal_status_t hf_client_enable(void); + +/** + * @brief Disable Audio HFP client profile or HF Role of HFP profile + * + * @remarks BT audio gateway devices will be able to disconnect. + * + * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value. + * @retval #OAL_STATUS_SUCCESS Successful + * + * @pre AG Host should be enabled with hf_client_enable(). + * + * @see hfp_enable() + */ +oal_status_t hf_client_disable(void); + +/** + * @brief Initiate a HFP connection with a remote audio gateway device + * + * @details Result will be notified through an OAL event + * + * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value. + * @retval #OAL_STATUS_SUCCESS Successful + * + * @pre HFP Client should be enabled with hf_client_enable(). + * + * @see OAL_EVENT_HFP_CLIENT_DISCONNECTED + */ +oal_status_t hf_client_connect(bt_address_t *device_address); + +/** + * @brief Terminate a HFP connection with a remote audio gateway device + * + * @details Result will be notified through an OAL event + * + * @return OAL_STATUS_SUCCESS on success, otherwise a non-zero error value. + * @retval #OAL_STATUS_SUCCESS Successful + * + * @pre HFP Client should be enabled with hf_client_enable(). + * + * @see OAL_EVENT_HFP_CLIENT_CONNECTED + */ +oal_status_t hf_client_disconnect(bt_address_t *device_address); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _OAL_HF_CLIENT_H_*/ diff --git a/bt-oal/oal-hf-client.c b/bt-oal/oal-hf-client.c new file mode 100644 index 0000000..46f3faf --- /dev/null +++ b/bt-oal/oal-hf-client.c @@ -0,0 +1,212 @@ +/* + * Open Adaptation Layer (OAL) + * + * Copyright (c) 2019 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 +#include + +#include +#include + +#include "oal-common.h" +#include "oal-internal.h" +#include "oal-hf-client.h" +#include "oal-utils.h" + +static const bthf_client_interface_t *blued_hf_client_interface = NULL; + +#define CHECK_OAL_HFP_CLIENT_ENABLED() \ + do { \ + if (blued_hf_client_interface == NULL) { \ + BT_ERR("OAL, HFP Client Not Enabled"); \ + return OAL_STATUS_NOT_READY; \ + } \ + } while (0) + +static void cb_hf_client_connection_state(bthf_client_connection_state_t state, unsigned int peer_feat, + unsigned int chld_feat, bt_bdaddr_t *bd_addr); + +static bthf_client_callbacks_t blued_hf_client_cb = { + .size = sizeof(blued_hf_client_cb), + .connection_state_cb = cb_hf_client_connection_state, + .audio_state_cb = NULL, + .vr_cmd_cb = NULL, + .network_state_cb = NULL, + .network_roaming_cb = NULL, + .network_signal_cb = NULL, + .battery_level_cb = NULL, + .current_operator_cb = NULL, + .call_cb = NULL, + .callsetup_cb = NULL, + .callheld_cb = NULL, + .resp_and_hold_cb = NULL, + .clip_cb = NULL, + .call_waiting_cb = NULL, + .current_calls_cb = NULL, + .volume_change_cb = NULL, + .cmd_complete_cb = NULL, + .subscriber_info_cb = NULL, + .in_band_ring_tone_cb = NULL, + .last_voice_tag_number_callback = NULL, + .ring_indication_cb = NULL, + .get_voice_data_cb = NULL +}; + +oal_status_t hf_client_enable(void) +{ + const bt_interface_t* blued_inf; + int ret; + + API_TRACE("HFP Client Enable"); + + if ((blued_inf = adapter_get_stack_interface()) == NULL) { + BT_ERR("Bluetooth module is not loaded"); + return OAL_STATUS_NOT_READY; + } + + if (blued_hf_client_interface != NULL) { + BT_WARN("HFP Client Interface is already initialized..."); + return OAL_STATUS_ALREADY_DONE; + } + + if ((blued_hf_client_interface = (const bthf_client_interface_t *)blued_inf->get_profile_interface(BT_PROFILE_HANDSFREE_CLIENT_ID)) == NULL) { + BT_ERR("OAL, Failed to get Bluetooth HFP Client Interface"); + return OAL_STATUS_INTERNAL_ERROR; + } + + BT_DBG("Got profile interface"); + if ((ret = blued_hf_client_interface->init(&blued_hf_client_cb)) != BT_STATUS_SUCCESS) { + BT_ERR("Failed to initialize Bluetooth HFP Client, status: %s", status2string(ret)); + blued_hf_client_interface = NULL; + return convert_to_oal_status(ret); + } + BT_DBG("OAL, Bluetooth HFP Client interface initialised"); + + return OAL_STATUS_SUCCESS; +} + +/* HFP Client deinit: Resets all the HFP Client information + * Note: Adapter should be disabled before calling deinit + * */ +oal_status_t hf_client_disable(void) +{ + API_TRACE("HFP Client disable"); + CHECK_OAL_HFP_CLIENT_ENABLED(); + + blued_hf_client_interface->cleanup(); + blued_hf_client_interface = NULL; + + return OAL_STATUS_SUCCESS; +} + +void hf_client_cleanup(void) +{ + API_TRACE("HFP Client Cleanup"); + blued_hf_client_interface = NULL; +} + +oal_status_t hf_client_connect(bt_address_t *device_address) +{ + int result = OAL_STATUS_SUCCESS; + bt_status_t status; + bdstr_t bdstr; + API_TRACE("HF Client Connect"); + + CHECK_OAL_HFP_CLIENT_ENABLED(); + OAL_CHECK_PARAMETER(device_address, return); + + BT_INFO("BT remote AG Device Address: %s", bdt_bd2str(device_address, &bdstr)); + /* Call connect function of Bluedroid*/ + status = blued_hf_client_interface->connect((bt_bdaddr_t *)device_address); + if ((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) { + BT_ERR("Connection could not be established, err: %s", status2string(status));; + result = convert_to_oal_status(status); + } + return result; +} + + +oal_status_t hf_client_disconnect(bt_address_t *device_address) +{ + int result = OAL_STATUS_SUCCESS; + bdstr_t bdstr; + bt_status_t status; + API_TRACE("HF Client Disconnect"); + + CHECK_OAL_HFP_CLIENT_ENABLED(); + OAL_CHECK_PARAMETER(device_address, return); + + BT_INFO("BT remote AG Address: %s", bdt_bd2str(device_address, &bdstr)); + /* call Disconnect function of Bluedroid */ + status = blued_hf_client_interface->disconnect((bt_bdaddr_t *)device_address); + if ((status != BT_STATUS_SUCCESS) && (status != BT_STATUS_DONE)) { + BT_ERR("OAL, Disconnection failed err: %s", status2string(status)); + result = convert_to_oal_status(status); + } + return result; +} + +void cb_hf_client_connection_state(bthf_client_connection_state_t state, unsigned int peer_feat, + unsigned int chld_feat, bt_bdaddr_t *bd_addr) +{ + int event_type; + bdstr_t bdstr; + bt_address_t * event_data = NULL; + event_data = g_new0(bt_address_t, 1); + memcpy(event_data->addr, bd_addr->address, BT_ADDRESS_BYTES_NUM); + + if (bd_addr == NULL) { + BT_ERR("Address is NULL"); + if (event_data) + g_free(event_data); + return; + } + + BT_INFO("HFP Client Profile state = [%d], BT Address = [%s]", state, bdt_bd2str((bt_address_t*)bd_addr, &bdstr)); + switch (state) { + case BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED: { + event_type = OAL_EVENT_HF_CLIENT_DISCONNECTED; + break; + } + case BTHF_CLIENT_CONNECTION_STATE_CONNECTING: { + event_type = OAL_EVENT_HF_CLIENT_CONNECTING; + break; + } + case BTHF_CLIENT_CONNECTION_STATE_CONNECTED: { + event_type = OAL_EVENT_HF_CLIENT_CONNECTED; + break; + } + case BTHF_CLIENT_CONNECTION_STATE_DISCONNECTING: { + event_type = OAL_EVENT_HF_CLIENT_DISCONNECTING; + break; + } + default: { + BT_INFO("Invalid state"); + if (event_data) + g_free(event_data); + return; + } + } + send_event_bda_trace(event_type, event_data, sizeof(bt_address_t), (bt_address_t*)bd_addr); +} + diff --git a/bt-service-adaptation/CMakeLists.txt b/bt-service-adaptation/CMakeLists.txt index 2822018..85fa87d 100644 --- a/bt-service-adaptation/CMakeLists.txt +++ b/bt-service-adaptation/CMakeLists.txt @@ -28,6 +28,7 @@ SET(SRCS ./services/audio/avrcp/bt-service-avrcp-tg.c ./services/audio/avrcp/bt-service-avrcp-ctrl.c ./services/gatt/bt-service-gatt.c +./services/audio/hf/bt-service-hf-client.c ) IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_FEATURE_BT_OBEX") diff --git a/bt-service-adaptation/services/adapter/bt-service-core-adapter.c b/bt-service-adaptation/services/adapter/bt-service-core-adapter.c index 7c24ccf..581c1b6 100644 --- a/bt-service-adaptation/services/adapter/bt-service-core-adapter.c +++ b/bt-service-adaptation/services/adapter/bt-service-core-adapter.c @@ -1002,6 +1002,11 @@ int _bt_init_profiles() if (ret != BLUETOOTH_ERROR_NONE) BT_ERR("_bt_gatt_init Failed"); + /* Initialize HF Client */ + ret = _bt_audio_initialize(BT_HFP_MODULE); + if (ret != BLUETOOTH_ERROR_NONE) + BT_ERR("_bt_audio_initialize(BT_HFP_MODULE) Failed"); + return BLUETOOTH_ERROR_NONE; } diff --git a/bt-service-adaptation/services/audio/bt-service-audio.c b/bt-service-adaptation/services/audio/bt-service-audio.c index 09ff2ed..ef7aac7 100644 --- a/bt-service-adaptation/services/audio/bt-service-audio.c +++ b/bt-service-adaptation/services/audio/bt-service-audio.c @@ -40,6 +40,8 @@ #include "bt-service-avrcp-tg.h" #include "bt-service-avrcp-ctrl.h" #include "bt-service-hf.h" +#include "bt-service-hf-client.h" +#include "oal-hf-client.h" #ifdef TIZEN_SUPPORT_DUAL_HF #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac" @@ -416,6 +418,8 @@ static int __bt_process_audio_profile_connect(bt_audio_type_t type, bluetooth_de case BT_AUDIO_A2DP_SOURCE: return _bt_a2dp_connect_remote_source(address); break; + case BT_AUDIO_AG: + return _bt_connect_remote_ag(address); default: BT_ERR("Unknown role"); return BLUETOOTH_ERROR_INTERNAL; @@ -517,7 +521,14 @@ int _bt_audio_initialize(bt_service_module_t module) break; } case BT_HFP_MODULE: { - return BLUETOOTH_ERROR_NOT_SUPPORT; + status = hf_client_enable(); + if (OAL_STATUS_SUCCESS != status) { + BT_ERR("Failed to initialize Bluetooth HFP client Profile, status: %d", status); + return BLUETOOTH_ERROR_INTERNAL; + } + /* Register Audio module event handler */ + _bt_service_register_event_handler_callback(module, _bt_hf_client_event_handler); + break; } case BT_AG_MODULE: { status = hfp_enable(1); @@ -1263,3 +1274,27 @@ void _bt_audio_set_current_role(bluetooth_audio_role_t role) BT_INFO("role: %s", (role == BLUETOOTH_A2DP_SINK) ? "AUDIO_SINK" : "AUDIO_SOURCE"); curr_audio_role = role; } + +int _bt_hf_connect(bluetooth_device_address_t *device_address) +{ + int result = BLUETOOTH_ERROR_NONE; + BT_INFO("+"); + + result = _bt_connect_remote_ag(device_address); + if (result != BLUETOOTH_ERROR_NONE) + BT_ERR("HF Client connect to remote AG failed"); + + return result; +} + +int _bt_hf_disconnect(bluetooth_device_address_t *device_address) +{ + int result = BLUETOOTH_ERROR_NONE; + BT_INFO("+"); + + result = _bt_disconnect_remote_ag(device_address); + if (result != BLUETOOTH_ERROR_NONE) + BT_ERR("HF Client disconnect to remote AG failed"); + + return result; +} diff --git a/bt-service-adaptation/services/audio/hf/bt-service-hf-client.c b/bt-service-adaptation/services/audio/hf/bt-service-hf-client.c new file mode 100644 index 0000000..6830b0d --- /dev/null +++ b/bt-service-adaptation/services/audio/hf/bt-service-hf-client.c @@ -0,0 +1,183 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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 "oal-hardware.h" +#include "oal-manager.h" +#include "oal-audio-src.h" +#include "oal-device-mgr.h" +#include "oal-hf-client.h" +#include "bt-service-common.h" + +#include +#include + + + + +static void __bt_reply_hf_client_disconnection_pending_request(bt_address_t *address) +{ + BT_DBG("+"); + char addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + bluetooth_device_address_t device_address; + GArray *out_param; + invocation_info_t *req_info; + int result = BLUETOOTH_ERROR_NONE; + + ret_if(NULL == address); + + memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH); + _bt_convert_addr_type_to_string(addr, address->addr); + + BT_INFO("HF Client Disconnection remote device [%s]", addr); + + /* Find Async request information*/ + req_info = _bt_get_request_info_data(BT_HF_DISCONNECT, addr); + if (NULL == req_info) { + BT_INFO("HF DisConnect request not found or possibly already replied.."); + + /* if HF Connect call fails on Bluez DBUS, Async callback from bluez will be received + __bt_hf_client_connect_cb) which will internally trigger HF DISCONNECTED event */ + req_info = _bt_get_request_info_data(BT_HF_CONNECT, addr); + if (NULL == req_info) { + BT_INFO("HF Connect request not found.."); + return; + } else { + BT_INFO("HF Connect request found..reply this request"); + } + } else { + BT_INFO("HF DisConnect request found..reply this request"); + } + + /* In any of the above cases, reply DBUS context */ + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, &device_address, sizeof(bluetooth_device_address_t)); + _bt_service_method_return(req_info->context, out_param, result); + g_array_free(out_param, TRUE); + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + + BT_DBG("-"); +} + +static void __bt_reply_hf_client_connection_pending_request(bt_address_t *address) +{ + BT_DBG("+"); + char addr[BT_ADDRESS_STRING_SIZE] = { 0 }; + bluetooth_device_address_t device_address; + GArray *out_param; + invocation_info_t *req_info; + int result = BLUETOOTH_ERROR_NONE; + + ret_if(NULL == address); + + memcpy(device_address.addr, address->addr, BLUETOOTH_ADDRESS_LENGTH); + _bt_convert_addr_type_to_string(addr, address->addr); + + BT_INFO("HF Client Connection remote device [%s]", addr); + + /* Find Async request information*/ + req_info = _bt_get_request_info_data(BT_HF_CONNECT, addr); + if (NULL == req_info) { + BT_INFO("HF Connect request not found or possibly already replied.."); + return; + + } else { + BT_INFO("HF Connect request found.."); + } + + /* In any of the above cases, reply DBUS context */ + out_param = g_array_new(FALSE, FALSE, sizeof(gchar)); + g_array_append_vals(out_param, &device_address, sizeof(bluetooth_device_address_t)); + _bt_service_method_return(req_info->context, out_param, result); + g_array_free(out_param, TRUE); + g_free(req_info->user_data); + _bt_free_info_from_invocation_list(req_info); + + BT_DBG("-"); +} + + +/* This event handler process events for HF Client role */ +void _bt_hf_client_event_handler(int oal_event, gpointer event_data) +{ + BT_INFO("+"); + bt_address_t *bt_addr = event_data; + + switch (oal_event) { + case OAL_EVENT_HF_CLIENT_DISCONNECTED: + /* Reply to async request for HF Client connect or disconnect request, if any */ + BT_INFO("HF client Profile disconnected, reply pending DBUS request and check waiting device"); + __bt_reply_hf_client_disconnection_pending_request(bt_addr); + break; + case OAL_EVENT_HF_CLIENT_CONNECTED: + BT_INFO("HF Client Profile connected, Event & DBUS context will be handled at finalizing SCO connect.."); + __bt_reply_hf_client_connection_pending_request(bt_addr); + break; + case OAL_EVENT_HF_CLIENT_CONNECTING: + BT_INFO("HF Client Profile connection successful, wait for Audio connect.."); + break; + case OAL_EVENT_HF_CLIENT_DISCONNECTING: + BT_INFO("HF Client Connecting or Disconnecting..No need to send event to app"); + break; + default: + break; + } +} + +int _bt_connect_remote_ag(bluetooth_device_address_t *device_address) +{ + oal_status_t status = OAL_STATUS_SUCCESS; + int result = BLUETOOTH_ERROR_NONE; + gboolean is_connected = FALSE; + + BT_INFO("+"); + + is_connected = device_get_svc_conn_state((bt_address_t*)device_address, HFP_SERVICE_ID); + if (is_connected == TRUE) { + BT_ERR("HF Client is already connected"); + return BLUETOOTH_ERROR_ALREADY_CONNECT; + } + + status = hf_client_connect((bt_address_t *)device_address); + if (status != OAL_STATUS_SUCCESS) { + BT_ERR("HF Client Connection could not be established, err: [%d]", status); + result = BLUETOOTH_ERROR_INTERNAL; + } + return result; +} + +int _bt_disconnect_remote_ag(bluetooth_device_address_t *device_address) +{ + oal_status_t status = OAL_STATUS_SUCCESS; + int result = BLUETOOTH_ERROR_NONE; + BT_INFO("+"); + + status = hf_client_disconnect((bt_address_t *)device_address); + if (status != OAL_STATUS_SUCCESS) { + BT_ERR("HF Client DisConnection err: [%d]", status); + result = BLUETOOTH_ERROR_INTERNAL; + } + return result; +} + diff --git a/bt-service-adaptation/services/bt-request-handler.c b/bt-service-adaptation/services/bt-request-handler.c index ee36a0f..d221e23 100644 --- a/bt-service-adaptation/services/bt-request-handler.c +++ b/bt-service-adaptation/services/bt-request-handler.c @@ -1647,6 +1647,46 @@ int __bt_bluez_request(int function_name, } break; } + case BT_HF_CONNECT: { + bluetooth_device_address_t address = { {0} }; + + __bt_service_get_parameters(in_param1, + &address, sizeof(bluetooth_device_address_t)); + + result = _bt_hf_connect(&address); + if (result != BLUETOOTH_ERROR_NONE) { + char addr[BT_ADDRESS_STRING_SIZE]; + _bt_convert_addr_type_to_string(addr, address.addr); + g_array_append_vals(*out_param1, addr, BT_ADDRESS_STRING_SIZE); + } else { + char *addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, address.addr); + sender = (char*)g_dbus_method_invocation_get_sender(context); + _bt_save_invocation_context(context, result, sender, + function_name, (gpointer)addr); + } + break; + } + case BT_HF_DISCONNECT: { + bluetooth_device_address_t address = { {0} }; + + __bt_service_get_parameters(in_param1, + &address, sizeof(bluetooth_device_address_t)); + + result = _bt_hf_disconnect(&address); + if (result != BLUETOOTH_ERROR_NONE) { + char addr[BT_ADDRESS_STRING_SIZE]; + _bt_convert_addr_type_to_string(addr, address.addr); + g_array_append_vals(*out_param1, addr, BT_ADDRESS_STRING_SIZE); + } else { + char *addr = g_malloc0(BT_ADDRESS_STRING_SIZE); + _bt_convert_addr_type_to_string(addr, address.addr); + sender = (char*)g_dbus_method_invocation_get_sender(context); + _bt_save_invocation_context(context, result, sender, + function_name, (gpointer)addr); + } + break; + } case BT_AVRCP_TARGET_CONNECT: { bluetooth_device_address_t address = { {0} }; diff --git a/bt-service-adaptation/services/bt-service-event-receiver.c b/bt-service-adaptation/services/bt-service-event-receiver.c index f915b37..d030450 100644 --- a/bt-service-adaptation/services/bt-service-event-receiver.c +++ b/bt-service-adaptation/services/bt-service-event-receiver.c @@ -49,6 +49,7 @@ _bt_service_event_handler_callback avrcp_ctrl_cb; _bt_service_event_handler_callback avrcp_cb; _bt_service_event_handler_callback adapter_le_cb; _bt_service_event_handler_callback adapter_gatt_cb; +_bt_service_event_handler_callback hf_client_cb; void _bt_service_register_event_handler_callback( bt_service_module_t module, _bt_service_event_handler_callback cb) @@ -86,6 +87,10 @@ void _bt_service_register_event_handler_callback( BT_INFO("Register BT_AG_MODULE callback"); ag_cb = cb; break; + case BT_HFP_MODULE: + BT_INFO("Register BT_HFP_MODULE callback"); + hf_client_cb = cb; + break; case BT_HEALTH_MODULE: BT_INFO("Register BT_HEALTH_MODULE callback"); hdp_cb = cb; @@ -269,6 +274,13 @@ static gboolean __bt_handle_oal_events(gpointer data) if (ag_cb) ag_cb(event_type, event_data); break; + case OAL_EVENT_HF_CLIENT_CONNECTING: + case OAL_EVENT_HF_CLIENT_DISCONNECTING: + case OAL_EVENT_HF_CLIENT_CONNECTED: + case OAL_EVENT_HF_CLIENT_DISCONNECTED: + if (hf_client_cb) + hf_client_cb(event_type, event_data); + break; case OAL_EVENT_HDP_APP_REGISTERED: case OAL_EVENT_HDP_APP_UNREGISTERED: case OAL_EVENT_HDP_CHANNEL_CONNECTED: diff --git a/bt-service-adaptation/services/include/bt-service-audio-common.h b/bt-service-adaptation/services/include/bt-service-audio-common.h index 41ceaff..176ce4d 100644 --- a/bt-service-adaptation/services/include/bt-service-audio-common.h +++ b/bt-service-adaptation/services/include/bt-service-audio-common.h @@ -43,7 +43,8 @@ typedef enum { BT_AVRCP_TARGET = 0x04, /* AVRCP Target Connection to remote AVRCP controller */ BT_AVRCP = 0x08, /* AVRCP ctrl Connection to remote AVRCP target */ BT_AUDIO_A2DP_SOURCE = 0x10, /* A2DP Sink Connection, remote device is A2DP Source */ - BT_AUDIO_HFP_SOURCE = 0x11 /* HSP and A2DP Sink Connection (BT_AUDIO_HSP and BT_AUDIO_A2DP_SOURCE)*/ + BT_AUDIO_HFP_SOURCE = 0x11, /* HSP and A2DP Sink Connection (BT_AUDIO_HSP and BT_AUDIO_A2DP_SOURCE)*/ + BT_AUDIO_AG = 0x12 /* BT_HF_CONNECT local device HF Client and remote device AG */ } bt_audio_type_t; typedef enum { @@ -124,6 +125,10 @@ int _bt_audio_select_role(bluetooth_audio_role_t role); void _bt_audio_set_current_role(bluetooth_audio_role_t role); +int _bt_hf_connect(bluetooth_device_address_t *device_address); + +int _bt_hf_disconnect(bluetooth_device_address_t *device_address); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bt-service-adaptation/services/include/bt-service-hf-client.h b/bt-service-adaptation/services/include/bt-service-hf-client.h new file mode 100644 index 0000000..3fd29c2 --- /dev/null +++ b/bt-service-adaptation/services/include/bt-service-hf-client.h @@ -0,0 +1,42 @@ +/* + * Bluetooth-frwk + * + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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_SERVICE_HF_CLIENT_H__ +#define __BT_SERVICE_HF_CLIENT_H__ + +#include "bt-service-event-receiver.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "oal-hardware.h" +#include +#include + +int _bt_connect_remote_ag(bluetooth_device_address_t *device_address); + +int _bt_disconnect_remote_ag(bluetooth_device_address_t *device_address); + +void _bt_hf_client_event_handler(int oal_event, gpointer event_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __BT_SERVICE_HF_CLIENT_H__ */ -- 2.7.4