[Adapt Audio HAL] Add A2DP Source role 83/88083/1
authorAnupam Roy <anupam.r@samsung.com>
Tue, 13 Sep 2016 08:36:49 +0000 (14:06 +0530)
committerAnupam Roy <anupam.r@samsung.com>
Tue, 13 Sep 2016 08:36:49 +0000 (14:06 +0530)
This patch primarily adds following:-
 a/ AV(Source) Android HAL interface
 b/ Implement Bluez based AV Init, Connect, Disconnect methods
 c/ Implemnt AV Connection event handlers

Change-Id: Ic794a3fe21317c9b4346bcd4f4c8ab253fd8db17
Signed-off-by: Anupam Roy <anupam.r@samsung.com>
16 files changed:
bt-oal/bluez_hal/CMakeLists.txt
bt-oal/bluez_hal/hardware/bt_av.h [new file with mode: 0644]
bt-oal/bluez_hal/inc/bt-hal-msg.h
bt-oal/bluez_hal/inc/bt-hal-utils.h
bt-oal/bluez_hal/inc/bt-hal.h
bt-oal/bluez_hal/src/bt-hal-agent.c
bt-oal/bluez_hal/src/bt-hal-av-dbus-handler.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-av-dbus-handler.h [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-av.c [new file with mode: 0644]
bt-oal/bluez_hal/src/bt-hal-av.h [new file with mode: 0644]
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-gap-agent.c
bt-oal/bluez_hal/src/bt-hal-internal.h
bt-oal/bluez_hal/src/bt-hal-utils.c

index 4d96cf2..8f25e7b 100644 (file)
@@ -11,6 +11,8 @@ SET(SRCS
 ./src/bt-hal-gap-agent.c
 ./src/bt-hal-agent.c
 ./src/bt-hal-hidhost.c
+./src/bt-hal-av.c
+./src/bt-hal-av-dbus-handler.c
 ./src/bt-hal-hid-dbus-handler.c
 ./src/bt-hal-socket.c
 ./src/bt-hal-rfcomm-dbus-handler.c
diff --git a/bt-oal/bluez_hal/hardware/bt_av.h b/bt-oal/bluez_hal/hardware/bt_av.h
new file mode 100644 (file)
index 0000000..7bd5df1
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_AV_H
+#define ANDROID_INCLUDE_BT_AV_H
+
+__BEGIN_DECLS
+
+/* Bluetooth AV connection states */
+typedef enum {
+    BTAV_CONNECTION_STATE_DISCONNECTED = 0,
+    BTAV_CONNECTION_STATE_CONNECTING,
+    BTAV_CONNECTION_STATE_CONNECTED,
+    BTAV_CONNECTION_STATE_DISCONNECTING
+} btav_connection_state_t;
+
+/* Bluetooth AV datapath states */
+typedef enum {
+    BTAV_AUDIO_STATE_REMOTE_SUSPEND = 0,
+    BTAV_AUDIO_STATE_STOPPED,
+    BTAV_AUDIO_STATE_STARTED,
+} btav_audio_state_t;
+
+
+/** Callback for connection state change.
+ *  state will have one of the values from btav_connection_state_t
+ */
+typedef void (* btav_connection_state_callback)(btav_connection_state_t state,
+                                                    bt_bdaddr_t *bd_addr);
+
+/** Callback for audiopath state change.
+ *  state will have one of the values from btav_audio_state_t
+ */
+typedef void (* btav_audio_state_callback)(btav_audio_state_t state,
+                                               bt_bdaddr_t *bd_addr);
+
+/** Callback for audio configuration change.
+ *  Used only for the A2DP sink interface.
+ *  state will have one of the values from btav_audio_state_t
+ *  sample_rate: sample rate in Hz
+ *  channel_count: number of channels (1 for mono, 2 for stereo)
+ */
+typedef void (* btav_audio_config_callback)(bt_bdaddr_t *bd_addr,
+                                                uint32_t sample_rate,
+                                                uint8_t channel_count);
+
+/** BT-AV callback structure. */
+typedef struct {
+    /** set to sizeof(btav_callbacks_t) */
+    size_t      size;
+    btav_connection_state_callback  connection_state_cb;
+    btav_audio_state_callback audio_state_cb;
+    btav_audio_config_callback audio_config_cb;
+} btav_callbacks_t;
+
+/**
+ * NOTE:
+ *
+ * 1. AVRCP 1.0 shall be supported initially. AVRCP passthrough commands
+ *    shall be handled internally via uinput
+ *
+ * 2. A2DP data path shall be handled via a socket pipe between the AudioFlinger
+ *    android_audio_hw library and the Bluetooth stack.
+ *
+ */
+/** Represents the standard BT-AV interface.
+ *  Used for both the A2DP source and sink interfaces.
+ */
+typedef struct {
+
+    /** set to sizeof(btav_interface_t) */
+    size_t          size;
+    /**
+     * Register the BtAv callbacks
+     */
+    bt_status_t (*init)( btav_callbacks_t* callbacks );
+
+    /** connect to headset */
+    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
+
+    /** dis-connect from headset */
+    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
+
+    /** Closes the interface. */
+    void  (*cleanup)( void );
+} btav_interface_t;
+
+__END_DECLS
+
+#endif /* ANDROID_INCLUDE_BT_AV_H */
index 5a5ce42..ef35182 100644 (file)
@@ -263,5 +263,34 @@ struct hal_ev_sock_connect {
        int     channel;
        int     status;
 } __attribute__((packed));
+
+/* A2DP (AV) Headers */
+#define HAL_EV_A2DP_STATE_DISCONNECTED             0x00
+#define HAL_EV_A2DP_STATE_CONNECTING               0x01
+#define HAL_EV_A2DP_STATE_CONNECTED                0x02
+#define HAL_EV_A2DP_STATE_DISCONNECTING            0x03
+
+#define HAL_EV_A2DP_CONN_STATE                  0x8C
+struct hal_ev_a2dp_conn_state {
+        uint8_t state;
+        uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_AUDIO_SUSPEND                       0x00
+#define HAL_AUDIO_STOPPED                       0x01
+#define HAL_AUDIO_STARTED                       0x02
+
+#define HAL_EV_A2DP_AUDIO_STATE                 0x8D
+struct hal_ev_a2dp_audio_state {
+        uint8_t state;
+        uint8_t bdaddr[6];
+} __attribute__((packed));
+
+#define HAL_EV_A2DP_AUDIO_CONFIG                0x8E
+struct hal_ev_a2dp_audio_config {
+        uint8_t  bdaddr[6];
+        uint32_t sample_rate;
+        uint8_t  channel_count;
+} __attribute__((packed));
 #endif //_BT_HAL_MSG_H_
 
index ca14b63..9f8c423 100644 (file)
@@ -34,7 +34,9 @@ static const char BT_BASE_UUID[] = {
 /** BT Profile Service UUID's */
 #define BT_HAL_HFP_AUDIO_GATEWAY_UUID "0000111f-0000-1000-8000-00805f9b34fb"
 #define BT_HAL_HSP_AUDIO_GATEWAY_UUID "00001112-0000-1000-8000-00805f9b34fb"
-#define BT_HAL_A2DP_UUID "0000110D-0000-1000-8000-00805F9B34FB"
+#define BT_HAL_A2DP_PROFILE_UUID "0000110d-0000-1000-8000-00805f9b34fb" /* This is A2DP Profile UUID */
+#define BT_HAL_A2DP_SOURCE_UUID "0000110a-0000-1000-8000-00805f9b34fb"  /* This is A2DP Profile Role(SRC) UUID */
+#define BT_HAL_A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"   /* This is A2DP Profile Role(SNK) UUID */
 #define BT_HAL_AVRCP_TARGET_UUID "0000110c-0000-1000-8000-00805f9b34fb"
 #define BT_HAL_AVRCP_REMOTE_UUID "0000110e-0000-1000-8000-00805f9b34fb"
 #define BT_HAL_OPP_UUID "00001105-0000-1000-8000-00805f9b34fb"
index 8a148ca..c1e46be 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <hardware/bluetooth.h>
 #include <hardware/bt_hh.h>
+#include <hardware/bt_av.h>
 #include <hardware/bt_sock.h>
 
 /*TODO: Profile interfaces headers and exposed methods of Android HAL framework to be included in next patches */
index 2a54a8a..d47b4cb 100644 (file)
@@ -672,7 +672,7 @@ static gboolean __bt_hal_authorize_request(GapAgentPrivate *agent, GDBusProxy *d
         * to bt-service or, launch bt-syspopup.
         */
 #ifdef TIZEN_SYSPOPUP_SUPPORTED
-       DBG("Launch Syspopup: AUTHORIZE_REQUEST");
+       DBG("Launch Syspopup: AUTHORIZE_REQUEST: UUID [%s]", uuid);
        _bt_hal_launch_system_popup(BT_HAL_AGENT_EVENT_AUTHORIZE_REQUEST,
                        name, NULL, NULL, _gap_agent_get_path(agent));
 #else
diff --git a/bt-oal/bluez_hal/src/bt-hal-av-dbus-handler.c b/bt-oal/bluez_hal/src/bt-hal-av-dbus-handler.c
new file mode 100644 (file)
index 0000000..e1fd343
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dlog.h>
+#include <vconf.h>
+
+#include "bt-hal-av-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-av handler */
+void _bt_hal_register_av_dbus_handler_cb(handle_stack_msg cb)
+{
+       event_cb = cb;
+}
+
+/* To send stack event to hal-av handler */
+void _bt_hal_unregister_av_dbus_handler_cb()
+{
+       event_cb = NULL;
+}
+
+static void __bt_av_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                                       gpointer user_data)
+{
+       GError *g_error = NULL;
+       struct hal_ev_a2dp_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("A2DP Connect 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);
+
+       DBG("Address: %s", address);
+       /*
+        * If result is success, AV Connecting event will be triggered
+        * from here.
+        */
+       if (result == BT_STATUS_SUCCESS) {
+               /* Prepare to send AV connecting event */
+               memset(&ev, 0, sizeof(ev));
+               ev.state = HAL_EV_A2DP_STATE_CONNECTING;
+               _bt_convert_addr_string_to_type(ev.bdaddr, address);
+               if (!event_cb)
+                       ERR("A2DP dbus handler callback not registered");
+               else
+                       event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
+       } else {
+               /* Prepare to send AV disconnected event */
+               memset(&ev, 0, sizeof(ev));
+               ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
+               _bt_convert_addr_string_to_type(ev.bdaddr, address);
+               if (!event_cb)
+                       ERR("HF DBUS handler callback not registered");
+               else
+                       event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
+       }
+
+       g_free(address);
+}
+
+bt_status_t _bt_hal_dbus_handler_av_connect(bt_bdaddr_t *bd_addr)
+{
+       char *address;
+       GDBusConnection *conn;
+       int ret;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       ret = _bt_connect_profile(address, A2DP_SINK_UUID,
+                       __bt_av_connect_cb, address);
+
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile(A2DP) Error");
+               return BT_STATUS_FAIL;
+       }
+       return BT_STATUS_SUCCESS;
+}
+
+static void __bt_av_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                                       gpointer user_data)
+{
+       GError *g_error = NULL;
+       struct hal_ev_a2dp_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("A2DP 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_FAIL)
+               DBG("A2DP Disconnect successful for Device: %s", address);
+       else
+               DBG("A2DP Disconnect un-successful for Device: %s", address);
+
+       if (result == BT_STATUS_FAIL) {
+               /* Prepare to send AV Disconnected event */
+               memset(&ev, 0, sizeof(ev));
+               _bt_convert_addr_string_to_type(ev.bdaddr, address);
+               ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
+               if (!event_cb)
+                       ERR("HF DBUS handler callback not registered");
+               else
+                       event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
+       } else {
+               /* Prepare to send AV Disconnecting event */
+               memset(&ev, 0, sizeof(ev));
+               _bt_convert_addr_string_to_type(ev.bdaddr, address);
+               ev.state = HAL_EV_A2DP_STATE_DISCONNECTING;
+               if (!event_cb)
+                       ERR("HF DBUS handler callback not registered");
+               else
+                       event_cb(HAL_EV_A2DP_CONN_STATE, (void *)&ev, sizeof(ev));
+       }
+       g_free(address);
+       DBG("-");
+}
+
+bt_status_t _bt_hal_dbus_handler_av_disconnect(bt_bdaddr_t *bd_addr)
+{
+       char *address;
+       GDBusConnection *conn;
+       int ret;
+
+       if(!bd_addr) {
+               ERR("bd_addr is NULL, return");
+               return BT_STATUS_PARM_INVALID;
+       }
+
+       conn = _bt_get_system_gconn();
+       if(!conn) {
+               ERR("_bt_get_system_gconn returned NULL, return");
+               return BT_STATUS_FAIL;
+       }
+
+       address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
+       if (!address) {
+               ERR("Memory allocation failed");
+               return BT_STATUS_NOMEM;
+       }
+       _bt_convert_addr_type_to_string(address, bd_addr->address);
+
+       ret = _bt_disconnect_profile(address, A2DP_SINK_UUID,
+                       __bt_av_disconnect_cb, address);
+
+       if (ret != BT_HAL_ERROR_NONE) {
+               ERR("_bt_connect_profile(AV) Error");
+               return BT_STATUS_FAIL;
+       }
+
+       return BT_STATUS_SUCCESS;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-av-dbus-handler.h b/bt-oal/bluez_hal/src/bt-hal-av-dbus-handler.h
new file mode 100644 (file)
index 0000000..7165d97
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *              http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _BT_HAL_AV_DBUS_HANDLER_H_
+#define _BT_HAL_AV_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_av_dbus_handler_cb(handle_stack_msg cb);
+
+void _bt_hal_unregister_av_dbus_handler_cb();
+
+bt_status_t _bt_hal_dbus_handler_av_connect(bt_bdaddr_t *bd_addr);
+
+bt_status_t _bt_hal_dbus_handler_av_disconnect(bt_bdaddr_t *bd_addr);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* _BT_HAL_AV_DBUS_HANDLER_H_*/
diff --git a/bt-oal/bluez_hal/src/bt-hal-av.c b/bt-oal/bluez_hal/src/bt-hal-av.c
new file mode 100644 (file)
index 0000000..fad7755
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * BLUETOOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#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-av-dbus-handler.h"
+
+static const btav_callbacks_t *bt_hal_av_cbacks;
+
+static bool interface_ready(void)
+{
+       return bt_hal_av_cbacks != NULL;
+}
+
+static bt_status_t av_connect(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return _bt_hal_dbus_handler_av_connect(bd_addr);
+}
+
+static bt_status_t av_disconnect(bt_bdaddr_t *bd_addr)
+{
+       DBG("");
+       return _bt_hal_dbus_handler_av_disconnect(bd_addr);
+}
+
+static void __bt_hal_handle_av_conn_state(void *buf, uint16_t len)
+{
+       struct hal_ev_a2dp_conn_state *ev = buf;
+
+       if (bt_hal_av_cbacks->connection_state_cb)
+               bt_hal_av_cbacks->connection_state_cb(ev->state, (bt_bdaddr_t *) ev->bdaddr);
+}
+
+static void __bt_hal_handle_av_audio_conn_state(void *buf, uint16_t len)
+{
+       struct hal_ev_a2dp_audio_state *ev = buf;
+
+       if (bt_hal_av_cbacks->audio_state_cb)
+               bt_hal_av_cbacks->audio_state_cb(ev->state, (bt_bdaddr_t *) ev->bdaddr);
+}
+
+static void __bt_hal_handle_av_events(int message, void *buf, uint16_t len)
+{
+       DBG("+");
+       if (!interface_ready())
+               return;
+       switch(message) {
+       case HAL_EV_A2DP_CONN_STATE:
+               DBG("Event: HAL_EV_A2DP_CONN_STATE");
+               __bt_hal_handle_av_conn_state(buf, len);
+               break;
+       case HAL_EV_A2DP_AUDIO_STATE:
+               DBG("Event: HAL_EV_A2DP_AUDIO_STATE");
+               __bt_hal_handle_av_audio_conn_state(buf, len);
+               break;
+       default:
+               DBG("Event Currently not handled!!");
+               break;
+       }
+       DBG("-");
+}
+
+static bt_status_t init(btav_callbacks_t* callbacks)
+{
+       DBG("");
+
+       if (interface_ready())
+               return BT_STATUS_DONE;
+
+       bt_hal_av_cbacks = callbacks;
+       DBG("Register A2DP Src events callback function");
+       _bt_hal_register_av_dbus_handler_cb(__bt_hal_handle_av_events);
+       _bt_hal_register_av_event_handler_cb(__bt_hal_handle_av_events);
+       return BT_STATUS_SUCCESS;
+}
+
+static void cleanup(void)
+{
+       DBG("");
+
+       if (!interface_ready())
+               return;
+
+       bt_hal_av_cbacks = NULL;
+}
+
+static btav_interface_t av_if = {
+       .size = sizeof(av_if),
+       .init = init,
+       .connect = av_connect,
+       .disconnect = av_disconnect,
+       .cleanup = cleanup
+};
+
+btav_interface_t *bt_get_av_interface(void)
+{
+       DBG("Get A2DP Src Profile Interface");
+       return &av_if;
+}
diff --git a/bt-oal/bluez_hal/src/bt-hal-av.h b/bt-oal/bluez_hal/src/bt-hal-av.h
new file mode 100644 (file)
index 0000000..3b5db39
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * BLUETOOTH HAL
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:  Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_HAL_AV_H__
+#define __BT_HAL_AV_H__
+
+#include <stdint.h>
+#include <glib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <stdio.h>
+
+btav_interface_t *bt_get_av_interface(void);
+
+#endif //__BT_HAL_AV_H__
index 67ecd42..b7eac19 100644 (file)
@@ -34,6 +34,7 @@
 #include <bt-hal-device-dbus-handler.h>
 #include <bt-hal-hidhost.h>
 #include <bt-hal-socket.h>
+#include <bt-hal-av.h>
 
 #define enum_prop_to_hal(prop, hal_prop, type) do { \
        static type e; \
@@ -219,7 +220,7 @@ static const void *get_profile_interface(const char *profile_id)
                return NULL;
 
        if (!strcmp(profile_id, BT_PROFILE_ADVANCED_AUDIO_ID))
-               return NULL;
+               return bt_get_av_interface();
 
        if (!strcmp(profile_id, BT_PROFILE_AV_RC_ID))
                return NULL;
index 7e29b05..d6f6fbd 100644 (file)
@@ -50,6 +50,7 @@
 static GDBusConnection *manager_conn;
 static handle_stack_msg event_cb = NULL;
 static handle_stack_msg hid_event_cb = NULL;
+static handle_stack_msg av_event_cb = NULL;
 static guint event_id;
 
 /* Forward declarations */
@@ -77,6 +78,7 @@ static void __bt_hal_device_properties_lookup(GVariant *result, char *address);
 static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *member,const char *path);
 static void __bt_hal_send_device_acl_connection_state_event(gboolean connected, const char *address);
 static void __bt_hal_handle_input_event(GVariant *msg, const char *path);
+static void __bt_hal_send_av_connection_state_event(gboolean connected, const char *address);
 
 static void __bt_hal_send_device_trust_state_event(gboolean is_trusted, const char *address);
 
@@ -1356,6 +1358,20 @@ static void __bt_hal_handle_device_specific_events(GVariant *msg, const char *me
                        else
                                DBG("Profile state: %d", state);
 
+               } else if ((strncmp(profile_uuid, A2DP_SINK_UUID, strlen(A2DP_SINK_UUID)) == 0)) {
+                        if (state == BT_HAL_PROFILE_STATE_CONNECTED) {
+                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_CONNECTED");
+                                __bt_hal_send_av_connection_state_event(TRUE, address);
+                        } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTED) {
+                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_DISCONNECTED");
+                                __bt_hal_send_av_connection_state_event(FALSE, address);
+                        } else if (state == BT_HAL_PROFILE_STATE_DISCONNECTING) {
+                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_DISCONNECTING");
+                        } else if (state == BT_HAL_PROFILE_STATE_CONNECTING) {
+                                DBG("A2DP Profile state changed: BT_PROFILE_STATE_CONNECTING");
+                        }
+                } else {
+                       DBG("Profile[%s] State changed status [%d] ", profile_uuid,state);
                }
                g_free(address);
                g_free(profile_uuid);
@@ -1374,3 +1390,36 @@ void _bt_hal_unregister_hid_event_handler_cb()
 {
                hid_event_cb = NULL;
 }
+
+/* A2DP Src Role(Remote:Sink) Events */
+void _bt_hal_register_av_event_handler_cb(handle_stack_msg cb)
+{
+       av_event_cb = cb;
+}
+
+void _bt_hal_unregister_av_event_handler_cb()
+{
+       av_event_cb = NULL;
+}
+
+static void __bt_hal_send_av_connection_state_event(gboolean connected, const char *address)
+{
+       DBG("+");
+       struct hal_ev_a2dp_conn_state ev;
+
+       if (connected == TRUE)
+               INFO("A2DP(Src) Profile Connected for address [%s]", address);
+       else
+               INFO("A2DP(Src) Profile DisConnected for address [%s]", address);
+
+       ev.state = (connected == TRUE) ?
+               HAL_EV_A2DP_STATE_CONNECTED :
+               HAL_EV_A2DP_STATE_DISCONNECTED;
+
+       _bt_convert_addr_string_to_type(ev.bdaddr, address);
+
+       if (!av_event_cb)
+               ERR("AV event handler not registered");
+       else
+               av_event_cb(HAL_EV_A2DP_CONN_STATE, &ev, sizeof(ev));
+}
index dea34a2..bef1c58 100644 (file)
@@ -44,6 +44,11 @@ void _bt_hal_register_hid_event_handler_cb(handle_stack_msg cb);
 
 void _bt_hal_unregister_hid_event_handler_cb();
 
+/* A2DP(SRC Role) Events*/
+void _bt_hal_register_av_event_handler_cb(handle_stack_msg cb);
+
+void _bt_hal_unregister_av_event_handler_cb();
+
 handle_stack_msg _bt_hal_get_stack_message_handler(void);
 
 int __bt_insert_hal_properties(void *buf, uint8_t type, uint16_t len, const void *val);
index 371a151..57503d4 100644 (file)
@@ -847,7 +847,7 @@ gboolean gap_agent_reply_confirmation(GapAgentPrivate *agent, const guint accept
 
        if (priv->exec_type != GAP_AGENT_EXEC_NO_OPERATION &&
                        priv->reply_context != NULL) {
-               if (accept == GAP_AGENT_ACCEPT) {
+               if (accept == GAP_AGENT_ACCEPT || accept == GAP_AGENT_ACCEPT_ALWAYS) {
                        g_dbus_method_invocation_return_value(priv->reply_context, NULL);
                        priv->canceled = FALSE;
                } else {
index 476427a..de4f522 100644 (file)
@@ -64,6 +64,7 @@ typedef enum {
 
 /* UUIDs */
 #define HID_UUID                "00001124-0000-1000-8000-00805f9b34fb"
+#define A2DP_SINK_UUID          "0000110b-0000-1000-8000-00805f9b34fb"
 
 /* TODO  More declarations to be added in subsequent patches */
 #ifdef __cplusplus
index 6be93c5..3bedd7e 100644 (file)
@@ -375,7 +375,9 @@ bt_service_id_t _bt_convert_uuid_string_to_service_id(const char *uuid)
                service_id = BT_HFP_SERVICE_ID;
        else if (!strcasecmp(uuid, BT_HAL_HSP_AUDIO_GATEWAY_UUID))
                service_id = BT_HSP_SERVICE_ID;
-       else if (!strcasecmp(uuid, BT_HAL_A2DP_UUID))
+       else if (!strcasecmp(uuid, BT_HAL_A2DP_SINK_UUID))
+               service_id = BT_A2DP_SERVICE_ID;
+       else if (!strcasecmp(uuid, BT_HAL_A2DP_PROFILE_UUID))
                service_id = BT_A2DP_SERVICE_ID;
        else if (!strcasecmp(uuid, BT_HAL_AVRCP_TARGET_UUID))
                service_id = BT_AVRCP_SERVICE_ID;
@@ -419,7 +421,9 @@ char *_bt_convert_service_id_to_uuid_string(bt_service_id_t service_id)
        case BT_HSP_SERVICE_ID:
                return g_strdup(BT_HAL_HSP_AUDIO_GATEWAY_UUID);
        case BT_A2DP_SERVICE_ID:
-               return g_strdup(BT_HAL_A2DP_UUID);
+               return g_strdup(BT_HAL_A2DP_SINK_UUID);
+       case BT_A2DP_SRC_SERVICE_ID:
+               return g_strdup(BT_HAL_A2DP_SOURCE_UUID);
        case BT_AVRCP_SERVICE_ID:
                return g_strdup(BT_HAL_AVRCP_TARGET_UUID);
        case BT_AVRCP_CT_SERVICE_ID:
@@ -444,7 +448,6 @@ char *_bt_convert_service_id_to_uuid_string(bt_service_id_t service_id)
                return g_strdup(BT_HAL_SAP_UUID_NEW);
        /* TODO: Add UUID for following service_ids */
        case BT_DUN_SERVICE_ID:
-       case BT_A2DP_SRC_SERVICE_ID:
        case BT_LAP_SERVICE_ID:
        case BT_ICP_SERVICE_ID:
        case BT_SYNC_SERVICE_ID: