Adapt HF Profile Connect & Disconnect to BT HAL framework 10/215810/3
authorAmit Purwar <amit.purwar@samsung.com>
Wed, 16 Oct 2019 06:09:50 +0000 (11:39 +0530)
committerAmit Purwar <amit.purwar@samsung.com>
Thu, 17 Oct 2019 04:16:42 +0000 (09:46 +0530)
Change-Id: I1c59ff115e7048b168fe7540514c5a7a3c815fc4
Signed-off-by: Amit Purwar <amit.purwar@samsung.com>
24 files changed:
bt-oal/CMakeLists.txt
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/inc/bt-hal.h
bt-oal/bluez_hal/src/bt-hal-bluetooth.c
bt-oal/bluez_hal/src/bt-hal-event-receiver.c
bt-oal/bluez_hal/src/bt-hal-event-receiver.h
bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hf-client-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hf-client.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-hf-client.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-internal.h
bt-oal/hardware/bt_hf_client.h [new file with mode: 0644]
bt-oal/include/oal-event.h
bt-oal/include/oal-hf-client.h [new file with mode: 0644]
bt-oal/oal-hf-client.c [new file with mode: 0644]
bt-service-adaptation/CMakeLists.txt
bt-service-adaptation/services/adapter/bt-service-core-adapter.c
bt-service-adaptation/services/audio/bt-service-audio.c
bt-service-adaptation/services/audio/hf/bt-service-hf-client.c [new file with mode: 0644]
bt-service-adaptation/services/bt-request-handler.c
bt-service-adaptation/services/bt-service-event-receiver.c
bt-service-adaptation/services/include/bt-service-audio-common.h
bt-service-adaptation/services/include/bt-service-hf-client.h [new file with mode: 0644]

index a864ae8..f8dbf7a 100755 (executable)
@@ -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
index d099a2a..d0216c9 100644 (file)
@@ -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})
index d9d249d..7c5b316 100644 (file)
@@ -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_
index 948729c..38c55f9 100644 (file)
@@ -29,6 +29,7 @@
 #include <hardware/bt_sock.h>
 #include <hardware/bt_hl.h>
 #include <hardware/bt_rc.h>
+#include <hardware/bt_hf_client.h>
 
 /*TODO: Profile interfaces headers and exposed methods of Android HAL framework to be included in next patches */
 #endif //_BT_HAL_H
index 547a613..2783924 100644 (file)
@@ -45,6 +45,7 @@
 #include <bt-hal-adapter-le.h>
 #include <bt-hal-agent.h>
 #endif
+#include <bt-hal-hf-client.h>
 
 #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();
 
index 38c838d..2f78578 100644 (file)
@@ -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;
index 29ce3b3..2996266 100644 (file)
@@ -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 (file)
index 0000000..84d954b
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#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 (file)
index 0000000..7c7d11a
--- /dev/null
@@ -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 <glib.h>
+#include <sys/types.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+
+#include "bt-hal-event-receiver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _bt_hal_register_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 (file)
index 0000000..8467d2a
--- /dev/null
@@ -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 <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlog.h>
+
+#include "bt-hal.h"
+#include "bt-hal-log.h"
+#include "bt-hal-msg.h"
+#include "bt-hal-utils.h"
+
+#include "bt-hal-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 (file)
index 0000000..e8d5b28
--- /dev/null
@@ -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 <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+bthf_client_interface_t *bt_get_hf_client_interface(void);
+
+#endif //__BT_HAL_HF_CLIENT_H__
+
index 80c6fc9..5746e60 100644 (file)
@@ -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 (file)
index 0000000..fdce093
--- /dev/null
@@ -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 */
index 96d6f38..b095a8c 100644 (file)
@@ -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 (file)
index 0000000..33edbc9
--- /dev/null
@@ -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 <glib.h>
+#include <sys/types.h>
+#include <oal-manager.h>
+#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 (file)
index 0000000..46f3faf
--- /dev/null
@@ -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 <stdio.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dlog.h>
+
+#include <bluetooth.h>
+#include <bt_hf_client.h>
+
+#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);
+}
+
index 2822018..85fa87d 100644 (file)
@@ -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")
index 7c24ccf..581c1b6 100644 (file)
@@ -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;
 }
 
index 09ff2ed..ef7aac7 100644 (file)
@@ -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 (file)
index 0000000..6830b0d
--- /dev/null
@@ -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 <sys/errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <vconf.h>
+
+#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 <bt-service-hf-client.h>
+#include <bt-service-event.h>
+
+
+
+
+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;
+}
+
index ee36a0f..d221e23 100644 (file)
@@ -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} };
 
index f915b37..d030450 100644 (file)
@@ -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:
index 41ceaff..176ce4d 100644 (file)
@@ -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 (file)
index 0000000..3fd29c2
--- /dev/null
@@ -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 <oal-manager.h>
+#include <bluetooth-api.h>
+
+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__ */